1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016,2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_host_config.h"
10 #if ((defined USB_HOST_CONFIG_CDC) && (USB_HOST_CONFIG_CDC))
11 #include "usb_host.h"
12 #include "usb_host_cdc.h"
13 #include "usb_host_devices.h"
14 
15 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
16 
USB_HostCdcClearInHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)17 static void USB_HostCdcClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
18 {
19     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
20 
21     cdcInstance->controlTransfer = NULL;
22     if (cdcInstance->inCallbackFn != NULL)
23     {
24         /* callback to application, the callback function is initialized in USB_HostCdcDataRecv */
25         cdcInstance->inCallbackFn(cdcInstance->inCallbackParam, cdcInstance->stallDataBuffer,
26                                   cdcInstance->stallDataLength, kStatus_USB_TransferStall);
27     }
28     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
29 }
30 
USB_HostCdcClearOutHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)31 static void USB_HostCdcClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
32 {
33     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
34 
35     cdcInstance->controlTransfer = NULL;
36     if (cdcInstance->outCallbackFn != NULL)
37     {
38         /* callback to application,the callback function is initialized in USB_HostCdcDataSend */
39         cdcInstance->outCallbackFn(cdcInstance->outCallbackParam, cdcInstance->stallDataBuffer,
40                                    cdcInstance->stallDataLength, kStatus_USB_TransferStall);
41     }
42     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
43 }
USB_HostCdcClearInterruptHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)44 static void USB_HostCdcClearInterruptHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
45 {
46     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
47 
48     cdcInstance->controlTransfer = NULL;
49     if (cdcInstance->interruptCallbackFn != NULL)
50     {
51         /* callback to application */
52         cdcInstance->interruptCallbackFn(cdcInstance->interruptCallbackParam, cdcInstance->stallDataBuffer,
53                                          cdcInstance->stallDataLength, kStatus_USB_TransferStall);
54     }
55     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
56 }
57 
USB_HostCdcClearHalt(usb_host_cdc_instance_struct_t * cdcInstance,usb_host_transfer_t * stallTransfer,host_inner_transfer_callback_t callbackFn,uint8_t endpoint)58 static usb_status_t USB_HostCdcClearHalt(usb_host_cdc_instance_struct_t *cdcInstance,
59                                          usb_host_transfer_t *stallTransfer,
60                                          host_inner_transfer_callback_t callbackFn,
61                                          uint8_t endpoint)
62 {
63     usb_status_t status;
64     usb_host_transfer_t *transfer;
65 
66     /* malloc one transfer */
67     status = USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer);
68     if (status != kStatus_USB_Success)
69     {
70 #ifdef HOST_ECHO
71         usb_echo("allocate transfer error\r\n");
72 #endif
73         return status;
74     }
75     cdcInstance->stallDataBuffer = stallTransfer->transferBuffer;
76     cdcInstance->stallDataLength = stallTransfer->transferSofar;
77     /* save the application callback function */
78     cdcInstance->controlCallbackFn    = NULL;
79     cdcInstance->controlCallbackParam = NULL;
80     /* initialize transfer */
81     transfer->callbackFn                 = callbackFn;
82     transfer->callbackParam              = cdcInstance;
83     transfer->transferBuffer             = NULL;
84     transfer->transferLength             = 0;
85     transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_CLEAR_FEATURE;
86     transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
87     transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT);
88     transfer->setupPacket->wIndex  = USB_SHORT_TO_LITTLE_ENDIAN(endpoint);
89     transfer->setupPacket->wLength = 0;
90     status                         = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer);
91 
92     if (status != kStatus_USB_Success)
93     {
94         (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
95     }
96     cdcInstance->controlTransfer = transfer;
97 
98     return status;
99 }
100 #endif
101 
102 /*!
103  * @brief cdc data in pipe transfer callback.
104  *
105  * @param param       callback parameter.
106  * @param transfer    callback transfer.
107  * @param status      transfer status.
108  */
USB_HostCdcDataInPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)109 static void USB_HostCdcDataInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
110 {
111     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
112 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
113     if (status == kStatus_USB_TransferStall)
114     {
115         if (USB_HostCdcClearHalt(cdcInstance, transfer, USB_HostCdcClearInHaltCallback,
116                                  (USB_REQUEST_TYPE_DIR_IN |
117                                   ((usb_host_pipe_t *)cdcInstance->inPipe)->endpointAddress)) == kStatus_USB_Success)
118         {
119             (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
120             return;
121         }
122     }
123 #endif
124 
125     if (cdcInstance->inCallbackFn != NULL)
126     {
127         /* callback to application, the callback function is initialized in USB_HostCdcDataRecv */
128         cdcInstance->inCallbackFn(cdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
129                                   status);
130     }
131     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
132 }
133 
134 /*!
135  * @brief cdc data out pipe transfer callback.
136  *
137  * @param param       callback parameter.
138  * @param transfer    callback transfer.
139  * @param status      transfer status.
140  */
USB_HostCdcDataOutPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)141 static void USB_HostCdcDataOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
142 {
143     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
144 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
145     if (status == kStatus_USB_TransferStall)
146     {
147         if (USB_HostCdcClearHalt(cdcInstance, transfer, USB_HostCdcClearOutHaltCallback,
148                                  (USB_REQUEST_TYPE_DIR_OUT |
149                                   ((usb_host_pipe_t *)cdcInstance->outPipe)->endpointAddress)) == kStatus_USB_Success)
150         {
151             (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
152             return;
153         }
154     }
155 #endif
156     if (cdcInstance->outCallbackFn != NULL)
157     {
158         /* callback to application,the callback function is initialized in USB_HostCdcDataSend */
159         cdcInstance->outCallbackFn(cdcInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar,
160                                    status);
161     }
162 
163     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
164 }
165 
166 /*!
167  * @brief cdc data out pipe transfer callback.
168  *
169  * @param param       callback parameter.
170  * @param transfer    callback transfer.
171  * @param status      transfer status.
172  */
USB_HostCdcInterruptPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)173 static void USB_HostCdcInterruptPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
174 {
175     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
176 
177 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
178     if (status == kStatus_USB_TransferStall)
179     {
180         if (USB_HostCdcClearHalt(
181                 cdcInstance, transfer, USB_HostCdcClearInterruptHaltCallback,
182                 (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)cdcInstance->interruptPipe)->endpointAddress)) ==
183             kStatus_USB_Success)
184         {
185             (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
186             return;
187         }
188     }
189 #endif
190 
191     if (cdcInstance->interruptCallbackFn != NULL)
192     {
193         cdcInstance->interruptCallbackFn(cdcInstance->interruptCallbackParam, transfer->transferBuffer,
194                                          transfer->transferSofar, status);
195     }
196     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
197 }
198 
199 /*!
200  * @brief cdc data out pipe transfer callback.
201  *
202  * @param param       callback parameter.
203  * @param transfer    callback transfer.
204  * @param status      transfer status.
205  */
USB_HostCdcControlPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)206 static void USB_HostCdcControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
207 {
208     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
209 
210     if (cdcInstance->controlCallbackFn != NULL)
211     {
212         /* callback to application, callback function is initialized in the USB_HostCdcControl,
213         USB_HostCdcSetControlInterface
214         or USB_HostCdcSetDataInterface, but is the same function */
215         cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, transfer->transferBuffer,
216                                        transfer->transferSofar, status);
217     }
218     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
219 }
220 
221 /*!
222  * @brief cdc open data interface.
223  *
224  * @param cdcInstance     cdc instance pointer.
225  *
226  * @return kStatus_USB_Success or error codes.
227  */
USB_HostCdcOpenDataInterface(usb_host_cdc_instance_struct_t * cdcInstance)228 static usb_status_t USB_HostCdcOpenDataInterface(usb_host_cdc_instance_struct_t *cdcInstance)
229 {
230     usb_status_t status;
231     uint8_t ep_index = 0;
232     usb_host_pipe_init_t pipeInit;
233     usb_descriptor_endpoint_t *ep_desc = NULL;
234     usb_host_interface_t *interfaceHandle;
235 
236     if (cdcInstance->inPipe != NULL)
237     {
238         status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->inPipe);
239 
240         if (status != kStatus_USB_Success)
241         {
242 #ifdef HOST_ECHO
243             usb_echo("error when close pipe\r\n");
244 #endif
245         }
246         cdcInstance->inPipe = NULL;
247     }
248 
249     if (cdcInstance->outPipe != NULL)
250     {
251         status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->outPipe);
252 
253         if (status != kStatus_USB_Success)
254         {
255 #ifdef HOST_ECHO
256             usb_echo("error when close pipe\r\n");
257 #endif
258         }
259         cdcInstance->outPipe = NULL;
260     }
261     status = USB_HostOpenDeviceInterface(cdcInstance->deviceHandle, cdcInstance->dataInterfaceHandle);
262     if (status != kStatus_USB_Success)
263     {
264         return status;
265     }
266     /* open interface pipes */
267     interfaceHandle = (usb_host_interface_t *)cdcInstance->dataInterfaceHandle;
268 
269     for (ep_index = 0; ep_index < interfaceHandle->epCount; ++ep_index)
270     {
271         ep_desc = interfaceHandle->epList[ep_index].epDesc;
272         if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
273              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
274             ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
275         {
276             pipeInit.devInstance     = cdcInstance->deviceHandle;
277             pipeInit.pipeType        = USB_ENDPOINT_BULK;
278             pipeInit.direction       = USB_IN;
279             pipeInit.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
280             pipeInit.interval        = ep_desc->bInterval;
281             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
282                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
283             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
284                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
285             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
286 
287             cdcInstance->bulkInPacketSize = pipeInit.maxPacketSize;
288             status                        = USB_HostOpenPipe(cdcInstance->hostHandle, &cdcInstance->inPipe, &pipeInit);
289             if (status != kStatus_USB_Success)
290             {
291 #ifdef HOST_ECHO
292                 usb_echo("usb_host_audio_set_interface fail to open pipe\r\n");
293 #endif
294                 return kStatus_USB_Error;
295             }
296         }
297         else if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
298                   USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
299                  ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
300         {
301             pipeInit.devInstance     = cdcInstance->deviceHandle;
302             pipeInit.pipeType        = USB_ENDPOINT_BULK;
303             pipeInit.direction       = USB_OUT;
304             pipeInit.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
305             pipeInit.interval        = ep_desc->bInterval;
306             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
307                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
308             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
309                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
310             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
311 
312             cdcInstance->bulkOutPacketSize = pipeInit.maxPacketSize;
313             status = USB_HostOpenPipe(cdcInstance->hostHandle, &cdcInstance->outPipe, &pipeInit);
314             if (status != kStatus_USB_Success)
315             {
316 #ifdef HOST_ECHO
317                 usb_echo("usb_host_cdc_set_dat_interface fail to open pipe\r\n");
318 #endif
319                 return kStatus_USB_Error;
320             }
321         }
322         else
323         {
324         }
325     }
326     return kStatus_USB_Success;
327 }
328 
329 /*!
330  * @brief cdc set data interface callback, open pipes.
331  *
332  * @param param       callback parameter.
333  * @param transfer    callback transfer.
334  * @param status      transfer status.
335  */
USB_HostCdcSetDataInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)336 static void USB_HostCdcSetDataInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
337 {
338     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
339 
340     cdcInstance->controlTransfer = NULL;
341     if (status == kStatus_USB_Success)
342     {
343         status = USB_HostCdcOpenDataInterface(cdcInstance);
344     }
345 
346     if (cdcInstance->controlCallbackFn != NULL)
347     {
348         /* callback to application, callback function is initialized in the USB_HostCdcControl,
349         USB_HostCdcSetControlInterface
350         or USB_HostCdcSetDataInterface, but is the same function */
351         cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, NULL, 0, status);
352     }
353     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
354 }
355 
356 /*!
357  * @brief cdc open control interface.
358  *
359  * @param cdcInstance     cdc instance pointer.
360  *
361  * @return kStatus_USB_Success or error codes.
362  */
USB_HostCdcOpenControlInterface(usb_host_cdc_instance_struct_t * cdcInstance)363 static usb_status_t USB_HostCdcOpenControlInterface(usb_host_cdc_instance_struct_t *cdcInstance)
364 {
365     usb_status_t status;
366     uint8_t ep_index = 0;
367     usb_host_pipe_init_t pipeInit;
368     usb_descriptor_endpoint_t *ep_desc = NULL;
369     usb_host_interface_t *interfaceHandle;
370 
371     if (cdcInstance->interruptPipe != NULL)
372     {
373         status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL);
374         if (status != kStatus_USB_Success)
375         {
376 #ifdef HOST_ECHO
377             usb_echo("error when cancel pipe\r\n");
378 #endif
379         }
380         status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->interruptPipe);
381 
382         if (status != kStatus_USB_Success)
383         {
384 #ifdef HOST_ECHO
385             usb_echo("error when close pipe\r\n");
386 #endif
387         }
388         cdcInstance->interruptPipe = NULL;
389     }
390 
391     status = USB_HostOpenDeviceInterface(cdcInstance->deviceHandle, cdcInstance->controlInterfaceHandle);
392     if (status != kStatus_USB_Success)
393     {
394         return status;
395     }
396     /* open interface pipes */
397     interfaceHandle = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle;
398 
399     for (ep_index = 0; ep_index < interfaceHandle->epCount; ++ep_index)
400     {
401         ep_desc = interfaceHandle->epList[ep_index].epDesc;
402         if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
403              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
404             ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
405         {
406             pipeInit.devInstance     = cdcInstance->deviceHandle;
407             pipeInit.pipeType        = USB_ENDPOINT_INTERRUPT;
408             pipeInit.direction       = USB_IN;
409             pipeInit.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
410             pipeInit.interval        = ep_desc->bInterval;
411             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
412                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
413             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
414                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
415             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
416 
417             cdcInstance->packetSize = pipeInit.maxPacketSize;
418 
419             status = USB_HostOpenPipe(cdcInstance->hostHandle, &cdcInstance->interruptPipe, &pipeInit);
420             if (status != kStatus_USB_Success)
421             {
422 #ifdef HOST_ECHO
423                 usb_echo("USB_HostCdcSetControlInterface fail to open pipe\r\n");
424 #endif
425                 return kStatus_USB_Error;
426             }
427         }
428     }
429     return kStatus_USB_Success;
430 }
431 
432 /*!
433  * @brief cdc set control interface callback, open pipes.
434  *
435  * @param param       callback parameter.
436  * @param transfer    callback transfer.
437  * @param status      transfer status.
438  */
USB_HostCdcSetContorlInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)439 static void USB_HostCdcSetContorlInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
440 {
441     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
442 
443     cdcInstance->controlTransfer = NULL;
444     if (status == kStatus_USB_Success)
445     {
446         status = USB_HostCdcOpenControlInterface(cdcInstance);
447     }
448 
449     if (cdcInstance->controlCallbackFn != NULL)
450     {
451         /* callback to application, callback function is initialized in the USB_HostCdcControl,
452         USB_HostCdcSetControlInterface
453         or USB_HostCdcSetDataInterface, but is the same function */
454         cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, NULL, 0, status);
455     }
456     (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
457 }
458 
459 /*!
460  * @brief initialize the cdc instance.
461  *
462  * This function allocate the resource for cdc instance.
463  *
464  * @param deviceHandle       the device handle.
465  * @param classHandle return class handle.
466  *
467  * @retval kStatus_USB_Success        The device is initialized successfully.
468  * @retval kStatus_USB_AllocFail      Allocate memory fail.
469  */
USB_HostCdcInit(usb_device_handle deviceHandle,usb_host_class_handle * classHandle)470 usb_status_t USB_HostCdcInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
471 {
472     usb_host_cdc_instance_struct_t *control_ptr =
473         (usb_host_cdc_instance_struct_t *)OSA_MemoryAllocate(sizeof(usb_host_cdc_instance_struct_t));
474     uint32_t info_value = 0U;
475     void *temp;
476 
477     if (control_ptr == NULL)
478     {
479         return kStatus_USB_AllocFail;
480     }
481 
482     control_ptr->deviceHandle           = deviceHandle;
483     control_ptr->controlInterfaceHandle = NULL;
484     control_ptr->dataInterfaceHandle    = NULL;
485     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &info_value);
486     temp                    = (uint32_t *)info_value;
487     control_ptr->hostHandle = (usb_host_handle)temp;
488     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &info_value);
489     temp                     = (uint32_t *)info_value;
490     control_ptr->controlPipe = (usb_host_pipe_handle)temp;
491 
492     *classHandle = control_ptr;
493     return kStatus_USB_Success;
494 }
495 
496 /*!
497  * @brief set control interface.
498  *
499  * This function bind the control interface with the cdc instance.
500  *
501  * @param classHandle      the class handle.
502  * @param interfaceHandle  the control interface handle.
503  * @param alternateSetting the alternate setting value.
504  * @param callbackFn       this callback is called after this function completes.
505  * @param callbackParam    the first parameter in the callback function.
506  *
507  * @retval kStatus_USB_Success        The device is initialized successfully.
508  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
509  * @retval kStatus_USB_Busy           There is no idle transfer.
510  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
511  * @retval kStatus_USB_Busy           callback return status, there is no idle pipe.
512  * @retval kStatus_USB_TransferStall  callback return status, the transfer is stall by device.
513  * @retval kStatus_USB_Error          callback return status, open pipe fail, please reference to USB_HostOpenPipe.
514  */
USB_HostCdcSetControlInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)515 usb_status_t USB_HostCdcSetControlInterface(usb_host_class_handle classHandle,
516                                             usb_host_interface_handle interfaceHandle,
517                                             uint8_t alternateSetting,
518                                             transfer_callback_t callbackFn,
519                                             void *callbackParam)
520 {
521     usb_status_t status;
522     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
523     usb_host_transfer_t *transfer;
524 
525     status = kStatus_USB_Success;
526     if (classHandle == NULL)
527     {
528         return kStatus_USB_InvalidParameter;
529     }
530 
531     cdcInstance->controlInterfaceHandle = interfaceHandle;
532 
533     /* cancel transfers */
534     if (cdcInstance->interruptPipe != NULL)
535     {
536         status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL);
537 
538         if (status != kStatus_USB_Success)
539         {
540 #ifdef HOST_ECHO
541             usb_echo("error when cancel pipe\r\n");
542 #endif
543         }
544     }
545 
546     if (alternateSetting == 0U)
547     {
548         if (callbackFn != NULL)
549         {
550             status = USB_HostCdcOpenControlInterface(cdcInstance);
551             callbackFn(callbackParam, NULL, 0U, status);
552         }
553     }
554     else
555     {
556         if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
557         {
558 #ifdef HOST_ECHO
559             usb_echo("error to get transfer\r\n");
560 #endif
561             return kStatus_USB_Error;
562         }
563         cdcInstance->controlCallbackFn    = callbackFn;
564         cdcInstance->controlCallbackParam = callbackParam;
565         /* initialize transfer */
566         transfer->callbackFn                 = USB_HostCdcSetContorlInterfaceCallback;
567         transfer->callbackParam              = cdcInstance;
568         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
569         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
570         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
571             ((usb_host_interface_t *)cdcInstance->controlInterfaceHandle)->interfaceDesc->bInterfaceNumber);
572         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
573         transfer->setupPacket->wLength = 0;
574         transfer->transferBuffer       = NULL;
575         transfer->transferLength       = 0;
576         status                         = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer);
577 
578         if (status == kStatus_USB_Success)
579         {
580             cdcInstance->controlTransfer = transfer;
581         }
582         else
583         {
584             (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
585         }
586     }
587 
588     return status;
589 }
590 
591 /*!
592  * @brief set data interface.
593  *
594  * This function bind the control interface with the cdc instance.
595  *
596  * @param classHandle      the class handle.
597  * @param interfaceHandle  the data interface handle.
598  * @param alternateSetting the alternate setting value.
599  * @param callbackFn       this callback is called after this function completes.
600  * @param callbackParam    the first parameter in the callback function.
601  *
602  * @retval kStatus_USB_Success        The device is initialized successfully.
603  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
604  * @retval kStatus_USB_Busy           There is no idle transfer.
605  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
606  * @retval kStatus_USB_Busy           callback return status, there is no idle pipe.
607  * @retval kStatus_USB_TransferStall  callback return status, the transfer is stall by device.
608  * @retval kStatus_USB_Error          callback return status, open pipe fail, please reference to USB_HostOpenPipe.
609  */
USB_HostCdcSetDataInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)610 usb_status_t USB_HostCdcSetDataInterface(usb_host_class_handle classHandle,
611                                          usb_host_interface_handle interfaceHandle,
612                                          uint8_t alternateSetting,
613                                          transfer_callback_t callbackFn,
614                                          void *callbackParam)
615 {
616     usb_status_t status;
617     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
618     usb_host_transfer_t *transfer;
619 
620     status = kStatus_USB_Success;
621     if (classHandle == NULL)
622     {
623         return kStatus_USB_InvalidParameter;
624     }
625 
626     cdcInstance->dataInterfaceHandle = interfaceHandle;
627 
628     /* cancel transfers */
629     if (cdcInstance->inPipe != NULL)
630     {
631         status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->inPipe, NULL);
632 
633         if (status != kStatus_USB_Success)
634         {
635 #ifdef HOST_ECHO
636             usb_echo("error when cancel pipe\r\n");
637 #endif
638         }
639     }
640 
641     if (cdcInstance->outPipe != NULL)
642     {
643         status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->outPipe, NULL);
644 
645         if (status != kStatus_USB_Success)
646         {
647 #ifdef HOST_ECHO
648             usb_echo("error when cancel pipe\r\n");
649 #endif
650         }
651     }
652 
653     if (alternateSetting == 0U)
654     {
655         if (callbackFn != NULL)
656         {
657             status = USB_HostCdcOpenDataInterface(cdcInstance);
658             callbackFn(callbackParam, NULL, 0, status);
659         }
660     }
661     else
662     {
663         if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
664         {
665 #ifdef HOST_ECHO
666             usb_echo("error to get transfer\r\n");
667 #endif
668             return kStatus_USB_Error;
669         }
670         cdcInstance->controlCallbackFn    = callbackFn;
671         cdcInstance->controlCallbackParam = callbackParam;
672         /* initialize transfer */
673         transfer->callbackFn                 = USB_HostCdcSetDataInterfaceCallback;
674         transfer->callbackParam              = cdcInstance;
675         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
676         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
677         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
678             ((usb_host_interface_t *)cdcInstance->dataInterfaceHandle)->interfaceDesc->bInterfaceNumber);
679         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
680         transfer->setupPacket->wLength = 0;
681         transfer->transferBuffer       = NULL;
682         transfer->transferLength       = 0;
683         status                         = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer);
684 
685         if (status == kStatus_USB_Success)
686         {
687             cdcInstance->controlTransfer = transfer;
688         }
689         else
690         {
691             (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
692         }
693     }
694 
695     return status;
696 }
697 
698 /*!
699  * @brief de-initialize the cdc instance.
700  *
701  * This function release the resource for cdc instance.
702  *
703  * @param deviceHandle   the device handle.
704  * @param classHandle    the class handle.
705  *
706  * @retval kStatus_USB_Success        The device is de-initialized successfully.
707  */
USB_HostCdcDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)708 usb_status_t USB_HostCdcDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
709 {
710     usb_status_t status                         = kStatus_USB_Error;
711     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
712 
713     if (deviceHandle == NULL)
714     {
715         return kStatus_USB_InvalidHandle;
716     }
717 
718     if (classHandle != NULL)
719     {
720         if (cdcInstance->interruptPipe != NULL)
721         {
722             status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL);
723             if (status != kStatus_USB_Success)
724             {
725 #ifdef HOST_ECHO
726                 usb_echo("error when Cancel pipe\r\n");
727 #endif
728             }
729             status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->interruptPipe);
730 
731             if (status != kStatus_USB_Success)
732             {
733 #ifdef HOST_ECHO
734                 usb_echo("error when close pipe\r\n");
735 #endif
736             }
737             cdcInstance->interruptPipe = NULL;
738         }
739 
740         (void)USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->controlInterfaceHandle);
741 
742         if (cdcInstance->inPipe != NULL)
743         {
744             status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->inPipe, NULL);
745             if (status != kStatus_USB_Success)
746             {
747 #ifdef HOST_ECHO
748                 usb_echo("error when Cancel pipe\r\n");
749 #endif
750             }
751             status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->inPipe);
752 
753             if (status != kStatus_USB_Success)
754             {
755 #ifdef HOST_ECHO
756                 usb_echo("error when close pipe\r\n");
757 #endif
758             }
759             cdcInstance->inPipe = NULL;
760         }
761         if (cdcInstance->outPipe != NULL)
762         {
763             status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->outPipe, NULL);
764             if (status != kStatus_USB_Success)
765             {
766 #ifdef HOST_ECHO
767                 usb_echo("error when Cancel pipe\r\n");
768 #endif
769             }
770             status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->outPipe);
771 
772             if (status != kStatus_USB_Success)
773             {
774 #ifdef HOST_ECHO
775                 usb_echo("error when close pipe\r\n");
776 #endif
777             }
778             cdcInstance->outPipe = NULL;
779         }
780         if ((cdcInstance->controlPipe != NULL) && (cdcInstance->controlTransfer != NULL))
781         {
782             status =
783                 USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->controlPipe, cdcInstance->controlTransfer);
784         }
785         (void)USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->dataInterfaceHandle);
786 
787         OSA_MemoryFree(cdcInstance);
788     }
789     else
790     {
791         (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
792         /*add for misra*/
793         status = kStatus_USB_Success;
794     }
795 
796     return status;
797 }
798 
799 /*!
800  * @brief receive data.
801  *
802  * This function implements cdc receiving data.
803  *
804  * @param classHandle    the class handle.
805  * @param buffer         the buffer pointer.
806  * @param bufferLength   the buffer length.
807  * @param callbackFn     this callback is called after this function completes.
808  * @param callbackParam  the first parameter in the callback function.
809  *
810  * @retval kStatus_USB_Success        receive request successfully.
811  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
812  * @retval kStatus_USB_Busy           There is no idle transfer.
813  * @retval kStatus_USB_Error          pipe is not initialized.
814  *                                    Or, send transfer fail, please reference to USB_HostRecv.
815  */
USB_HostCdcDataRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)816 usb_status_t USB_HostCdcDataRecv(usb_host_class_handle classHandle,
817                                  uint8_t *buffer,
818                                  uint32_t bufferLength,
819                                  transfer_callback_t callbackFn,
820                                  void *callbackParam)
821 {
822     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
823     usb_host_transfer_t *transfer;
824 
825     if (classHandle == NULL)
826     {
827         return kStatus_USB_InvalidHandle;
828     }
829 
830     if (cdcInstance->inPipe == NULL)
831     {
832         return kStatus_USB_Error;
833     }
834 
835     if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
836     {
837 #ifdef HOST_ECHO
838         usb_echo("error to get transfer\r\n");
839 #endif
840         return kStatus_USB_Error;
841     }
842     cdcInstance->inCallbackFn    = callbackFn;
843     cdcInstance->inCallbackParam = callbackParam;
844     transfer->transferBuffer     = buffer;
845     transfer->transferLength     = bufferLength;
846     transfer->callbackFn         = USB_HostCdcDataInPipeCallback;
847     transfer->callbackParam      = cdcInstance;
848 
849     if (USB_HostRecv(cdcInstance->hostHandle, cdcInstance->inPipe, transfer) != kStatus_USB_Success)
850     {
851 #ifdef HOST_ECHO
852         usb_echo("failed to USB_HostRecv\r\n");
853 #endif
854         (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
855         return kStatus_USB_Error;
856     }
857 
858     return kStatus_USB_Success;
859 }
860 
861 /*!
862  * @brief send data.
863  *
864  * This function implements cdc sending data.
865  *
866  * @param classHandle    the class handle.
867  * @param buffer         the buffer pointer.
868  * @param bufferLength   the buffer length.
869  * @param callbackFn     this callback is called after this function completes.
870  * @param callbackParam  the first parameter in the callback function.
871  *
872  * @retval kStatus_USB_Success          receive request successfully.
873  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
874  * @retval kStatus_USB_Busy             There is no idle transfer.
875  * @retval kStatus_USB_Error            pipe is not initialized.
876  *                                    Or, send transfer fail, please reference to USB_HostSend.
877  */
USB_HostCdcDataSend(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)878 usb_status_t USB_HostCdcDataSend(usb_host_class_handle classHandle,
879                                  uint8_t *buffer,
880                                  uint32_t bufferLength,
881                                  transfer_callback_t callbackFn,
882                                  void *callbackParam)
883 {
884     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
885     usb_host_transfer_t *transfer;
886 
887     if (classHandle == NULL)
888     {
889         return kStatus_USB_InvalidHandle;
890     }
891 
892     if (cdcInstance->outPipe == NULL)
893     {
894         return kStatus_USB_Error;
895     }
896 
897     if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
898     {
899 #ifdef HOST_ECHO
900         usb_echo("error to get transfer\r\n");
901 #endif
902         return kStatus_USB_Error;
903     }
904     cdcInstance->outCallbackFn    = callbackFn;
905     cdcInstance->outCallbackParam = callbackParam;
906     transfer->transferBuffer      = buffer;
907     transfer->transferLength      = bufferLength;
908     transfer->callbackFn          = USB_HostCdcDataOutPipeCallback;
909     transfer->callbackParam       = cdcInstance;
910 
911     if (USB_HostSend(cdcInstance->hostHandle, cdcInstance->outPipe, transfer) != kStatus_USB_Success)
912     {
913 #ifdef HOST_ECHO
914         usb_echo("failed to USB_HostSend\r\n");
915 #endif
916         (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
917         return kStatus_USB_Error;
918     }
919     return kStatus_USB_Success;
920 }
921 
922 /*!
923  * @brief interrupt receive data.
924  *
925  * This function implements interrupt receiving data.
926  *
927  * @param classHandle     the class handle.
928  * @param buffer          the buffer pointer.
929  * @param bufferLength    the buffer length.
930  * @param callbackFn      this callback is called after this function completes.
931  * @param callbackParam   the first parameter in the callback function.
932  *
933  * @retval kStatus_USB_Success         receive request successfully.
934  * @retval kStatus_USB_InvalidHandle   The classHandle is NULL pointer.
935  * @retval kStatus_USB_Busy            There is no idle transfer.
936  * @retval kStatus_USB_Error           pipe is not initialized.
937  *                                    Or, send transfer fail, please reference to USB_HostRecv.
938  */
USB_HostCdcInterruptRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)939 usb_status_t USB_HostCdcInterruptRecv(usb_host_class_handle classHandle,
940                                       uint8_t *buffer,
941                                       uint32_t bufferLength,
942                                       transfer_callback_t callbackFn,
943                                       void *callbackParam)
944 {
945     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
946     usb_host_transfer_t *transfer;
947 
948     if (classHandle == NULL)
949     {
950         return kStatus_USB_InvalidHandle;
951     }
952 
953     if (cdcInstance->interruptPipe == NULL)
954     {
955         return kStatus_USB_Error;
956     }
957 
958     if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
959     {
960 #ifdef HOST_ECHO
961         usb_echo("error to get transfer\r\n");
962 #endif
963         return kStatus_USB_Error;
964     }
965     cdcInstance->interruptCallbackFn    = callbackFn;
966     cdcInstance->interruptCallbackParam = callbackParam;
967     transfer->transferBuffer            = buffer;
968     transfer->transferLength            = bufferLength;
969     transfer->callbackFn                = USB_HostCdcInterruptPipeCallback;
970     transfer->callbackParam             = cdcInstance;
971 
972     if (USB_HostRecv(cdcInstance->hostHandle, cdcInstance->interruptPipe, transfer) != kStatus_USB_Success)
973     {
974 #ifdef HOST_ECHO
975         usb_echo("failed to usb_interrupt_recv\r\n");
976 #endif
977         (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
978         return kStatus_USB_Error;
979     }
980     return kStatus_USB_Success;
981 }
982 /*!
983  * @brief get pipe max packet size.
984  *
985  * @param[in] classHandle the class handle.
986  * @param[in] pipeType    It's value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
987  * USB_ENDPOINT_INTERRUPT.
988  *                        Please reference to usb_spec.h
989  * @param[in] direction   pipe direction.
990  *
991  * @retval 0        The classHandle is NULL.
992  * @retval max packet size.
993  */
USB_HostCdcGetPacketsize(usb_host_class_handle classHandle,uint8_t pipeType,uint8_t direction)994 uint16_t USB_HostCdcGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
995 {
996     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
997     if (classHandle == NULL)
998     {
999         return 0;
1000     }
1001 
1002     if (pipeType == USB_ENDPOINT_BULK)
1003     {
1004         if (direction == USB_IN)
1005         {
1006             return cdcInstance->bulkInPacketSize;
1007         }
1008         else
1009         {
1010             return cdcInstance->bulkOutPacketSize;
1011         }
1012     }
1013 
1014     return 0;
1015 }
1016 
1017 /*!
1018  * @brief cdc send control transfer common code.
1019  *
1020  * @param classHandle    the class handle.
1021  * @param request_type   setup packet request type.
1022  * @param request        setup packet request value.
1023  * @param wvalue_l       setup packet wvalue low byte.
1024  * @param wvalue_h       setup packet wvalue high byte.
1025  * @param wlength        setup packet wlength value.
1026  * @param data           data buffer pointer
1027  * @param callbackFn     this callback is called after this function completes.
1028  * @param callbackParam  the first parameter in the callback function.
1029  *
1030  * @return An error code or kStatus_USB_Success.
1031  */
USB_HostCdcControl(usb_host_class_handle classHandle,uint8_t request_type,uint8_t request,uint8_t wvalue_l,uint8_t wvalue_h,uint16_t wlength,uint8_t * data,transfer_callback_t callbackFn,void * callbackParam)1032 usb_status_t USB_HostCdcControl(usb_host_class_handle classHandle,
1033                                 uint8_t request_type,
1034                                 uint8_t request,
1035                                 uint8_t wvalue_l,
1036                                 uint8_t wvalue_h,
1037                                 uint16_t wlength,
1038                                 uint8_t *data,
1039                                 transfer_callback_t callbackFn,
1040                                 void *callbackParam)
1041 {
1042     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1043     usb_host_transfer_t *transfer;
1044 
1045     if (classHandle == NULL)
1046     {
1047         return kStatus_USB_InvalidHandle;
1048     }
1049 
1050     if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
1051     {
1052 #ifdef HOST_ECHO
1053         usb_echo("error to get transfer\r\n");
1054 #endif
1055         return kStatus_USB_Error;
1056     }
1057     cdcInstance->controlCallbackFn    = callbackFn;
1058     cdcInstance->controlCallbackParam = callbackParam;
1059 
1060     transfer->transferBuffer             = data;
1061     transfer->transferLength             = wlength;
1062     transfer->callbackFn                 = USB_HostCdcControlPipeCallback;
1063     transfer->callbackParam              = cdcInstance;
1064     transfer->setupPacket->bmRequestType = request_type;
1065     transfer->setupPacket->bRequest      = request;
1066     transfer->setupPacket->wValue        = USB_SHORT_TO_LITTLE_ENDIAN(wvalue_l | (uint16_t)((uint16_t)wvalue_h << 8));
1067     transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
1068         ((usb_host_interface_t *)cdcInstance->controlInterfaceHandle)->interfaceDesc->bInterfaceNumber);
1069     transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
1070 
1071     if (USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer) != kStatus_USB_Success)
1072     {
1073 #ifdef HOST_ECHO
1074         usb_echo("failed for USB_HostSendSetup\r\n");
1075 #endif
1076         (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
1077         return kStatus_USB_Error;
1078     }
1079     cdcInstance->controlTransfer = transfer;
1080 
1081     return kStatus_USB_Success;
1082 }
1083 
1084 /*!
1085  * @brief cdc get line coding.
1086  *
1087  * This function implements cdc GetLineCoding request.refer to pstn spec.
1088  *
1089  * @param classHandle    the class handle.
1090  * @param buffer         the buffer pointer.
1091  * @param bufferLength   the buffer length.
1092  * @param callbackFn     this callback is called after this function completes.
1093  * @param callbackParam  the first parameter in the callback function.
1094  *
1095  * @retval kStatus_USB_Success        request successfully.
1096  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1097  * @retval kStatus_USB_Busy           There is no idle transfer.
1098  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
1099  */
USB_HostCdcGetAcmLineCoding(usb_host_class_handle classHandle,usb_host_cdc_line_coding_struct_t * uartLineCoding,transfer_callback_t callbackFn,void * callbackParam)1100 usb_status_t USB_HostCdcGetAcmLineCoding(usb_host_class_handle classHandle,
1101                                          usb_host_cdc_line_coding_struct_t *uartLineCoding,
1102                                          transfer_callback_t callbackFn,
1103                                          void *callbackParam)
1104 {
1105     return USB_HostCdcControl(
1106         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1107         USB_HOST_CDC_GET_LINE_CODING, 0, 0, 7, (uint8_t *)uartLineCoding, callbackFn, callbackParam);
1108 }
1109 
1110 /*!
1111  * @brief cdc set line coding.
1112  *
1113  * This function implements cdc SetLineCoding request.refer to pstn spec.
1114  *
1115  * @param classHandle    the class handle.
1116  * @param buffer         the buffer pointer.
1117  * @param bufferLength   the buffer length.
1118  * @param callbackFn     this callback is called after this function completes.
1119  * @param callbackParam  the first parameter in the callback function.
1120  *
1121  * @retval kStatus_USB_Success        request successfully.
1122  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1123  * @retval kStatus_USB_Busy           There is no idle transfer.
1124  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
1125  */
USB_HostCdcSetAcmLineCoding(usb_host_class_handle classHandle,usb_host_cdc_line_coding_struct_t * uartLineCoding,transfer_callback_t callbackFn,void * callbackParam)1126 usb_status_t USB_HostCdcSetAcmLineCoding(usb_host_class_handle classHandle,
1127                                          usb_host_cdc_line_coding_struct_t *uartLineCoding,
1128                                          transfer_callback_t callbackFn,
1129                                          void *callbackParam)
1130 {
1131     return USB_HostCdcControl(
1132         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1133         USB_HOST_CDC_SET_LINE_CODING, 0, 0, 7, (uint8_t *)uartLineCoding, callbackFn, callbackParam);
1134 }
1135 
1136 /*!
1137  * @brief cdc setControlLineState.
1138  *
1139  * This function implements cdc etControlLineState request.refer to pstn spec.
1140  *
1141  * @param classHandle   the class handle.
1142  * @param buffer        the buffer pointer.
1143  * @param bufferLength  the buffer length.
1144  * @param callbackFn    this callback is called after this function completes.
1145  * @param callbackParam the first parameter in the callback function.
1146  *
1147  * @retval kStatus_USB_Success        request successfully.
1148  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1149  * @retval kStatus_USB_Busy           There is no idle transfer.
1150  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
1151  */
USB_HostCdcSetAcmCtrlState(usb_host_class_handle classHandle,uint8_t dtr,uint8_t rts,transfer_callback_t callbackFn,void * callbackParam)1152 usb_status_t USB_HostCdcSetAcmCtrlState(
1153     usb_host_class_handle classHandle, uint8_t dtr, uint8_t rts, transfer_callback_t callbackFn, void *callbackParam)
1154 {
1155     uint16_t lineState = 0U;
1156 
1157     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1158 
1159     lineState = (0U != dtr) ? USB_HOST_CDC_CONTROL_LINE_STATE_DTR : 0U;
1160     lineState |= (0U != rts) ? USB_HOST_CDC_CONTROL_LINE_STATE_RTS : 0U;
1161     return USB_HostCdcControl(
1162         cdcInstance, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1163         USB_HOST_CDC_SET_CONTROL_LINE_STATE, (uint8_t)USB_SHORT_GET_LOW(lineState), USB_SHORT_GET_HIGH(lineState), 0U,
1164         NULL, callbackFn, callbackParam);
1165 }
1166 
1167 /*!
1168  * @brief cdc send encapsulated command.
1169  *
1170  * This function implements cdc SEND_ENCAPSULATED_COMMAND request.refer to cdc 1.2 spec.
1171  *
1172  * @param classHandle    the class handle.
1173  * @param buffer         the buffer pointer.
1174  * @param bufferLength   the buffer length.
1175  * @param callbackFn     this callback is called after this function completes.
1176  * @param callbackParam  the first parameter in the callback function.
1177  *
1178  * @retval kStatus_USB_Success        request successfully.
1179  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1180  * @retval kStatus_USB_Busy           There is no idle transfer.
1181  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
1182  */
USB_HostCdcSendEncapsulatedCommand(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)1183 usb_status_t USB_HostCdcSendEncapsulatedCommand(usb_host_class_handle classHandle,
1184                                                 uint8_t *buffer,
1185                                                 uint16_t bufferLength,
1186                                                 transfer_callback_t callbackFn,
1187                                                 void *callbackParam)
1188 {
1189     return USB_HostCdcControl(
1190         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1191         USB_HOST_CDC_SEND_ENCAPSULATED_COMMAND, 0U, 0U, bufferLength, buffer, callbackFn, callbackParam);
1192 }
1193 
1194 /*!
1195  * @brief cdc get encapsulated response.
1196  *
1197  * This function implements cdc GET_ENCAPSULATED_RESPONSE request.refer to cdc 1.2 spec.
1198  *
1199  * @param classHandle    the class handle.
1200  * @param buffer         the buffer pointer.
1201  * @param bufferLength   the buffer length.
1202  * @param callbackFn     this callback is called after this function completes.
1203  * @param callbackParam  the first parameter in the callback function.
1204  *
1205  * @retval kStatus_USB_Success        request successfully.
1206  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1207  * @retval kStatus_USB_Busy           There is no idle transfer.
1208  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
1209  */
USB_HostCdcGetEncapsulatedResponse(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)1210 usb_status_t USB_HostCdcGetEncapsulatedResponse(usb_host_class_handle classHandle,
1211                                                 uint8_t *buffer,
1212                                                 uint16_t bufferLength,
1213                                                 transfer_callback_t callbackFn,
1214                                                 void *callbackParam)
1215 {
1216     return USB_HostCdcControl(
1217         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1218         USB_HOST_CDC_GET_ENCAPSULATED_RESPONSE, 0, 0, bufferLength, buffer, callbackFn, callbackParam);
1219 }
1220 
1221 /*!
1222  * @brief cdc get acm descriptor.
1223  *
1224  * This function is hunting for class specific acm decriptor in the configuration ,get the corresponding
1225  * descriptor .
1226  *
1227  * @param classHandle          the class handle.
1228  * @param headDesc             the head function descriptor pointer.
1229  * @param callManageDesc       the call management functional descriptor pointer.
1230  * @param abstractControlDesc  the abstract control management functional pointer.
1231  * @param unionInterfaceDesc   the union functional descriptor pointer.
1232  *
1233  * @retval kStatus_USB_Error          analyse descriptor error.
1234  */
USB_HostCdcGetAcmDescriptor(usb_host_class_handle classHandle,usb_host_cdc_head_function_desc_struct_t ** headDesc,usb_host_cdc_call_manage_desc_struct_t ** callManageDesc,usb_host_cdc_abstract_control_desc_struct_t ** abstractControlDesc,usb_host_cdc_union_interface_desc_struct_t ** unionInterfaceDesc)1235 usb_status_t USB_HostCdcGetAcmDescriptor(usb_host_class_handle classHandle,
1236                                          usb_host_cdc_head_function_desc_struct_t **headDesc,
1237                                          usb_host_cdc_call_manage_desc_struct_t **callManageDesc,
1238                                          usb_host_cdc_abstract_control_desc_struct_t **abstractControlDesc,
1239                                          usb_host_cdc_union_interface_desc_struct_t **unionInterfaceDesc)
1240 {
1241     usb_status_t status;
1242     usb_descriptor_union_t *ptr1;
1243     uint32_t end_address;
1244     usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1245     usb_cdc_func_desc_struct_t *cdc_common_ptr;
1246     usb_host_interface_t *interface_handle;
1247     void *temp;
1248 
1249     status           = kStatus_USB_Success;
1250     interface_handle = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle;
1251     temp             = (void *)interface_handle->interfaceExtension;
1252     ptr1             = (usb_descriptor_union_t *)temp;
1253     end_address      = (uint32_t)(interface_handle->interfaceExtension + interface_handle->interfaceExtensionLength);
1254 
1255     while ((uint32_t)ptr1 < end_address)
1256     {
1257         temp           = (void *)&ptr1->common;
1258         cdc_common_ptr = (usb_cdc_func_desc_struct_t *)temp;
1259         switch (cdc_common_ptr->common.bDescriptorSubtype)
1260         {
1261             case USB_HOST_DESC_SUBTYPE_HEADER:
1262                 *headDesc = &cdc_common_ptr->head;
1263                 if ((((uint32_t)((*headDesc)->bcdCDC[1U]) << 8U) + (*headDesc)->bcdCDC[0U]) > 0x0110U)
1264                 {
1265                     status = kStatus_USB_Error;
1266                 }
1267                 break;
1268             case USB_HOST_DESC_SUBTYPE_UNION:
1269                 if (cdc_common_ptr->unionDesc.bControlInterface == interface_handle->interfaceDesc->bInterfaceNumber)
1270                 {
1271                     *unionInterfaceDesc = &cdc_common_ptr->unionDesc;
1272                 }
1273                 else
1274                 {
1275                     status = kStatus_USB_Error;
1276                 }
1277                 break;
1278             case USB_HOST_DESC_SUBTYPE_CM:
1279                 *callManageDesc = &cdc_common_ptr->callManage;
1280                 break;
1281             case USB_HOST_DESC_SUBTYPE_ACM:
1282                 *abstractControlDesc = &cdc_common_ptr->acm;
1283                 break;
1284             default:
1285                 /*no action*/
1286                 break;
1287         }
1288 
1289         if (kStatus_USB_Success != status)
1290         {
1291             break;
1292         }
1293         temp = (void *)((uint8_t *)ptr1 + ptr1->common.bLength);
1294         ptr1 = (usb_descriptor_union_t *)temp;
1295     }
1296     cdcInstance->headDesc            = *headDesc;
1297     cdcInstance->callManageDesc      = *callManageDesc;
1298     cdcInstance->abstractControlDesc = *abstractControlDesc;
1299     cdcInstance->unionInterfaceDesc  = *unionInterfaceDesc;
1300     return status;
1301 }
1302 
1303 #endif
1304