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_HID) && (USB_HOST_CONFIG_HID))
11 #include "usb_host.h"
12 #include "usb_host_hid.h"
13 
14 /*******************************************************************************
15  * API
16  ******************************************************************************/
17 
18 /*!
19  * @brief hid in pipe transfer callback.
20  *
21  * @param param       callback parameter.
22  * @param transfer    callback transfer.
23  * @param status      transfer status.
24  */
25 static void USB_HostHidInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
26 
27 /*!
28  * @brief hid out pipe transfer callback.
29  *
30  * @param param       callback parameter.
31  * @param transfer    callback transfer.
32  * @param status      transfer status.
33  */
34 static void USB_HostHidOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
35 
36 /*!
37  * @brief hid control pipe transfer callback.
38  *
39  * @param param       callback parameter.
40  * @param transfer    callback transfer.
41  * @param status      transfer status.
42  */
43 static void USB_HostHidControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
44 
45 /*!
46  * @brief hid open interface. It is called when set interface request success or open alternate setting 0 interface.
47  *
48  * @param hidInstance     hid instance pointer.
49  *
50  * @return kStatus_USB_Success or error codes.
51  */
52 static usb_status_t USB_HostHidOpenInterface(usb_host_hid_instance_t *hidInstance);
53 
54 /*!
55  * @brief hid set interface callback, open pipes.
56  *
57  * @param param       callback parameter.
58  * @param transfer    callback transfer.
59  * @param status      transfer status.
60  */
61 static void USB_HostHidSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
62 
63 /*!
64  * @brief hid send control transfer common code.
65  *
66  * @param classHandle    the class handle.
67  * @param requestType    setup packet request type.
68  * @param request        setup packet request value.
69  * @param wvalueL        setup packet wvalue low byte.
70  * @param wvalueH        setup packet wvalue high byte.
71  * @param wlength        setup packet wlength value.
72  * @param data           data buffer pointer
73  * @param callbackFn     this callback is called after this function completes.
74  * @param callbackParam  the first parameter in the callback function.
75  *
76  * @return An error code or kStatus_USB_Success.
77  */
78 static usb_status_t USB_HostHidControl(usb_host_class_handle classHandle,
79                                        uint8_t requestType,
80                                        uint8_t request,
81                                        uint8_t wvalueL,
82                                        uint8_t wvalueH,
83                                        uint16_t wlength,
84                                        uint8_t *data,
85                                        transfer_callback_t callbackFn,
86                                        void *callbackParam);
87 
88 /*******************************************************************************
89  * Definitions
90  ******************************************************************************/
91 /*******************************************************************************
92  * Prototypes
93  ******************************************************************************/
94 /*******************************************************************************
95  * Variables
96  ******************************************************************************/
97 /*******************************************************************************
98  * Code
99  ******************************************************************************/
100 
101 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
102 
USB_HostHidClearInHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)103 static void USB_HostHidClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
104 {
105     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
106 
107     hidInstance->controlTransfer = NULL;
108     if (hidInstance->inCallbackFn != NULL)
109     {
110         /* callback to application, callback function is initialized in the USB_HostHidRecv */
111         hidInstance->inCallbackFn(hidInstance->inCallbackParam, hidInstance->stallDataBuffer,
112                                   hidInstance->stallDataLength, kStatus_USB_TransferStall);
113     }
114     (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
115 }
116 
USB_HostHidClearOutHaltCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)117 static void USB_HostHidClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
118 {
119     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
120 
121     hidInstance->controlTransfer = NULL;
122     if (hidInstance->outCallbackFn != NULL)
123     {
124         /* callback to application, callback function is initialized in USB_HostHidSend */
125         hidInstance->outCallbackFn(hidInstance->outCallbackParam, hidInstance->stallDataBuffer,
126                                    hidInstance->stallDataLength, kStatus_USB_TransferStall);
127     }
128     (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
129 }
130 
USB_HostHidClearHalt(usb_host_hid_instance_t * hidInstance,usb_host_transfer_t * stallTransfer,host_inner_transfer_callback_t callbackFn,uint8_t endpoint)131 static usb_status_t USB_HostHidClearHalt(usb_host_hid_instance_t *hidInstance,
132                                          usb_host_transfer_t *stallTransfer,
133                                          host_inner_transfer_callback_t callbackFn,
134                                          uint8_t endpoint)
135 {
136     usb_status_t status;
137     usb_host_transfer_t *transfer;
138 
139     /* malloc one transfer */
140     status = USB_HostMallocTransfer(hidInstance->hostHandle, &transfer);
141     if (status != kStatus_USB_Success)
142     {
143 #ifdef HOST_ECHO
144         usb_echo("allocate transfer error\r\n");
145 #endif
146         return status;
147     }
148     hidInstance->stallDataBuffer = stallTransfer->transferBuffer;
149     hidInstance->stallDataLength = stallTransfer->transferSofar;
150     /* save the application callback function */
151     hidInstance->controlCallbackFn    = NULL;
152     hidInstance->controlCallbackParam = NULL;
153     /* initialize transfer */
154     transfer->callbackFn                 = callbackFn;
155     transfer->callbackParam              = hidInstance;
156     transfer->transferBuffer             = NULL;
157     transfer->transferLength             = 0;
158     transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_CLEAR_FEATURE;
159     transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
160     transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT);
161     transfer->setupPacket->wIndex  = USB_SHORT_TO_LITTLE_ENDIAN(endpoint);
162     transfer->setupPacket->wLength = 0;
163     status                         = USB_HostSendSetup(hidInstance->hostHandle, hidInstance->controlPipe, transfer);
164 
165     if (status != kStatus_USB_Success)
166     {
167         (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
168     }
169     hidInstance->controlTransfer = transfer;
170 
171     return status;
172 }
173 #endif
174 
USB_HostHidInPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)175 static void USB_HostHidInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
176 {
177     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
178 
179 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
180     if (status == kStatus_USB_TransferStall)
181     {
182         if (USB_HostHidClearHalt(hidInstance, transfer, USB_HostHidClearInHaltCallback,
183                                  (USB_REQUEST_TYPE_DIR_IN |
184                                   ((usb_host_pipe_t *)hidInstance->inPipe)->endpointAddress)) == kStatus_USB_Success)
185         {
186             (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
187             return;
188         }
189     }
190 #endif
191     if (hidInstance->inCallbackFn != NULL)
192     {
193         /* callback to application, callback function is initialized in the USB_HostHidRecv */
194         hidInstance->inCallbackFn(hidInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
195                                   status);
196     }
197     (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
198 }
199 
USB_HostHidOutPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)200 static void USB_HostHidOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
201 {
202     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
203 
204 #if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
205     if (status == kStatus_USB_TransferStall)
206     {
207         if (USB_HostHidClearHalt(hidInstance, transfer, USB_HostHidClearOutHaltCallback,
208                                  (USB_REQUEST_TYPE_DIR_OUT |
209                                   ((usb_host_pipe_t *)hidInstance->outPipe)->endpointAddress)) == kStatus_USB_Success)
210         {
211             (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
212             return;
213         }
214     }
215 #endif
216     if (hidInstance->outCallbackFn != NULL)
217     {
218         /* callback to application, callback function is initialized in USB_HostHidSend */
219         hidInstance->outCallbackFn(hidInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar,
220                                    status); /* callback to application */
221     }
222     (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
223 }
224 
USB_HostHidControlCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)225 static void USB_HostHidControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
226 {
227     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
228 
229     hidInstance->controlTransfer = NULL;
230     if (hidInstance->controlCallbackFn != NULL)
231     {
232         /* callback to application, callback function is initialized in the USB_HostHidSetInterface
233         or USB_HostHidControl, but is the same function */
234         hidInstance->controlCallbackFn(hidInstance->controlCallbackParam, transfer->transferBuffer,
235                                        transfer->transferSofar, status);
236     }
237     (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
238 }
239 
USB_HostHidOpenInterface(usb_host_hid_instance_t * hidInstance)240 static usb_status_t USB_HostHidOpenInterface(usb_host_hid_instance_t *hidInstance)
241 {
242     usb_status_t status;
243     uint8_t epIndex = 0;
244     usb_host_pipe_init_t pipeInit;
245     usb_descriptor_endpoint_t *epDesc = NULL;
246     usb_host_interface_t *interfacePointer;
247 
248     if (hidInstance->inPipe != NULL) /* close interrupt in pipe if it is open */
249     {
250         status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->inPipe);
251 
252         if (status != kStatus_USB_Success)
253         {
254 #ifdef HOST_ECHO
255             usb_echo("error when close pipe\r\n");
256 #endif
257         }
258         hidInstance->inPipe = NULL;
259     }
260     if (hidInstance->outPipe != NULL) /* close interrupt out pipe if it is open */
261     {
262         status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->outPipe);
263 
264         if (status != kStatus_USB_Success)
265         {
266 #ifdef HOST_ECHO
267             usb_echo("error when close pipe\r\n");
268 #endif
269         }
270         hidInstance->outPipe = NULL;
271     }
272 
273     /* open interface pipes */
274     interfacePointer = (usb_host_interface_t *)hidInstance->interfaceHandle;
275     for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex)
276     {
277         epDesc = interfacePointer->epList[epIndex].epDesc;
278         if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
279              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
280             ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
281         {
282             pipeInit.devInstance     = hidInstance->deviceHandle;
283             pipeInit.pipeType        = USB_ENDPOINT_INTERRUPT;
284             pipeInit.direction       = USB_IN;
285             pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
286             pipeInit.interval        = epDesc->bInterval;
287             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
288                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
289             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
290                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
291             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
292 
293             hidInstance->inPacketSize = pipeInit.maxPacketSize;
294 
295             status = USB_HostOpenPipe(hidInstance->hostHandle, &hidInstance->inPipe, &pipeInit);
296             if (status != kStatus_USB_Success)
297             {
298 #ifdef HOST_ECHO
299                 usb_echo("USB_HostHidSetInterface fail to open pipe\r\n");
300 #endif
301                 return kStatus_USB_Error;
302             }
303         }
304         else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
305                   USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
306                  ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
307         {
308             pipeInit.devInstance     = hidInstance->deviceHandle;
309             pipeInit.pipeType        = USB_ENDPOINT_INTERRUPT;
310             pipeInit.direction       = USB_OUT;
311             pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
312             pipeInit.interval        = epDesc->bInterval;
313             pipeInit.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
314                                                  USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
315             pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
316                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
317             pipeInit.nakCount        = USB_HOST_CONFIG_MAX_NAK;
318 
319             hidInstance->outPacketSize = pipeInit.maxPacketSize;
320 
321             status = USB_HostOpenPipe(hidInstance->hostHandle, &hidInstance->outPipe, &pipeInit);
322             if (status != kStatus_USB_Success)
323             {
324 #ifdef HOST_ECHO
325                 usb_echo("USB_HostHidSetInterface fail to open pipe\r\n");
326 #endif
327                 return kStatus_USB_Error;
328             }
329         }
330         else
331         {
332         }
333     }
334 
335     return kStatus_USB_Success;
336 }
337 
USB_HostHidSetInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)338 static void USB_HostHidSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
339 {
340     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
341 
342     hidInstance->controlTransfer = NULL;
343     if (status == kStatus_USB_Success)
344     {
345         status = USB_HostHidOpenInterface(hidInstance); /* hid open interface */
346     }
347 
348     if (hidInstance->controlCallbackFn != NULL)
349     {
350         /* callback to application, callback function is initialized in the USB_HostHidSetInterface
351         or USB_HostHidControl, but is the same function */
352         hidInstance->controlCallbackFn(hidInstance->controlCallbackParam, NULL, 0, status);
353     }
354     (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
355 }
356 
USB_HostHidInit(usb_device_handle deviceHandle,usb_host_class_handle * classHandle)357 usb_status_t USB_HostHidInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
358 {
359     uint32_t infoValue = 0U;
360     uint32_t *temp;
361     usb_host_hid_instance_t *hidInstance =
362         (usb_host_hid_instance_t *)OSA_MemoryAllocate(sizeof(usb_host_hid_instance_t)); /* malloc hid class instance */
363 
364     if (hidInstance == NULL)
365     {
366         return kStatus_USB_AllocFail;
367     }
368 
369     /* initialize hid instance */
370     hidInstance->deviceHandle    = deviceHandle;
371     hidInstance->interfaceHandle = NULL;
372     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &infoValue);
373     temp                    = (uint32_t *)infoValue;
374     hidInstance->hostHandle = (usb_host_handle)temp;
375     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &infoValue);
376     temp                     = (uint32_t *)infoValue;
377     hidInstance->controlPipe = (usb_host_pipe_handle)temp;
378 
379     *classHandle = hidInstance;
380     return kStatus_USB_Success;
381 }
382 
USB_HostHidSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)383 usb_status_t USB_HostHidSetInterface(usb_host_class_handle classHandle,
384                                      usb_host_interface_handle interfaceHandle,
385                                      uint8_t alternateSetting,
386                                      transfer_callback_t callbackFn,
387                                      void *callbackParam)
388 {
389     usb_status_t status;
390     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
391     usb_host_transfer_t *transfer;
392 
393     if (classHandle == NULL)
394     {
395         return kStatus_USB_InvalidParameter;
396     }
397 
398     hidInstance->interfaceHandle = interfaceHandle;
399     status                       = USB_HostOpenDeviceInterface(hidInstance->deviceHandle,
400                                          interfaceHandle); /* notify host driver the interface is open */
401     if (status != kStatus_USB_Success)
402     {
403         return status;
404     }
405 
406     /* cancel transfers */
407     if (hidInstance->inPipe != NULL)
408     {
409         status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->inPipe, NULL);
410 
411         if (status != kStatus_USB_Success)
412         {
413 #ifdef HOST_ECHO
414             usb_echo("error when cancel pipe\r\n");
415 #endif
416         }
417     }
418     if (hidInstance->outPipe != NULL)
419     {
420         status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->outPipe, NULL);
421 
422         if (status != kStatus_USB_Success)
423         {
424 #ifdef HOST_ECHO
425             usb_echo("error when cancel pipe\r\n");
426 #endif
427         }
428     }
429 
430     if (alternateSetting == 0U) /* open interface directly */
431     {
432         if (callbackFn != NULL)
433         {
434             status = USB_HostHidOpenInterface(hidInstance);
435             callbackFn(callbackParam, NULL, 0, status);
436         }
437     }
438     else /* send setup transfer */
439     {
440         /* malloc one transfer */
441         if (USB_HostMallocTransfer(hidInstance->hostHandle, &transfer) != kStatus_USB_Success)
442         {
443 #ifdef HOST_ECHO
444             usb_echo("error to get transfer\r\n");
445 #endif
446             return kStatus_USB_Error;
447         }
448 
449         /* save the application callback function */
450         hidInstance->controlCallbackFn    = callbackFn;
451         hidInstance->controlCallbackParam = callbackParam;
452         /* initialize transfer */
453         transfer->callbackFn                 = USB_HostHidSetInterfaceCallback;
454         transfer->callbackParam              = hidInstance;
455         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
456         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
457         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
458             ((usb_host_interface_t *)hidInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
459         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
460         transfer->setupPacket->wLength = 0U;
461         transfer->transferBuffer       = NULL;
462         transfer->transferLength       = 0U;
463         status                         = USB_HostSendSetup(hidInstance->hostHandle, hidInstance->controlPipe, transfer);
464 
465         if (status == kStatus_USB_Success)
466         {
467             hidInstance->controlTransfer = transfer;
468         }
469         else
470         {
471             (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
472         }
473     }
474 
475     return status;
476 }
477 
USB_HostHidDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)478 usb_status_t USB_HostHidDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
479 {
480     usb_status_t status;
481     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
482 
483     if (deviceHandle == NULL)
484     {
485         return kStatus_USB_InvalidHandle;
486     }
487 
488     if (classHandle != NULL) /* class instance has initialized */
489     {
490         if (hidInstance->inPipe != NULL)
491         {
492             status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->inPipe, NULL); /* cancel pipe */
493             if (status != kStatus_USB_Success)
494             {
495 #ifdef HOST_ECHO
496                 usb_echo("error when cancel pipe\r\n");
497 #endif
498             }
499             status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->inPipe); /* close pipe */
500 
501             if (status != kStatus_USB_Success)
502             {
503 #ifdef HOST_ECHO
504                 usb_echo("error when close pipe\r\n");
505 #endif
506             }
507             hidInstance->inPipe = NULL;
508         }
509         if (hidInstance->outPipe != NULL)
510         {
511             status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->outPipe, NULL); /* cancel pipe */
512             if (status != kStatus_USB_Success)
513             {
514 #ifdef HOST_ECHO
515                 usb_echo("error when cancel pipe\r\n");
516 #endif
517             }
518             status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->outPipe); /* close pipe */
519 
520             if (status != kStatus_USB_Success)
521             {
522 #ifdef HOST_ECHO
523                 usb_echo("error when close pipe\r\n");
524 #endif
525             }
526             hidInstance->outPipe = NULL;
527         }
528         if ((hidInstance->controlPipe != NULL) &&
529             (hidInstance->controlTransfer != NULL)) /* cancel control transfer if there is on-going control transfer */
530         {
531             status =
532                 USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->controlPipe, hidInstance->controlTransfer);
533             if (status != kStatus_USB_Success)
534             {
535 #ifdef HOST_ECHO
536                 usb_echo("error when cancel pipe\r\n");
537 #endif
538             }
539         }
540         (void)USB_HostCloseDeviceInterface(
541             deviceHandle, hidInstance->interfaceHandle); /* notify host driver the interface is closed */
542         OSA_MemoryFree(hidInstance);
543     }
544     else
545     {
546         (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
547     }
548 
549     return kStatus_USB_Success;
550 }
551 
USB_HostHidGetPacketsize(usb_host_class_handle classHandle,uint8_t pipeType,uint8_t direction)552 uint16_t USB_HostHidGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
553 {
554     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
555     if (classHandle == NULL)
556     {
557         return 0U;
558     }
559 
560     if (pipeType == USB_ENDPOINT_INTERRUPT)
561     {
562         if (direction == USB_IN)
563         {
564             return hidInstance->inPacketSize;
565         }
566         else
567         {
568             return hidInstance->outPacketSize;
569         }
570     }
571 
572     return 0;
573 }
574 
USB_HostHidRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)575 usb_status_t USB_HostHidRecv(usb_host_class_handle classHandle,
576                              uint8_t *buffer,
577                              uint32_t bufferLength,
578                              transfer_callback_t callbackFn,
579                              void *callbackParam)
580 {
581     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
582     usb_host_transfer_t *transfer;
583 
584     if (classHandle == NULL)
585     {
586         return kStatus_USB_InvalidHandle;
587     }
588 
589     if (hidInstance->inPipe == NULL)
590     {
591         return kStatus_USB_Error;
592     }
593 
594     /* malloc one transfer */
595     if (USB_HostMallocTransfer(hidInstance->hostHandle, &transfer) != kStatus_USB_Success)
596     {
597 #ifdef HOST_ECHO
598         usb_echo("error to get transfer\r\n");
599 #endif
600         return kStatus_USB_Busy;
601     }
602     /* save the application callback function */
603     hidInstance->inCallbackFn    = callbackFn;
604     hidInstance->inCallbackParam = callbackParam;
605     /* initialize transfer */
606     transfer->transferBuffer = buffer;
607     transfer->transferLength = bufferLength;
608     transfer->callbackFn     = USB_HostHidInPipeCallback;
609     transfer->callbackParam  = hidInstance;
610 
611     if (USB_HostRecv(hidInstance->hostHandle, hidInstance->inPipe, transfer) !=
612         kStatus_USB_Success) /* call host driver api */
613     {
614 #ifdef HOST_ECHO
615         usb_echo("failed to USB_HostRecv\r\n");
616 #endif
617         (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
618         return kStatus_USB_Error;
619     }
620 
621     return kStatus_USB_Success;
622 }
623 
USB_HostHidSend(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)624 usb_status_t USB_HostHidSend(usb_host_class_handle classHandle,
625                              uint8_t *buffer,
626                              uint32_t bufferLength,
627                              transfer_callback_t callbackFn,
628                              void *callbackParam)
629 {
630     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
631     usb_host_transfer_t *transfer;
632 
633     if (classHandle == NULL)
634     {
635         return kStatus_USB_InvalidHandle;
636     }
637 
638     if (hidInstance->outPipe == NULL)
639     {
640         return kStatus_USB_Error;
641     }
642 
643     /* malloc one transfer */
644     if (USB_HostMallocTransfer(hidInstance->hostHandle, &transfer) != kStatus_USB_Success)
645     {
646 #ifdef HOST_ECHO
647         usb_echo("error to get transfer\r\n");
648 #endif
649         return kStatus_USB_Error;
650     }
651     /* save the application callback function */
652     hidInstance->outCallbackFn    = callbackFn;
653     hidInstance->outCallbackParam = callbackParam;
654     /* initialize transfer */
655     transfer->transferBuffer = buffer;
656     transfer->transferLength = bufferLength;
657     transfer->callbackFn     = USB_HostHidOutPipeCallback;
658     transfer->callbackParam  = hidInstance;
659 
660     if (USB_HostSend(hidInstance->hostHandle, hidInstance->outPipe, transfer) !=
661         kStatus_USB_Success) /* call host driver api */
662     {
663 #ifdef HOST_ECHO
664         usb_echo("failed to USB_HostSend\r\n");
665 #endif
666         (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
667         return kStatus_USB_Error;
668     }
669 
670     return kStatus_USB_Success;
671 }
672 
USB_HostHidControl(usb_host_class_handle classHandle,uint8_t requestType,uint8_t request,uint8_t wvalueL,uint8_t wvalueH,uint16_t wlength,uint8_t * data,transfer_callback_t callbackFn,void * callbackParam)673 static usb_status_t USB_HostHidControl(usb_host_class_handle classHandle,
674                                        uint8_t requestType,
675                                        uint8_t request,
676                                        uint8_t wvalueL,
677                                        uint8_t wvalueH,
678                                        uint16_t wlength,
679                                        uint8_t *data,
680                                        transfer_callback_t callbackFn,
681                                        void *callbackParam)
682 {
683     usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
684     usb_host_transfer_t *transfer;
685 
686     if (classHandle == NULL)
687     {
688         return kStatus_USB_InvalidHandle;
689     }
690 
691     /* malloc one transfer */
692     if (USB_HostMallocTransfer(hidInstance->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_Busy;
698     }
699     /* save the application callback function */
700     hidInstance->controlCallbackFn    = callbackFn;
701     hidInstance->controlCallbackParam = callbackParam;
702     /* initialize transfer */
703     transfer->transferBuffer             = data;
704     transfer->transferLength             = wlength;
705     transfer->callbackFn                 = USB_HostHidControlCallback;
706     transfer->callbackParam              = hidInstance;
707     transfer->setupPacket->bmRequestType = requestType;
708     transfer->setupPacket->bRequest      = request;
709     transfer->setupPacket->wValue        = USB_SHORT_TO_LITTLE_ENDIAN(wvalueL | (uint16_t)((uint16_t)wvalueH << 8));
710     transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
711         ((usb_host_interface_t *)hidInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
712     transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
713 
714     if (USB_HostSendSetup(hidInstance->hostHandle, hidInstance->controlPipe, transfer) !=
715         kStatus_USB_Success) /* call host driver api */
716     {
717 #ifdef HOST_ECHO
718         usb_echo("failed for USB_HostSendSetup\r\n");
719 #endif
720         (void)USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
721         return kStatus_USB_Error;
722     }
723     hidInstance->controlTransfer = transfer;
724 
725     return kStatus_USB_Success;
726 }
727 
USB_HostHidGetReportDescriptor(usb_host_class_handle classHandle,uint8_t * buffer,uint16_t buffer_len,transfer_callback_t callbackFn,void * callbackParam)728 usb_status_t USB_HostHidGetReportDescriptor(usb_host_class_handle classHandle,
729                                             uint8_t *buffer,
730                                             uint16_t buffer_len,
731                                             transfer_callback_t callbackFn,
732                                             void *callbackParam)
733 {
734     return USB_HostHidControl(
735         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_STANDARD | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
736         USB_REQUEST_STANDARD_GET_DESCRIPTOR, 0, USB_DESCRIPTOR_TYPE_HID_REPORT, buffer_len, buffer, callbackFn,
737         callbackParam);
738 }
739 
USB_HostHidGetIdle(usb_host_class_handle classHandle,uint8_t reportId,uint8_t * idleRate,transfer_callback_t callbackFn,void * callbackParam)740 usb_status_t USB_HostHidGetIdle(usb_host_class_handle classHandle,
741                                 uint8_t reportId,
742                                 uint8_t *idleRate,
743                                 transfer_callback_t callbackFn,
744                                 void *callbackParam)
745 {
746     return USB_HostHidControl(
747         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
748         USB_HOST_HID_GET_IDLE, reportId, 0, 1, idleRate, callbackFn, callbackParam);
749 }
750 
USB_HostHidSetIdle(usb_host_class_handle classHandle,uint8_t reportId,uint8_t idleRate,transfer_callback_t callbackFn,void * callbackParam)751 usb_status_t USB_HostHidSetIdle(usb_host_class_handle classHandle,
752                                 uint8_t reportId,
753                                 uint8_t idleRate,
754                                 transfer_callback_t callbackFn,
755                                 void *callbackParam)
756 {
757     return USB_HostHidControl(
758         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
759         USB_HOST_HID_SET_IDLE, reportId, idleRate, 0, NULL, callbackFn, callbackParam);
760 }
761 
USB_HostHidGetProtocol(usb_host_class_handle classHandle,uint8_t * protocol,transfer_callback_t callbackFn,void * callbackParam)762 usb_status_t USB_HostHidGetProtocol(usb_host_class_handle classHandle,
763                                     uint8_t *protocol,
764                                     transfer_callback_t callbackFn,
765                                     void *callbackParam)
766 {
767     return USB_HostHidControl(
768         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
769         USB_HOST_HID_GET_PROTOCOL, 0, 0, 1, protocol, callbackFn, callbackParam);
770 }
771 
USB_HostHidSetProtocol(usb_host_class_handle classHandle,uint8_t protocol,transfer_callback_t callbackFn,void * callbackParam)772 usb_status_t USB_HostHidSetProtocol(usb_host_class_handle classHandle,
773                                     uint8_t protocol,
774                                     transfer_callback_t callbackFn,
775                                     void *callbackParam)
776 {
777     return USB_HostHidControl(
778         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
779         USB_HOST_HID_SET_PROTOCOL, protocol, 0, 0, NULL, callbackFn, callbackParam);
780 }
781 
USB_HostHidGetReport(usb_host_class_handle classHandle,uint8_t reportId,uint8_t reportType,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)782 usb_status_t USB_HostHidGetReport(usb_host_class_handle classHandle,
783                                   uint8_t reportId,
784                                   uint8_t reportType,
785                                   uint8_t *buffer,
786                                   uint32_t bufferLength,
787                                   transfer_callback_t callbackFn,
788                                   void *callbackParam)
789 {
790     return USB_HostHidControl(
791         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
792         USB_HOST_HID_GET_REPORT, reportId, reportType, (uint16_t)bufferLength, buffer, callbackFn, callbackParam);
793 }
794 
USB_HostHidSetReport(usb_host_class_handle classHandle,uint8_t reportId,uint8_t reportType,uint8_t * buffer,uint32_t bufferLength,transfer_callback_t callbackFn,void * callbackParam)795 usb_status_t USB_HostHidSetReport(usb_host_class_handle classHandle,
796                                   uint8_t reportId,
797                                   uint8_t reportType,
798                                   uint8_t *buffer,
799                                   uint32_t bufferLength,
800                                   transfer_callback_t callbackFn,
801                                   void *callbackParam)
802 {
803     return USB_HostHidControl(
804         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
805         USB_HOST_HID_SET_REPORT, reportId, reportType, (uint16_t)bufferLength, buffer, callbackFn, callbackParam);
806 }
807 
808 #endif /* USB_HOST_CONFIG_HID */
809