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_HUB) && (USB_HOST_CONFIG_HUB))
11 #include "usb_host.h"
12 #include "usb_host_hub.h"
13 
14 /*******************************************************************************
15  * Definitions
16  ******************************************************************************/
17 
18 /*******************************************************************************
19  * Prototypes
20  ******************************************************************************/
21 /*!
22  * @brief hub control transfer callback.
23  *
24  * @param param       callback parameter.
25  * @param transfer    callback transfer.
26  * @param status      transfer status.
27  */
28 static void USB_HostHubControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
29 
30 /*!
31  * @brief hub interrupt in transfer callback.
32  *
33  * @param param       callback parameter.
34  * @param transfer    callback transfer.
35  * @param status      transfer status.
36  */
37 static void USB_HostHubInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
38 
39 /*!
40  * @brief USB_HostHubSendPortReset's transfer callback.
41  *
42  * @param param       callback parameter.
43  * @param transfer    callback transfer.
44  * @param status      transfer status.
45  */
46 static void USB_HostHubResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
47 
48 /*!
49  * @brief hub control transfer common code.
50  *
51  * @param classHandle   the class handle.
52  * @param requestType   request type.
53  * @param request        setup packet request field.
54  * @param wvalue         setup packet wValue field.
55  * @param windex         setup packet wIndex field.
56  * @param buffer         the buffer pointer.
57  * @param bufferLength     the buffer length.
58  * @param callbackFn    this callback is called after this function completes.
59  * @param callbackParam the first parameter in the callback function.
60  *
61  * @return kStatus_USB_Success or error codes.
62  */
63 static usb_status_t USB_HostHubClassRequestCommon(usb_host_class_handle classHandle,
64                                                   uint8_t requestType,
65                                                   uint8_t request,
66                                                   uint16_t wvalue,
67                                                   uint16_t windex,
68                                                   uint8_t *buffer,
69                                                   uint16_t bufferLength,
70                                                   transfer_callback_t callbackFn,
71                                                   void *callbackParam);
72 
73 /*******************************************************************************
74  * Variables
75  ******************************************************************************/
76 
77 /*******************************************************************************
78  * Code
79  ******************************************************************************/
80 
USB_HostHubControlCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)81 static void USB_HostHubControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
82 {
83     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
84 
85     hubInstance->controlTransfer = NULL;
86     if (NULL != hubInstance->controlCallbackFn)
87     {
88         /* callback to application, callback function is initialized in the USB_HostPrinterControl,
89         USB_HostPrinterSetInterface
90         or USB_HostHubClassRequestCommon, but is the same function */
91         hubInstance->controlCallbackFn(hubInstance->controlCallbackParam, transfer->transferBuffer,
92                                        transfer->transferSofar, status); /* callback to application */
93     }
94     (void)USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
95 }
96 
USB_HostHubInPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)97 static void USB_HostHubInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
98 {
99     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
100 
101     if (NULL != hubInstance->inCallbackFn)
102     {
103         /* callback to application, callback function is initialized in the USB_HostHubInterruptRecv */
104         hubInstance->inCallbackFn(hubInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
105                                   status); /* callback to application */
106     }
107     (void)USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
108 }
109 
USB_HostHubResetCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)110 static void USB_HostHubResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
111 {
112     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
113 
114     /* note: there is not callback to application, the re-enumeration will start automatically after reset. */
115     (void)USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
116 }
117 
USB_HostHubClassRequestCommon(usb_host_class_handle classHandle,uint8_t requestType,uint8_t request,uint16_t wvalue,uint16_t windex,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)118 static usb_status_t USB_HostHubClassRequestCommon(usb_host_class_handle classHandle,
119                                                   uint8_t requestType,
120                                                   uint8_t request,
121                                                   uint16_t wvalue,
122                                                   uint16_t windex,
123                                                   uint8_t *buffer,
124                                                   uint16_t bufferLength,
125                                                   transfer_callback_t callbackFn,
126                                                   void *callbackParam)
127 {
128     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
129     usb_host_transfer_t *transfer;
130 
131     if (hubInstance->controlTransfer != NULL)
132     {
133         return kStatus_USB_Busy;
134     }
135 
136     /* get transfer */
137     if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success)
138     {
139 #ifdef HOST_ECHO
140         usb_echo("error to get transfer\r\n");
141 #endif
142         return kStatus_USB_Error;
143     }
144 
145     /* save hub application callback */
146     hubInstance->controlCallbackFn    = callbackFn;
147     hubInstance->controlCallbackParam = callbackParam;
148 
149     /* initialize transfer */
150     transfer->transferBuffer             = buffer;
151     transfer->transferLength             = bufferLength;
152     transfer->callbackFn                 = USB_HostHubControlCallback;
153     transfer->callbackParam              = hubInstance;
154     transfer->setupPacket->bmRequestType = requestType;
155     transfer->setupPacket->bRequest      = request;
156     transfer->setupPacket->wValue        = USB_SHORT_TO_LITTLE_ENDIAN(wvalue);
157     transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(windex);
158     transfer->setupPacket->wLength       = USB_SHORT_TO_LITTLE_ENDIAN(bufferLength);
159 
160     /* send transfer */
161     if (USB_HostSendSetup(hubInstance->hostHandle, hubInstance->controlPipe, transfer) != kStatus_USB_Success)
162     {
163 #ifdef HOST_ECHO
164         usb_echo("Error in hid get report descriptor\r\n");
165 #endif
166         (void)USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
167         return kStatus_USB_Error;
168     }
169     hubInstance->controlTransfer = transfer; /* record the on-going setup transfer */
170     return kStatus_USB_Success;
171 }
172 
USB_HostHubInit(usb_device_handle deviceHandle,usb_host_class_handle * classHandle)173 usb_status_t USB_HostHubInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
174 {
175     /* malloc the hub instance */
176     usb_host_hub_instance_t *hubInstance =
177         (usb_host_hub_instance_t *)OSA_MemoryAllocate(sizeof(usb_host_hub_instance_t));
178     uint32_t *temp;
179     uint32_t infoValue = 0U;
180 
181     if (hubInstance == NULL)
182     {
183         return kStatus_USB_AllocFail;
184     }
185 
186 #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
187     hubInstance->hubDescriptor    = (uint8_t *)SDK_Malloc(7 + (USB_HOST_HUB_MAX_PORT >> 3) + 1, USB_CACHE_LINESIZE);
188     hubInstance->portStatusBuffer = (uint8_t *)SDK_Malloc(4, USB_CACHE_LINESIZE);
189     hubInstance->hubStatusBuffer  = (uint8_t *)SDK_Malloc(4, USB_CACHE_LINESIZE);
190     hubInstance->hubBitmapBuffer  = (uint8_t *)SDK_Malloc((USB_HOST_HUB_MAX_PORT >> 3) + 1, USB_CACHE_LINESIZE);
191 #endif
192 
193     /* initialize hub instance structure */
194     hubInstance->deviceHandle    = deviceHandle;
195     hubInstance->interfaceHandle = NULL;
196     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &infoValue);
197     temp                    = (uint32_t *)infoValue;
198     hubInstance->hostHandle = (usb_host_handle)temp;
199     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &infoValue);
200     temp                     = (uint32_t *)infoValue;
201     hubInstance->controlPipe = (usb_host_pipe_handle)temp;
202     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceLevel, &infoValue);
203     hubInstance->hubLevel = (uint8_t)infoValue;
204 
205     *classHandle = hubInstance; /* return the hub class handle */
206     return kStatus_USB_Success;
207 }
208 
USB_HostHubSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)209 usb_status_t USB_HostHubSetInterface(usb_host_class_handle classHandle,
210                                      usb_host_interface_handle interfaceHandle,
211                                      uint8_t alternateSetting,
212                                      transfer_callback_t callbackFn,
213                                      void *callbackParam)
214 {
215     usb_status_t status;
216     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
217     usb_host_interface_t *interface      = (usb_host_interface_t *)interfaceHandle;
218     usb_descriptor_endpoint_t *epDesc    = NULL;
219     usb_host_pipe_init_t pipeInit;
220     uint8_t epIndex;
221 
222     if (classHandle == NULL)
223     {
224         return kStatus_USB_InvalidHandle;
225     }
226 
227     hubInstance->interfaceHandle = interfaceHandle; /* save the interface handle */
228 
229     /* notify the host driver that the interface is used by class */
230     status = USB_HostOpenDeviceInterface(hubInstance->deviceHandle, interfaceHandle);
231     if (status != kStatus_USB_Success)
232     {
233         return status;
234     }
235 
236     /* close opened hub interrupt pipe */
237     if (hubInstance->interruptPipe != NULL)
238     {
239         status = USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->interruptPipe, NULL);
240         if (status != kStatus_USB_Success)
241         {
242 #ifdef HOST_ECHO
243             usb_echo("error when Cancel pipe\r\n");
244 #endif
245         }
246         status = USB_HostClosePipe(hubInstance->hostHandle, hubInstance->interruptPipe);
247         if (status != kStatus_USB_Success)
248         {
249 #ifdef HOST_ECHO
250             usb_echo("error when close pipe\r\n");
251 #endif
252         }
253         hubInstance->interruptPipe = NULL;
254     }
255 
256     /* open hub interrupt pipe */
257     for (epIndex = 0; epIndex < interface->epCount; ++epIndex)
258     {
259         epDesc = interface->epList[epIndex].epDesc;
260         if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
261              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
262             ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
263         {
264             /* get pipe information from endpoint descriptor */
265             pipeInit.devInstance     = hubInstance->deviceHandle;
266             pipeInit.pipeType        = USB_ENDPOINT_INTERRUPT;
267             pipeInit.direction       = USB_IN;
268             pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
269             pipeInit.interval        = epDesc->bInterval;
270             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
271                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
272             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
273                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
274             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
275 
276             /* open hub interrupt in pipe */
277             status = USB_HostOpenPipe(hubInstance->hostHandle, &hubInstance->interruptPipe, &pipeInit);
278             if (status != kStatus_USB_Success)
279             {
280 #ifdef HOST_ECHO
281                 usb_echo("usb_host_hid_set_interface fail to open pipe\r\n");
282 #endif
283                 return kStatus_USB_Error;
284             }
285             break;
286         }
287     }
288 
289     /* hub don't support alternatesetting that is not 0 */
290     if (alternateSetting == 0U)
291     {
292         if (callbackFn != NULL)
293         {
294             callbackFn(callbackParam, NULL, 0, kStatus_USB_Success);
295         }
296     }
297     else
298     {
299 #ifdef HOST_ECHO
300         usb_echo("host don't support alternate setting\r\n");
301 #endif
302         return kStatus_USB_Error;
303     }
304 
305     return status;
306 }
307 
USB_HostHubDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)308 usb_status_t USB_HostHubDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
309 {
310     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
311     usb_status_t status                  = kStatus_USB_Success;
312     if (deviceHandle == NULL)
313     {
314         return kStatus_USB_InvalidHandle;
315     }
316 
317     if (classHandle != NULL)
318     {
319         /* close opened hub interrupt pipe */
320         if (hubInstance->interruptPipe != NULL)
321         {
322             status = USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->interruptPipe, NULL);
323             if (status != kStatus_USB_Success)
324             {
325 #ifdef HOST_ECHO
326                 usb_echo("error when Cancel pipe\r\n");
327 #endif
328             }
329             status = USB_HostClosePipe(hubInstance->hostHandle, hubInstance->interruptPipe);
330             if (status != kStatus_USB_Success)
331             {
332 #ifdef HOST_ECHO
333                 usb_echo("hub close interrupt pipe error\r\n");
334 #endif
335             }
336             hubInstance->interruptPipe = NULL;
337         }
338 
339         /* cancel control transfer if exist */
340         if ((hubInstance->controlPipe != NULL) && (hubInstance->controlTransfer != NULL))
341         {
342             status =
343                 USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->controlPipe, hubInstance->controlTransfer);
344         }
345 
346         /* notify host driver that the interface will not be used */
347         (void)USB_HostCloseDeviceInterface(deviceHandle, hubInstance->interfaceHandle);
348 #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
349         SDK_Free(hubInstance->hubDescriptor);
350         SDK_Free(hubInstance->portStatusBuffer);
351         SDK_Free(hubInstance->hubStatusBuffer);
352         SDK_Free(hubInstance->hubBitmapBuffer);
353 #endif
354         OSA_MemoryFree(hubInstance);
355     }
356     else
357     {
358         /* notify host driver that the interface will not be used */
359         (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
360     }
361 
362     return status;
363 }
364 
USB_HostHubInterruptRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)365 usb_status_t USB_HostHubInterruptRecv(usb_host_class_handle classHandle,
366                                       uint8_t *buffer,
367                                       uint16_t bufferLength,
368                                       transfer_callback_t callbackFn,
369                                       void *callbackParam)
370 {
371     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
372     usb_host_transfer_t *transfer;
373 
374     if (classHandle == NULL)
375     {
376         return kStatus_USB_InvalidHandle;
377     }
378 
379     /* get transfer */
380     if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success)
381     {
382 #ifdef HOST_ECHO
383         usb_echo("error to get transfer\r\n");
384 #endif
385         return kStatus_USB_Error;
386     }
387 
388     /* save hub application callback */
389     hubInstance->inCallbackFn    = callbackFn;
390     hubInstance->inCallbackParam = callbackParam;
391 
392     /* initialize transfer */
393     transfer->transferBuffer = buffer;
394     transfer->transferLength = bufferLength;
395     transfer->callbackFn     = USB_HostHubInPipeCallback;
396     transfer->callbackParam  = hubInstance;
397 
398     /* call host driver API to receive data */
399     if (USB_HostRecv(hubInstance->hostHandle, hubInstance->interruptPipe, transfer) != kStatus_USB_Success)
400     {
401 #ifdef HOST_ECHO
402         usb_echo("failed to USB_HostRecv\r\n");
403 #endif
404         (void)USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
405         return kStatus_USB_Error;
406     }
407 
408     return kStatus_USB_Success;
409 }
410 
USB_HostHubSendPortReset(usb_host_class_handle classHandle,uint8_t portNumber)411 usb_status_t USB_HostHubSendPortReset(usb_host_class_handle classHandle, uint8_t portNumber)
412 {
413     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
414     usb_host_transfer_t *transfer;
415 
416     if (classHandle == NULL)
417     {
418         return kStatus_USB_InvalidHandle;
419     }
420 
421     /* get transfer */
422     if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success)
423     {
424 #ifdef HOST_ECHO
425         usb_echo("error to get transfer\r\n");
426 #endif
427         return kStatus_USB_Busy;
428     }
429 
430     /* initialize transfer */
431     transfer->transferBuffer = NULL;
432     transfer->transferLength = 0;
433     transfer->callbackFn     = USB_HostHubResetCallback;
434     transfer->callbackParam  = hubInstance;
435     transfer->setupPacket->bmRequestType =
436         USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER;
437     transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_FEATURE;
438     transfer->setupPacket->wValue   = USB_SHORT_TO_LITTLE_ENDIAN(PORT_RESET);
439     transfer->setupPacket->wIndex   = USB_SHORT_TO_LITTLE_ENDIAN(portNumber);
440     transfer->setupPacket->wLength  = 0;
441 
442     /* send the transfer */
443     if (USB_HostSendSetup(hubInstance->hostHandle, hubInstance->controlPipe, transfer) != kStatus_USB_Success)
444     {
445 #ifdef HOST_ECHO
446         usb_echo("Error in hid get report descriptor\r\n");
447 #endif
448         (void)USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
449         return kStatus_USB_Error;
450     }
451     return kStatus_USB_Success;
452 }
453 
454 /*!
455  * @brief hub get descriptor.
456  *
457  * This function implements get hub descriptor specific request.
458  *
459  * @param classHandle   the class handle.
460  * @param buffer         the buffer pointer.
461  * @param bufferLength     the buffer length.
462  * @param callbackFn    this callback is called after this function completes.
463  * @param callbackParam the first parameter in the callback function.
464  *
465  * @retval kStatus_USB_Success        send successfully.
466  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
467  * @retval kStatus_USB_Busy           There is no idle transfer.
468  * @retval kStatus_USB_Error          pipe is not initialized.
469  *                                    Or, send transfer fail, please reference to USB_HostSendSetup.
470  */
USB_HostHubGetDescriptor(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)471 usb_status_t USB_HostHubGetDescriptor(usb_host_class_handle classHandle,
472                                       uint8_t *buffer,
473                                       uint16_t bufferLength,
474                                       transfer_callback_t callbackFn,
475                                       void *callbackParam)
476 {
477     return USB_HostHubClassRequestCommon(
478         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_DEVICE,
479         USB_REQUEST_STANDARD_GET_DESCRIPTOR, 0x00, 0, buffer, bufferLength, callbackFn, callbackParam);
480 }
481 
482 /*!
483  * @brief hub clear feature.
484  *
485  * This function implements clear hub feature specific request.
486  *
487  * @param classHandle   the class handle.
488  * @param buffer         the buffer pointer.
489  * @param bufferLength     the buffer length.
490  * @param callbackFn    this callback is called after this function completes.
491  * @param callbackParam the first parameter in the callback function.
492  *
493  * @retval kStatus_USB_Success        send successfully.
494  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
495  * @retval kStatus_USB_Busy           There is no idle transfer.
496  * @retval kStatus_USB_Error          pipe is not initialized.
497  *                                    Or, send transfer fail, please reference to USB_HostSendSetup.
498  */
USB_HostHubClearFeature(usb_host_class_handle classHandle,uint8_t feature,transfer_callback_t callbackFn,void * callbackParam)499 usb_status_t USB_HostHubClearFeature(usb_host_class_handle classHandle,
500                                      uint8_t feature,
501                                      transfer_callback_t callbackFn,
502                                      void *callbackParam)
503 {
504     return USB_HostHubClassRequestCommon(classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS,
505                                          USB_REQUEST_STANDARD_CLEAR_FEATURE, feature, 0, NULL, 0, callbackFn,
506                                          callbackParam);
507 }
508 
509 /*!
510  * @brief hub get status.
511  *
512  * This function implements get hub status specific request.
513  *
514  * @param classHandle   the class handle.
515  * @param buffer         the buffer pointer.
516  * @param bufferLength     the buffer length.
517  * @param callbackFn    this callback is called after this function completes.
518  * @param callbackParam the first parameter in the callback function.
519  *
520  * @retval kStatus_USB_Success        send successfully.
521  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
522  * @retval kStatus_USB_Busy           There is no idle transfer.
523  * @retval kStatus_USB_Error          pipe is not initialized.
524  *                                    Or, send transfer fail, please reference to USB_HostSendSetup.
525  */
USB_HostHubGetStatus(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)526 usb_status_t USB_HostHubGetStatus(usb_host_class_handle classHandle,
527                                   uint8_t *buffer,
528                                   uint16_t bufferLength,
529                                   transfer_callback_t callbackFn,
530                                   void *callbackParam)
531 {
532     return USB_HostHubClassRequestCommon(classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS,
533                                          USB_REQUEST_STANDARD_GET_STATUS, 0, 0, buffer, bufferLength, callbackFn,
534                                          callbackParam);
535 }
536 
537 /*!
538  * @brief hub set feature.
539  *
540  * This function implements set hub feature specific request.
541  *
542  * @param classHandle   the class handle.
543  * @param buffer         the buffer pointer.
544  * @param bufferLength     the buffer length.
545  * @param callbackFn    this callback is called after this function completes.
546  * @param callbackParam the first parameter in the callback function.
547  *
548  * @retval kStatus_USB_Success        send successfully.
549  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
550  * @retval kStatus_USB_Busy           There is no idle transfer.
551  * @retval kStatus_USB_Error          pipe is not initialized.
552  *                                    Or, send transfer fail, please reference to USB_HostSendSetup.
553  */
USB_HostHubSetPortFeature(usb_host_class_handle classHandle,uint8_t portNumber,uint8_t feature,transfer_callback_t callbackFn,void * callbackParam)554 usb_status_t USB_HostHubSetPortFeature(usb_host_class_handle classHandle,
555                                        uint8_t portNumber,
556                                        uint8_t feature,
557                                        transfer_callback_t callbackFn,
558                                        void *callbackParam)
559 {
560     return USB_HostHubClassRequestCommon(
561         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
562         USB_REQUEST_STANDARD_SET_FEATURE, feature, portNumber, NULL, 0, callbackFn, callbackParam);
563 }
564 
565 /*!
566  * @brief hub clear port feature.
567  *
568  * This function implements clear hub port feature specific request.
569  *
570  * @param classHandle   the class handle.
571  * @param buffer         the buffer pointer.
572  * @param bufferLength     the buffer length.
573  * @param callbackFn    this callback is called after this function completes.
574  * @param callbackParam the first parameter in the callback function.
575  *
576  * @retval kStatus_USB_Success        send successfully.
577  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
578  * @retval kStatus_USB_Busy           There is no idle transfer.
579  * @retval kStatus_USB_Error          pipe is not initialized.
580  *                                    Or, send transfer fail, please reference to USB_HostSendSetup.
581  */
USB_HostHubClearPortFeature(usb_host_class_handle classHandle,uint8_t portNumber,uint8_t feature,transfer_callback_t callbackFn,void * callbackParam)582 usb_status_t USB_HostHubClearPortFeature(usb_host_class_handle classHandle,
583                                          uint8_t portNumber,
584                                          uint8_t feature,
585                                          transfer_callback_t callbackFn,
586                                          void *callbackParam)
587 {
588     return USB_HostHubClassRequestCommon(
589         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
590         USB_REQUEST_STANDARD_CLEAR_FEATURE, feature, portNumber, NULL, 0, callbackFn, callbackParam);
591 }
592 
593 /*!
594  * @brief hub port get status.
595  *
596  * This function implements get hub port status specific request.
597  *
598  * @param classHandle   the class handle.
599  * @param buffer         the buffer pointer.
600  * @param bufferLength     the buffer length.
601  * @param callbackFn    this callback is called after this function completes.
602  * @param callbackParam the first parameter in the callback function.
603  *
604  * @retval kStatus_USB_Success        send successfully.
605  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
606  * @retval kStatus_USB_Busy           There is no idle transfer.
607  * @retval kStatus_USB_Error          pipe is not initialized.
608  *                                    Or, send transfer fail, please reference to USB_HostSendSetup.
609  */
USB_HostHubGetPortStatus(usb_host_class_handle classHandle,uint8_t portNumber,uint8_t * buffer,uint16_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)610 usb_status_t USB_HostHubGetPortStatus(usb_host_class_handle classHandle,
611                                       uint8_t portNumber,
612                                       uint8_t *buffer,
613                                       uint16_t bufferLength,
614                                       transfer_callback_t callbackFn,
615                                       void *callbackParam)
616 {
617     return USB_HostHubClassRequestCommon(
618         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
619         USB_REQUEST_STANDARD_GET_STATUS, 0, portNumber, buffer, bufferLength, callbackFn, callbackParam);
620 }
621 
622 #endif /* USB_HOST_CONFIG_HUB */
623