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