GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_hid_descriptor_send.c Lines: 51 51 100.0 %
Date: 2024-12-12 17:16:36 Branches: 21 21 100.0 %

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
/**   Device HID Class                                                    */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define UX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "ux_api.h"
28
#include "ux_device_class_hid.h"
29
#include "ux_device_stack.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_device_class_hid_descriptor_send                PORTABLE C      */
37
/*                                                           6.1.8        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function sends back the class descriptor required by the host. */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    descriptor_type                       Descriptor type               */
49
/*    descriptor_index                      Index of descriptor           */
50
/*    host_length                           Length requested by host      */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    Completion Status                                                   */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    (ux_slave_dcd_function)               DCD dispatch function         */
59
/*    _ux_device_stack_transfer_request     Process transfer request      */
60
/*    _ux_utility_memory_copy               Memory copy                   */
61
/*                                                                        */
62
/*  CALLED BY                                                             */
63
/*                                                                        */
64
/*    Application                                                         */
65
/*    Device Stack                                                        */
66
/*                                                                        */
67
/*  RELEASE HISTORY                                                       */
68
/*                                                                        */
69
/*    DATE              NAME                      DESCRIPTION             */
70
/*                                                                        */
71
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
72
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
73
/*                                            verified memset and memcpy  */
74
/*                                            cases,                      */
75
/*                                            resulting in version 6.1    */
76
/*  08-02-2021     Chaoqiong Xiao           Modified comment(s),          */
77
/*                                            fixed HID descriptor search,*/
78
/*                                            resulting in version 6.1.8  */
79
/*                                                                        */
80
/**************************************************************************/
81
460
UINT  _ux_device_class_hid_descriptor_send(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type,
82
                                            ULONG request_index, ULONG host_length)
83
{
84
85
UX_SLAVE_DCD                    *dcd;
86
UX_SLAVE_DEVICE                 *device;
87
UX_SLAVE_TRANSFER               *transfer_request;
88
UX_SLAVE_ENDPOINT               *endpoint;
89
UCHAR *                         device_framework;
90
UCHAR *                         device_framework_end;
91
ULONG                           descriptor_length;
92
460
UINT                            status =  UX_ERROR;
93
ULONG                           length;
94
460
UCHAR                           interface_number = 0xFF;
95
96
    UX_PARAMETER_NOT_USED(request_index);
97
98
    /* If trace is enabled, insert this event into the trace buffer.  */
99
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_DESCRIPTOR_SEND, hid, descriptor_type, request_index, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
100
101
    /* Get the pointer to the DCD.  */
102
460
    dcd =  &_ux_system_slave -> ux_system_slave_dcd;
103
104
    /* Get the pointer to the device.  */
105
460
    device =  &_ux_system_slave -> ux_system_slave_device;
106
107
    /* Get the control endpoint associated with the device.  */
108
460
    endpoint =  &device -> ux_slave_device_control_endpoint;
109
110
    /* Get the pointer to the transfer request associated with the endpoint.  */
111
460
    transfer_request =  &endpoint -> ux_slave_endpoint_transfer_request;
112
113
    /* Set the direction to OUT.  */
114
460
    transfer_request -> ux_slave_transfer_request_phase =  UX_TRANSFER_PHASE_DATA_OUT;
115
116
    /* Shift the descriptor type in the low byte field.  */
117
460
    descriptor_type =  (UCHAR) ((descriptor_type >> 8) & 0xff);
118
119
    /* What type of descriptor do we need to return?  */
120
460
    switch (descriptor_type)
121
    {
122
123
6
    case UX_DEVICE_CLASS_HID_DESCRIPTOR_HID:
124
125
        /* We should have a HID descriptor as part of the config descriptor.  */
126
6
        device_framework =  _ux_system_slave -> ux_system_slave_device_framework;
127
6
        device_framework_end = device_framework + _ux_system_slave -> ux_system_slave_device_framework_length;
128
129
        /* Parse the device framework and locate the HID descriptor.
130
           There is only one HID descriptor.  */
131
30
        while (device_framework < device_framework_end)
132
        {
133
134
            /* Get the type of the current descriptor.  */
135
28
            descriptor_type =  *(device_framework + 1);
136
137
            /* And its length.  */
138
28
            descriptor_length =  (ULONG) *device_framework;
139
140
            /* Save interface number for later check.  */
141
28
            if (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM)
142
7
                interface_number = *(device_framework + 2);
143
144
            /* Check if this is a HID report descriptor.  */
145
28
            if ((descriptor_type == UX_DEVICE_CLASS_HID_DESCRIPTOR_HID) &&
146
7
                (interface_number == (UCHAR)request_index))
147
            {
148
149
                /* Ensure the host does not demand a length beyond our descriptor (Windows does that)
150
                   and do not return more than what is allowed.  */
151
4
                if (descriptor_length < host_length)
152
1
                    length =  descriptor_length;
153
                else
154
3
                    length =  host_length;
155
156
                /* Check buffer length, since descriptor length may exceed buffer...  */
157
4
                if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH)
158
                {
159
160
                    /* Error trap. */
161
1
                    _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
162
163
                    /* If trace is enabled, insert this event into the trace buffer.  */
164
                    UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
165
166
                    /* Stall the endpoint.  */
167
1
                    status =  dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint);
168
1
                    break;
169
                }
170
171
                /* Copy the device descriptor into the transfer request memory.  */
172
3
                _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
173
                                            device_framework, length); /* Use case of memcpy is verified. */
174
175
                /* We can return the configuration descriptor.  */
176
3
                status =  _ux_device_stack_transfer_request(transfer_request, length, host_length);
177
3
                break;
178
179
            }
180
181
            /* Point to the next descriptor.  */
182
24
            device_framework +=  descriptor_length;
183
        }
184
185
        /* Stall the endpoint if not found or corrupt.  */
186
6
        if (device_framework >= device_framework_end)
187
2
            status =  dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint);
188
189
6
        break;
190
191
452
    case UX_DEVICE_CLASS_HID_DESCRIPTOR_REPORT:
192
193
        /* Get the length of entire configuration descriptor.  */
194
452
        descriptor_length =  hid -> ux_device_class_hid_report_length;
195
196
        /* Ensure the host does not demand a length beyond our descriptor (Windows does that)
197
           and do not return more than what is allowed.  */
198
452
        if (descriptor_length < host_length)
199
4
            length =  descriptor_length;
200
        else
201
448
            length =  host_length;
202
203
        /* Check buffer length, since total descriptors length may exceed buffer...  */
204
452
        if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH)
205
        {
206
207
            /* Error trap. */
208
1
            _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
209
210
            /* If trace is enabled, insert this event into the trace buffer.  */
211
            UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
212
213
            /* Stall the endpoint.  */
214
1
            status =  dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint);
215
1
            break;
216
        }
217
218
        /* Copy the device descriptor into the transfer request memory.  */
219
451
        _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
220
451
                                    hid -> ux_device_class_hid_report_address, length); /* Use case of memcpy is verified. */
221
222
        /* We can return the report descriptor.  */
223
451
        status =  _ux_device_stack_transfer_request(transfer_request, length, host_length);
224
451
        break;
225
226
2
    case UX_DEVICE_CLASS_HID_DESCRIPTOR_PHYSICAL:
227
228
        /* Not treated for now.  Fall through and Stall endpoint.  */
229
230
    default:
231
232
        /* Stall the endpoint.  */
233
2
        dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint);
234
2
        return(UX_ERROR);
235
    }
236
237
    /* Return the status to the caller.  */
238
458
    return(status);
239
}
240