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