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 defined(USB_HOST_CONFIG_CDC_ECM) && USB_HOST_CONFIG_CDC_ECM
654 usb_host_interface_t *ifPointer = (usb_host_interface_t *)interfaceHandle;
655 usb_descriptor_union_t *ifBuffer = (usb_descriptor_union_t *)(ifPointer->interfaceExtension);
656 uint32_t extIndex = 0;
657
658 for (; extIndex < ifPointer->interfaceExtensionLength;
659 extIndex += ifBuffer->common.bLength,
660 ifBuffer = (usb_descriptor_union_t *)((uint8_t *)ifBuffer + ifBuffer->common.bLength))
661 {
662 if (ifBuffer->common.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE &&
663 ifBuffer->interface.bAlternateSetting == alternateSetting)
664 {
665 ifPointer->epCount = ifBuffer->interface.bNumEndpoints;
666 break;
667 }
668 }
669
670 for (uint32_t epIndex = 0; epIndex < ifPointer->epCount && extIndex < ifPointer->interfaceExtensionLength;
671 extIndex += ifBuffer->common.bLength,
672 ifBuffer = (usb_descriptor_union_t *)((uint8_t *)ifBuffer + ifBuffer->common.bLength))
673 {
674 if (ifBuffer->common.bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT)
675 {
676 ifPointer->epList[epIndex].epDesc = (usb_descriptor_endpoint_t *)ifBuffer;
677 epIndex++;
678 }
679 }
680 #endif
681
682 if (alternateSetting == 0U)
683 {
684 if (callbackFn != NULL)
685 {
686 status = USB_HostCdcOpenDataInterface(cdcInstance);
687 callbackFn(callbackParam, NULL, 0, status);
688 }
689 }
690 else
691 {
692 if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
693 {
694 #ifdef HOST_ECHO
695 usb_echo("error to get transfer\r\n");
696 #endif
697 return kStatus_USB_Error;
698 }
699 cdcInstance->controlCallbackFn = callbackFn;
700 cdcInstance->controlCallbackParam = callbackParam;
701 /* initialize transfer */
702 transfer->callbackFn = USB_HostCdcSetDataInterfaceCallback;
703 transfer->callbackParam = cdcInstance;
704 transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_INTERFACE;
705 transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
706 transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(
707 ((usb_host_interface_t *)cdcInstance->dataInterfaceHandle)->interfaceDesc->bInterfaceNumber);
708 transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
709 transfer->setupPacket->wLength = 0;
710 transfer->transferBuffer = NULL;
711 transfer->transferLength = 0;
712 status = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer);
713
714 if (status == kStatus_USB_Success)
715 {
716 cdcInstance->controlTransfer = transfer;
717 }
718 else
719 {
720 (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
721 }
722 }
723
724 return status;
725 }
726
727 /*!
728 * @brief de-initialize the cdc instance.
729 *
730 * This function release the resource for cdc instance.
731 *
732 * @param deviceHandle the device handle.
733 * @param classHandle the class handle.
734 *
735 * @retval kStatus_USB_Success The device is de-initialized successfully.
736 */
USB_HostCdcDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)737 usb_status_t USB_HostCdcDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
738 {
739 usb_status_t status = kStatus_USB_Error;
740 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
741
742 if (deviceHandle == NULL)
743 {
744 return kStatus_USB_InvalidHandle;
745 }
746
747 if (classHandle != NULL)
748 {
749 if (cdcInstance->interruptPipe != NULL)
750 {
751 status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL);
752 if (status != kStatus_USB_Success)
753 {
754 #ifdef HOST_ECHO
755 usb_echo("error when Cancel pipe\r\n");
756 #endif
757 }
758 status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->interruptPipe);
759
760 if (status != kStatus_USB_Success)
761 {
762 #ifdef HOST_ECHO
763 usb_echo("error when close pipe\r\n");
764 #endif
765 }
766 cdcInstance->interruptPipe = NULL;
767 }
768
769 (void)USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->controlInterfaceHandle);
770
771 if (cdcInstance->inPipe != NULL)
772 {
773 status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->inPipe, NULL);
774 if (status != kStatus_USB_Success)
775 {
776 #ifdef HOST_ECHO
777 usb_echo("error when Cancel pipe\r\n");
778 #endif
779 }
780 status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->inPipe);
781
782 if (status != kStatus_USB_Success)
783 {
784 #ifdef HOST_ECHO
785 usb_echo("error when close pipe\r\n");
786 #endif
787 }
788 cdcInstance->inPipe = NULL;
789 }
790 if (cdcInstance->outPipe != NULL)
791 {
792 status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->outPipe, NULL);
793 if (status != kStatus_USB_Success)
794 {
795 #ifdef HOST_ECHO
796 usb_echo("error when Cancel pipe\r\n");
797 #endif
798 }
799 status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->outPipe);
800
801 if (status != kStatus_USB_Success)
802 {
803 #ifdef HOST_ECHO
804 usb_echo("error when close pipe\r\n");
805 #endif
806 }
807 cdcInstance->outPipe = NULL;
808 }
809 if ((cdcInstance->controlPipe != NULL) && (cdcInstance->controlTransfer != NULL))
810 {
811 status =
812 USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->controlPipe, cdcInstance->controlTransfer);
813 }
814 (void)USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->dataInterfaceHandle);
815
816 OSA_MemoryFree(cdcInstance);
817 }
818 else
819 {
820 (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
821 /*add for misra*/
822 status = kStatus_USB_Success;
823 }
824
825 return status;
826 }
827
828 /*!
829 * @brief receive data.
830 *
831 * This function implements cdc receiving data.
832 *
833 * @param classHandle the class handle.
834 * @param buffer the buffer pointer.
835 * @param bufferLength the buffer length.
836 * @param callbackFn this callback is called after this function completes.
837 * @param callbackParam the first parameter in the callback function.
838 *
839 * @retval kStatus_USB_Success receive request successfully.
840 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
841 * @retval kStatus_USB_Busy There is no idle transfer.
842 * @retval kStatus_USB_Error pipe is not initialized.
843 * Or, send transfer fail, please reference to USB_HostRecv.
844 */
USB_HostCdcDataRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)845 usb_status_t USB_HostCdcDataRecv(usb_host_class_handle classHandle,
846 uint8_t *buffer,
847 uint32_t bufferLength,
848 transfer_callback_t callbackFn,
849 void *callbackParam)
850 {
851 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
852 usb_host_transfer_t *transfer;
853
854 if (classHandle == NULL)
855 {
856 return kStatus_USB_InvalidHandle;
857 }
858
859 if (cdcInstance->inPipe == NULL)
860 {
861 return kStatus_USB_Error;
862 }
863
864 if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
865 {
866 #ifdef HOST_ECHO
867 usb_echo("error to get transfer\r\n");
868 #endif
869 return kStatus_USB_Error;
870 }
871 cdcInstance->inCallbackFn = callbackFn;
872 cdcInstance->inCallbackParam = callbackParam;
873 transfer->transferBuffer = buffer;
874 transfer->transferLength = bufferLength;
875 transfer->callbackFn = USB_HostCdcDataInPipeCallback;
876 transfer->callbackParam = cdcInstance;
877
878 if (USB_HostRecv(cdcInstance->hostHandle, cdcInstance->inPipe, transfer) != kStatus_USB_Success)
879 {
880 #ifdef HOST_ECHO
881 usb_echo("failed to USB_HostRecv\r\n");
882 #endif
883 (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
884 return kStatus_USB_Error;
885 }
886
887 return kStatus_USB_Success;
888 }
889
890 /*!
891 * @brief send data.
892 *
893 * This function implements cdc sending data.
894 *
895 * @param classHandle the class handle.
896 * @param buffer the buffer pointer.
897 * @param bufferLength the buffer length.
898 * @param callbackFn this callback is called after this function completes.
899 * @param callbackParam the first parameter in the callback function.
900 *
901 * @retval kStatus_USB_Success receive request successfully.
902 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
903 * @retval kStatus_USB_Busy There is no idle transfer.
904 * @retval kStatus_USB_Error pipe is not initialized.
905 * Or, send transfer fail, please reference to USB_HostSend.
906 */
USB_HostCdcDataSend(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)907 usb_status_t USB_HostCdcDataSend(usb_host_class_handle classHandle,
908 uint8_t *buffer,
909 uint32_t bufferLength,
910 transfer_callback_t callbackFn,
911 void *callbackParam)
912 {
913 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
914 usb_host_transfer_t *transfer;
915
916 if (classHandle == NULL)
917 {
918 return kStatus_USB_InvalidHandle;
919 }
920
921 if (cdcInstance->outPipe == NULL)
922 {
923 return kStatus_USB_Error;
924 }
925
926 if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
927 {
928 #ifdef HOST_ECHO
929 usb_echo("error to get transfer\r\n");
930 #endif
931 return kStatus_USB_Error;
932 }
933 cdcInstance->outCallbackFn = callbackFn;
934 cdcInstance->outCallbackParam = callbackParam;
935 transfer->transferBuffer = buffer;
936 transfer->transferLength = bufferLength;
937 transfer->callbackFn = USB_HostCdcDataOutPipeCallback;
938 transfer->callbackParam = cdcInstance;
939
940 if (USB_HostSend(cdcInstance->hostHandle, cdcInstance->outPipe, transfer) != kStatus_USB_Success)
941 {
942 #ifdef HOST_ECHO
943 usb_echo("failed to USB_HostSend\r\n");
944 #endif
945 (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
946 return kStatus_USB_Error;
947 }
948 return kStatus_USB_Success;
949 }
950
951 /*!
952 * @brief interrupt receive data.
953 *
954 * This function implements interrupt receiving data.
955 *
956 * @param classHandle the class handle.
957 * @param buffer the buffer pointer.
958 * @param bufferLength the buffer length.
959 * @param callbackFn this callback is called after this function completes.
960 * @param callbackParam the first parameter in the callback function.
961 *
962 * @retval kStatus_USB_Success receive request successfully.
963 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
964 * @retval kStatus_USB_Busy There is no idle transfer.
965 * @retval kStatus_USB_Error pipe is not initialized.
966 * Or, send transfer fail, please reference to USB_HostRecv.
967 */
USB_HostCdcInterruptRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)968 usb_status_t USB_HostCdcInterruptRecv(usb_host_class_handle classHandle,
969 uint8_t *buffer,
970 uint32_t bufferLength,
971 transfer_callback_t callbackFn,
972 void *callbackParam)
973 {
974 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
975 usb_host_transfer_t *transfer;
976
977 if (classHandle == NULL)
978 {
979 return kStatus_USB_InvalidHandle;
980 }
981
982 if (cdcInstance->interruptPipe == NULL)
983 {
984 return kStatus_USB_Error;
985 }
986
987 if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
988 {
989 #ifdef HOST_ECHO
990 usb_echo("error to get transfer\r\n");
991 #endif
992 return kStatus_USB_Error;
993 }
994 cdcInstance->interruptCallbackFn = callbackFn;
995 cdcInstance->interruptCallbackParam = callbackParam;
996 transfer->transferBuffer = buffer;
997 transfer->transferLength = bufferLength;
998 transfer->callbackFn = USB_HostCdcInterruptPipeCallback;
999 transfer->callbackParam = cdcInstance;
1000
1001 if (USB_HostRecv(cdcInstance->hostHandle, cdcInstance->interruptPipe, transfer) != kStatus_USB_Success)
1002 {
1003 #ifdef HOST_ECHO
1004 usb_echo("failed to usb_interrupt_recv\r\n");
1005 #endif
1006 (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
1007 return kStatus_USB_Error;
1008 }
1009 return kStatus_USB_Success;
1010 }
1011 /*!
1012 * @brief get pipe max packet size.
1013 *
1014 * @param[in] classHandle the class handle.
1015 * @param[in] pipeType It's value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
1016 * USB_ENDPOINT_INTERRUPT.
1017 * Please reference to usb_spec.h
1018 * @param[in] direction pipe direction.
1019 *
1020 * @retval 0 The classHandle is NULL.
1021 * @retval max packet size.
1022 */
USB_HostCdcGetPacketsize(usb_host_class_handle classHandle,uint8_t pipeType,uint8_t direction)1023 uint16_t USB_HostCdcGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
1024 {
1025 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1026 if (classHandle == NULL)
1027 {
1028 return 0;
1029 }
1030
1031 if (pipeType == USB_ENDPOINT_BULK)
1032 {
1033 if (direction == USB_IN)
1034 {
1035 return cdcInstance->bulkInPacketSize;
1036 }
1037 else
1038 {
1039 return cdcInstance->bulkOutPacketSize;
1040 }
1041 }
1042
1043 return 0;
1044 }
1045
1046 /*!
1047 * @brief cdc send control transfer common code.
1048 *
1049 * @param classHandle the class handle.
1050 * @param request_type setup packet request type.
1051 * @param request setup packet request value.
1052 * @param wvalue_l setup packet wvalue low byte.
1053 * @param wvalue_h setup packet wvalue high byte.
1054 * @param wlength setup packet wlength value.
1055 * @param data data buffer pointer
1056 * @param callbackFn this callback is called after this function completes.
1057 * @param callbackParam the first parameter in the callback function.
1058 *
1059 * @return An error code or kStatus_USB_Success.
1060 */
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)1061 usb_status_t USB_HostCdcControl(usb_host_class_handle classHandle,
1062 uint8_t request_type,
1063 uint8_t request,
1064 uint8_t wvalue_l,
1065 uint8_t wvalue_h,
1066 uint16_t wlength,
1067 uint8_t *data,
1068 transfer_callback_t callbackFn,
1069 void *callbackParam)
1070 {
1071 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1072 usb_host_transfer_t *transfer;
1073
1074 if (classHandle == NULL)
1075 {
1076 return kStatus_USB_InvalidHandle;
1077 }
1078
1079 if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
1080 {
1081 #ifdef HOST_ECHO
1082 usb_echo("error to get transfer\r\n");
1083 #endif
1084 return kStatus_USB_Error;
1085 }
1086 cdcInstance->controlCallbackFn = callbackFn;
1087 cdcInstance->controlCallbackParam = callbackParam;
1088
1089 transfer->transferBuffer = data;
1090 transfer->transferLength = wlength;
1091 transfer->callbackFn = USB_HostCdcControlPipeCallback;
1092 transfer->callbackParam = cdcInstance;
1093 transfer->setupPacket->bmRequestType = request_type;
1094 transfer->setupPacket->bRequest = request;
1095 transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(wvalue_l | (uint16_t)((uint16_t)wvalue_h << 8));
1096 transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(
1097 ((usb_host_interface_t *)cdcInstance->controlInterfaceHandle)->interfaceDesc->bInterfaceNumber);
1098 transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
1099
1100 if (USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer) != kStatus_USB_Success)
1101 {
1102 #ifdef HOST_ECHO
1103 usb_echo("failed for USB_HostSendSetup\r\n");
1104 #endif
1105 (void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
1106 return kStatus_USB_Error;
1107 }
1108 cdcInstance->controlTransfer = transfer;
1109
1110 return kStatus_USB_Success;
1111 }
1112
1113 /*!
1114 * @brief cdc get line coding.
1115 *
1116 * This function implements cdc GetLineCoding request.refer to pstn spec.
1117 *
1118 * @param classHandle the class handle.
1119 * @param buffer the buffer pointer.
1120 * @param bufferLength the buffer length.
1121 * @param callbackFn this callback is called after this function completes.
1122 * @param callbackParam the first parameter in the callback function.
1123 *
1124 * @retval kStatus_USB_Success request successfully.
1125 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
1126 * @retval kStatus_USB_Busy There is no idle transfer.
1127 * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup.
1128 */
USB_HostCdcGetAcmLineCoding(usb_host_class_handle classHandle,usb_host_cdc_line_coding_struct_t * uartLineCoding,transfer_callback_t callbackFn,void * callbackParam)1129 usb_status_t USB_HostCdcGetAcmLineCoding(usb_host_class_handle classHandle,
1130 usb_host_cdc_line_coding_struct_t *uartLineCoding,
1131 transfer_callback_t callbackFn,
1132 void *callbackParam)
1133 {
1134 return USB_HostCdcControl(
1135 classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1136 USB_HOST_CDC_GET_LINE_CODING, 0, 0, 7, (uint8_t *)uartLineCoding, callbackFn, callbackParam);
1137 }
1138
1139 /*!
1140 * @brief cdc set line coding.
1141 *
1142 * This function implements cdc SetLineCoding request.refer to pstn spec.
1143 *
1144 * @param classHandle the class handle.
1145 * @param buffer the buffer pointer.
1146 * @param bufferLength the buffer length.
1147 * @param callbackFn this callback is called after this function completes.
1148 * @param callbackParam the first parameter in the callback function.
1149 *
1150 * @retval kStatus_USB_Success request successfully.
1151 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
1152 * @retval kStatus_USB_Busy There is no idle transfer.
1153 * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup.
1154 */
USB_HostCdcSetAcmLineCoding(usb_host_class_handle classHandle,usb_host_cdc_line_coding_struct_t * uartLineCoding,transfer_callback_t callbackFn,void * callbackParam)1155 usb_status_t USB_HostCdcSetAcmLineCoding(usb_host_class_handle classHandle,
1156 usb_host_cdc_line_coding_struct_t *uartLineCoding,
1157 transfer_callback_t callbackFn,
1158 void *callbackParam)
1159 {
1160 return USB_HostCdcControl(
1161 classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1162 USB_HOST_CDC_SET_LINE_CODING, 0, 0, 7, (uint8_t *)uartLineCoding, callbackFn, callbackParam);
1163 }
1164
1165 /*!
1166 * @brief cdc setControlLineState.
1167 *
1168 * This function implements cdc etControlLineState request.refer to pstn spec.
1169 *
1170 * @param classHandle the class handle.
1171 * @param buffer the buffer pointer.
1172 * @param bufferLength the buffer length.
1173 * @param callbackFn this callback is called after this function completes.
1174 * @param callbackParam the first parameter in the callback function.
1175 *
1176 * @retval kStatus_USB_Success request successfully.
1177 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
1178 * @retval kStatus_USB_Busy There is no idle transfer.
1179 * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup.
1180 */
USB_HostCdcSetAcmCtrlState(usb_host_class_handle classHandle,uint8_t dtr,uint8_t rts,transfer_callback_t callbackFn,void * callbackParam)1181 usb_status_t USB_HostCdcSetAcmCtrlState(
1182 usb_host_class_handle classHandle, uint8_t dtr, uint8_t rts, transfer_callback_t callbackFn, void *callbackParam)
1183 {
1184 uint16_t lineState = 0U;
1185
1186 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1187
1188 lineState = (0U != dtr) ? USB_HOST_CDC_CONTROL_LINE_STATE_DTR : 0U;
1189 lineState |= (0U != rts) ? USB_HOST_CDC_CONTROL_LINE_STATE_RTS : 0U;
1190 return USB_HostCdcControl(
1191 cdcInstance, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1192 USB_HOST_CDC_SET_CONTROL_LINE_STATE, (uint8_t)USB_SHORT_GET_LOW(lineState), USB_SHORT_GET_HIGH(lineState), 0U,
1193 NULL, callbackFn, callbackParam);
1194 }
1195
1196 /*!
1197 * @brief cdc send encapsulated command.
1198 *
1199 * This function implements cdc SEND_ENCAPSULATED_COMMAND request.refer to cdc 1.2 spec.
1200 *
1201 * @param classHandle the class handle.
1202 * @param buffer the buffer pointer.
1203 * @param bufferLength the buffer length.
1204 * @param callbackFn this callback is called after this function completes.
1205 * @param callbackParam the first parameter in the callback function.
1206 *
1207 * @retval kStatus_USB_Success request successfully.
1208 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
1209 * @retval kStatus_USB_Busy There is no idle transfer.
1210 * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup.
1211 */
USB_HostCdcSendEncapsulatedCommand(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)1212 usb_status_t USB_HostCdcSendEncapsulatedCommand(usb_host_class_handle classHandle,
1213 uint8_t *buffer,
1214 uint16_t bufferLength,
1215 transfer_callback_t callbackFn,
1216 void *callbackParam)
1217 {
1218 return USB_HostCdcControl(
1219 classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1220 USB_HOST_CDC_SEND_ENCAPSULATED_COMMAND, 0U, 0U, bufferLength, buffer, callbackFn, callbackParam);
1221 }
1222
1223 /*!
1224 * @brief cdc get encapsulated response.
1225 *
1226 * This function implements cdc GET_ENCAPSULATED_RESPONSE request.refer to cdc 1.2 spec.
1227 *
1228 * @param classHandle the class handle.
1229 * @param buffer the buffer pointer.
1230 * @param bufferLength the buffer length.
1231 * @param callbackFn this callback is called after this function completes.
1232 * @param callbackParam the first parameter in the callback function.
1233 *
1234 * @retval kStatus_USB_Success request successfully.
1235 * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
1236 * @retval kStatus_USB_Busy There is no idle transfer.
1237 * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup.
1238 */
USB_HostCdcGetEncapsulatedResponse(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)1239 usb_status_t USB_HostCdcGetEncapsulatedResponse(usb_host_class_handle classHandle,
1240 uint8_t *buffer,
1241 uint16_t bufferLength,
1242 transfer_callback_t callbackFn,
1243 void *callbackParam)
1244 {
1245 return USB_HostCdcControl(
1246 classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1247 USB_HOST_CDC_GET_ENCAPSULATED_RESPONSE, 0, 0, bufferLength, buffer, callbackFn, callbackParam);
1248 }
1249
1250 /*!
1251 * @brief cdc get acm descriptor.
1252 *
1253 * This function is hunting for class specific acm decriptor in the configuration ,get the corresponding
1254 * descriptor .
1255 *
1256 * @param classHandle the class handle.
1257 * @param headDesc the head function descriptor pointer.
1258 * @param callManageDesc the call management functional descriptor pointer.
1259 * @param abstractControlDesc the abstract control management functional pointer.
1260 * @param unionInterfaceDesc the union functional descriptor pointer.
1261 *
1262 * @retval kStatus_USB_Error analyse descriptor error.
1263 */
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)1264 usb_status_t USB_HostCdcGetAcmDescriptor(usb_host_class_handle classHandle,
1265 usb_host_cdc_head_function_desc_struct_t **headDesc,
1266 usb_host_cdc_call_manage_desc_struct_t **callManageDesc,
1267 usb_host_cdc_abstract_control_desc_struct_t **abstractControlDesc,
1268 usb_host_cdc_union_interface_desc_struct_t **unionInterfaceDesc)
1269 {
1270 usb_status_t status;
1271 usb_descriptor_union_t *ptr1;
1272 uint32_t end_address;
1273 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1274 usb_cdc_func_desc_struct_t *cdc_common_ptr;
1275 usb_host_interface_t *interface_handle;
1276 void *temp;
1277
1278 status = kStatus_USB_Success;
1279 interface_handle = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle;
1280 temp = (void *)interface_handle->interfaceExtension;
1281 ptr1 = (usb_descriptor_union_t *)temp;
1282 end_address = (uint32_t)(interface_handle->interfaceExtension + interface_handle->interfaceExtensionLength);
1283
1284 while ((uint32_t)ptr1 < end_address)
1285 {
1286 temp = (void *)&ptr1->common;
1287 cdc_common_ptr = (usb_cdc_func_desc_struct_t *)temp;
1288 switch (cdc_common_ptr->common.bDescriptorSubtype)
1289 {
1290 case USB_HOST_DESC_SUBTYPE_HEADER:
1291 *headDesc = &cdc_common_ptr->head;
1292 if ((((uint32_t)((*headDesc)->bcdCDC[1U]) << 8U) + (*headDesc)->bcdCDC[0U]) > 0x0110U)
1293 {
1294 status = kStatus_USB_Error;
1295 }
1296 break;
1297 case USB_HOST_DESC_SUBTYPE_UNION:
1298 if (cdc_common_ptr->unionDesc.bControlInterface == interface_handle->interfaceDesc->bInterfaceNumber)
1299 {
1300 *unionInterfaceDesc = &cdc_common_ptr->unionDesc;
1301 }
1302 else
1303 {
1304 status = kStatus_USB_Error;
1305 }
1306 break;
1307 case USB_HOST_DESC_SUBTYPE_CM:
1308 *callManageDesc = &cdc_common_ptr->callManage;
1309 break;
1310 case USB_HOST_DESC_SUBTYPE_ACM:
1311 *abstractControlDesc = &cdc_common_ptr->acm;
1312 break;
1313 default:
1314 /*no action*/
1315 break;
1316 }
1317
1318 if (kStatus_USB_Success != status)
1319 {
1320 break;
1321 }
1322 temp = (void *)((uint8_t *)ptr1 + ptr1->common.bLength);
1323 ptr1 = (usb_descriptor_union_t *)temp;
1324 }
1325 cdcInstance->headDesc = *headDesc;
1326 cdcInstance->callManageDesc = *callManageDesc;
1327 cdcInstance->abstractControlDesc = *abstractControlDesc;
1328 cdcInstance->unionInterfaceDesc = *unionInterfaceDesc;
1329 return status;
1330 }
1331
USB_HostCdcGetEcmDescriptor(usb_host_class_handle classHandle,usb_host_cdc_head_function_desc_struct_t ** headDesc,usb_host_cdc_union_interface_desc_struct_t ** unionInterfaceDesc,usb_host_cdc_ethernet_networking_desc_struct_t ** ethernetNetworkingDesc)1332 usb_status_t USB_HostCdcGetEcmDescriptor(usb_host_class_handle classHandle,
1333 usb_host_cdc_head_function_desc_struct_t **headDesc,
1334 usb_host_cdc_union_interface_desc_struct_t **unionInterfaceDesc,
1335 usb_host_cdc_ethernet_networking_desc_struct_t **ethernetNetworkingDesc)
1336 {
1337 usb_status_t status = kStatus_USB_Success;
1338
1339 usb_host_cdc_head_function_desc_struct_t *ifHeadDesc = NULL;
1340 usb_host_cdc_union_interface_desc_struct_t *ifUnionInterfaceDesc = NULL;
1341 usb_host_cdc_ethernet_networking_desc_struct_t *ifEthernetNetworkingDesc = NULL;
1342
1343 usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
1344 usb_host_interface_t *ifPointer = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle;
1345 usb_descriptor_union_t *ifBuffer = (usb_descriptor_union_t *)(ifPointer->interfaceExtension);
1346 usb_cdc_func_desc_struct_t *funcBuffer;
1347
1348 for (uint32_t ifIndex = 0; ifIndex < ifPointer->interfaceExtensionLength; ifIndex += ifBuffer->common.bLength,
1349 ifBuffer = (usb_descriptor_union_t *)((uint8_t *)ifBuffer + ifBuffer->common.bLength))
1350 {
1351 if (ifBuffer->common.bDescriptorType == 0x24U)
1352 {
1353 funcBuffer = (usb_cdc_func_desc_struct_t *)ifBuffer;
1354 switch (funcBuffer->common.bDescriptorSubtype)
1355 {
1356 case USB_HOST_DESC_SUBTYPE_HEADER:
1357 ifHeadDesc = &funcBuffer->head;
1358 if ((((uint32_t)(ifHeadDesc->bcdCDC[1U]) << 8U) + ifHeadDesc->bcdCDC[0U]) > 0x0110U)
1359 {
1360 status = kStatus_USB_Error;
1361 }
1362 break;
1363
1364 case USB_HOST_DESC_SUBTYPE_UNION:
1365 if (funcBuffer->unionDesc.bControlInterface == ifPointer->interfaceDesc->bInterfaceNumber)
1366 {
1367 ifUnionInterfaceDesc = &funcBuffer->unionDesc;
1368 }
1369 else
1370 {
1371 status = kStatus_USB_Error;
1372 }
1373 break;
1374
1375 case USB_HOST_DESC_SUBTYPE_ECM:
1376 ifEthernetNetworkingDesc = &funcBuffer->ecm;
1377 cdcInstance->headDesc = ifHeadDesc;
1378 cdcInstance->unionInterfaceDesc = ifUnionInterfaceDesc;
1379 cdcInstance->ethernetNetworkingDesc = ifEthernetNetworkingDesc;
1380 if (headDesc)
1381 {
1382 *headDesc = cdcInstance->headDesc;
1383 }
1384 if (unionInterfaceDesc)
1385 {
1386 *unionInterfaceDesc = cdcInstance->unionInterfaceDesc;
1387 }
1388 if (ethernetNetworkingDesc)
1389 {
1390 *ethernetNetworkingDesc = cdcInstance->ethernetNetworkingDesc;
1391 }
1392 break;
1393
1394 default:
1395 break;
1396 }
1397 if (status != kStatus_USB_Success)
1398 {
1399 break;
1400 }
1401 }
1402 }
1403 return status;
1404 }
1405 #endif
1406