1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "usb_device_config.h"
10 #include "usb.h"
11 #include "usb_device.h"
12
13 #include "usb_device_class.h"
14
15 #if ((defined(USB_DEVICE_CONFIG_PHDC)) && (USB_DEVICE_CONFIG_PHDC > 0U))
16 #include "usb_device_phdc.h"
17
18 /*******************************************************************************
19 * Definitions
20 ******************************************************************************/
21
22 /*******************************************************************************
23 * Prototypes
24 ******************************************************************************/
25
26 /*! @brief local function prototypes */
27 static usb_status_t USB_DevicePhdcAllocateHandle(usb_device_phdc_struct_t **handle);
28 static usb_status_t USB_DevicePhdcFreeHandle(usb_device_phdc_struct_t *handle);
29 static usb_status_t USB_DevicePhdcBulkInCallback(usb_device_handle handle,
30 usb_device_endpoint_callback_message_struct_t *message,
31 void *callbackParam);
32 static usb_status_t USB_DevicePhdcBulkOutCallback(usb_device_handle handle,
33 usb_device_endpoint_callback_message_struct_t *message,
34 void *callbackParam);
35 static usb_status_t USB_DevicePhdcInterruptInCallback(usb_device_handle handle,
36 usb_device_endpoint_callback_message_struct_t *message,
37 void *callbackParam);
38 static usb_status_t USB_DevicePhdcEndpointsInit(usb_device_phdc_struct_t *phdcHandle);
39 static usb_status_t USB_DevicePhdcEndpointsDeinit(usb_device_phdc_struct_t *phdcHandle);
40
41 /*******************************************************************************
42 * Variables
43 ******************************************************************************/
44
45 /*! @brief the PHDC device instance */
USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE)46 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_phdc_struct_t
47 g_phdcHandle[USB_DEVICE_CONFIG_PHDC];
48
49 /*******************************************************************************
50 * Code
51 ******************************************************************************/
52
53 /*!
54 * @brief Allocate a device PHDC class handle.
55 *
56 * This function allocates a device PHDC class handle.
57 *
58 * @param handle It is out parameter, is used to return pointer of the device PHDC class handle to the caller.
59 *
60 * @retval kStatus_USB_Success Get a device PHDC class handle successfully.
61 * @retval kStatus_USB_Busy Cannot allocate a device PHDC class handle.
62 */
63 static usb_status_t USB_DevicePhdcAllocateHandle(usb_device_phdc_struct_t **handle)
64 {
65 uint32_t count;
66 for (count = 0; count < USB_DEVICE_CONFIG_PHDC; count++)
67 {
68 if (NULL == g_phdcHandle[count].handle)
69 {
70 *handle = &g_phdcHandle[count];
71 return kStatus_USB_Success;
72 }
73 }
74 return kStatus_USB_Busy;
75 }
76
77 /*!
78 * @brief Free a device PHDC class handle.
79 *
80 * This function frees a device PHDC class handle.
81 *
82 * @param handle The device PHDC class handle.
83 *
84 * @retval kStatus_USB_Success Free device PHDC class handle successfully.
85 */
USB_DevicePhdcFreeHandle(usb_device_phdc_struct_t * handle)86 static usb_status_t USB_DevicePhdcFreeHandle(usb_device_phdc_struct_t *handle)
87 {
88 handle->handle = NULL;
89 handle->configStruct = (usb_device_class_config_struct_t *)NULL;
90 handle->configuration = 0U;
91 handle->alternate = 0U;
92 return kStatus_USB_Success;
93 }
94
95 /*!
96 * @brief bulk IN endpoint callback function.
97 *
98 * This callback function is used to notify upper layer the transfer result of a transfer.
99 * This callback pointer is passed when the bulk IN pipe initialized.
100 *
101 * @param handle The device handle. It equals the value returned from USB_DeviceInit.
102 * @param message The result of the bulk IN pipe transfer.
103 * @param callbackParam The parameter for this callback. It is same with
104 * usb_device_endpoint_callback_struct_t::callbackParam.
105 * In the class, the value is the PHDC class handle.
106 *
107 * @retval kStatus_USB_Success The transfer is successful.
108 * @retval kStatus_USB_InvalidHandle The device handle not be found.
109 */
USB_DevicePhdcBulkInCallback(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)110 static usb_status_t USB_DevicePhdcBulkInCallback(usb_device_handle handle,
111 usb_device_endpoint_callback_message_struct_t *message,
112 void *callbackParam)
113 {
114 usb_device_phdc_struct_t *phdcHandle;
115 usb_status_t status = kStatus_USB_Error;
116
117 phdcHandle = (usb_device_phdc_struct_t *)callbackParam;
118
119 if (NULL == phdcHandle)
120 {
121 return kStatus_USB_InvalidHandle;
122 }
123 phdcHandle->bulkIn.isBusy = 0U;
124 if ((NULL != phdcHandle->configStruct) && (NULL != phdcHandle->configStruct->classCallback))
125 {
126 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
127 it is from the second parameter of classInit */
128 status = phdcHandle->configStruct->classCallback((class_handle_t)phdcHandle,
129 kUSB_DevicePhdcEventBulkInSendComplete, message);
130 }
131
132 return status;
133 }
134
135 /*!
136 * @brief bulk OUT endpoint callback function.
137 *
138 * This callback function is used to notify upper layer the transfer result of a transfer.
139 * This callback pointer is passed when the bulk OUT pipe initialized.
140 *
141 * @param handle The device handle. It equals the value returned from USB_DeviceInit.
142 * @param message The result of the bulk OUT pipe transfer.
143 * @param callbackParam The parameter for this callback. It is same with
144 * usb_device_endpoint_callback_struct_t::callbackParam.
145 * In the class, the value is the PHDC class handle.
146 *
147 * @retval kStatus_USB_Success The transfer is successful.
148 * @retval kStatus_USB_InvalidHandle The device handle not be found.
149 */
USB_DevicePhdcBulkOutCallback(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)150 static usb_status_t USB_DevicePhdcBulkOutCallback(usb_device_handle handle,
151 usb_device_endpoint_callback_message_struct_t *message,
152 void *callbackParam)
153 {
154 usb_device_phdc_struct_t *phdcHandle;
155 usb_status_t status = kStatus_USB_Error;
156
157 phdcHandle = (usb_device_phdc_struct_t *)callbackParam;
158
159 if (NULL == phdcHandle)
160 {
161 return kStatus_USB_InvalidHandle;
162 }
163 phdcHandle->bulkOut.isBusy = 0U;
164 if ((NULL != phdcHandle->configStruct) && (NULL != phdcHandle->configStruct->classCallback))
165 {
166 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
167 it is from the second parameter of classInit */
168 status = phdcHandle->configStruct->classCallback((class_handle_t)phdcHandle, kUSB_DevicePhdcEventDataReceived,
169 message);
170 }
171
172 return status;
173 }
174
175 /*!
176 * @brief Interrupt IN endpoint callback function.
177 *
178 * This callback function is used to notify upper layer the transfer result of a transfer.
179 * This callback pointer is passed when the interrupt IN pipe initialized.
180 *
181 * @param handle The device handle. It equals the value returned from USB_DeviceInit.
182 * @param message The result of the interrupt IN pipe transfer.
183 * @param callbackParam The parameter for this callback. It is same with
184 * usb_device_endpoint_callback_struct_t::callbackParam.
185 * In the class, the value is the PHDC class handle.
186 *
187 * @retval kStatus_USB_Success The transfer is successful.
188 * @retval kStatus_USB_InvalidHandle The device handle not be found.
189 */
USB_DevicePhdcInterruptInCallback(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)190 static usb_status_t USB_DevicePhdcInterruptInCallback(usb_device_handle handle,
191 usb_device_endpoint_callback_message_struct_t *message,
192 void *callbackParam)
193 {
194 usb_device_phdc_struct_t *phdcHandle;
195 usb_status_t status = kStatus_USB_Error;
196
197 phdcHandle = (usb_device_phdc_struct_t *)callbackParam;
198
199 if (NULL == phdcHandle)
200 {
201 return kStatus_USB_InvalidHandle;
202 }
203 phdcHandle->interruptIn.isBusy = 0U;
204 if ((NULL != phdcHandle->configStruct) && (NULL != phdcHandle->configStruct->classCallback))
205 {
206 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
207 it is from the second parameter of classInit */
208 status = phdcHandle->configStruct->classCallback((class_handle_t)phdcHandle,
209 kUSB_DevicePhdcEventInterruptInSendComplete, message);
210 }
211 return status;
212 }
213
214 /*!
215 * @brief Initialize the endpoints of the PHDC class.
216 *
217 * This callback function is used to initialize the endpoints of the PHDC class.
218 *
219 * @param phdcHandle The device PHDC class handle. It equals the value returned from
220 * usb_device_class_config_struct_t::classHandle.
221 *
222 * @retval kStatus_USB_Success The PHDC endpoint is initialized successful.
223 * @retval kStatus_USB_Error The interfaces not be found.
224 */
USB_DevicePhdcEndpointsInit(usb_device_phdc_struct_t * phdcHandle)225 static usb_status_t USB_DevicePhdcEndpointsInit(usb_device_phdc_struct_t *phdcHandle)
226 {
227 usb_device_interface_list_t *interfaceList;
228 usb_device_interface_struct_t *interface = (usb_device_interface_struct_t *)NULL;
229 usb_status_t status = kStatus_USB_Error;
230 if (NULL == phdcHandle)
231 {
232 return status;
233 }
234 if (phdcHandle->configuration > phdcHandle->configStruct->classInfomation->configurations)
235 {
236 return status;
237 }
238 /* gets the interface list */
239 interfaceList = &phdcHandle->configStruct->classInfomation->interfaceList[phdcHandle->configuration - 1U];
240 for (uint32_t count = 0U; count < interfaceList->count; count++)
241 {
242 if (USB_DEVICE_CONFIG_PHDC_CLASS_CODE == interfaceList->interfaces[count].classCode)
243 {
244 for (uint32_t index = 0U; index < interfaceList->interfaces[count].count; index++)
245 {
246 if (interfaceList->interfaces[count].interface[index].alternateSetting == phdcHandle->alternate)
247 {
248 interface = &interfaceList->interfaces[count].interface[index];
249 break;
250 }
251 }
252 phdcHandle->interfaceNumber = interfaceList->interfaces[count].interfaceNumber;
253 break;
254 }
255 }
256 if (NULL == interface)
257 {
258 return status;
259 }
260 phdcHandle->interfaceHandle = interface;
261 for (uint32_t count = 0U; count < interface->endpointList.count; count++)
262 {
263 usb_device_endpoint_init_struct_t epInitStruct;
264 usb_device_endpoint_callback_struct_t epCallback;
265 epInitStruct.zlt = 0U;
266 epInitStruct.interval = interface->endpointList.endpoint[count].interval;
267 epInitStruct.endpointAddress = interface->endpointList.endpoint[count].endpointAddress;
268 epInitStruct.maxPacketSize = interface->endpointList.endpoint[count].maxPacketSize;
269 epInitStruct.transferType = interface->endpointList.endpoint[count].transferType;
270 if (USB_ENDPOINT_INTERRUPT == epInitStruct.transferType)
271 {
272 epCallback.callbackFn = USB_DevicePhdcInterruptInCallback;
273 phdcHandle->interruptIn.ep = (epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
274 phdcHandle->interruptIn.pipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
275 phdcHandle->interruptIn.pipeStall = 0U;
276 phdcHandle->interruptIn.pipeDataLen = 0U;
277 }
278 else if (USB_IN == ((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
279 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT))
280 {
281 epCallback.callbackFn = USB_DevicePhdcBulkInCallback;
282 phdcHandle->bulkIn.ep = (epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
283 phdcHandle->bulkIn.pipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
284 phdcHandle->bulkIn.pipeStall = 0U;
285 phdcHandle->bulkIn.pipeDataLen = 0U;
286 }
287 else
288 {
289 epCallback.callbackFn = USB_DevicePhdcBulkOutCallback;
290 phdcHandle->bulkOut.ep = (epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
291 phdcHandle->bulkOut.pipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
292 phdcHandle->bulkOut.pipeStall = 0U;
293 phdcHandle->bulkOut.pipeDataLen = 0U;
294 }
295 epCallback.callbackParam = phdcHandle;
296
297 status = USB_DeviceInitEndpoint(phdcHandle->handle, &epInitStruct, &epCallback);
298 }
299 return status;
300 }
301
302 /*!
303 * @brief De-initialize the endpoints of the PHDC class.
304 *
305 * This callback function is used to de-initialize the endpoints of the PHC class.
306 *
307 * @param phdcHandle The device PHDC class handle. It equals the value returned from
308 * usb_device_class_config_struct_t::classHandle.
309 *
310 * @retval kStatus_USB_Success The PHDC endpoint is de-initialized successful.
311 * @retval kStatus_USB_Error The interface handle not be found.
312 */
USB_DevicePhdcEndpointsDeinit(usb_device_phdc_struct_t * phdcHandle)313 static usb_status_t USB_DevicePhdcEndpointsDeinit(usb_device_phdc_struct_t *phdcHandle)
314 {
315 usb_status_t status = kStatus_USB_Error;
316
317 if (NULL == phdcHandle->interfaceHandle)
318 {
319 return status;
320 }
321 for (uint32_t count = 0; count < phdcHandle->interfaceHandle->endpointList.count; count++)
322 {
323 status = USB_DeviceDeinitEndpoint(phdcHandle->handle,
324 phdcHandle->interfaceHandle->endpointList.endpoint[count].endpointAddress);
325 }
326 return status;
327 }
328
329 /*!
330 * @brief Handle the event passed to the PHDC class.
331 *
332 * This function handles the event passed to the PHDC class.
333 *
334 * @param[in] handle The PHDC class handle, got from the usb_device_class_config_struct_t::classHandle.
335 * @param[in] event The event codes. Please refer to the enumeration usb_device_class_event_t.
336 * @param[in,out] param The param type is determined by the event code.
337 *
338 * @retval kStatus_USB_Success Free device handle successfully.
339 * @retval kStatus_USB_InvalidParameter The device handle not be found.
340 * @retval kStatus_USB_InvalidRequest The request is invalid, and the control pipe will be stalled by the caller.
341 */
USB_DevicePhdcEvent(void * handle,uint32_t event,void * param)342 usb_status_t USB_DevicePhdcEvent(void *handle, uint32_t event, void *param)
343 {
344 usb_device_phdc_struct_t *phdcHandle;
345 usb_status_t error = kStatus_USB_Error;
346 uint16_t interfaceAlternate;
347 uint8_t *temp8;
348 uint8_t alternate;
349 usb_device_class_event_t eventCode = (usb_device_class_event_t)event;
350 if ((NULL == param) || (NULL == handle))
351 {
352 return kStatus_USB_InvalidHandle;
353 }
354
355 phdcHandle = (usb_device_phdc_struct_t *)handle;
356
357 switch (eventCode)
358 {
359 case kUSB_DeviceClassEventDeviceReset:
360 phdcHandle->configuration = 0U;
361 phdcHandle->bulkIn.isBusy = 0U;
362 phdcHandle->bulkOut.isBusy = 0U;
363 phdcHandle->interruptIn.isBusy = 0U;
364 error = kStatus_USB_Success;
365 break;
366 case kUSB_DeviceClassEventSetConfiguration:
367 temp8 = ((uint8_t *)param);
368 if (NULL == phdcHandle->configStruct)
369 {
370 break;
371 }
372 if (*temp8 == phdcHandle->configuration)
373 {
374 error = kStatus_USB_Success;
375 break;
376 }
377
378 if (0U != phdcHandle->configuration)
379 {
380 error = USB_DevicePhdcEndpointsDeinit(phdcHandle);
381 }
382 phdcHandle->configuration = *temp8;
383 phdcHandle->alternate = 0U;
384 error = USB_DevicePhdcEndpointsInit(phdcHandle);
385 break;
386 case kUSB_DeviceClassEventSetInterface:
387 if (NULL == phdcHandle->configStruct)
388 {
389 break;
390 }
391
392 interfaceAlternate = *((uint16_t *)param);
393 alternate = (uint8_t)(interfaceAlternate & 0xFFU);
394
395 if (phdcHandle->interfaceNumber != ((uint8_t)(interfaceAlternate >> 8U)))
396 {
397 break;
398 }
399 if (alternate == phdcHandle->alternate)
400 {
401 error = kStatus_USB_Success;
402 break;
403 }
404 error = USB_DevicePhdcEndpointsDeinit(phdcHandle);
405 phdcHandle->alternate = alternate;
406 error = USB_DevicePhdcEndpointsInit(phdcHandle);
407 break;
408 case kUSB_DeviceClassEventSetEndpointHalt:
409 if ((NULL == phdcHandle->configStruct) || (NULL == phdcHandle->interfaceHandle))
410 {
411 break;
412 }
413 temp8 = ((uint8_t *)param);
414 for (uint32_t count = 0; count < phdcHandle->interfaceHandle->endpointList.count; count++)
415 {
416 if (*temp8 == phdcHandle->interfaceHandle->endpointList.endpoint[count].endpointAddress)
417 {
418 /* Only stall the endpoint belongs to the class */
419 if (USB_ENDPOINT_INTERRUPT ==
420 phdcHandle->interfaceHandle->endpointList.endpoint[count].transferType)
421 {
422 phdcHandle->interruptIn.pipeStall = 1U;
423 }
424 else if (USB_IN == ((phdcHandle->interfaceHandle->endpointList.endpoint[count].endpointAddress &
425 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
426 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT))
427 {
428 phdcHandle->bulkIn.pipeStall = 1U;
429 }
430 else
431 {
432 phdcHandle->bulkOut.pipeStall = 1U;
433 }
434 error = USB_DeviceStallEndpoint(phdcHandle->handle, *temp8);
435 }
436 }
437 break;
438 case kUSB_DeviceClassEventClearEndpointHalt:
439 if ((NULL == phdcHandle->configStruct) || (NULL == phdcHandle->interfaceHandle))
440 {
441 break;
442 }
443 temp8 = ((uint8_t *)param);
444 for (uint32_t count = 0U; count < phdcHandle->interfaceHandle->endpointList.count; count++)
445 {
446 if (*temp8 == phdcHandle->interfaceHandle->endpointList.endpoint[count].endpointAddress)
447 {
448 error = USB_DeviceUnstallEndpoint(phdcHandle->handle, *temp8);
449 if (USB_ENDPOINT_INTERRUPT ==
450 phdcHandle->interfaceHandle->endpointList.endpoint[count].transferType)
451 {
452 if (0U != phdcHandle->interruptIn.pipeStall)
453 {
454 phdcHandle->interruptIn.pipeStall = 0U;
455 if ((uint8_t *)USB_INVALID_TRANSFER_BUFFER != phdcHandle->interruptIn.pipeDataBuffer)
456 {
457 error = USB_DeviceSendRequest(phdcHandle->handle, (phdcHandle->interruptIn.ep),
458 phdcHandle->interruptIn.pipeDataBuffer,
459 phdcHandle->interruptIn.pipeDataLen);
460 if (kStatus_USB_Success != error)
461 {
462 usb_device_endpoint_callback_message_struct_t endpointCallbackMessage;
463 endpointCallbackMessage.buffer = phdcHandle->interruptIn.pipeDataBuffer;
464 endpointCallbackMessage.length = phdcHandle->interruptIn.pipeDataLen;
465 endpointCallbackMessage.isSetup = 0U;
466 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
467 error = USB_DevicePhdcInterruptInCallback(phdcHandle->handle,
468 (void *)&endpointCallbackMessage, handle);
469 #else
470 (void)USB_DevicePhdcInterruptInCallback(phdcHandle->handle,
471 (void *)&endpointCallbackMessage, handle);
472 #endif
473 }
474 phdcHandle->interruptIn.pipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
475 phdcHandle->interruptIn.pipeDataLen = 0U;
476 }
477 }
478 }
479 else if (USB_IN == ((phdcHandle->interfaceHandle->endpointList.endpoint[count].endpointAddress &
480 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
481 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT))
482 {
483 if (0U != phdcHandle->bulkIn.pipeStall)
484 {
485 phdcHandle->bulkIn.pipeStall = 0U;
486 if ((uint8_t *)USB_INVALID_TRANSFER_BUFFER != phdcHandle->bulkIn.pipeDataBuffer)
487 {
488 error = USB_DeviceSendRequest(phdcHandle->handle, (phdcHandle->bulkIn.ep),
489 phdcHandle->bulkIn.pipeDataBuffer,
490 phdcHandle->bulkIn.pipeDataLen);
491 if (kStatus_USB_Success != error)
492 {
493 usb_device_endpoint_callback_message_struct_t endpointCallbackMessage;
494 endpointCallbackMessage.buffer = phdcHandle->bulkIn.pipeDataBuffer;
495 endpointCallbackMessage.length = phdcHandle->bulkIn.pipeDataLen;
496 endpointCallbackMessage.isSetup = 0U;
497 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
498 error = USB_DevicePhdcBulkInCallback(phdcHandle->handle,
499 (void *)&endpointCallbackMessage, handle);
500 #else
501 (void)USB_DevicePhdcBulkInCallback(phdcHandle->handle,
502 (void *)&endpointCallbackMessage, handle);
503 #endif
504 }
505 phdcHandle->bulkIn.pipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
506 phdcHandle->bulkIn.pipeDataLen = 0U;
507 }
508 }
509 }
510 else
511 {
512 if (0U != phdcHandle->bulkOut.pipeStall)
513 {
514 phdcHandle->bulkOut.pipeStall = 0U;
515 if ((uint8_t *)USB_INVALID_TRANSFER_BUFFER != phdcHandle->bulkOut.pipeDataBuffer)
516 {
517 error = USB_DeviceRecvRequest(phdcHandle->handle, (phdcHandle->bulkOut.ep),
518 phdcHandle->bulkOut.pipeDataBuffer,
519 phdcHandle->bulkOut.pipeDataLen);
520 if (kStatus_USB_Success != error)
521 {
522 usb_device_endpoint_callback_message_struct_t endpointCallbackMessage;
523 endpointCallbackMessage.buffer = phdcHandle->bulkOut.pipeDataBuffer;
524 endpointCallbackMessage.length = phdcHandle->bulkOut.pipeDataLen;
525 endpointCallbackMessage.isSetup = 0U;
526 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
527 error = USB_DevicePhdcBulkOutCallback(phdcHandle->handle,
528 (void *)&endpointCallbackMessage, handle);
529 #else
530 (void)USB_DevicePhdcBulkOutCallback(phdcHandle->handle,
531 (void *)&endpointCallbackMessage, handle);
532 #endif
533 }
534 phdcHandle->bulkOut.pipeDataBuffer = (uint8_t *)USB_INVALID_TRANSFER_BUFFER;
535 phdcHandle->bulkOut.pipeDataLen = 0U;
536 }
537 }
538 }
539 }
540 }
541 break;
542 case kUSB_DeviceClassEventClassRequest:
543 {
544 usb_device_control_request_struct_t *controlRequest = (usb_device_control_request_struct_t *)param;
545
546 if ((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) !=
547 USB_REQUEST_TYPE_RECIPIENT_INTERFACE)
548 {
549 break;
550 }
551
552 if ((controlRequest->setup->wIndex & 0xFFU) != phdcHandle->interfaceNumber)
553 {
554 break;
555 }
556
557 error = kStatus_USB_InvalidRequest;
558 switch (controlRequest->setup->bRequest)
559 {
560 case USB_DEVICE_PHDC_REQUEST_SET_FEATURE:
561 {
562 if (((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
563 USB_REQUEST_TYPE_DIR_OUT) &&
564 (controlRequest->setup->wLength == 0U))
565 {
566 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
567 it is from the second parameter of classInit */
568 error = phdcHandle->configStruct->classCallback(
569 (class_handle_t)phdcHandle, kUSB_DevicePhdcEventSetFeature, &controlRequest->setup->wValue);
570 }
571 }
572 break;
573 case USB_DEVICE_PHDC_REQUEST_CLEAR_FEATURE:
574 {
575 if (((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
576 USB_REQUEST_TYPE_DIR_OUT) &&
577 (controlRequest->setup->wLength == 0U))
578 {
579 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
580 it is from the second parameter of classInit */
581 error = phdcHandle->configStruct->classCallback((class_handle_t)phdcHandle,
582 kUSB_DevicePhdcEventClearFeature,
583 &controlRequest->setup->wValue);
584 }
585 }
586 break;
587 case USB_DEVICE_PHDC_REQUEST_GET_STATUS:
588 {
589 if (((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) ==
590 USB_REQUEST_TYPE_DIR_IN) &&
591 (controlRequest->setup->wLength <= 2U))
592 {
593 /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
594 it is from the second parameter of classInit */
595 error = phdcHandle->configStruct->classCallback((class_handle_t)phdcHandle,
596 kUSB_DevicePhdcEventGetStatus, controlRequest);
597 }
598 }
599 break;
600 default:
601 /* no action */
602 break;
603 }
604 }
605 break;
606 default:
607 /* no action */
608 break;
609 }
610 return error;
611 }
612
613 /*!
614 * @brief Initialize the PHDC class.
615 *
616 * This function is used to initialize the PHDC class.
617 *
618 * @param controllerId The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
619 * @param config The class configuration information.
620 * @param handle It is output parameter, is used to return pointer of the PHDC class handle to the caller.
621 *
622 * @retval kStatus_USB_Success The PHDC class is initialized successfully.
623 * @retval kStatus_USB_Busy No PHDC device handle available for allocation.
624 * @retval kStatus_USB_InvalidHandle The PHDC device handle allocation failure.
625 * @retval kStatus_USB_InvalidParameter The USB device handle allocation failure.
626 */
USB_DevicePhdcInit(uint8_t controllerId,usb_device_class_config_struct_t * config,class_handle_t * handle)627 usb_status_t USB_DevicePhdcInit(uint8_t controllerId, usb_device_class_config_struct_t *config, class_handle_t *handle)
628 {
629 usb_device_phdc_struct_t *phdcHandle;
630 usb_status_t error = kStatus_USB_Error;
631
632 error = USB_DevicePhdcAllocateHandle(&phdcHandle);
633
634 if (kStatus_USB_Success != error)
635 {
636 return error;
637 }
638
639 error = USB_DeviceClassGetDeviceHandle(controllerId, &phdcHandle->handle);
640
641 if (kStatus_USB_Success != error)
642 {
643 return error;
644 }
645
646 if (NULL == phdcHandle->handle)
647 {
648 return kStatus_USB_InvalidHandle;
649 }
650 phdcHandle->configStruct = config;
651 phdcHandle->configuration = 0U;
652 phdcHandle->alternate = 0xff;
653
654 *handle = (class_handle_t)phdcHandle;
655 return error;
656 }
657
658 /*!
659 * @brief De-initialize the device PHDC class.
660 *
661 * The function de-initializes the device PHDC class.
662 *
663 * @param handle The PHDC class handle got from usb_device_class_config_struct_t::classHandle.
664 *
665 * @retval kStatus_USB_InvalidHandle The device handle not be found.
666 * @retva; kStatus_USB_Success The PHDC class is de-initialized successful.
667 */
USB_DevicePhdcDeinit(class_handle_t handle)668 usb_status_t USB_DevicePhdcDeinit(class_handle_t handle)
669 {
670 usb_device_phdc_struct_t *phdcHandle;
671 usb_status_t error = kStatus_USB_Error;
672
673 phdcHandle = (usb_device_phdc_struct_t *)handle;
674
675 if (NULL == phdcHandle)
676 {
677 return kStatus_USB_InvalidHandle;
678 }
679 error = USB_DevicePhdcEndpointsDeinit(phdcHandle);
680 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
681 if (kStatus_USB_Success != USB_DevicePhdcFreeHandle(phdcHandle))
682 {
683 return kStatus_USB_Error;
684 }
685 #else
686 (void)USB_DevicePhdcFreeHandle(phdcHandle);
687 #endif
688 return error;
689 }
690
691 /*!
692 * @brief Send data through a specified endpoint.
693 *
694 * The function is used to send data through a specified endpoint.
695 * The function calls #USB_DeviceSendRequest internally.
696 *
697 * @param[in] handle The PHDC class handle got from usb_device_class_config_struct_t::classHandle.
698 * @param[in] ep Endpoint index.
699 * @param[in] buffer The memory address to hold the data need to be sent.
700 * @param[in] length The data length need to be sent.
701 *
702 * @retval kStatus_USB_InvalidHandle The device handle not be found.
703 * @retval kStatus_USB_Busy The previous transfer is pending.
704 * @retva; kStatus_USB_Success The sending is successful.
705 */
USB_DevicePhdcSend(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)706 usb_status_t USB_DevicePhdcSend(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
707 {
708 usb_device_phdc_struct_t *phdcHandle;
709 usb_device_phdc_pipe_t *pipe;
710 usb_status_t error;
711
712 if (NULL == handle)
713 {
714 return kStatus_USB_InvalidHandle;
715 }
716 phdcHandle = (usb_device_phdc_struct_t *)handle;
717 if (phdcHandle->bulkIn.ep == ep)
718 {
719 pipe = &(phdcHandle->bulkIn);
720 }
721 else if (phdcHandle->interruptIn.ep == ep)
722 {
723 pipe = &(phdcHandle->interruptIn);
724 }
725 else
726 {
727 return kStatus_USB_InvalidParameter;
728 }
729
730 if (1U == pipe->isBusy)
731 {
732 return kStatus_USB_Busy;
733 }
734 pipe->isBusy = 1U;
735
736 if (0U != pipe->pipeStall)
737 {
738 pipe->pipeDataBuffer = buffer;
739 pipe->pipeDataLen = length;
740 return kStatus_USB_Success;
741 }
742 error = USB_DeviceSendRequest(phdcHandle->handle, ep, buffer, length);
743 if (kStatus_USB_Success != error)
744 {
745 pipe->isBusy = 0U;
746 }
747 return error;
748 }
749
750 /*!
751 * @brief Receive data through a specified endpoint.
752 *
753 * The function is used to receive data through a specified endpoint.
754 * The function calls #USB_DeviceRecvRequest internally.
755 *
756 * @param[in] handle The PHDC class handle got from usb_device_class_config_struct_t::classHandle.
757 * @param[in] ep Endpoint index.
758 * @param[in] buffer The memory address to save the received data.
759 * @param[in] length The data length want to be received.
760 *
761 * @retval kStatus_USB_InvalidHandle The device handle not be found.
762 * @retval kStatus_USB_Busy The previous transfer is pending.
763 * @retva; kStatus_USB_Success The receiving is successful.
764 */
USB_DevicePhdcRecv(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)765 usb_status_t USB_DevicePhdcRecv(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
766 {
767 usb_device_phdc_struct_t *phdcHandle;
768 usb_status_t error;
769
770 if (NULL == handle)
771 {
772 return kStatus_USB_InvalidHandle;
773 }
774 phdcHandle = (usb_device_phdc_struct_t *)handle;
775 if (1U == phdcHandle->bulkOut.isBusy)
776 {
777 return kStatus_USB_Busy;
778 }
779 phdcHandle->bulkOut.isBusy = 1U;
780
781 if (0U != phdcHandle->bulkOut.pipeStall)
782 {
783 phdcHandle->bulkOut.pipeDataBuffer = buffer;
784 phdcHandle->bulkOut.pipeDataLen = length;
785 return kStatus_USB_Success;
786 }
787 error = USB_DeviceRecvRequest(phdcHandle->handle, ep, buffer, length);
788 if (kStatus_USB_Success != error)
789 {
790 phdcHandle->bulkOut.isBusy = 0U;
791 }
792 return error;
793 }
794
795 #endif
796