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