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 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   HID Class                                                           */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_host_class_hid.h"
30 #include "ux_host_stack.h"
31 
32 
33 #if defined(UX_HOST_STANDALONE)
34 
35 extern UINT ux_host_class_hid_report_set_buffer_allocate(
36         UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report,
37         UCHAR **allocated);
38 
39 
40 /**************************************************************************/
41 /*                                                                        */
42 /*  FUNCTION                                               RELEASE        */
43 /*                                                                        */
44 /*    _ux_host_class_hid_report_set_run                   PORTABLE C      */
45 /*                                                           6.1.12       */
46 /*  AUTHOR                                                                */
47 /*                                                                        */
48 /*    Chaoqiong Xiao, Microsoft Corporation                               */
49 /*                                                                        */
50 /*  DESCRIPTION                                                           */
51 /*                                                                        */
52 /*    This function sets a report (input/output/feature) to the device.   */
53 /*    The report can be either decompressed by the stack or raw.          */
54 /*                                                                        */
55 /*    This function is for standalone mode.                               */
56 /*                                                                        */
57 /*  INPUT                                                                 */
58 /*                                                                        */
59 /*    hid                                   Pointer to HID class          */
60 /*    client_report                         Pointer to client report      */
61 /*                                                                        */
62 /*  OUTPUT                                                                */
63 /*                                                                        */
64 /*    Completion Status                                                   */
65 /*                                                                        */
66 /*  CALLS                                                                 */
67 /*                                                                        */
68 /*    _ux_host_class_hid_report_compress    Compress HID report           */
69 /*    _ux_host_stack_class_instance_verify  Verify the instance is valid  */
70 /*    _ux_host_stack_transfer_run           Process transfer states       */
71 /*    _ux_utility_memory_allocate           Allocate memory block         */
72 /*    _ux_utility_memory_copy               Copy memory block             */
73 /*    _ux_utility_memory_free               Release memory block          */
74 /*                                                                        */
75 /*  CALLED BY                                                             */
76 /*                                                                        */
77 /*    Application                                                         */
78 /*    HID Class                                                           */
79 /*                                                                        */
80 /*  RELEASE HISTORY                                                       */
81 /*                                                                        */
82 /*    DATE              NAME                      DESCRIPTION             */
83 /*                                                                        */
84 /*  01-31-2022     Chaoqiong Xiao           Initial Version 6.1.10        */
85 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
86 /*                                            added interrupt OUT support,*/
87 /*                                            resulting in version 6.1.12 */
88 /*                                                                        */
89 /**************************************************************************/
_ux_host_class_hid_report_set_run(UX_HOST_CLASS_HID * hid,UX_HOST_CLASS_HID_CLIENT_REPORT * client_report)90 UINT  _ux_host_class_hid_report_set_run(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report)
91 {
92 
93 UX_INTERRUPT_SAVE_AREA
94 UX_DEVICE                   *device;
95 UX_ENDPOINT                 *control_endpoint;
96 UX_TRANSFER                 *transfer_request;
97 UCHAR                       *report_buffer;
98 UX_HOST_CLASS_HID_REPORT    *hid_report;
99 UINT                        status;
100 
101 
102     /* If trace is enabled, insert this event into the trace buffer.  */
103     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REPORT_SET, hid, client_report, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
104 
105     /* Get the report pointer from the caller.  */
106     hid_report =  client_report -> ux_host_class_hid_client_report;
107 
108     /* Ensure the instance is valid.  */
109     if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS)
110     {
111 
112         /* If trace is enabled, insert this event into the trace buffer.  */
113         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
114 
115         hid -> ux_host_class_hid_status = UX_HOST_CLASS_INSTANCE_UNKNOWN;
116         return(UX_STATE_EXIT);
117     }
118 
119     /* Get device.  */
120     device = hid -> ux_host_class_hid_device;
121 
122     /* Sanity check.  */
123     if (device == UX_NULL ||
124         device -> ux_device_handle != (ULONG)(ALIGN_TYPE)device)
125     {
126 
127         /* If trace is enabled, insert this event into the trace buffer.  */
128         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN,
129                                     device, 0, 0, UX_TRACE_ERRORS, 0, 0)
130 
131         hid -> ux_host_class_hid_status = UX_DEVICE_HANDLE_UNKNOWN;
132         return(UX_STATE_EXIT);
133     }
134 
135 #if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT)
136 
137     /* Check if there is an interrupt OUT endpoint.  */
138     if (hid -> ux_host_class_hid_interrupt_out_endpoint != UX_NULL)
139     {
140 
141         /* Transfer the report by using the interrupt OUT endpoint.  */
142         transfer_request = &hid -> ux_host_class_hid_interrupt_out_endpoint -> ux_endpoint_transfer_request;
143     }
144     else
145 #endif
146     {
147 
148         /* We need to get the default control endpoint transfer request pointer.  */
149         control_endpoint =  &device -> ux_device_control_endpoint;
150         transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
151     }
152 
153     /* Waiting transfer done.  */
154     if (hid -> ux_host_class_hid_cmd_state == UX_STATE_WAIT)
155     {
156 
157         /* Process background tasks.  */
158         _ux_system_tasks_run();
159 
160         /* Check if transfer is done.  */
161         if (transfer_request -> ux_transfer_request_state < UX_STATE_WAIT)
162         {
163 
164             /* Free allocated resource.  */
165             _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
166             hid -> ux_host_class_hid_allocated = UX_NULL;
167 
168             /* Unlock.  */
169             hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK;
170             device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK;
171 
172             /* We are done.  */
173             hid -> ux_host_class_hid_cmd_state = UX_STATE_IDLE;
174             hid -> ux_host_class_hid_status =
175                         transfer_request -> ux_transfer_request_completion_code;
176             return(UX_STATE_NEXT);
177         }
178 
179         /* Keep waiting.  */
180         return(UX_STATE_WAIT);
181     }
182 
183     /* Check state or protection status.  */
184     UX_DISABLE
185     if ((hid -> ux_host_class_hid_flags & UX_HOST_CLASS_HID_FLAG_LOCK) ||
186         (device -> ux_device_flags & UX_DEVICE_FLAG_LOCK))
187     {
188 
189         /* Locked.  */
190         UX_RESTORE
191         return(UX_STATE_LOCK);
192     }
193     hid -> ux_host_class_hid_flags |= UX_HOST_CLASS_HID_FLAG_LOCK;
194     device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK;
195     hid -> ux_host_class_hid_cmd_state = UX_STATE_WAIT;
196     UX_RESTORE
197 
198     /* Build the report buffer for SET_REPORT request.  */
199     status = ux_host_class_hid_report_set_buffer_allocate(hid, client_report, &report_buffer);
200     if (status != UX_SUCCESS)
201     {
202 
203         /* If trace is enabled, insert this event into the trace buffer.  */
204         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, status,
205                             hid, client_report, 0, UX_TRACE_ERRORS, 0, 0)
206 
207         /* Error code.  */
208         hid -> ux_host_class_hid_status = status;
209 
210         /* Unlock.  */
211         hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK;
212         device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK;
213 
214         /* State error.  */
215         hid -> ux_host_class_hid_cmd_state = UX_STATE_ERROR;
216         return(UX_STATE_ERROR);
217     }
218     hid -> ux_host_class_hid_allocated = report_buffer;
219 
220     /* Create a transfer request for the SET_REPORT request.  */
221     transfer_request -> ux_transfer_request_data_pointer =     report_buffer;
222     transfer_request -> ux_transfer_request_requested_length = hid_report -> ux_host_class_hid_report_byte_length;
223     transfer_request -> ux_transfer_request_function =         UX_HOST_CLASS_HID_SET_REPORT;
224     transfer_request -> ux_transfer_request_type =             UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
225     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);
226     transfer_request -> ux_transfer_request_index =            hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber;
227     UX_TRANSFER_STATE_RESET(transfer_request);
228 
229     /* Send request to HCD layer.  */
230     status =  _ux_host_stack_transfer_run(transfer_request);
231     if (status != UX_STATE_WAIT)
232     {
233         _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
234         hid -> ux_host_class_hid_allocated = UX_NULL;
235 
236         hid -> ux_host_class_hid_status =
237                     transfer_request -> ux_transfer_request_completion_code;
238 
239         /* Unlock.  */
240         hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK;
241         device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK;
242 
243         hid -> ux_host_class_hid_cmd_state = (UCHAR)status;
244     }
245 
246     /* Return the function status */
247     return(status);
248 }
249 #endif
250