1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
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_control_request PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function manages the based sent by the host on the control */
45 /* endpoints with a CLASS or VENDOR SPECIFIC type. */
46 /* */
47 /* INPUT */
48 /* */
49 /* hid Pointer to hid class */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* None */
54 /* */
55 /* CALLS */
56 /* */
57 /* _ux_device_stack_transfer_request Transfer request */
58 /* _ux_device_class_hid_report_get Process Get_Report request */
59 /* _ux_device_class_hid_report_set Process Set_Report request */
60 /* _ux_device_class_hid_descriptor_send Send requested descriptor */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* HID Class */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
71 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
72 /* prefixed UX to MS_TO_TICK, */
73 /* used UX prefix to refer to */
74 /* TX symbols instead of using */
75 /* them directly, */
76 /* resulting in version 6.1 */
77 /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */
78 /* fixed compile warnings 64b, */
79 /* resulting in version 6.1.2 */
80 /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */
81 /* added Get/Set Protocol */
82 /* request support, */
83 /* resulting in version 6.1.3 */
84 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
85 /* added standalone support, */
86 /* resulting in version 6.1.10 */
87 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
88 /* resulting in version 6.1.11 */
89 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
90 /* fixed parameter/variable */
91 /* names conflict C++ keyword, */
92 /* resulting in version 6.1.12 */
93 /* */
94 /**************************************************************************/
_ux_device_class_hid_control_request(UX_SLAVE_CLASS_COMMAND * command)95 UINT _ux_device_class_hid_control_request(UX_SLAVE_CLASS_COMMAND *command)
96 {
97
98 UX_SLAVE_TRANSFER *transfer_request;
99 UX_SLAVE_DEVICE *device;
100 UX_SLAVE_CLASS *class_ptr;
101 ULONG request;
102 ULONG request_value;
103 ULONG request_index;
104 ULONG request_length;
105 ULONG descriptor_type;
106 UCHAR duration;
107 UX_SLAVE_CLASS_HID *hid;
108
109 /* Get the pointer to the device. */
110 device = &_ux_system_slave -> ux_system_slave_device;
111
112 /* Get the pointer to the transfer request associated with the control endpoint. */
113 transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request;
114
115 /* Extract all necessary fields of the request. */
116 request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST);
117 request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE);
118 request_index = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_INDEX);
119 request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
120
121 /* Duration - upper byte of wValue. */
122 duration = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE + 1);
123
124 /* Get the class container. */
125 class_ptr = command -> ux_slave_class_command_class_ptr;
126
127 /* Get the storage instance from this class container. */
128 hid = (UX_SLAVE_CLASS_HID *) class_ptr -> ux_slave_class_instance;
129
130 /* Here we proceed only the standard request we know of at the device level. */
131 switch (request)
132 {
133
134 case UX_DEVICE_CLASS_HID_COMMAND_GET_REPORT:
135
136 /* Send the requested report to the host. */
137 _ux_device_class_hid_report_get(hid, request_value, request_index, request_length);
138 break;
139
140 case UX_DEVICE_CLASS_HID_COMMAND_SET_REPORT:
141
142 /* Extract the descriptor type. */
143 descriptor_type = (request_value & 0xff00) >> 8;
144
145 /* Get the requested report from the host. */
146 _ux_device_class_hid_report_set(hid, descriptor_type, request_index, request_length);
147 break;
148
149 case UX_GET_DESCRIPTOR:
150
151 /* Send the requested descriptor to the host. */
152 _ux_device_class_hid_descriptor_send(hid, request_value, request_index, request_length);
153 break;
154
155 case UX_DEVICE_CLASS_HID_COMMAND_GET_IDLE:
156 case UX_DEVICE_CLASS_HID_COMMAND_SET_IDLE:
157
158 /* Ignore Report ID for now. */
159
160 if (request == UX_DEVICE_CLASS_HID_COMMAND_GET_IDLE)
161 {
162
163 /* Send the idle rate. */
164 *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)hid -> ux_device_class_hid_event_idle_rate;
165 _ux_device_stack_transfer_request(transfer_request, 1, request_length);
166 }
167 else
168 {
169
170 /* Accept the idle rate if it changes. */
171 if ((UCHAR)hid -> ux_device_class_hid_event_idle_rate != duration)
172 {
173
174 hid -> ux_device_class_hid_event_idle_rate = duration;
175 if (duration == 0)
176 {
177
178 /* No need to repeat last report, no timeout. */
179 hid -> ux_device_class_hid_event_wait_timeout = UX_WAIT_FOREVER;
180 }
181 else
182 {
183
184 /* Calculate the timeout value. Weighted as 4ms. */
185 hid -> ux_device_class_hid_event_wait_timeout = (ULONG)UX_MS_TO_TICK((ULONG)duration << 2u);
186
187 /* Be sure to have a timeout that is not zero. */
188 if (hid -> ux_device_class_hid_event_wait_timeout == 0)
189 hid -> ux_device_class_hid_event_wait_timeout ++;
190
191 #if defined(UX_DEVICE_STANDALONE)
192
193 /* Restart event checking if no transfer in progress. */
194 if (hid -> ux_device_class_hid_event_state != UX_STATE_WAIT)
195 hid -> ux_device_class_hid_event_state = UX_STATE_RESET;
196 #else
197
198 /* Set an event to wake up the interrupt thread. */
199 _ux_device_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, UX_DEVICE_CLASS_HID_NEW_IDLE_RATE, UX_OR);
200 #endif
201 }
202 }
203 }
204 break;
205
206 case UX_DEVICE_CLASS_HID_COMMAND_GET_PROTOCOL:
207
208 /* Send the protocol. */
209 *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)hid -> ux_device_class_hid_protocol;
210 _ux_device_stack_transfer_request(transfer_request, 1, request_length);
211 break;
212
213 case UX_DEVICE_CLASS_HID_COMMAND_SET_PROTOCOL:
214
215 /* Accept the protocol. */
216 hid -> ux_device_class_hid_protocol = request_value;
217 break;
218
219 default:
220
221 /* Unknown function. It's not handled. */
222 return(UX_ERROR);
223 }
224
225 /* It's handled. */
226 return(UX_SUCCESS);
227 }
228
229