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: 2026-03-06 18:57:10 Branches: 21 21 100.0 %

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