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 #if defined(UX_DEVICE_STANDALONE)
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_device_class_hid_read_run PORTABLE C */
38 /* 6.1.12 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function reads from the HID class. */
46 /* This function must not be used with receiver related functions. */
47 /* This function is for standalone mode. */
48 /* */
49 /* INPUT */
50 /* */
51 /* hid Address of hid class */
52 /* instance */
53 /* buffer Pointer to buffer to save */
54 /* received data */
55 /* requested_length Length of bytes to read */
56 /* actual_length Pointer to save number of */
57 /* bytes read */
58 /* */
59 /* OUTPUT */
60 /* */
61 /* None */
62 /* */
63 /* CALLS */
64 /* */
65 /* _ux_device_stack_transfer_request Transfer request */
66 /* _ux_utility_memory_copy Copy memory */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Application */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 07-29-2022 Chaoqiong Xiao Initial Version 6.1.12 */
77 /* */
78 /**************************************************************************/
_ux_device_class_hid_read_run(UX_SLAVE_CLASS_HID * hid,UCHAR * buffer,ULONG requested_length,ULONG * actual_length)79 UINT _ux_device_class_hid_read_run(UX_SLAVE_CLASS_HID *hid, UCHAR *buffer,
80 ULONG requested_length, ULONG *actual_length)
81 {
82 #if !defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT)
83 UX_PARAMETER_NOT_USED(hid);
84 UX_PARAMETER_NOT_USED(buffer);
85 UX_PARAMETER_NOT_USED(requested_length);
86 UX_PARAMETER_NOT_USED(actual_length);
87 return(UX_FUNCTION_NOT_SUPPORTED);
88 #else
89
90 UX_SLAVE_ENDPOINT *endpoint;
91 UX_SLAVE_DEVICE *device;
92 UX_SLAVE_TRANSFER *transfer_request;
93 UINT read_state;
94 UINT status= UX_SUCCESS;
95
96
97 /* If trace is enabled, insert this event into the trace buffer. */
98 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_READ, hid, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
99
100 /* Get the pointer to the device. */
101 device = &_ux_system_slave -> ux_system_slave_device;
102
103 /* As long as the device is in the CONFIGURED state. */
104 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
105 {
106
107 /* Error trap. */
108 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
109
110 /* If trace is enabled, insert this event into the trace buffer. */
111 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
112
113 /* Cannot proceed with command, the interface is down. */
114 hid -> ux_device_class_hid_read_state = UX_STATE_RESET;
115 hid -> ux_device_class_hid_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN;
116 return(UX_STATE_EXIT);
117 }
118
119 /* Locate the endpoint. */
120 endpoint = hid -> ux_device_class_hid_read_endpoint;
121
122 /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */
123 if (endpoint == UX_NULL)
124 {
125 /* Error trap. */
126 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN);
127
128 hid -> ux_device_class_hid_read_state = UX_STATE_RESET;
129 hid -> ux_device_class_hid_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN;
130 return(UX_STATE_EXIT);
131 }
132
133 /* All HID reading are on the endpoint OUT, from the host. */
134 transfer_request = &endpoint -> ux_slave_endpoint_transfer_request;
135
136 /* Handle state cases. */
137 read_state = hid -> ux_device_class_hid_read_state;
138 switch(read_state)
139 {
140 case UX_STATE_RESET:
141 hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_READ_START;
142 hid -> ux_device_class_hid_read_status = UX_TRANSFER_NO_ANSWER;
143 hid -> ux_device_class_hid_read_buffer = buffer;
144 hid -> ux_device_class_hid_read_requested_length = requested_length;
145 hid -> ux_device_class_hid_read_actual_length = 0;
146
147 /* Fall through. */
148 case UX_DEVICE_CLASS_HID_READ_START:
149
150 /* Get remaining requested length. */
151 requested_length = hid -> ux_device_class_hid_read_requested_length -
152 hid -> ux_device_class_hid_read_actual_length;
153
154 /* There is no remaining, we are done. */
155 if (requested_length == 0)
156 {
157 *actual_length = hid -> ux_device_class_hid_read_actual_length;
158 hid -> ux_device_class_hid_read_state = UX_STATE_RESET;
159 hid -> ux_device_class_hid_read_status = UX_SUCCESS;
160 return(UX_STATE_NEXT);
161 }
162
163 /* Check if we have enough in the local buffer. */
164 if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH)
165
166 /* We have too much to transfer. */
167 hid -> ux_device_class_hid_read_transfer_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH;
168
169 else
170
171 /* We can proceed with the demanded length. */
172 hid -> ux_device_class_hid_read_transfer_length = requested_length;
173
174 /* Next state. */
175 hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_READ_WAIT;
176 UX_SLAVE_TRANSFER_STATE_RESET(transfer_request);
177
178 /* Fall through. */
179 case UX_DEVICE_CLASS_HID_READ_WAIT:
180
181 /* Send the request to the device controller. */
182 status = _ux_device_stack_transfer_run(transfer_request,
183 hid -> ux_device_class_hid_read_transfer_length,
184 hid -> ux_device_class_hid_read_transfer_length);
185
186 /* Error case. */
187 if (status < UX_STATE_NEXT)
188 {
189
190 hid -> ux_device_class_hid_read_state = UX_STATE_RESET;
191 hid -> ux_device_class_hid_read_status =
192 transfer_request -> ux_slave_transfer_request_completion_code;
193 return(UX_STATE_EXIT);
194 }
195
196 /* Success case. */
197 if (status == UX_STATE_NEXT)
198 {
199
200 /* We need to copy the buffer locally. */
201 _ux_utility_memory_copy(hid -> ux_device_class_hid_read_buffer,
202 transfer_request -> ux_slave_transfer_request_data_pointer,
203 transfer_request -> ux_slave_transfer_request_actual_length); /* Use case of memcpy is verified. */
204
205 /* Next buffer address. */
206 hid -> ux_device_class_hid_read_buffer +=
207 transfer_request -> ux_slave_transfer_request_actual_length;
208
209 /* Set the length actually received. */
210 hid -> ux_device_class_hid_read_actual_length +=
211 transfer_request -> ux_slave_transfer_request_actual_length;
212
213 /* Last transfer status. */
214 hid -> ux_device_class_hid_read_status =
215 transfer_request -> ux_slave_transfer_request_completion_code;
216
217 /* Update actual length. */
218 *actual_length = hid -> ux_device_class_hid_read_actual_length;
219
220 /* Check short packet. */
221 if (transfer_request -> ux_slave_transfer_request_actual_length <
222 transfer_request -> ux_slave_transfer_request_requested_length)
223 {
224
225 /* It's done. */
226 hid -> ux_device_class_hid_read_state = UX_STATE_RESET;
227 return(UX_STATE_NEXT);
228 }
229
230 /* Next state. */
231 hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_READ_START;
232 }
233
234 /* Keep waiting. */
235 return(UX_STATE_WAIT);
236
237 /* Receiver running states. */
238 case UX_DEVICE_CLASS_HID_RECEIVER_START: /* Fall through. */
239 case UX_DEVICE_CLASS_HID_RECEIVER_WAIT: /* Fall through. */
240 case UX_DEVICE_CLASS_HID_RECEIVER_ERROR:
241
242 /* Receiver running. */
243 return(UX_STATE_ERROR);
244
245 default: /* Error. */
246 hid -> ux_device_class_hid_read_status = UX_INVALID_STATE;
247 hid -> ux_device_class_hid_read_state = UX_STATE_RESET;
248 break;
249 }
250
251 /* Error case. */
252 return(UX_STATE_EXIT);
253 #endif
254 }
255 #endif
256