1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 - 2017 NXP
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of the copyright holder nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <usb/include/usb_device_config.h>
32 #include <usb/include/usb.h>
33 
34 #include "usb_device.h"
35 #include "usb_device_dci.h"
36 
37 #include "fsl_device_registers.h"
38 
39 #if ((defined(USB_DEVICE_CONFIG_NUM)) && (USB_DEVICE_CONFIG_NUM > 0U))
40 
41 #if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
42 #include "usb_device_khci.h"
43 #endif
44 
45 #if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
46 #include "usb_device_ehci.h"
47 #endif
48 
49 #if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
50      ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
51 #include "usb_device_lpcip3511.h"
52 #endif
53 
54 #if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
55 #include "fsl_cache.h"
56 #endif
57 /*******************************************************************************
58  * Definitions
59  ******************************************************************************/
60 
61 /*******************************************************************************
62  * Prototypes
63  ******************************************************************************/
64 static usb_status_t USB_DeviceAllocateHandle(uint8_t controllerId, usb_device_struct_t **handle);
65 static usb_status_t USB_DeviceFreeHandle(usb_device_struct_t *handle);
66 static usb_status_t USB_DeviceGetControllerInterface(
67     uint8_t controllerId, const usb_device_controller_interface_struct_t **controllerInterface);
68 static usb_status_t USB_DeviceTransfer(usb_device_handle handle,
69                                        uint8_t endpointAddress,
70                                        uint8_t *buffer,
71                                        uint32_t length);
72 static usb_status_t USB_DeviceControl(usb_device_handle handle, usb_device_control_type_t type, void *param);
73 static usb_status_t USB_DeviceResetNotification(usb_device_struct_t *handle,
74         usb_device_callback_message_struct_t *message);
75 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
76 static usb_status_t USB_DeviceSuspendNotification(usb_device_struct_t *handle,
77         usb_device_callback_message_struct_t *message);
78 static usb_status_t USB_DeviceResumeNotification(usb_device_struct_t *handle,
79         usb_device_callback_message_struct_t *message);
80 #if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
81 static usb_status_t USB_DeviceSleepNotification(usb_device_struct_t *handle,
82         usb_device_callback_message_struct_t *message);
83 
84 #endif
85 #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
86 #if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
87 static usb_status_t USB_DeviceDetachNotification(usb_device_struct_t *handle,
88         usb_device_callback_message_struct_t *message);
89 static usb_status_t USB_DeviceAttachNotification(usb_device_struct_t *handle,
90         usb_device_callback_message_struct_t *message);
91 #endif
92 static usb_status_t USB_DeviceNotification(usb_device_struct_t *handle, usb_device_callback_message_struct_t *message);
93 
94 /*******************************************************************************
95  * Variables
96  ******************************************************************************/
97 
98 USB_GLOBAL static usb_device_struct_t s_UsbDevice[USB_DEVICE_CONFIG_NUM];
99 
100 /*******************************************************************************
101  * Code
102  ******************************************************************************/
103 
104 /*!
105  * @brief Allocate a device handle.
106  *
107  * This function allocates a device handle.
108  *
109  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
110  * @param handle          It is out parameter, is used to return pointer of the device handle to the caller.
111  *
112  * @retval kStatus_USB_Success              Get a device handle successfully.
113  * @retval kStatus_USB_Busy                 Cannot allocate a device handle.
114  * @retval kStatus_USB_Error                The device has been initialized.
115  */
USB_DeviceAllocateHandle(uint8_t controllerId,usb_device_struct_t ** handle)116 static usb_status_t USB_DeviceAllocateHandle(uint8_t controllerId, usb_device_struct_t **handle)
117 {
118     uint32_t count;
119     USB_OSA_SR_ALLOC();
120 
121     USB_OSA_ENTER_CRITICAL();
122     /* Check the controller is initialized or not. */
123     for (count = 0U; count < USB_DEVICE_CONFIG_NUM; count++)
124     {
125         if ((NULL != s_UsbDevice[count].controllerHandle) && (controllerId == s_UsbDevice[count].controllerId))
126         {
127             USB_OSA_EXIT_CRITICAL();
128             return kStatus_USB_Error;
129         }
130     }
131     /* Get a free device handle. */
132     for (count = 0U; count < USB_DEVICE_CONFIG_NUM; count++)
133     {
134         if (NULL == s_UsbDevice[count].controllerHandle)
135         {
136             s_UsbDevice[count].controllerId = controllerId;
137             *handle = &s_UsbDevice[count];
138             USB_OSA_EXIT_CRITICAL();
139             return kStatus_USB_Success;
140         }
141     }
142     USB_OSA_EXIT_CRITICAL();
143     return kStatus_USB_Busy;
144 }
145 
146 /*!
147  * @brief Free a device handle.
148  *
149  * This function frees a device handle.
150  *
151  * @param handle          The device handle.
152  *
153  * @retval kStatus_USB_Success              Free device handle successfully.
154  */
USB_DeviceFreeHandle(usb_device_struct_t * handle)155 static usb_status_t USB_DeviceFreeHandle(usb_device_struct_t *handle)
156 {
157     USB_OSA_SR_ALLOC();
158 
159     USB_OSA_ENTER_CRITICAL();
160     handle->controllerHandle = NULL;
161     handle->controllerId = 0U;
162     USB_OSA_EXIT_CRITICAL();
163     return kStatus_USB_Success;
164 }
165 
166 #if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
167 /* KHCI device driver interface */
168 static const usb_device_controller_interface_struct_t s_UsbDeviceKhciInterface = {
169     USB_DeviceKhciInit, USB_DeviceKhciDeinit, USB_DeviceKhciSend,
170     USB_DeviceKhciRecv, USB_DeviceKhciCancel, USB_DeviceKhciControl
171 };
172 #endif
173 
174 #if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
175 /* EHCI device driver interface */
176 static const usb_device_controller_interface_struct_t s_UsbDeviceEhciInterface = {
177     USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend,
178     USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl
179 };
180 #endif
181 
182 #if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
183      ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
184 /* EHCI device driver interface */
185 static const usb_device_controller_interface_struct_t s_UsbDeviceLpc3511IpInterface = {
186     USB_DeviceLpc3511IpInit, USB_DeviceLpc3511IpDeinit, USB_DeviceLpc3511IpSend,
187     USB_DeviceLpc3511IpRecv, USB_DeviceLpc3511IpCancel, USB_DeviceLpc3511IpControl
188 };
189 #endif
190 
191 /*!
192  * @brief Get the controller interface handle.
193  *
194  * This function is used to get the controller interface handle.
195  *
196  * @param controllerId          The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
197  * @param controllerInterface   It is out parameter, is used to return pointer of the device controller handle to the
198  * caller.
199  *
200  * @retval kStatus_USB_Success              Get a device handle successfully.
201  * @retval kStatus_USB_ControllerNotFound   The controller id is invalided.
202  */
USB_DeviceGetControllerInterface(uint8_t controllerId,const usb_device_controller_interface_struct_t ** controllerInterface)203 static usb_status_t USB_DeviceGetControllerInterface(
204     uint8_t controllerId, const usb_device_controller_interface_struct_t **controllerInterface)
205 {
206     usb_status_t error = kStatus_USB_ControllerNotFound;
207     switch (controllerId)
208     {
209 #if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U))
210     /* Get the KHCI controller driver interface */
211     case kUSB_ControllerKhci0:
212     case kUSB_ControllerKhci1:
213         *controllerInterface = (const usb_device_controller_interface_struct_t *)&s_UsbDeviceKhciInterface;
214         error = kStatus_USB_Success;
215         break;
216 #endif
217 #if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U))
218     /* Get the EHCI controller driver interface */
219     case kUSB_ControllerEhci0:
220     case kUSB_ControllerEhci1:
221         error = kStatus_USB_Success;
222         *controllerInterface = (const usb_device_controller_interface_struct_t *)&s_UsbDeviceEhciInterface;
223         break;
224 #endif
225 #if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
226      ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
227     /* Get the EHCI controller driver interface */
228     case kUSB_ControllerLpcIp3511Fs0:
229     case kUSB_ControllerLpcIp3511Fs1:
230     case kUSB_ControllerLpcIp3511Hs0:
231     case kUSB_ControllerLpcIp3511Hs1:
232         error = kStatus_USB_Success;
233         *controllerInterface = (const usb_device_controller_interface_struct_t *)&s_UsbDeviceLpc3511IpInterface;
234         break;
235 #endif
236     default:
237         break;
238     }
239     return error;
240 }
241 
242 /*!
243  * @brief Start a new transfer.
244  *
245  * This function is used to start a new transfer.
246  *
247  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
248  * @param endpointAddress       Endpoint address. Bit7 is direction, 0U - USB_OUT, 1U - USB_IN.
249  * @param buffer                 The memory address to be transferred, or the memory address to hold the data need to be
250  * sent.
251  * @param length                 The length of the data.
252  *
253  * @retval kStatus_USB_Success              Get a device handle successfully.
254  * @retval kStatus_USB_InvalidHandle        The device handle is invalided.
255  * @retval kStatus_USB_ControllerNotFound   The controller interface is not found.
256  * @retval kStatus_USB_Error                The device is doing reset.
257  */
USB_DeviceTransfer(usb_device_handle handle,uint8_t endpointAddress,uint8_t * buffer,uint32_t length)258 static usb_status_t USB_DeviceTransfer(usb_device_handle handle,
259                                        uint8_t endpointAddress,
260                                        uint8_t *buffer,
261                                        uint32_t length)
262 {
263     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
264     usb_status_t error = kStatus_USB_Error;
265     uint8_t endpoint = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
266     uint8_t direction = (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
267                         USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
268     USB_OSA_SR_ALLOC();
269 
270     if (NULL == deviceHandle)
271     {
272         return kStatus_USB_InvalidHandle;
273     }
274 
275     if (NULL != deviceHandle->controllerInterface)
276     {
277         if (deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy)
278         {
279             return kStatus_USB_Busy;
280         }
281         USB_OSA_ENTER_CRITICAL();
282         deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 1U;
283         USB_OSA_EXIT_CRITICAL();
284         if (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)
285         {
286 #if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
287             if (length)
288             {
289                 DCACHE_CleanByRange((uint32_t)buffer, length);
290             }
291 #endif
292             /* Call the controller send interface. */
293             error = deviceHandle->controllerInterface->deviceSend(deviceHandle->controllerHandle, endpointAddress,
294                     buffer, length);
295         }
296         else
297         {
298 #if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
299             if (length)
300             {
301                 DCACHE_CleanInvalidateByRange((uint32_t)buffer, length);
302             }
303 #endif
304             /* Call the controller receive interface. */
305             error = deviceHandle->controllerInterface->deviceRecv(deviceHandle->controllerHandle, endpointAddress,
306                     buffer, length);
307         }
308         if (kStatus_USB_Success != error)
309         {
310             USB_OSA_ENTER_CRITICAL();
311             deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
312             USB_OSA_EXIT_CRITICAL();
313         }
314     }
315     else
316     {
317         error = kStatus_USB_ControllerNotFound;
318     }
319     return error;
320 }
321 
322 /*!
323  * @brief Control the status of the selected item.
324  *
325  * This function is used to control the status of the selected item..
326  *
327  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
328  * @param type                   The control type, please refer to the enumeration usb_device_control_type_t.
329  * @param param                  The param type is determined by the selected item.
330  *
331  * @retval kStatus_USB_Success              Get a device handle successfully.
332  * @retval kStatus_USB_InvalidHandle        The device handle is invalided.
333  * @retval kStatus_USB_ControllerNotFound   The controller interface is not found.
334  * @retval kStatus_USB_Error                Unsupport type.
335  *                                          Or, the param is NULL pointer.
336  */
USB_DeviceControl(usb_device_handle handle,usb_device_control_type_t type,void * param)337 static usb_status_t USB_DeviceControl(usb_device_handle handle, usb_device_control_type_t type, void *param)
338 {
339     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
340     usb_status_t error = kStatus_USB_Error;
341 
342     if (NULL == deviceHandle)
343     {
344         return kStatus_USB_InvalidHandle;
345     }
346 
347     if (NULL != deviceHandle->controllerInterface)
348     {
349         /* Call the controller control interface. */
350         error = deviceHandle->controllerInterface->deviceControl(deviceHandle->controllerHandle, type, param);
351     }
352     else
353     {
354         error = kStatus_USB_ControllerNotFound;
355     }
356     return error;
357 }
358 
359 /*!
360  * @brief Handle the reset notification.
361  *
362  * This function is used to handle the reset notification.
363  *
364  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
365  * @param message                The device callback message handle.
366  *
367  * @retval kStatus_USB_Success              Get a device handle successfully.
368  */
USB_DeviceResetNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)369 static usb_status_t USB_DeviceResetNotification(usb_device_struct_t *handle,
370         usb_device_callback_message_struct_t *message)
371 {
372 #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
373     USB_OSA_SR_ALLOC();
374 #endif
375 
376     handle->isResetting = 1U;
377 
378 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
379     /* Clear remote wakeup feature */
380     handle->remotewakeup = 0U;
381 #endif
382 
383 #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
384     USB_OSA_ENTER_CRITICAL();
385     handle->epCallbackDirectly = 1;
386     USB_OSA_EXIT_CRITICAL();
387 #endif
388     /* Set the controller to default status. */
389     USB_DeviceControl(handle, kUSB_DeviceControlSetDefaultStatus, NULL);
390 #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
391     USB_OSA_ENTER_CRITICAL();
392     handle->epCallbackDirectly = 0;
393     USB_OSA_EXIT_CRITICAL();
394 #endif
395 
396     handle->state = kUSB_DeviceStateDefault;
397     handle->deviceAddress = 0U;
398 
399     for (uint32_t count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++)
400     {
401         handle->epCallback[count].callbackFn = (usb_device_endpoint_callback_t)NULL;
402         handle->epCallback[count].callbackParam = NULL;
403         handle->epCallback[count].isBusy = 0U;
404     }
405 
406     /* Call device callback to notify the application that the USB bus reset signal detected. */
407     handle->deviceCallback(handle, kUSB_DeviceEventBusReset, NULL);
408 
409     handle->isResetting = 0U;
410     return kStatus_USB_Success;
411 }
412 
413 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
414 /*!
415  * @brief Handle the suspend notification.
416  *
417  * This function is used to handle the suspend notification.
418  *
419  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
420  * @param message                The device callback message handle.
421  *
422  * @return A USB error code or kStatus_USB_Success.
423  */
USB_DeviceSuspendNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)424 static usb_status_t USB_DeviceSuspendNotification(usb_device_struct_t *handle,
425         usb_device_callback_message_struct_t *message)
426 {
427     /* Call device callback to notify the application that the USB bus suspend signal detected. */
428     return handle->deviceCallback(handle, kUSB_DeviceEventSuspend, NULL);
429 }
430 
431 /*!
432  * @brief Handle the resume notification.
433  *
434  * This function is used to handle the resume notification.
435  *
436  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
437  * @param message                The device callback message handle.
438  *
439  * @return A USB error code or kStatus_USB_Success.
440  */
USB_DeviceResumeNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)441 static usb_status_t USB_DeviceResumeNotification(usb_device_struct_t *handle,
442         usb_device_callback_message_struct_t *message)
443 {
444     /* Call device callback to notify the application that the USB bus resume signal detected. */
445     return handle->deviceCallback(handle, kUSB_DeviceEventResume, NULL);
446 }
447 #if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
448 /*!
449  * @brief Handle the suspend notification.
450  *
451  * This function is used to handle the suspend notification.
452  *
453  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
454  * @param message                The device callback message handle.
455  *
456  * @return A USB error code or kStatus_USB_Success.
457  */
USB_DeviceSleepNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)458 static usb_status_t USB_DeviceSleepNotification(usb_device_struct_t *handle,
459         usb_device_callback_message_struct_t *message)
460 {
461     /* Call device callback to notify the application that the USB bus suspend signal detected. */
462     return handle->deviceCallback(handle, kUSB_DeviceEventSleeped, NULL);
463 }
464 #endif
465 /*!
466  * @brief Handle the remotewakeup notification.
467  *
468  * This function is used to handle the remotewakeup notification.
469  *
470  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
471  * @param flag                   The buffer pointer to store remotewakeup flag.
472  *
473  * @return A USB error code or kStatus_USB_Success.
474  */
USB_DeviceGetRemoteWakeUp(usb_device_struct_t * handle,uint8_t ** flag)475 usb_status_t USB_DeviceGetRemoteWakeUp(usb_device_struct_t *handle, uint8_t **flag)
476 {
477     /* Call device callback to notify the application that the USB bus suspend signal detected. */
478     return USB_DeviceControl(handle, kUSB_DeviceControlGetRemoteWakeUp, flag);
479 }
480 
481 #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */
482 
483 #if (defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U))
USB_DeviceErrorNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)484 usb_status_t USB_DeviceErrorNotification(usb_device_struct_t *handle, usb_device_callback_message_struct_t *message)
485 {
486     /* Call device callback to notify the application that the USB bus error signal detected. */
487     return handle->deviceCallback(handle, kUSB_DeviceEventError, NULL);
488 }
489 #endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */
490 
491 #if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
492 /*!
493  * @brief Handle the detach notification.
494  *
495  * This function is used to handle the detach notification.
496  *
497  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
498  * @param message                The device callback message handle.
499  *
500  * @return A USB error code or kStatus_USB_Success.
501  */
USB_DeviceDetachNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)502 static usb_status_t USB_DeviceDetachNotification(usb_device_struct_t *handle,
503         usb_device_callback_message_struct_t *message)
504 {
505     /* Call device callback to notify the application that the device is disconnected from a host. */
506     return handle->deviceCallback(handle, kUSB_DeviceEventDetach, NULL);
507 }
508 
509 /*!
510  * @brief Handle the attach notification.
511  *
512  * This function is used to handle the attach notification.
513  *
514  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
515  * @param message                The device callback message handle.
516  *
517  * @return A USB error code or kStatus_USB_Success.
518  */
USB_DeviceAttachNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)519 static usb_status_t USB_DeviceAttachNotification(usb_device_struct_t *handle,
520         usb_device_callback_message_struct_t *message)
521 {
522     /* Call device callback to notify the application that the device is connected to a host. */
523     return handle->deviceCallback(handle, kUSB_DeviceEventAttach, NULL);
524 }
525 #endif
526 
527 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
528     ((defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U)) ||        \
529      (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
530 /*!
531  * @brief Handle the dcd module timeout notification.
532  *
533  * This function is used to handle the dcd module timeout notification.
534  *
535  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
536  * @param message                The device callback message handle.
537  *
538  * @return A USB error code or kStatus_USB_Success.
539  */
USB_DeviceDcdTimeOutNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)540 static usb_status_t USB_DeviceDcdTimeOutNotification(usb_device_struct_t *handle,
541         usb_device_callback_message_struct_t *message)
542 {
543     /* Call device callback to notify the application that the device charger detect timeout happened. */
544     return handle->deviceCallback(handle, kUSB_DeviceEventDcdTimeOut, NULL);
545 }
546 
547 /*!
548  * @brief Handle the dcd module unknown port type notification.
549  *
550  * This function is used to handle the dcd module unknown port type notification.
551  *
552  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
553  * @param message                The device callback message handle.
554  *
555  * @return A USB error code or kStatus_USB_Success.
556  */
USB_DeviceDcdUnknownPortTypeNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)557 static usb_status_t USB_DeviceDcdUnknownPortTypeNotification(usb_device_struct_t *handle,
558         usb_device_callback_message_struct_t *message)
559 {
560     /* Call device callback to notify the application that the device charger detect unknown port type happened. */
561     return handle->deviceCallback(handle, kUSB_DeviceEventDcdUnknownType, NULL);
562 }
563 
564 /*!
565  * @brief Handle the SDP facility is detected notification.
566  *
567  * This function is used to handle the SDP facility is detectednotification.
568  *
569  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
570  * @param message                The device callback message handle.
571  *
572  * @return A USB error code or kStatus_USB_Success.
573  */
USB_DeviceDcdSDPDetectNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)574 static usb_status_t USB_DeviceDcdSDPDetectNotification(usb_device_struct_t *handle,
575         usb_device_callback_message_struct_t *message)
576 {
577     /* Call device callback to notify the application that the SDP facility is detected. */
578     return handle->deviceCallback(handle, kUSB_DeviceEventSDPDetected, NULL);
579 }
580 
581 /*!
582  * @brief Handle the charging port is detected notification.
583  *
584  * This function is used to handle the charging port is detectednotification.
585  *
586  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
587  * @param message                The device callback message handle.
588  *
589  * @return A USB error code or kStatus_USB_Success.
590  */
USB_DeviceDcdChargingPortDetectNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)591 static usb_status_t USB_DeviceDcdChargingPortDetectNotification(usb_device_struct_t *handle,
592         usb_device_callback_message_struct_t *message)
593 {
594     /* Call device callback to notify the application that the charing port is detected. */
595     return handle->deviceCallback(handle, kUSB_DeviceEventChargingPortDetected, NULL);
596 }
597 
598 /*!
599  * @brief Handle the CDP facility is detected notification.
600  *
601  * This function is used to handle the CDP facility is detectednotification.
602  *
603  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
604  * @param message                The device callback message handle.
605  *
606  * @return A USB error code or kStatus_USB_Success.
607  */
USB_DeviceDcdChargingHostDetectNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)608 static usb_status_t USB_DeviceDcdChargingHostDetectNotification(usb_device_struct_t *handle,
609         usb_device_callback_message_struct_t *message)
610 {
611     /* Call device callback to notify the application that the CDP facility is detected. */
612     return handle->deviceCallback(handle, kUSB_DeviceEventChargingHostDetected, NULL);
613 }
614 
615 /*!
616  * @brief Handle the DCP facility is detected notification.
617  *
618  * This function is used to handle the DCP facility is detectednotification.
619  *
620  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
621  * @param message                The device callback message handle.
622  *
623  * @return A USB error code or kStatus_USB_Success.
624  */
625 
USB_DeviceDcdDedicatedChargerDetectNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)626 static usb_status_t USB_DeviceDcdDedicatedChargerDetectNotification(usb_device_struct_t *handle,
627         usb_device_callback_message_struct_t *message)
628 {
629     /* Call device callback to notify the application that the DCP facility is detected. */
630     return handle->deviceCallback(handle, kUSB_DeviceEventDedicatedChargerDetected, NULL);
631 }
632 #endif
633 
634 /*!
635  * @brief Handle the attach notification.
636  *
637  * This function is used to handle the attach notification.
638  *
639  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
640  * @param message                The device callback message handle.
641  *
642  * @return A USB error code or kStatus_USB_Success.
643  */
USB_DeviceNotification(usb_device_struct_t * handle,usb_device_callback_message_struct_t * message)644 static usb_status_t USB_DeviceNotification(usb_device_struct_t *handle, usb_device_callback_message_struct_t *message)
645 {
646     uint8_t endpoint = message->code & USB_ENDPOINT_NUMBER_MASK;
647     uint8_t direction = (message->code & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
648                         USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
649     usb_status_t error = kStatus_USB_Error;
650 
651     switch (message->code)
652     {
653     case kUSB_DeviceNotifyBusReset:
654         error = USB_DeviceResetNotification(handle, message);
655         break;
656 #if (defined(USB_DEVICE_CONFIG_LOW_POWER_MODE) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
657     case kUSB_DeviceNotifySuspend:
658         error = USB_DeviceSuspendNotification(handle, message);
659         break;
660     case kUSB_DeviceNotifyResume:
661         error = USB_DeviceResumeNotification(handle, message);
662         break;
663 #if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
664     case kUSB_DeviceNotifyLPMSleep:
665         error = USB_DeviceSleepNotification(handle, message);
666         break;
667 #endif
668 #endif
669 
670 #if (defined(USB_DEVICE_CONFIG_ERROR_HANDLING) && (USB_DEVICE_CONFIG_ERROR_HANDLING > 0U))
671     case kUSB_DeviceNotifyError:
672         error = USB_DeviceErrorNotification(handle, message);
673         break;
674 #endif
675 
676 #if USB_DEVICE_CONFIG_DETACH_ENABLE
677     case kUSB_DeviceNotifyDetach:
678         error = USB_DeviceDetachNotification(handle, message);
679         break;
680     case kUSB_DeviceNotifyAttach:
681         error = USB_DeviceAttachNotification(handle, message);
682         break;
683 #endif
684 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
685     ((defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U)) ||        \
686      (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
687     case kUSB_DeviceNotifyDcdTimeOut:
688         error = USB_DeviceDcdTimeOutNotification(handle, message);
689         break;
690     case kUSB_DeviceNotifyDcdUnknownPortType:
691         error = USB_DeviceDcdUnknownPortTypeNotification(handle, message);
692         break;
693     case kUSB_DeviceNotifySDPDetected:
694         error = USB_DeviceDcdSDPDetectNotification(handle, message);
695         break;
696     case kUSB_DeviceNotifyChargingPortDetected:
697         error = USB_DeviceDcdChargingPortDetectNotification(handle, message);
698         break;
699     case kUSB_DeviceNotifyChargingHostDetected:
700         error = USB_DeviceDcdChargingHostDetectNotification(handle, message);
701         break;
702     case kUSB_DeviceNotifyDedicatedChargerDetected:
703         error = USB_DeviceDcdDedicatedChargerDetectNotification(handle, message);
704         break;
705 #endif
706 
707     default:
708         if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS)
709         {
710             if (handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn)
711             {
712                 usb_device_endpoint_callback_message_struct_t endpointCallbackMessage;
713                 endpointCallbackMessage.buffer = message->buffer;
714                 endpointCallbackMessage.length = message->length;
715                 endpointCallbackMessage.isSetup = message->isSetup;
716                 if (message->isSetup)
717                 {
718                     handle->epCallback[0].isBusy = 0U;
719                     handle->epCallback[1].isBusy = 0U;
720                 }
721                 else
722                 {
723                     handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
724                 }
725                 /* Call endpoint callback */
726                 error = handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn(
727                             handle, &endpointCallbackMessage,
728                             handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam);
729             }
730         }
731         break;
732     }
733     return error;
734 }
735 
736 /*!
737  * @brief Notify the device that the controller status changed.
738  *
739  * This function is used to notify the device that the controller status changed.
740  *
741  * @param handle                 The device handle. It equals the value returned from USB_DeviceInit.
742  * @param message                The device callback message handle.
743  *
744  * @return A USB error code or kStatus_USB_Success.
745  */
USB_DeviceNotificationTrigger(void * handle,void * msg)746 usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
747 {
748     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
749     usb_device_callback_message_struct_t *message = (usb_device_callback_message_struct_t *)msg;
750 
751     if ((NULL == msg) || (NULL == handle))
752     {
753         return kStatus_USB_InvalidHandle;
754     }
755 
756     /* The device callback is invalid or not. */
757     if (!deviceHandle->deviceCallback)
758     {
759         return kStatus_USB_Error;
760     }
761 
762 #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
763     if (deviceHandle->epCallbackDirectly)
764     {
765         if ((message->code & USB_ENDPOINT_NUMBER_MASK) && (!(message->code & 0x70U)))
766         {
767             return USB_DeviceNotification(deviceHandle, message);
768         }
769     }
770 
771     /* Add the message to message queue when the device task is enabled. */
772     if (kStatus_USB_OSA_Success != USB_OsaMsgqSend(deviceHandle->notificationQueue, (void *)message))
773     {
774         return kStatus_USB_Busy;
775     }
776     return kStatus_USB_Success;
777 #else
778     /* Handle the notification by calling USB_DeviceNotification. */
779     return USB_DeviceNotification(deviceHandle, message);
780 #endif
781 }
782 
783 /*!
784  * @brief Initialize the USB device stack.
785  *
786  * This function initializes the USB device module specified by the controllerId.
787  *
788  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
789  * @param deviceCallback Function pointer of the device callback.
790  * @param handle          It is out parameter, is used to return pointer of the device handle to the caller.
791  *
792  * @retval kStatus_USB_Success              The device is initialized successfully.
793  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer.
794  * @retval kStatus_USB_Busy                 Cannot allocate a device handle.
795  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller according to the controller id.
796  * @retval kStatus_USB_InvalidControllerInterface  The controller driver interfaces is invaild, There is an empty
797  * interface entity.
798  * @retval kStatus_USB_Error                The macro USB_DEVICE_CONFIG_ENDPOINTS is more than IP's endpoint number.
799  *                                          Or, the device has been initialized.
800  *                                          Or, the message queue is created failed.
801  */
USB_DeviceInit(uint8_t controllerId,usb_device_callback_t deviceCallback,usb_device_handle * handle)802 usb_status_t USB_DeviceInit(uint8_t controllerId, usb_device_callback_t deviceCallback, usb_device_handle *handle)
803 {
804     usb_device_struct_t *deviceHandle = NULL;
805     usb_status_t error;
806     uint32_t count;
807 
808     if (NULL == handle)
809     {
810         return kStatus_USB_InvalidHandle;
811     }
812 
813     /* Allocate a device handle by using the controller id. */
814     error = USB_DeviceAllocateHandle(controllerId, &deviceHandle);
815 
816     if (kStatus_USB_Success != error)
817     {
818         return error;
819     }
820 
821     /* Save the device callback */
822     deviceHandle->deviceCallback = deviceCallback;
823     /* Save the controller id */
824     deviceHandle->controllerId = controllerId;
825     /* Clear the device address */
826     deviceHandle->deviceAddress = 0U;
827     /* Clear the device reset state */
828     deviceHandle->isResetting = 0U;
829 
830     /* Initialize the enpoints */
831     for (count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++)
832     {
833         deviceHandle->epCallback[count].callbackFn = (usb_device_endpoint_callback_t)NULL;
834         deviceHandle->epCallback[count].callbackParam = NULL;
835         deviceHandle->epCallback[count].isBusy = 0U;
836     }
837 
838     /* Get the controller interface according to the controller id */
839     error = USB_DeviceGetControllerInterface(controllerId, &deviceHandle->controllerInterface);
840     if (kStatus_USB_Success != error)
841     {
842         USB_DeviceFreeHandle(deviceHandle);
843         return error;
844     }
845     if (NULL == deviceHandle->controllerInterface)
846     {
847         USB_DeviceFreeHandle(deviceHandle);
848         return kStatus_USB_ControllerNotFound;
849     }
850     if (((usb_device_controller_init_t)NULL == deviceHandle->controllerInterface->deviceInit) ||
851             ((usb_device_controller_deinit_t)NULL == deviceHandle->controllerInterface->deviceDeinit) ||
852             ((usb_device_controller_send_t)NULL == deviceHandle->controllerInterface->deviceSend) ||
853             ((usb_device_controller_recv_t)NULL == deviceHandle->controllerInterface->deviceRecv) ||
854             ((usb_device_controller_cancel_t)NULL == deviceHandle->controllerInterface->deviceCancel) ||
855             ((usb_device_controller_control_t)NULL == deviceHandle->controllerInterface->deviceControl))
856     {
857         USB_DeviceFreeHandle(deviceHandle);
858         return kStatus_USB_InvalidControllerInterface;
859     }
860 
861 #if USB_DEVICE_CONFIG_USE_TASK
862     /* Create a message queue when the device handle is enabled. */
863     if (kStatus_USB_OSA_Success !=
864             USB_OsaMsgqCreate(&deviceHandle->notificationQueue, USB_DEVICE_CONFIG_MAX_MESSAGES,
865                               (1U + (sizeof(usb_device_callback_message_struct_t) - 1U) / sizeof(uint32_t))))
866     {
867         USB_DeviceDeinit(deviceHandle);
868         return kStatus_USB_Error;
869     }
870 #endif
871 
872     *handle = deviceHandle;
873 
874     /* Initialize the controller */
875     error = deviceHandle->controllerInterface->deviceInit(controllerId, deviceHandle, &deviceHandle->controllerHandle);
876     if (kStatus_USB_Success != error)
877     {
878         USB_DeviceDeinit(deviceHandle);
879         *handle = NULL;
880         return error;
881     }
882     /* Set the device to deafult state */
883     deviceHandle->state = kUSB_DeviceStateDefault;
884 
885     return error;
886 }
887 
888 /*!
889  * @brief Enable the device functionality.
890  *
891  * The function enables the device functionality, so that the device can be recognized by the host when the device
892  * detects that it has been connected to a host.
893  *
894  * @param handle The device handle got from USB_DeviceInit.
895  *
896  * @retval kStatus_USB_Success              The device is run successfully.
897  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
898  * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
899  *
900  */
USB_DeviceRun(usb_device_handle handle)901 usb_status_t USB_DeviceRun(usb_device_handle handle)
902 {
903     return USB_DeviceControl(handle, kUSB_DeviceControlRun, NULL);
904 }
905 /*!
906  * @brief Disable the device functionality.
907  *
908  * The function disables the device functionality, after this function called, even the device is detached to the host,
909  * and the device can't work.
910  *
911  * @param handle The device handle got from USB_DeviceInit.
912  *
913  * @retval kStatus_USB_Success              The device is stopped successfully.
914  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
915  * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
916  */
USB_DeviceStop(usb_device_handle handle)917 usb_status_t USB_DeviceStop(usb_device_handle handle)
918 {
919     return USB_DeviceControl(handle, kUSB_DeviceControlStop, NULL);
920 }
921 /*!
922  * @brief De-initialize the device controller.
923  *
924  * The function de-initializes the device controller specified by the handle.
925  *
926  * @param handle The device handle got from USB_DeviceInit.
927  *
928  * @retval kStatus_USB_Success              The device is stopped successfully.
929  * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
930  */
USB_DeviceDeinit(usb_device_handle handle)931 usb_status_t USB_DeviceDeinit(usb_device_handle handle)
932 {
933     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
934 
935     if (NULL == deviceHandle)
936     {
937         return kStatus_USB_InvalidHandle;
938     }
939     /* De-initialize the controller */
940     if (NULL != deviceHandle->controllerInterface)
941     {
942         deviceHandle->controllerInterface->deviceDeinit(deviceHandle->controllerHandle);
943         deviceHandle->controllerInterface = (usb_device_controller_interface_struct_t *)NULL;
944     }
945 
946 #if USB_DEVICE_CONFIG_USE_TASK
947     /* Destroy the message queue. */
948     if (NULL != deviceHandle->notificationQueue)
949     {
950         USB_OsaMsgqDestroy(deviceHandle->notificationQueue);
951         deviceHandle->notificationQueue = NULL;
952     }
953 #endif
954 
955     /* Free the device handle. */
956     USB_DeviceFreeHandle(deviceHandle);
957     return kStatus_USB_Success;
958 }
959 
960 /*!
961  * @brief Send data through a specified endpoint.
962  *
963  * The function is used to send data through a specified endpoint.
964  *
965  * @param handle The device handle got from USB_DeviceInit.
966  * @param endpointAddress Endpoint index.
967  * @param buffer The memory address to hold the data need to be sent.
968  * @param length The data length need to be sent.
969  *
970  * @retval kStatus_USB_Success              The send request is sent successfully.
971  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
972  * @retval kStatus_USB_Busy                 Cannot allocate dtds for current tansfer in EHCI driver.
973  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
974  * @retval kStatus_USB_Error                The device is doing reset.
975  *
976  * @note The return value just means if the sending request is successful or not; the transfer done is notified by the
977  * corresponding callback function.
978  * Currently, only one transfer request can be supported for one specific endpoint.
979  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
980  * should implement a queue in the application level.
981  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
982  * callback).
983  */
USB_DeviceSendRequest(usb_device_handle handle,uint8_t endpointAddress,uint8_t * buffer,uint32_t length)984 usb_status_t USB_DeviceSendRequest(usb_device_handle handle, uint8_t endpointAddress, uint8_t *buffer, uint32_t length)
985 {
986     return USB_DeviceTransfer(handle, (endpointAddress & USB_ENDPOINT_NUMBER_MASK) |
987                               (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
988                               buffer, length);
989 }
990 
991 /*!
992  * @brief Receive data through a specified endpoint.
993  *
994  * The function is used to receive data through a specified endpoint.
995  *
996  * @param handle The device handle got from USB_DeviceInit.
997  * @param endpointAddress Endpoint index.
998  * @param buffer The memory address to save the received data.
999  * @param length The data length want to be received.
1000  *
1001  * @retval kStatus_USB_Success              The receive request is sent successfully.
1002  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1003  * @retval kStatus_USB_Busy                 Cannot allocate dtds for current tansfer in EHCI driver.
1004  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1005  * @retval kStatus_USB_Error                The device is doing reset.
1006  *
1007  * @note The return value just means if the receiving request is successful or not; the transfer done is notified by the
1008  * corresponding callback function.
1009  * Currently, only one transfer request can be supported for one specific endpoint.
1010  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
1011  * should implement a queue in the application level.
1012  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
1013  * callback).
1014  */
USB_DeviceRecvRequest(usb_device_handle handle,uint8_t endpointAddress,uint8_t * buffer,uint32_t length)1015 usb_status_t USB_DeviceRecvRequest(usb_device_handle handle, uint8_t endpointAddress, uint8_t *buffer, uint32_t length)
1016 {
1017     return USB_DeviceTransfer(handle, (endpointAddress & USB_ENDPOINT_NUMBER_MASK) |
1018                               (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT),
1019                               buffer, length);
1020 }
1021 
1022 /*!
1023  * @brief Cancel the pending transfer in a specified endpoint.
1024  *
1025  * The function is used to cancel the pending transfer in a specified endpoint.
1026  *
1027  * @param handle The device handle got from USB_DeviceInit.
1028  * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
1029  *
1030  * @retval kStatus_USB_Success              The transfer is cancelled.
1031  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1032  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1033  */
USB_DeviceCancel(usb_device_handle handle,uint8_t endpointAddress)1034 usb_status_t USB_DeviceCancel(usb_device_handle handle, uint8_t endpointAddress)
1035 {
1036     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
1037     usb_status_t error = kStatus_USB_Error;
1038 
1039     if (NULL == deviceHandle)
1040     {
1041         return kStatus_USB_InvalidHandle;
1042     }
1043 
1044     if (NULL != deviceHandle->controllerInterface)
1045     {
1046         error = deviceHandle->controllerInterface->deviceCancel(deviceHandle->controllerHandle, endpointAddress);
1047     }
1048     else
1049     {
1050         error = kStatus_USB_ControllerNotFound;
1051     }
1052     return error;
1053 }
1054 
1055 /*!
1056  * @brief Initialize a specified endpoint.
1057  *
1058  * The function is used to initialize a specified endpoint and the corresponding endpoint callback is also initialized.
1059  *
1060  * @param handle The device handle got from USB_DeviceInit.
1061  * @param epInit Endpoint initizlization structure. Please refer to the structure usb_device_endpoint_init_struct_t.
1062  * @param epCallback Endpoint callback structure. Please refer to the structure
1063  * usb_device_endpoint_callback_struct_t.
1064  *
1065  * @retval kStatus_USB_Success              The endpoint is initialized successfully.
1066  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1067  * @retval kStatus_USB_InvalidParameter     The epInit or epCallback is NULL pointer. Or the endpoint number is
1068  * more than USB_DEVICE_CONFIG_ENDPOINTS.
1069  * @retval kStatus_USB_Busy                 The endpoint is busy in EHCI driver.
1070  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1071  */
USB_DeviceInitEndpoint(usb_device_handle handle,usb_device_endpoint_init_struct_t * epInit,usb_device_endpoint_callback_struct_t * epCallback)1072 usb_status_t USB_DeviceInitEndpoint(usb_device_handle handle,
1073                                     usb_device_endpoint_init_struct_t *epInit,
1074                                     usb_device_endpoint_callback_struct_t *epCallback)
1075 {
1076     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
1077     uint8_t endpoint;
1078     uint8_t direction;
1079 
1080     if (!deviceHandle)
1081     {
1082         return kStatus_USB_InvalidHandle;
1083     }
1084 
1085     if ((!epInit) || (!epCallback))
1086     {
1087         return kStatus_USB_InvalidParameter;
1088     }
1089 
1090     endpoint = epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK;
1091     direction = (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
1092                 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
1093 
1094     if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS)
1095     {
1096         deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn = epCallback->callbackFn;
1097         deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam =
1098             epCallback->callbackParam;
1099         deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
1100     }
1101     else
1102     {
1103         return kStatus_USB_InvalidParameter;
1104     }
1105     return USB_DeviceControl(handle, kUSB_DeviceControlEndpointInit, epInit);
1106 }
1107 
1108 /*!
1109  * @brief De-initizlize a specified endpoint.
1110  *
1111  * The function is used to de-initizlize a specified endpoint.
1112  *
1113  * @param handle The device handle got from USB_DeviceInit.
1114  * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
1115  *
1116  * @retval kStatus_USB_Success              The endpoint is de-initialized successfully.
1117  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1118  * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
1119  * @retval kStatus_USB_Busy                 The endpoint is busy in EHCI driver.
1120  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1121  */
USB_DeviceDeinitEndpoint(usb_device_handle handle,uint8_t endpointAddress)1122 usb_status_t USB_DeviceDeinitEndpoint(usb_device_handle handle, uint8_t endpointAddress)
1123 {
1124     usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
1125     uint8_t endpoint = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
1126     uint8_t direction = (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
1127                         USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
1128     usb_status_t error = kStatus_USB_Error;
1129 #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
1130     USB_OSA_SR_ALLOC();
1131 #endif
1132 
1133     if (!deviceHandle)
1134     {
1135         return kStatus_USB_InvalidHandle;
1136     }
1137 #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
1138     USB_OSA_ENTER_CRITICAL();
1139     deviceHandle->epCallbackDirectly = 1;
1140     USB_OSA_EXIT_CRITICAL();
1141 #endif
1142     error = USB_DeviceControl(handle, kUSB_DeviceControlEndpointDeinit, &endpointAddress);
1143 #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U))
1144     USB_OSA_ENTER_CRITICAL();
1145     deviceHandle->epCallbackDirectly = 0;
1146     USB_OSA_EXIT_CRITICAL();
1147 #endif
1148 
1149     if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS)
1150     {
1151         deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn =
1152             (usb_device_endpoint_callback_t)NULL;
1153         deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam = NULL;
1154         deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
1155     }
1156     else
1157     {
1158         return kStatus_USB_InvalidParameter;
1159     }
1160     return error;
1161 }
1162 
1163 /*!
1164  * @brief Stall a specified endpoint.
1165  *
1166  * The function is used to stall a specified endpoint.
1167  *
1168  * @param handle The device handle got from USB_DeviceInit.
1169  * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
1170  *
1171  * @retval kStatus_USB_Success              The endpoint is stalled successfully.
1172  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1173  * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
1174  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1175  */
USB_DeviceStallEndpoint(usb_device_handle handle,uint8_t endpointAddress)1176 usb_status_t USB_DeviceStallEndpoint(usb_device_handle handle, uint8_t endpointAddress)
1177 {
1178     if ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) < USB_DEVICE_CONFIG_ENDPOINTS)
1179     {
1180         return USB_DeviceControl(handle, kUSB_DeviceControlEndpointStall, &endpointAddress);
1181     }
1182     else
1183     {
1184         return kStatus_USB_InvalidParameter;
1185     }
1186 }
1187 
1188 /*!
1189  * @brief Un-stall a specified endpoint.
1190  *
1191  * The function is used to un-stall a specified endpoint.
1192  *
1193  * @param handle The device handle got from USB_DeviceInit.
1194  * @param endpointAddress Endpoint address, bit7 is the direction of endpoint, 1U - IN, abd 0U - OUT.
1195  *
1196  * @retval kStatus_USB_Success              The endpoint is un-stalled successfully.
1197  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1198  * @retval kStatus_USB_InvalidParameter     The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS.
1199  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1200  */
USB_DeviceUnstallEndpoint(usb_device_handle handle,uint8_t endpointAddress)1201 usb_status_t USB_DeviceUnstallEndpoint(usb_device_handle handle, uint8_t endpointAddress)
1202 {
1203     if ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) < USB_DEVICE_CONFIG_ENDPOINTS)
1204     {
1205         return USB_DeviceControl(handle, kUSB_DeviceControlEndpointUnstall, &endpointAddress);
1206     }
1207     else
1208     {
1209         return kStatus_USB_InvalidParameter;
1210     }
1211 }
1212 
1213 /*!
1214  * @brief Get the status of the selected item.
1215  *
1216  * The function is used to get the status of the selected item.
1217  *
1218  * @param handle The device handle got from USB_DeviceInit.
1219  * @param type   The selected item. Please refer to the structure usb_device_status_t.
1220  * @param param  The param type is determined by the selected item.
1221  *
1222  * @retval kStatus_USB_Success              Get status successfully.
1223  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1224  * @retval kStatus_USB_InvalidParameter     The param is NULL pointer.
1225  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1226  * @retval kStatus_USB_Error                Unsupported type.
1227  */
USB_DeviceGetStatus(usb_device_handle handle,usb_device_status_t type,void * param)1228 usb_status_t USB_DeviceGetStatus(usb_device_handle handle, usb_device_status_t type, void *param)
1229 {
1230     uint8_t *temp8;
1231     usb_status_t error = kStatus_USB_Error;
1232 
1233     if (NULL == param)
1234     {
1235         return kStatus_USB_InvalidParameter;
1236     }
1237     switch (type)
1238     {
1239     case kUSB_DeviceStatusSpeed:
1240         error = USB_DeviceControl(handle, kUSB_DeviceControlGetSpeed, param);
1241         break;
1242     case kUSB_DeviceStatusOtg:
1243         error = USB_DeviceControl(handle, kUSB_DeviceControlGetOtgStatus, param);
1244         break;
1245     case kUSB_DeviceStatusDeviceState:
1246         temp8 = (uint8_t *)param;
1247         error = kStatus_USB_Success;
1248         *temp8 = ((usb_device_struct_t *)handle)->state;
1249         break;
1250     case kUSB_DeviceStatusAddress:
1251         temp8 = (uint8_t *)param;
1252         error = kStatus_USB_Success;
1253         *temp8 = ((usb_device_struct_t *)handle)->deviceAddress;
1254         break;
1255     case kUSB_DeviceStatusDevice:
1256         error = USB_DeviceControl(handle, kUSB_DeviceControlGetDeviceStatus, param);
1257         break;
1258     case kUSB_DeviceStatusEndpoint:
1259         error = USB_DeviceControl(handle, kUSB_DeviceControlGetEndpointStatus, param);
1260         break;
1261     case kUSB_DeviceStatusSynchFrame:
1262         error = USB_DeviceControl(handle, kUSB_DeviceControlGetSynchFrame, param);
1263         break;
1264 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
1265     case kUSB_DeviceStatusRemoteWakeup:
1266         temp8 = (uint8_t *)param;
1267         error = kStatus_USB_Success;
1268         *temp8 = ((usb_device_struct_t *)handle)->remotewakeup;
1269         break;
1270 #endif
1271     default:
1272         break;
1273     }
1274     return error;
1275 }
1276 
1277 /*!
1278  * @brief Set the status of the selected item.
1279  *
1280  * The function is used to set the status of the selected item.
1281  *
1282  * @param handle The device handle got from USB_DeviceInit.
1283  * @param type The selected item. Please refer to the structure usb_device_status_t.
1284  * @param param The param type is determined by the selected item.
1285  *
1286  * @retval kStatus_USB_Success              Set status successfully.
1287  * @retval kStatus_USB_InvalidHandle        The handle is a NULL pointer. Or the controller handle is invalid.
1288  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1289  * @retval kStatus_USB_Error                Unsupported type, or the param is NULL pointer.
1290  */
USB_DeviceSetStatus(usb_device_handle handle,usb_device_status_t type,void * param)1291 usb_status_t USB_DeviceSetStatus(usb_device_handle handle, usb_device_status_t type, void *param)
1292 {
1293     usb_status_t error = kStatus_USB_Error;
1294     switch (type)
1295     {
1296 #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U) ||                  \
1297      (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))) && \
1298     (defined(USB_DEVICE_CONFIG_USB20_TEST_MODE) && (USB_DEVICE_CONFIG_USB20_TEST_MODE > 0U))
1299     case kUSB_DeviceStatusTestMode:
1300         error = USB_DeviceControl(handle, kUSB_DeviceControlSetTestMode, param);
1301         break;
1302 #endif
1303     case kUSB_DeviceStatusOtg:
1304         error = USB_DeviceControl(handle, kUSB_DeviceControlSetOtgStatus, param);
1305         break;
1306     case kUSB_DeviceStatusDeviceState:
1307         if (NULL != param)
1308         {
1309             error = kStatus_USB_Success;
1310             ((usb_device_struct_t *)handle)->state = (uint8_t)(*(uint8_t *)param);
1311         }
1312         break;
1313     case kUSB_DeviceStatusAddress:
1314         if (kUSB_DeviceStateAddressing != ((usb_device_struct_t *)handle)->state)
1315         {
1316             if (NULL != param)
1317             {
1318                 error = kStatus_USB_Success;
1319                 ((usb_device_struct_t *)handle)->deviceAddress = (uint8_t)(*(uint8_t *)param);
1320                 ((usb_device_struct_t *)handle)->state = kUSB_DeviceStateAddressing;
1321             }
1322         }
1323         else
1324         {
1325             error = USB_DeviceControl(handle, kUSB_DeviceControlSetDeviceAddress,
1326                                       &((usb_device_struct_t *)handle)->deviceAddress);
1327         }
1328         break;
1329     case kUSB_DeviceStatusBusResume:
1330         error = USB_DeviceControl(handle, kUSB_DeviceControlResume, param);
1331         break;
1332     case kUSB_DeviceStatusBusSleepResume:
1333         error = USB_DeviceControl(handle, kUSB_DeviceControlSleepResume, param);
1334         break;
1335 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
1336     case kUSB_DeviceStatusRemoteWakeup:
1337         if (NULL != param)
1338         {
1339             error = kStatus_USB_Success;
1340             ((usb_device_struct_t *)handle)->remotewakeup = (uint8_t)(*(uint8_t *)param);
1341         }
1342         break;
1343 #endif
1344     case kUSB_DeviceStatusBusSuspend:
1345         error = USB_DeviceControl(handle, kUSB_DeviceControlSuspend, param);
1346         break;
1347     case kUSB_DeviceStatusBusSleep:
1348         error = USB_DeviceControl(handle, kUSB_DeviceControlSleep, param);
1349         break;
1350     default:
1351         break;
1352     }
1353     return error;
1354 }
1355 
1356 #if (defined(USB_DEVICE_CHARGER_DETECT_ENABLE) && (USB_DEVICE_CHARGER_DETECT_ENABLE > 0U)) && \
1357     ((defined(FSL_FEATURE_SOC_USBDCD_COUNT) && (FSL_FEATURE_SOC_USBDCD_COUNT > 0U)) ||        \
1358      (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
1359 /*!
1360  * @brief Initializes the device dcd module.
1361  *
1362  * The function initializes the device dcd module.
1363  *
1364  * @param handle The device handle got from USB_DeviceInit.
1365  *
1366  * @retval kStatus_USB_Success              The device is run successfully.
1367  * @retval kStatus_USB_ControllerNotFound   Cannot find the controller.
1368  * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
1369  *
1370  */
USB_DeviceDcdInitModule(usb_device_handle handle,void * time_param)1371 usb_status_t USB_DeviceDcdInitModule(usb_device_handle handle, void *time_param)
1372 {
1373     return USB_DeviceControl(handle, kUSB_DeviceControlDcdInitModule, time_param);
1374 }
1375 
1376 /*!
1377  * @brief De-initializes the device dcd module.
1378  *
1379  * The function de-intializes the device dcd module.
1380  *
1381  * @param handle The device handle got from USB_DeviceInit.
1382  *
1383  * @retval kStatus_USB_Success              The device is run successfully.
1384  * @retval kStatus_USB_InvalidHandle        The device handle is a NULL pointer. Or the controller handle is invalid.
1385  *
1386  */
USB_DeviceDcdDeinitModule(usb_device_handle handle)1387 usb_status_t USB_DeviceDcdDeinitModule(usb_device_handle handle)
1388 {
1389     return USB_DeviceControl(handle, kUSB_DeviceControlDcdDeinitModule, NULL);
1390 }
1391 #endif
1392 
1393 #if USB_DEVICE_CONFIG_USE_TASK
1394 /*!
1395  * @brief Device task function.
1396  *
1397  * The function is used to handle controller message.
1398  * This function should not be called in applicartion directly.
1399  *
1400  * @param handle The device handle got from USB_DeviceInit.
1401  */
USB_DeviceTaskFunction(void * deviceHandle)1402 void USB_DeviceTaskFunction(void *deviceHandle)
1403 {
1404     usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
1405     static usb_device_callback_message_struct_t message;
1406 
1407     if (deviceHandle)
1408     {
1409         /* Get the message from the queue */
1410         if (kStatus_USB_OSA_Success == USB_OsaMsgqRecv(handle->notificationQueue, (uint32_t *)&message, 0U))
1411         {
1412             /* Handle the message */
1413             USB_DeviceNotification(handle, &message);
1414         }
1415     }
1416 }
1417 #endif
1418 
1419 /*!
1420  * @brief Get dvice stack version function.
1421  *
1422  * The function is used to get dvice stack version.
1423  *
1424  * @param[out] version The version structure pointer to keep the device stack version.
1425  *
1426  */
USB_DeviceGetVersion(uint32_t * version)1427 void USB_DeviceGetVersion(uint32_t *version)
1428 {
1429     if (version)
1430     {
1431         *version =
1432             (uint32_t)USB_MAKE_VERSION(USB_STACK_VERSION_MAJOR, USB_STACK_VERSION_MINOR, USB_STACK_VERSION_BUGFIX);
1433     }
1434 }
1435 
1436 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
1437 /*!
1438  * @brief Update the hardware tick.
1439  *
1440  * The function is used to update the hardware tick.
1441  *
1442  * @param[in] handle The device handle got from #USB_DeviceInit.
1443  * @param[in] tick Current hardware tick.
1444  *
1445  */
USB_DeviceUpdateHwTick(usb_device_handle handle,uint64_t tick)1446 usb_status_t USB_DeviceUpdateHwTick(usb_device_handle handle, uint64_t tick)
1447 {
1448     usb_device_struct_t *deviceHandle;
1449     usb_status_t status = kStatus_USB_Success;
1450 
1451     if (handle == NULL)
1452     {
1453         return kStatus_USB_InvalidHandle;
1454     }
1455     deviceHandle = (usb_device_struct_t *)handle;
1456 
1457     deviceHandle->hwTick = tick;
1458 
1459     return status;
1460 }
1461 #endif
1462 #endif /* USB_DEVICE_CONFIG_NUM */
1463