common: Implement USB0 interrupt handler.
[gps-watch.git] / src / common / virtual_com.c
1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015, Freescale Semiconductor, Inc.
4  * Copyright 2016-2017 NXP
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted (subject to the limitations in the disclaimer below) provided
9  * that the following conditions are met:
10  *
11  * o Redistributions of source code must retain the above copyright notice, this list
12  *   of conditions and the following disclaimer.
13  *
14  * o Redistributions in binary form must reproduce the above copyright notice, this
15  *   list of conditions and the following disclaimer in the documentation and/or
16  *   other materials provided with the distribution.
17  *
18  * o Neither the name of the copyright holder nor the names of its
19  *   contributors may be used to endorse or promote products derived from this
20  *   software without specific prior written permission.
21  *
22  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #include "fsl_device_registers.h"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #include "usb_device_config.h"
40 #include "usb.h"
41 #include "usb_device.h"
42
43 #include "usb_device_cdc_acm.h"
44 #include "usb_device_ch9.h"
45
46 #include "usb_device_descriptor.h"
47 #include "virtual_com.h"
48 #if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
49 #include "fsl_sysmpu.h"
50 #endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
51 #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)
52 #include "usb_phy.h"
53 #endif
54
55 /* Provided by users. */
56 extern void USB_DeviceClockInit(void);
57 extern void USB_DeviceIsrEnable(void);
58 /*******************************************************************************
59 * Definitions
60 ******************************************************************************/
61
62 /*******************************************************************************
63 * Variables
64 ******************************************************************************/
65 /* Data structure of virtual com device */
66 usb_cdc_vcom_struct_t s_cdcVcom;
67
68 /* Line codinig of cdc device */
69 static uint8_t s_lineCoding[LINE_CODING_SIZE] = {
70     /* E.g. 0x00,0xC2,0x01,0x00 : 0x0001C200 is 115200 bits per second */
71     (LINE_CODING_DTERATE >> 0U) & 0x000000FFU,
72     (LINE_CODING_DTERATE >> 8U) & 0x000000FFU,
73     (LINE_CODING_DTERATE >> 16U) & 0x000000FFU,
74     (LINE_CODING_DTERATE >> 24U) & 0x000000FFU,
75     LINE_CODING_CHARFORMAT,
76     LINE_CODING_PARITYTYPE,
77     LINE_CODING_DATABITS};
78
79 /* Abstract state of cdc device */
80 static uint8_t s_abstractState[COMM_FEATURE_DATA_SIZE] = {(STATUS_ABSTRACT_STATE >> 0U) & 0x00FFU,
81                                                           (STATUS_ABSTRACT_STATE >> 8U) & 0x00FFU};
82
83 /* Country code of cdc device */
84 static uint8_t s_countryCode[COMM_FEATURE_DATA_SIZE] = {(COUNTRY_SETTING >> 0U) & 0x00FFU,
85                                                         (COUNTRY_SETTING >> 8U) & 0x00FFU};
86
87 /* CDC ACM information */
88 static usb_cdc_acm_info_t s_usbCdcAcmInfo = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0};
89
90 /* Data buffer for receiving and sending*/
91 static uint8_t s_currRecvBuf[DATA_BUFF_SIZE];
92 volatile static uint32_t s_recvSize = 0;
93 volatile static uint32_t s_sendSize = 0;
94 volatile static uint8_t s_sendComplete = 0;
95 volatile static uint8_t s_currRecvIndex = 0;
96 static uint32_t s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
97 /*******************************************************************************
98 * Prototypes
99 ******************************************************************************/
100
101 /*******************************************************************************
102 * Code
103 ******************************************************************************/
104 /*!
105  * @brief Interrupt in pipe callback function.
106  *
107  * This function serves as the callback function for interrupt in pipe.
108  *
109  * @param handle The USB device handle.
110  * @param message The endpoint callback message
111  * @param callbackParam The parameter of the callback.
112  *
113  * @return A USB error code or kStatus_USB_Success.
114  */
115 usb_status_t USB_DeviceCdcAcmInterruptIn(usb_device_handle handle,
116                                          usb_device_endpoint_callback_message_struct_t *message,
117                                          void *callbackParam)
118 {
119     usb_status_t error = kStatus_USB_Error;
120
121     return error;
122 }
123
124 /*!
125  * @brief Bulk in pipe callback function.
126  *
127  * This function serves as the callback function for bulk in pipe.
128  *
129  * @param handle The USB device handle.
130  * @param message The endpoint callback message
131  * @param callbackParam The parameter of the callback.
132  *
133  * @return A USB error code or kStatus_USB_Success.
134  */
135 usb_status_t USB_DeviceCdcAcmBulkIn(usb_device_handle handle,
136                                     usb_device_endpoint_callback_message_struct_t *message,
137                                     void *callbackParam)
138 {
139     usb_status_t error = kStatus_USB_Error;
140
141     if ((message->length != 0) && (!(message->length % s_usbBulkMaxPacketSize)))
142     {
143         /* If the last packet is the size of endpoint, then send also zero-ended packet,
144          ** meaning that we want to inform the host that we do not have any additional
145          ** data, so it can flush the output.
146          */
147         USB_DeviceSendRequest(handle, USB_CDC_VCOM_BULK_IN_ENDPOINT, NULL, 0);
148     }
149     else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
150     {
151         if ((message->buffer != NULL) || ((message->buffer == NULL) && (message->length == 0)))
152         {
153             /* User: add your own code for send complete event */
154             s_sendComplete = 1;
155 #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
156     defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) &&             \
157     defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
158             USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
159 #endif
160         }
161     }
162     else if ((0 == s_sendComplete) && (1 == s_cdcVcom.attach) && (0 == s_cdcVcom.startTransactions))
163     {
164         s_sendComplete = 1;
165     }
166     else
167     {
168     }
169     return error;
170 }
171
172 /*!
173  * @brief Bulk out pipe callback function.
174  *
175  * This function serves as the callback function for bulk out pipe.
176  *
177  * @param handle The USB device handle.
178  * @param message The endpoint callback message
179  * @param callbackParam The parameter of the callback.
180  *
181  * @return A USB error code or kStatus_USB_Success.
182  */
183 usb_status_t USB_DeviceCdcAcmBulkOut(usb_device_handle handle,
184                                      usb_device_endpoint_callback_message_struct_t *message,
185                                      void *callbackParam)
186 {
187     usb_status_t error = kStatus_USB_Error;
188     if (USB_UNINITIALIZED_VAL_32 == message->length)
189     {
190         s_recvSize = 0xFFFFFFFFU;
191     }
192     else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
193     {
194         s_recvSize = message->length;
195 #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
196     defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) &&             \
197     defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
198         USB0->INTEN |= USB_INTEN_SOFTOKEN_MASK;
199 #endif
200         if (!s_recvSize)
201         {
202 #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
203     defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) &&             \
204     defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
205             USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
206 #endif
207         }
208     }
209     else
210     {
211     }
212     return error;
213 }
214
215 /*!
216  * @brief Get the setup packet buffer.
217  *
218  * This function provides the buffer for setup packet.
219  *
220  * @param handle The USB device handle.
221  * @param setupBuffer The pointer to the address of setup packet buffer.
222  *
223  * @return A USB error code or kStatus_USB_Success.
224  */
225 usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer)
226 {
227     static uint32_t cdcVcomSetup[2];
228     if (NULL == setupBuffer)
229     {
230         return kStatus_USB_InvalidParameter;
231     }
232     *setupBuffer = (usb_setup_struct_t *)&cdcVcomSetup;
233     return kStatus_USB_Success;
234 }
235
236 /*!
237  * @brief Get the setup packet data buffer.
238  *
239  * This function gets the data buffer for setup packet.
240  *
241  * @param handle The USB device handle.
242  * @param setup The pointer to the setup packet.
243  * @param length The pointer to the length of the data buffer.
244  * @param buffer The pointer to the address of setup packet data buffer.
245  *
246  * @return A USB error code or kStatus_USB_Success.
247  */
248 usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
249                                              usb_setup_struct_t *setup,
250                                              uint32_t *length,
251                                              uint8_t **buffer)
252 {
253     static uint8_t setupOut[8];
254     if ((NULL == buffer) || ((*length) > sizeof(setupOut)))
255     {
256         return kStatus_USB_InvalidRequest;
257     }
258     *buffer = setupOut;
259     return kStatus_USB_Success;
260 }
261
262 /*!
263  * @brief Configure remote wakeup feature.
264  *
265  * This function configures the remote wakeup feature.
266  *
267  * @param handle The USB device handle.
268  * @param enable 1: enable, 0: disable.
269  *
270  * @return A USB error code or kStatus_USB_Success.
271  */
272 usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable)
273 {
274     return kStatus_USB_InvalidRequest;
275 }
276
277 /*!
278  * @brief CDC class specific callback function.
279  *
280  * This function handles the CDC class specific requests.
281  *
282  * @param handle The USB device handle.
283  * @param setup The pointer to the setup packet.
284  * @param length The pointer to the length of the data buffer.
285  * @param buffer The pointer to the address of setup packet data buffer.
286  *
287  * @return A USB error code or kStatus_USB_Success.
288  */
289 usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
290                                            usb_setup_struct_t *setup,
291                                            uint32_t *length,
292                                            uint8_t **buffer)
293 {
294     usb_status_t error = kStatus_USB_InvalidRequest;
295
296     usb_cdc_acm_info_t *acmInfo = &s_usbCdcAcmInfo;
297     uint32_t len;
298     uint16_t *uartBitmap;
299     if (setup->wIndex != USB_CDC_VCOM_COMM_INTERFACE_INDEX)
300     {
301         return error;
302     }
303
304     switch (setup->bRequest)
305     {
306         case USB_DEVICE_CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
307             break;
308         case USB_DEVICE_CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
309             break;
310         case USB_DEVICE_CDC_REQUEST_SET_COMM_FEATURE:
311             if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == setup->wValue)
312             {
313                 *buffer = s_abstractState;
314             }
315             else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == setup->wValue)
316             {
317                 *buffer = s_countryCode;
318             }
319             else
320             {
321             }
322             error = kStatus_USB_Success;
323             break;
324         case USB_DEVICE_CDC_REQUEST_GET_COMM_FEATURE:
325             if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == setup->wValue)
326             {
327                 *buffer = s_abstractState;
328                 *length = COMM_FEATURE_DATA_SIZE;
329             }
330             else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == setup->wValue)
331             {
332                 *buffer = s_countryCode;
333                 *length = COMM_FEATURE_DATA_SIZE;
334             }
335             else
336             {
337             }
338             error = kStatus_USB_Success;
339             break;
340         case USB_DEVICE_CDC_REQUEST_CLEAR_COMM_FEATURE:
341             break;
342         case USB_DEVICE_CDC_REQUEST_GET_LINE_CODING:
343             *buffer = s_lineCoding;
344             *length = LINE_CODING_SIZE;
345             error = kStatus_USB_Success;
346             break;
347         case USB_DEVICE_CDC_REQUEST_SET_LINE_CODING:
348             *buffer = s_lineCoding;
349             error = kStatus_USB_Success;
350             break;
351         case USB_DEVICE_CDC_REQUEST_SET_CONTROL_LINE_STATE:
352         {
353             acmInfo->dteStatus = setup->wValue;
354             /* activate/deactivate Tx carrier */
355             if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
356             {
357                 acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
358             }
359             else
360             {
361                 acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
362             }
363
364             /* activate carrier and DTE */
365             if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
366             {
367                 acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
368             }
369             else
370             {
371                 acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
372             }
373
374             /* Indicates to DCE if DTE is present or not */
375             acmInfo->dtePresent = (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE) ? true : false;
376
377             /* Initialize the serial state buffer */
378             acmInfo->serialStateBuf[0] = NOTIF_REQUEST_TYPE;                        /* bmRequestType */
379             acmInfo->serialStateBuf[1] = USB_DEVICE_CDC_REQUEST_SERIAL_STATE_NOTIF; /* bNotification */
380             acmInfo->serialStateBuf[2] = 0x00;                                      /* wValue */
381             acmInfo->serialStateBuf[3] = 0x00;
382             acmInfo->serialStateBuf[4] = 0x00; /* wIndex */
383             acmInfo->serialStateBuf[5] = 0x00;
384             acmInfo->serialStateBuf[6] = UART_BITMAP_SIZE; /* wLength */
385             acmInfo->serialStateBuf[7] = 0x00;
386             /* Notifiy to host the line state */
387             acmInfo->serialStateBuf[4] = setup->wIndex;
388             /* Lower byte of UART BITMAP */
389             uartBitmap = (uint16_t *)&acmInfo->serialStateBuf[NOTIF_PACKET_SIZE + UART_BITMAP_SIZE - 2];
390             *uartBitmap = acmInfo->uartState;
391             len = (uint32_t)(NOTIF_PACKET_SIZE + UART_BITMAP_SIZE);
392             error = USB_DeviceSendRequest(handle, USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT, acmInfo->serialStateBuf, len);
393
394             /* Update status */
395             if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
396             {
397                 /*    To do: CARRIER_ACTIVATED */
398             }
399             else
400             {
401                 /* To do: CARRIER_DEACTIVATED */
402             }
403             if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
404             {
405                 /* DTE_ACTIVATED */
406                 if (1 == s_cdcVcom.attach)
407                 {
408                     s_cdcVcom.startTransactions = 1;
409 #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
410     defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) &&             \
411     defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
412                     USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
413 #endif
414                 }
415             }
416             else
417             {
418                 /* DTE_DEACTIVATED */
419                 if (1 == s_cdcVcom.attach)
420                 {
421                     s_cdcVcom.startTransactions = 0;
422                 }
423             }
424         }
425         break;
426         case USB_DEVICE_CDC_REQUEST_SEND_BREAK:
427             break;
428         default:
429             break;
430     }
431
432     return error;
433 }
434
435 /*!
436  * @brief USB device callback function.
437  *
438  * This function handles the usb device specific requests.
439  *
440  * @param handle          The USB device handle.
441  * @param event           The USB device event type.
442  * @param param           The parameter of the device specific request.
443  *
444  * @return A USB error code or kStatus_USB_Success.
445  */
446 usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param)
447 {
448     usb_status_t error = kStatus_USB_Error;
449     uint8_t *temp8 = (uint8_t *)param;
450
451     switch (event)
452     {
453         case kUSB_DeviceEventBusReset:
454         {
455             USB_DeviceControlPipeInit(s_cdcVcom.deviceHandle);
456             s_cdcVcom.attach = 0;
457 #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)) || \
458     (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
459             if (kStatus_USB_Success ==
460                 USB_DeviceGetStatus(s_cdcVcom.deviceHandle, kUSB_DeviceStatusSpeed, &s_cdcVcom.speed))
461             {
462                 USB_DeviceSetSpeed(handle, s_cdcVcom.speed);
463             }
464 #endif
465         }
466         break;
467         case kUSB_DeviceEventSetConfiguration:
468             if (param)
469             {
470                 s_cdcVcom.attach = 1;
471                 s_cdcVcom.currentConfiguration = *temp8;
472                 if (USB_CDC_VCOM_CONFIGURE_INDEX == (*temp8))
473                 {
474                     usb_device_endpoint_init_struct_t epInitStruct;
475                     usb_device_endpoint_callback_struct_t endpointCallback;
476
477                     /* Initiailize endpoint for interrupt pipe */
478                     endpointCallback.callbackFn = USB_DeviceCdcAcmInterruptIn;
479                     endpointCallback.callbackParam = handle;
480
481                     epInitStruct.zlt = 0;
482                     epInitStruct.transferType = USB_ENDPOINT_INTERRUPT;
483                     epInitStruct.endpointAddress = USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT |
484                                                    (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
485                     if (USB_SPEED_HIGH == s_cdcVcom.speed)
486                     {
487                         epInitStruct.maxPacketSize = HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE;
488                     }
489                     else
490                     {
491                         epInitStruct.maxPacketSize = FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE;
492                     }
493
494                     USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback);
495
496                     /* Initiailize endpoints for bulk pipe */
497                     endpointCallback.callbackFn = USB_DeviceCdcAcmBulkIn;
498                     endpointCallback.callbackParam = handle;
499
500                     epInitStruct.zlt = 0;
501                     epInitStruct.transferType = USB_ENDPOINT_BULK;
502                     epInitStruct.endpointAddress =
503                         USB_CDC_VCOM_BULK_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
504                     if (USB_SPEED_HIGH == s_cdcVcom.speed)
505                     {
506                         epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_IN_PACKET_SIZE;
507                     }
508                     else
509                     {
510                         epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_IN_PACKET_SIZE;
511                     }
512
513                     USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback);
514
515                     endpointCallback.callbackFn = USB_DeviceCdcAcmBulkOut;
516                     endpointCallback.callbackParam = handle;
517
518                     epInitStruct.zlt = 0;
519                     epInitStruct.transferType = USB_ENDPOINT_BULK;
520                     epInitStruct.endpointAddress =
521                         USB_CDC_VCOM_BULK_OUT_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
522                     if (USB_SPEED_HIGH == s_cdcVcom.speed)
523                     {
524                         epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
525                     }
526                     else
527                     {
528                         epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
529                     }
530
531                     USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback);
532
533                     if (USB_SPEED_HIGH == s_cdcVcom.speed)
534                     {
535                         s_usbBulkMaxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
536                     }
537                     else
538                     {
539                         s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
540                     }
541                 }
542             }
543             break;
544         default:
545             break;
546     }
547
548     return error;
549 }
550
551 /*!
552  * @brief USB configure endpoint function.
553  *
554  * This function configure endpoint status.
555  *
556  * @param handle The USB device handle.
557  * @param ep Endpoint address.
558  * @param status A flag to indicate whether to stall the endpoint. 1: stall, 0: unstall.
559  *
560  * @return A USB error code or kStatus_USB_Success.
561  */
562 usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle, uint8_t ep, uint8_t status)
563 {
564     if (status)
565     {
566         return USB_DeviceStallEndpoint(handle, ep);
567     }
568     else
569     {
570         return USB_DeviceUnstallEndpoint(handle, ep);
571     }
572 }
573
574 /* See virtual_com.h for documentation of this function. */
575 void USB_VcomWriteBlocking(usb_device_handle baseAddr, const uint8_t *buf, size_t count)
576 {
577     while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1))
578     {
579     };
580     USB_DeviceSendRequest((usb_device_handle)baseAddr, USB_CDC_VCOM_BULK_IN_ENDPOINT, (uint8_t *)buf, count);
581     while (!s_sendComplete)
582     {
583     };
584     s_sendComplete = 0;
585 }
586
587 /* See virtual_com.h for documentation of this function. */
588 status_t USB_VcomReadBlocking(usb_device_handle baseAddr, uint8_t *buf, size_t count)
589 {
590     status_t error = kStatus_Success;
591     size_t bufIndex = 0U, bytesToReceive = 0U;
592     assert(count != 0U);
593
594     /* Waiting for the USB ready. */
595     while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1))
596     {
597     };
598
599     do
600     {
601         /* If no receive request. */
602         if (s_recvSize <= 0)
603         {
604             if (kStatus_USB_Success !=
605                 USB_DeviceRecvRequest(baseAddr, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize))
606             {
607                 return kStatus_Fail;
608             }
609             s_currRecvIndex = 0;
610         }
611         /* Waiting for data received by virtual com. */
612         while (s_recvSize <= 0)
613         {
614         };
615
616         /* When receive request is error. */
617         if (0xFFFFFFFFU == s_recvSize)
618         {
619             /* Waiting for the USB ready and transfer started. */
620             while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1))
621             {
622             };
623             s_recvSize = 0;
624         }
625         else
626         {
627             bytesToReceive = MIN(count, s_recvSize);
628             memcpy((void *)&buf[bufIndex], s_currRecvBuf + s_currRecvIndex, bytesToReceive);
629             count -= bytesToReceive;
630             s_recvSize -= bytesToReceive;
631             bufIndex += bytesToReceive;
632             s_currRecvIndex += bytesToReceive;
633         }
634     } while (0U != count);
635     return error;
636 }
637
638 /* See virtual_com.h for documentation of this function. */
639 usb_device_handle USB_VcomInit(void)
640 {
641     usb_device_handle deviceHandle = NULL;
642
643     USB_DeviceClockInit();
644
645 #if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
646     SYSMPU_Enable(SYSMPU, 0);
647 #endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
648
649     s_cdcVcom.speed = USB_SPEED_FULL;
650     s_cdcVcom.attach = 0;
651     s_cdcVcom.deviceHandle = NULL;
652
653     if (kStatus_USB_Success != USB_DeviceInit(CONTROLLER_ID, USB_DeviceCallback, &s_cdcVcom.deviceHandle))
654     {
655         deviceHandle = NULL;
656     }
657     else
658     {
659         deviceHandle = s_cdcVcom.deviceHandle;
660         USB_DeviceIsrEnable();
661         USB_DeviceRun(s_cdcVcom.deviceHandle);
662     }
663     return deviceHandle;
664 }
665
666 /* See virtual_com.h for documentation of this function. */
667 void USB_VcomDeinit(usb_device_handle deviceHandle)
668 {
669     USB_DeviceStop(deviceHandle);
670     USB_DeviceDeinit(deviceHandle);
671     s_cdcVcom.deviceHandle = NULL;
672 #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)
673     USB_EhciPhyDeinit(CONTROLLER_ID);
674 #endif
675 #if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0)
676     CLOCK_DisableUsbfs0Clock();
677 #endif
678 #if defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)
679     /* enable USB IP clock, user code. */
680     CLOCK_DisableClock(kCLOCK_Usbd0);
681 #endif /* USB_DEVICE_CONFIG_LPCIP3511FS */
682
683 #if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
684 /* enable USB IP clock,user code. */
685 #endif /* USB_DEVICE_CONFIG_LPCIP3511HS */
686 }
687
688 void
689 USB0_IRQHandler (void)
690 {
691         USB_DeviceKhciIsrFunction (s_cdcVcom.deviceHandle);
692 }