GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_hid_report_get.c Lines: 45 49 91.8 %
Date: 2024-12-12 17:16:36 Branches: 22 26 84.6 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** USBX Component                                                        */
16
/**                                                                       */
17
/**   HID Class                                                           */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
23
/* Include necessary system files.  */
24
25
#define UX_SOURCE_CODE
26
27
#include "ux_api.h"
28
#include "ux_host_class_hid.h"
29
#include "ux_host_stack.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_host_class_hid_report_get                       PORTABLE C      */
37
/*                                                           6.1.10       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function gets a report (input/output/feature) from the device. */
45
/*    The report can be either decompressed by the stack or raw.          */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    hid                                   Pointer to HID class          */
50
/*    client_report                         Pointer to client report      */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    Completion Status                                                   */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _ux_host_class_hid_report_decompress  Decompress HID report         */
59
/*    _ux_host_stack_class_instance_verify  Verify the instance is valid  */
60
/*    _ux_host_stack_transfer_request       Process transfer request      */
61
/*    _ux_utility_memory_allocate           Allocate memory block         */
62
/*    _ux_utility_memory_copy               Copy memory block             */
63
/*    _ux_utility_memory_free               Release memory block          */
64
/*    _ux_host_semaphore_get                Get protection semaphore      */
65
/*    _ux_host_semaphore_put                Release protection semaphore  */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    Application                                                         */
70
/*    HID Class                                                           */
71
/*                                                                        */
72
/*  RELEASE HISTORY                                                       */
73
/*                                                                        */
74
/*    DATE              NAME                      DESCRIPTION             */
75
/*                                                                        */
76
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
77
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
78
/*                                            verified memset and memcpy  */
79
/*                                            cases, accepted both INPUT  */
80
/*                                            and FEATURE reports,        */
81
/*                                            resulting in version 6.1    */
82
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
83
/*                                            added standalone support,   */
84
/*                                            resulting in version 6.1.10 */
85
/*                                                                        */
86
/**************************************************************************/
87
15
UINT  _ux_host_class_hid_report_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report)
88
{
89
#if defined(UX_HOST_STANDALONE)
90
UX_INTERRUPT_SAVE_AREA
91
#endif
92
UX_ENDPOINT                     *control_endpoint;
93
UX_TRANSFER                     *transfer_request;
94
UCHAR                           *report_buffer;
95
UX_HOST_CLASS_HID_REPORT        *hid_report;
96
UINT                            status;
97
98
    /* If trace is enabled, insert this event into the trace buffer.  */
99
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REPORT_GET, hid, client_report, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
100
101
    /* Ensure the instance is valid.  */
102
15
    if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS)
103
    {
104
105
        /* Error trap. */
106
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN);
107
108
        /* If trace is enabled, insert this event into the trace buffer.  */
109
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
110
111
1
        return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
112
    }
113
114
    /* Protect thread reentry to this instance.  */
115
14
    _ux_host_class_hid_lock_fail_return(hid);
116
117
    /* Get the report pointer from the caller.  */
118
13
    hid_report =  client_report -> ux_host_class_hid_client_report;
119
120
    /* Ensure this is a INPUT report or FEATURE report.  */
121
13
    if (hid_report -> ux_host_class_hid_report_type != UX_HOST_CLASS_HID_REPORT_TYPE_INPUT &&
122
2
        hid_report -> ux_host_class_hid_report_type != UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE)
123
    {
124
125
        /* Unprotect thread reentry to this instance.  */
126
1
        _ux_host_class_hid_unlock(hid);
127
128
        /* If trace is enabled, insert this event into the trace buffer.  */
129
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
130
131
        /* Return error.  */
132
1
        return(UX_HOST_CLASS_HID_REPORT_ERROR);
133
    }
134
135
    /* Check the report length, if 0, we don't need to do anything.  */
136
12
    if (hid_report -> ux_host_class_hid_report_byte_length == 0)
137
    {
138
139
        /* Unprotect thread reentry to this instance.  */
140
1
        _ux_host_class_hid_unlock(hid);
141
142
        /* Error trap. */
143
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR);
144
145
        /* If trace is enabled, insert this event into the trace buffer.  */
146
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
147
148
        /* Return error code.  */
149
1
        return(UX_HOST_CLASS_HID_REPORT_ERROR);
150
    }
151
152
    /* Get some memory for reading the report.  */
153
11
    report_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length);
154
11
    if (report_buffer == UX_NULL)
155
    {
156
157
        /* Unprotect thread reentry to this instance.  */
158
1
        _ux_host_class_hid_unlock(hid);
159
160
        /* Return error code.  */
161
1
        return(UX_MEMORY_INSUFFICIENT);
162
    }
163
164
    /* We need to get the default control endpoint transfer request pointer.  */
165
10
    control_endpoint =  &hid -> ux_host_class_hid_device -> ux_device_control_endpoint;
166
10
    transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
167
168
    /* Protect the control endpoint semaphore here.  It will be unprotected in the
169
       transfer request function.  */
170
#if defined(UX_HOST_STANDALONE)
171
    UX_DISABLE
172
    if (hid -> ux_host_class_hid_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK)
173
    {
174
        _ux_utility_memory_free(report_buffer);
175
        hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK;
176
        UX_RESTORE
177
        return(UX_BUSY);
178
    }
179
    hid -> ux_host_class_hid_device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK;
180
    transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK;
181
    UX_TRANSFER_STATE_RESET(transfer_request);
182
    UX_RESTORE
183
#else
184
10
    status =  _ux_host_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER);
185
186
    /* Check for status.  */
187
10
    if (status != UX_SUCCESS)
188
    {
189
190
        /* Something went wrong. */
191
192
        /* Free all resources.  */
193
1
        _ux_utility_memory_free(report_buffer);
194
195
        /* Unprotect thread reentry to this instance.  */
196
1
        _ux_host_class_hid_unlock(hid);
197
198
1
        return(status);
199
    }
200
#endif
201
202
    /* Create a transfer request for the GET_REPORT request.  */
203
9
    transfer_request -> ux_transfer_request_data_pointer =      report_buffer;
204
9
    transfer_request -> ux_transfer_request_requested_length =  hid_report -> ux_host_class_hid_report_byte_length;
205
9
    transfer_request -> ux_transfer_request_function =          UX_HOST_CLASS_HID_GET_REPORT;
206
9
    transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
207
9
    transfer_request -> ux_transfer_request_value =             (UINT)((USHORT) hid_report -> ux_host_class_hid_report_id | (USHORT) hid_report -> ux_host_class_hid_report_type << 8);
208
9
    transfer_request -> ux_transfer_request_index =             hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber;
209
210
    /* Send request to HCD layer.  */
211
9
    status =  _ux_host_stack_transfer_request(transfer_request);
212
213
    /* Check for correct transfer and entire descriptor returned.  */
214

9
    if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == hid_report -> ux_host_class_hid_report_byte_length))
215
    {
216
217
        /* The report is now in memory in a raw format. The application may desire to keep it that way!  */
218
7
        if (client_report -> ux_host_class_hid_client_report_flags & UX_HOST_CLASS_HID_REPORT_RAW)
219
        {
220
221
            /* Ensure the user has given us enough memory for the raw buffer.  */
222
5
            if (client_report -> ux_host_class_hid_client_report_length >= transfer_request -> ux_transfer_request_actual_length)
223
            {
224
225
                /* We have enough memory to store the raw buffer.  */
226
4
                _ux_utility_memory_copy(client_report -> ux_host_class_hid_client_report_buffer, report_buffer, transfer_request -> ux_transfer_request_actual_length); /* Use case of memcpy is verified. */
227
228
                /* Set status to success.  */
229
4
                status =  UX_SUCCESS;
230
            }
231
            else
232
            {
233
234
                /* Error trap. */
235
1
                _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW);
236
237
                /* If trace is enabled, insert this event into the trace buffer.  */
238
                UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_BUFFER_OVERFLOW, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
239
240
                /* Set overflow status.  */
241
1
                status =  UX_BUFFER_OVERFLOW;
242
            }
243
        }
244
        else
245
        {
246
247
            /* The report buffer must be parsed and decompressed.  */
248
2
            status =  _ux_host_class_hid_report_decompress(hid, client_report, report_buffer, transfer_request -> ux_transfer_request_actual_length);
249
        }
250
    }
251
    else
252
    {
253
254
        /* Error trap. */
255
2
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR);
256
257
        /* If trace is enabled, insert this event into the trace buffer.  */
258
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
259
260
        /* Set report error status.  */
261
2
        status =  UX_HOST_CLASS_HID_REPORT_ERROR;
262
    }
263
264
    /* Free all resources.  */
265
9
    _ux_utility_memory_free(report_buffer);
266
267
    /* Unprotect thread reentry to this instance.  */
268
9
    _ux_host_class_hid_unlock(hid);
269
270
    /* Return the completion status.  */
271
9
    return(status);
272
}
273
274
/**************************************************************************/
275
/*                                                                        */
276
/*  FUNCTION                                               RELEASE        */
277
/*                                                                        */
278
/*    _uxe_host_class_hid_report_get                      PORTABLE C      */
279
/*                                                           6.3.0        */
280
/*  AUTHOR                                                                */
281
/*                                                                        */
282
/*    Chaoqiong Xiao, Microsoft Corporation                               */
283
/*                                                                        */
284
/*  DESCRIPTION                                                           */
285
/*                                                                        */
286
/*    This function checks errors in HID report get function call.        */
287
/*                                                                        */
288
/*  INPUT                                                                 */
289
/*                                                                        */
290
/*    hid                                   Pointer to HID class          */
291
/*    client_report                         Pointer to client report      */
292
/*                                                                        */
293
/*  OUTPUT                                                                */
294
/*                                                                        */
295
/*    Status                                                              */
296
/*                                                                        */
297
/*  CALLS                                                                 */
298
/*                                                                        */
299
/*    _ux_host_class_hid_report_get         get a report                  */
300
/*                                                                        */
301
/*  CALLED BY                                                             */
302
/*                                                                        */
303
/*    Application                                                         */
304
/*                                                                        */
305
/*  RELEASE HISTORY                                                       */
306
/*                                                                        */
307
/*    DATE              NAME                      DESCRIPTION             */
308
/*                                                                        */
309
/*  10-31-2023     Chaoqiong Xiao           Initial Version 6.3.0         */
310
/*                                                                        */
311
/**************************************************************************/
312
UINT  _uxe_host_class_hid_report_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report)
313
{
314
315
    /* Sanity checks.  */
316
    if ((hid == UX_NULL) || (client_report == UX_NULL))
317
        return(UX_INVALID_PARAMETER);
318
319
    /* Invoke report ID get function.  */
320
    return(_ux_host_class_hid_report_get(hid, client_report));
321
}