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>© 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