xref: /btstack/port/stm32-f4discovery-usb/Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c (revision a8f7f3fcbcd51f8d2e92aca076b6a9f812db358c)
1 /**
2   ******************************************************************************
3   * @file    usbh_hid.c
4   * @author  MCD Application Team
5   * @brief   This file is the HID Layer Handlers for USB Host HID class.
6   *
7   * @verbatim
8   *
9   *          ===================================================================
10   *                                HID Class  Description
11   *          ===================================================================
12   *           This module manages the HID class V1.11 following the "Device Class Definition
13   *           for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
14   *           This driver implements the following aspects of the specification:
15   *             - The Boot Interface Subclass
16   *             - The Mouse and Keyboard protocols
17   *
18   *  @endverbatim
19   *
20   ******************************************************************************
21   * @attention
22   *
23   * <h2><center>&copy; Copyright (c) 2015 STMicroelectronics.
24   * All rights reserved.</center></h2>
25   *
26   * This software component is licensed by ST under Ultimate Liberty license
27   * SLA0044, the "License"; You may not use this file except in compliance with
28   * the License. You may obtain a copy of the License at:
29   *                      www.st.com/SLA0044
30   *
31   ******************************************************************************
32   */
33 
34 /* BSPDependencies
35 - "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
36 - "stm32xxxxx_{eval}{discovery}_io.c"
37 - "stm32xxxxx_{eval}{discovery}{adafruit}_lcd.c"
38 - "stm32xxxxx_{eval}{discovery}_sdram.c"
39 EndBSPDependencies */
40 
41 /* Includes ------------------------------------------------------------------*/
42 #include "usbh_hid.h"
43 #include "usbh_hid_parser.h"
44 
45 
46 /** @addtogroup USBH_LIB
47 * @{
48 */
49 
50 /** @addtogroup USBH_CLASS
51 * @{
52 */
53 
54 /** @addtogroup USBH_HID_CLASS
55 * @{
56 */
57 
58 /** @defgroup USBH_HID_CORE
59 * @brief    This file includes HID Layer Handlers for USB Host HID class.
60 * @{
61 */
62 
63 /** @defgroup USBH_HID_CORE_Private_TypesDefinitions
64 * @{
65 */
66 /**
67 * @}
68 */
69 
70 
71 /** @defgroup USBH_HID_CORE_Private_Defines
72 * @{
73 */
74 /**
75 * @}
76 */
77 
78 
79 /** @defgroup USBH_HID_CORE_Private_Macros
80 * @{
81 */
82 /**
83 * @}
84 */
85 
86 
87 /** @defgroup USBH_HID_CORE_Private_Variables
88 * @{
89 */
90 
91 /**
92 * @}
93 */
94 
95 
96 /** @defgroup USBH_HID_CORE_Private_FunctionPrototypes
97 * @{
98 */
99 
100 static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost);
101 static USBH_StatusTypeDef USBH_HID_InterfaceDeInit(USBH_HandleTypeDef *phost);
102 static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost);
103 static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost);
104 static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost);
105 static void  USBH_HID_ParseHIDDesc(HID_DescTypeDef *desc, uint8_t *buf);
106 
107 extern USBH_StatusTypeDef USBH_HID_MouseInit(USBH_HandleTypeDef *phost);
108 extern USBH_StatusTypeDef USBH_HID_KeybdInit(USBH_HandleTypeDef *phost);
109 
110 USBH_ClassTypeDef  HID_Class =
111 {
112   "HID",
113   USB_HID_CLASS,
114   USBH_HID_InterfaceInit,
115   USBH_HID_InterfaceDeInit,
116   USBH_HID_ClassRequest,
117   USBH_HID_Process,
118   USBH_HID_SOFProcess,
119   NULL,
120 };
121 /**
122 * @}
123 */
124 
125 
126 /** @defgroup USBH_HID_CORE_Private_Functions
127 * @{
128 */
129 
130 
131 /**
132   * @brief  USBH_HID_InterfaceInit
133   *         The function init the HID class.
134   * @param  phost: Host handle
135   * @retval USBH Status
136   */
USBH_HID_InterfaceInit(USBH_HandleTypeDef * phost)137 static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost)
138 {
139   USBH_StatusTypeDef status;
140   HID_HandleTypeDef *HID_Handle;
141   uint8_t max_ep;
142   uint8_t num = 0U;
143   uint8_t interface;
144 
145   interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFFU);
146 
147   if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
148   {
149     USBH_DbgLog("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
150     return USBH_FAIL;
151   }
152 
153   status = USBH_SelectInterface(phost, interface);
154 
155   if (status != USBH_OK)
156   {
157     return USBH_FAIL;
158   }
159 
160   phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc(sizeof(HID_HandleTypeDef));
161   HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
162 
163   if (HID_Handle == NULL)
164   {
165     USBH_DbgLog("Cannot allocate memory for HID Handle");
166     return USBH_FAIL;
167   }
168 
169   /* Initialize hid handler */
170   USBH_memset(HID_Handle, 0, sizeof(HID_HandleTypeDef));
171 
172   HID_Handle->state = HID_ERROR;
173 
174   /*Decode Bootclass Protocol: Mouse or Keyboard*/
175   if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE)
176   {
177     USBH_UsrLog("KeyBoard device found!");
178     HID_Handle->Init = USBH_HID_KeybdInit;
179   }
180   else if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol  == HID_MOUSE_BOOT_CODE)
181   {
182     USBH_UsrLog("Mouse device found!");
183     HID_Handle->Init = USBH_HID_MouseInit;
184   }
185   else
186   {
187     USBH_UsrLog("Protocol not supported.");
188     return USBH_FAIL;
189   }
190 
191   HID_Handle->state     = HID_INIT;
192   HID_Handle->ctl_state = HID_REQ_INIT;
193   HID_Handle->ep_addr   = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
194   HID_Handle->length    = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
195   HID_Handle->poll      = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval;
196 
197   if (HID_Handle->poll  < HID_MIN_POLL)
198   {
199     HID_Handle->poll = HID_MIN_POLL;
200   }
201 
202   /* Check fo available number of endpoints */
203   /* Find the number of EPs in the Interface Descriptor */
204   /* Choose the lower number in order not to overrun the buffer allocated */
205   max_ep = ((phost->device.CfgDesc.Itf_Desc[interface].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
206              phost->device.CfgDesc.Itf_Desc[interface].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS);
207 
208 
209   /* Decode endpoint IN and OUT address from interface descriptor */
210   for (num = 0U; num < max_ep; num++)
211   {
212     if (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[num].bEndpointAddress & 0x80U)
213     {
214       HID_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[num].bEndpointAddress);
215       HID_Handle->InPipe = USBH_AllocPipe(phost, HID_Handle->InEp);
216 
217       /* Open pipe for IN endpoint */
218       USBH_OpenPipe(phost, HID_Handle->InPipe, HID_Handle->InEp, phost->device.address,
219                     phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length);
220 
221       USBH_LL_SetToggle(phost, HID_Handle->InPipe, 0U);
222     }
223     else
224     {
225       HID_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[num].bEndpointAddress);
226       HID_Handle->OutPipe  = USBH_AllocPipe(phost, HID_Handle->OutEp);
227 
228       /* Open pipe for OUT endpoint */
229       USBH_OpenPipe(phost, HID_Handle->OutPipe, HID_Handle->OutEp, phost->device.address,
230                     phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length);
231 
232       USBH_LL_SetToggle(phost, HID_Handle->OutPipe, 0U);
233     }
234   }
235 
236   return USBH_OK;
237 }
238 
239 /**
240   * @brief  USBH_HID_InterfaceDeInit
241   *         The function DeInit the Pipes used for the HID class.
242   * @param  phost: Host handle
243   * @retval USBH Status
244   */
USBH_HID_InterfaceDeInit(USBH_HandleTypeDef * phost)245 static USBH_StatusTypeDef USBH_HID_InterfaceDeInit(USBH_HandleTypeDef *phost)
246 {
247   HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
248 
249   if (HID_Handle->InPipe != 0x00U)
250   {
251     USBH_ClosePipe(phost, HID_Handle->InPipe);
252     USBH_FreePipe(phost, HID_Handle->InPipe);
253     HID_Handle->InPipe = 0U;     /* Reset the pipe as Free */
254   }
255 
256   if (HID_Handle->OutPipe != 0x00U)
257   {
258     USBH_ClosePipe(phost, HID_Handle->OutPipe);
259     USBH_FreePipe(phost, HID_Handle->OutPipe);
260     HID_Handle->OutPipe = 0U;     /* Reset the pipe as Free */
261   }
262 
263   if (phost->pActiveClass->pData)
264   {
265     USBH_free(phost->pActiveClass->pData);
266     phost->pActiveClass->pData = 0U;
267   }
268 
269   return USBH_OK;
270 }
271 
272 /**
273   * @brief  USBH_HID_ClassRequest
274   *         The function is responsible for handling Standard requests
275   *         for HID class.
276   * @param  phost: Host handle
277   * @retval USBH Status
278   */
USBH_HID_ClassRequest(USBH_HandleTypeDef * phost)279 static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost)
280 {
281 
282   USBH_StatusTypeDef status         = USBH_BUSY;
283   USBH_StatusTypeDef classReqStatus = USBH_BUSY;
284   HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
285 
286   /* Switch HID state machine */
287   switch (HID_Handle->ctl_state)
288   {
289   case HID_REQ_INIT:
290   case HID_REQ_GET_HID_DESC:
291 
292     USBH_HID_ParseHIDDesc(&HID_Handle->HID_Desc, phost->device.CfgDesc_Raw);
293 
294     HID_Handle->ctl_state = HID_REQ_GET_REPORT_DESC;
295 
296     break;
297   case HID_REQ_GET_REPORT_DESC:
298 
299     /* Get Report Desc */
300     classReqStatus = USBH_HID_GetHIDReportDescriptor(phost, HID_Handle->HID_Desc.wItemLength);
301     if (classReqStatus == USBH_OK)
302     {
303       /* The descriptor is available in phost->device.Data */
304       HID_Handle->ctl_state = HID_REQ_SET_IDLE;
305     }
306     else if (classReqStatus == USBH_NOT_SUPPORTED)
307     {
308       USBH_ErrLog("Control error: HID: Device Get Report Descriptor request failed");
309       status = USBH_FAIL;
310     }
311     else
312     {
313       /* .. */
314     }
315 
316     break;
317 
318   case HID_REQ_SET_IDLE:
319 
320     classReqStatus = USBH_HID_SetIdle(phost, 0U, 0U);
321 
322     /* set Idle */
323     if (classReqStatus == USBH_OK)
324     {
325       HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;
326     }
327     else
328     {
329       if (classReqStatus == USBH_NOT_SUPPORTED)
330       {
331         HID_Handle->ctl_state = HID_REQ_SET_PROTOCOL;
332       }
333     }
334     break;
335 
336   case HID_REQ_SET_PROTOCOL:
337     /* set protocol */
338     classReqStatus = USBH_HID_SetProtocol(phost, 0U);
339     if (classReqStatus == USBH_OK)
340     {
341       HID_Handle->ctl_state = HID_REQ_IDLE;
342 
343       /* all requests performed*/
344       phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
345       status = USBH_OK;
346     }
347     else if (classReqStatus == USBH_NOT_SUPPORTED)
348     {
349       USBH_ErrLog("Control error: HID: Device Set protocol request failed");
350       status = USBH_FAIL;
351     }
352     else
353     {
354       /* .. */
355     }
356     break;
357 
358   case HID_REQ_IDLE:
359   default:
360     break;
361   }
362 
363   return status;
364 }
365 
366 /**
367   * @brief  USBH_HID_Process
368   *         The function is for managing state machine for HID data transfers
369   * @param  phost: Host handle
370   * @retval USBH Status
371   */
USBH_HID_Process(USBH_HandleTypeDef * phost)372 static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
373 {
374   USBH_StatusTypeDef status = USBH_OK;
375   HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
376   uint32_t XferSize;
377 
378   switch (HID_Handle->state)
379   {
380     case HID_INIT:
381       HID_Handle->Init(phost);
382       HID_Handle->state = HID_IDLE;
383 
384 #if (USBH_USE_OS == 1U)
385       phost->os_msg = (uint32_t)USBH_URB_EVENT;
386 #if (osCMSIS < 0x20000U)
387       (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
388 #else
389       (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
390 #endif
391 #endif
392       break;
393 
394     case HID_IDLE:
395       status = USBH_HID_GetReport(phost, 0x01U, 0U, HID_Handle->pData, (uint8_t)HID_Handle->length);
396       if (status == USBH_OK)
397       {
398         HID_Handle->state = HID_SYNC;
399       }
400       else if (status == USBH_BUSY)
401       {
402         HID_Handle->state = HID_IDLE;
403         status = USBH_OK;
404       }
405       else if (status == USBH_NOT_SUPPORTED)
406       {
407         HID_Handle->state = HID_SYNC;
408         status = USBH_OK;
409       }
410       else
411       {
412         HID_Handle->state = HID_ERROR;
413         status = USBH_FAIL;
414       }
415 
416 #if (USBH_USE_OS == 1U)
417       phost->os_msg = (uint32_t)USBH_URB_EVENT;
418 #if (osCMSIS < 0x20000U)
419       (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
420 #else
421       (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
422 #endif
423 #endif
424       break;
425 
426     case HID_SYNC:
427       /* Sync with start of Even Frame */
428       if (phost->Timer & 1U)
429       {
430         HID_Handle->state = HID_GET_DATA;
431       }
432 
433 #if (USBH_USE_OS == 1U)
434       phost->os_msg = (uint32_t)USBH_URB_EVENT;
435 #if (osCMSIS < 0x20000U)
436       (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
437 #else
438       (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
439 #endif
440 #endif
441       break;
442 
443     case HID_GET_DATA:
444       USBH_InterruptReceiveData(phost, HID_Handle->pData,
445                                 (uint8_t)HID_Handle->length,
446                                 HID_Handle->InPipe);
447 
448       HID_Handle->state = HID_POLL;
449       HID_Handle->timer = phost->Timer;
450       HID_Handle->DataReady = 0U;
451       break;
452 
453     case HID_POLL:
454       if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_DONE)
455       {
456         XferSize = USBH_LL_GetLastXferSize(phost, HID_Handle->InPipe);
457 
458         if ((HID_Handle->DataReady == 0U) && (XferSize != 0U))
459         {
460           USBH_HID_FifoWrite(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
461           HID_Handle->DataReady = 1U;
462           USBH_HID_EventCallback(phost);
463 
464 #if (USBH_USE_OS == 1U)
465           phost->os_msg = (uint32_t)USBH_URB_EVENT;
466 #if (osCMSIS < 0x20000U)
467           (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
468 #else
469           (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
470 #endif
471 #endif
472         }
473       }
474       else
475       {
476         /* IN Endpoint Stalled */
477         if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_STALL)
478         {
479           /* Issue Clear Feature on interrupt IN endpoint */
480           if (USBH_ClrFeature(phost, HID_Handle->ep_addr) == USBH_OK)
481           {
482             /* Change state to issue next IN token */
483             HID_Handle->state = HID_GET_DATA;
484           }
485         }
486       }
487       break;
488 
489     default:
490       break;
491   }
492 
493   return status;
494 }
495 
496 /**
497   * @brief  USBH_HID_SOFProcess
498   *         The function is for managing the SOF Process
499   * @param  phost: Host handle
500   * @retval USBH Status
501   */
USBH_HID_SOFProcess(USBH_HandleTypeDef * phost)502 static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
503 {
504   HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
505 
506   if (HID_Handle->state == HID_POLL)
507   {
508     if ((phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
509     {
510       HID_Handle->state = HID_GET_DATA;
511 
512 #if (USBH_USE_OS == 1U)
513       phost->os_msg = (uint32_t)USBH_URB_EVENT;
514 #if (osCMSIS < 0x20000U)
515       (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
516 #else
517       (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
518 #endif
519 #endif
520     }
521   }
522   return USBH_OK;
523 }
524 
525 /**
526 * @brief  USBH_Get_HID_ReportDescriptor
527   *         Issue report Descriptor command to the device. Once the response
528   *         received, parse the report descriptor and update the status.
529   * @param  phost: Host handle
530   * @param  Length : HID Report Descriptor Length
531   * @retval USBH Status
532   */
USBH_HID_GetHIDReportDescriptor(USBH_HandleTypeDef * phost,uint16_t length)533 USBH_StatusTypeDef USBH_HID_GetHIDReportDescriptor(USBH_HandleTypeDef *phost,
534                                                    uint16_t length)
535 {
536 
537   USBH_StatusTypeDef status;
538 
539   status = USBH_GetDescriptor(phost,
540                               USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD,
541                               USB_DESC_HID_REPORT,
542                               phost->device.Data,
543                               length);
544 
545   /* HID report descriptor is available in phost->device.Data.
546   In case of USB Boot Mode devices for In report handling ,
547   HID report descriptor parsing is not required.
548   In case, for supporting Non-Boot Protocol devices and output reports,
549   user may parse the report descriptor*/
550 
551 
552   return status;
553 }
554 
555 /**
556   * @brief  USBH_Get_HID_Descriptor
557   *         Issue HID Descriptor command to the device. Once the response
558   *         received, parse the report descriptor and update the status.
559   * @param  phost: Host handle
560   * @param  Length : HID Descriptor Length
561   * @retval USBH Status
562   */
USBH_HID_GetHIDDescriptor(USBH_HandleTypeDef * phost,uint16_t length)563 USBH_StatusTypeDef USBH_HID_GetHIDDescriptor(USBH_HandleTypeDef *phost,
564                                              uint16_t length)
565 {
566   USBH_StatusTypeDef status;
567 
568   status = USBH_GetDescriptor(phost,
569                               USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD,
570                               USB_DESC_HID,
571                               phost->device.Data,
572                               length);
573 
574   return status;
575 }
576 
577 /**
578   * @brief  USBH_Set_Idle
579   *         Set Idle State.
580   * @param  phost: Host handle
581   * @param  duration: Duration for HID Idle request
582   * @param  reportId : Targeted report ID for Set Idle request
583   * @retval USBH Status
584   */
USBH_HID_SetIdle(USBH_HandleTypeDef * phost,uint8_t duration,uint8_t reportId)585 USBH_StatusTypeDef USBH_HID_SetIdle(USBH_HandleTypeDef *phost,
586                                     uint8_t duration,
587                                     uint8_t reportId)
588 {
589 
590   phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \
591                                          USB_REQ_TYPE_CLASS;
592 
593 
594   phost->Control.setup.b.bRequest = USB_HID_SET_IDLE;
595   phost->Control.setup.b.wValue.w = (uint16_t)(((uint32_t)duration << 8U) | (uint32_t)reportId);
596 
597   phost->Control.setup.b.wIndex.w = 0U;
598   phost->Control.setup.b.wLength.w = 0U;
599 
600   return USBH_CtlReq(phost, 0U, 0U);
601 }
602 
603 
604 /**
605   * @brief  USBH_HID_Set_Report
606   *         Issues Set Report
607   * @param  phost: Host handle
608   * @param  reportType  : Report type to be sent
609   * @param  reportId    : Targeted report ID for Set Report request
610   * @param  reportBuff  : Report Buffer
611   * @param  reportLen   : Length of data report to be send
612   * @retval USBH Status
613   */
USBH_HID_SetReport(USBH_HandleTypeDef * phost,uint8_t reportType,uint8_t reportId,uint8_t * reportBuff,uint8_t reportLen)614 USBH_StatusTypeDef USBH_HID_SetReport(USBH_HandleTypeDef *phost,
615                                       uint8_t reportType,
616                                       uint8_t reportId,
617                                       uint8_t *reportBuff,
618                                       uint8_t reportLen)
619 {
620 
621   phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \
622                                          USB_REQ_TYPE_CLASS;
623 
624 
625   phost->Control.setup.b.bRequest = USB_HID_SET_REPORT;
626   phost->Control.setup.b.wValue.w = (uint16_t)(((uint32_t)reportType << 8U) | (uint32_t)reportId);
627 
628   phost->Control.setup.b.wIndex.w = 0U;
629   phost->Control.setup.b.wLength.w = reportLen;
630 
631   return USBH_CtlReq(phost, reportBuff, (uint16_t)reportLen);
632 }
633 
634 
635 /**
636   * @brief  USBH_HID_GetReport
637   *         retreive Set Report
638   * @param  phost: Host handle
639   * @param  reportType  : Report type to be sent
640   * @param  reportId    : Targeted report ID for Set Report request
641   * @param  reportBuff  : Report Buffer
642   * @param  reportLen   : Length of data report to be send
643   * @retval USBH Status
644   */
USBH_HID_GetReport(USBH_HandleTypeDef * phost,uint8_t reportType,uint8_t reportId,uint8_t * reportBuff,uint8_t reportLen)645 USBH_StatusTypeDef USBH_HID_GetReport(USBH_HandleTypeDef *phost,
646                                       uint8_t reportType,
647                                       uint8_t reportId,
648                                       uint8_t *reportBuff,
649                                       uint8_t reportLen)
650 {
651 
652   phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_RECIPIENT_INTERFACE | \
653                                          USB_REQ_TYPE_CLASS;
654 
655 
656   phost->Control.setup.b.bRequest = USB_HID_GET_REPORT;
657   phost->Control.setup.b.wValue.w = (uint16_t)(((uint32_t)reportType << 8U) | (uint32_t)reportId);
658 
659   phost->Control.setup.b.wIndex.w = 0U;
660   phost->Control.setup.b.wLength.w = reportLen;
661 
662   return USBH_CtlReq(phost, reportBuff, (uint16_t)reportLen);
663 }
664 
665 /**
666   * @brief  USBH_Set_Protocol
667   *         Set protocol State.
668   * @param  phost: Host handle
669   * @param  protocol : Set Protocol for HID : boot/report protocol
670   * @retval USBH Status
671   */
USBH_HID_SetProtocol(USBH_HandleTypeDef * phost,uint8_t protocol)672 USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost,
673                                         uint8_t protocol)
674 {
675   phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE
676                                          | USB_REQ_TYPE_CLASS;
677 
678   phost->Control.setup.b.bRequest = USB_HID_SET_PROTOCOL;
679   if (protocol)
680   {
681     phost->Control.setup.b.wValue.w = 0U;
682   }
683   else
684   {
685     phost->Control.setup.b.wValue.w = 1U;
686   }
687 
688   phost->Control.setup.b.wIndex.w = 0U;
689   phost->Control.setup.b.wLength.w = 0U;
690 
691   return USBH_CtlReq(phost, 0U, 0U);
692 
693 }
694 
695 /**
696   * @brief  USBH_ParseHIDDesc
697   *         This function Parse the HID descriptor
698   * @param  desc: HID Descriptor
699   * @param  buf: Buffer where the source descriptor is available
700   * @retval None
701   */
USBH_HID_ParseHIDDesc(HID_DescTypeDef * desc,uint8_t * buf)702 static void  USBH_HID_ParseHIDDesc(HID_DescTypeDef *desc, uint8_t *buf)
703 {
704   USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf;
705   uint16_t CfgDescLen;
706   uint16_t ptr;
707 
708   CfgDescLen = LE16(buf + 2U);
709 
710   if (CfgDescLen > USB_CONFIGURATION_DESC_SIZE)
711   {
712     ptr = USB_LEN_CFG_DESC;
713 
714     while (ptr < CfgDescLen)
715     {
716       pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr);
717 
718       if (pdesc->bDescriptorType == USB_DESC_TYPE_HID)
719       {
720         desc->bLength = *(uint8_t *)((uint8_t *)pdesc + 0U);
721         desc->bDescriptorType = *(uint8_t *)((uint8_t *)pdesc + 1U);
722         desc->bcdHID = LE16((uint8_t *)pdesc + 2U);
723         desc->bCountryCode = *(uint8_t *)((uint8_t *)pdesc + 4U);
724         desc->bNumDescriptors = *(uint8_t *)((uint8_t *)pdesc + 5U);
725         desc->bReportDescriptorType = *(uint8_t *)((uint8_t *)pdesc + 6U);
726         desc->wItemLength = LE16((uint8_t *)pdesc + 7U);
727         break;
728       }
729     }
730   }
731 }
732 
733 /**
734   * @brief  USBH_HID_GetDeviceType
735   *         Return Device function.
736   * @param  phost: Host handle
737   * @retval HID function: HID_MOUSE / HID_KEYBOARD
738   */
USBH_HID_GetDeviceType(USBH_HandleTypeDef * phost)739 HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost)
740 {
741   HID_TypeTypeDef   type = HID_UNKNOWN;
742   uint8_t InterfaceProtocol;
743 
744   if (phost->gState == HOST_CLASS)
745   {
746     InterfaceProtocol = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol;
747     if (InterfaceProtocol == HID_KEYBRD_BOOT_CODE)
748     {
749       type = HID_KEYBOARD;
750     }
751     else
752     {
753       if (InterfaceProtocol == HID_MOUSE_BOOT_CODE)
754       {
755         type = HID_MOUSE;
756       }
757     }
758   }
759   return type;
760 }
761 
762 
763 /**
764   * @brief  USBH_HID_GetPollInterval
765   *         Return HID device poll time
766   * @param  phost: Host handle
767   * @retval poll time (ms)
768   */
USBH_HID_GetPollInterval(USBH_HandleTypeDef * phost)769 uint8_t USBH_HID_GetPollInterval(USBH_HandleTypeDef *phost)
770 {
771   HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
772 
773   if ((phost->gState == HOST_CLASS_REQUEST) ||
774       (phost->gState == HOST_INPUT) ||
775       (phost->gState == HOST_SET_CONFIGURATION) ||
776       (phost->gState == HOST_CHECK_CLASS) ||
777       ((phost->gState == HOST_CLASS)))
778   {
779     return (uint8_t)(HID_Handle->poll);
780   }
781   else
782   {
783     return 0U;
784   }
785 }
786 /**
787   * @brief  USBH_HID_FifoInit
788   *         Initialize FIFO.
789   * @param  f: Fifo address
790   * @param  buf: Fifo buffer
791   * @param  size: Fifo Size
792   * @retval none
793   */
USBH_HID_FifoInit(FIFO_TypeDef * f,uint8_t * buf,uint16_t size)794 void USBH_HID_FifoInit(FIFO_TypeDef *f, uint8_t *buf, uint16_t size)
795 {
796   f->head = 0U;
797   f->tail = 0U;
798   f->lock = 0U;
799   f->size = size;
800   f->buf = buf;
801 }
802 
803 /**
804   * @brief  USBH_HID_FifoRead
805   *         Read from FIFO.
806   * @param  f: Fifo address
807   * @param  buf: read buffer
808   * @param  nbytes: number of item to read
809   * @retval number of read items
810   */
USBH_HID_FifoRead(FIFO_TypeDef * f,void * buf,uint16_t nbytes)811 uint16_t USBH_HID_FifoRead(FIFO_TypeDef *f, void *buf, uint16_t nbytes)
812 {
813   uint16_t i;
814   uint8_t *p;
815 
816   p = (uint8_t *) buf;
817 
818   if (f->lock == 0U)
819   {
820     f->lock = 1U;
821 
822     for (i = 0U; i < nbytes; i++)
823     {
824       if (f->tail != f->head)
825       {
826         *p++ = f->buf[f->tail];
827         f->tail++;
828 
829         if (f->tail == f->size)
830         {
831           f->tail = 0U;
832         }
833       }
834       else
835       {
836         f->lock = 0U;
837         return i;
838       }
839     }
840   }
841 
842   f->lock = 0U;
843 
844   return nbytes;
845 }
846 
847 /**
848   * @brief  USBH_HID_FifoWrite
849   *         Write To FIFO.
850   * @param  f: Fifo address
851   * @param  buf: read buffer
852   * @param  nbytes: number of item to write
853   * @retval number of written items
854   */
USBH_HID_FifoWrite(FIFO_TypeDef * f,void * buf,uint16_t nbytes)855 uint16_t USBH_HID_FifoWrite(FIFO_TypeDef *f, void *buf, uint16_t  nbytes)
856 {
857   uint16_t i;
858   uint8_t *p;
859 
860   p = (uint8_t *) buf;
861 
862   if (f->lock == 0U)
863   {
864     f->lock = 1U;
865 
866     for (i = 0U; i < nbytes; i++)
867     {
868       if ((f->head + 1U == f->tail) ||
869           ((f->head + 1U == f->size) && (f->tail == 0U)))
870       {
871         f->lock = 0U;
872         return i;
873       }
874       else
875       {
876         f->buf[f->head] = *p++;
877         f->head++;
878 
879         if (f->head == f->size)
880         {
881           f->head = 0U;
882         }
883       }
884     }
885   }
886 
887   f->lock = 0U;
888 
889   return nbytes;
890 }
891 
892 /**
893 * @brief  The function is a callback about HID Data events
894 *  @param  phost: Selected device
895 * @retval None
896 */
USBH_HID_EventCallback(USBH_HandleTypeDef * phost)897 __weak void USBH_HID_EventCallback(USBH_HandleTypeDef *phost)
898 {
899   /* Prevent unused argument(s) compilation warning */
900   UNUSED(phost);
901 }
902 /**
903 * @}
904 */
905 
906 /**
907 * @}
908 */
909 
910 /**
911 * @}
912 */
913 
914 
915 /**
916 * @}
917 */
918 
919 
920 /**
921 * @}
922 */
923 
924 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
925