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