Merge pull request #93 from zyp/master
[fw/stlink] / example / stm32f4 / STM32_USB_Device_Library / Class / hid / src / usbd_hid_core.c
1 /**
2   ******************************************************************************
3   * @file    usbd_hid_core.c
4   * @author  MCD Application Team
5   * @version V1.0.0
6   * @date    22-July-2011
7   * @brief   This file provides the HID core functions.
8   *
9   * @verbatim
10   *      
11   *          ===================================================================      
12   *                                HID Class  Description
13   *          =================================================================== 
14   *           This module manages the HID class V1.11 following the "Device Class Definition
15   *           for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
16   *           This driver implements the following aspects of the specification:
17   *             - The Boot Interface Subclass
18   *             - The Mouse protocol
19   *             - Usage Page : Generic Desktop
20   *             - Usage : Joystick)
21   *             - Collection : Application 
22   *      
23   * @note     In HS mode and when the DMA is used, all variables and data structures
24   *           dealing with the DMA during the transaction process should be 32-bit aligned.
25   *           
26   *      
27   *  @endverbatim
28   *
29   ******************************************************************************
30   * @attention
31   *
32   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
33   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
34   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
35   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
36   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
37   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
38   *
39   * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
40   ******************************************************************************
41   */ 
42
43 /* Includes ------------------------------------------------------------------*/
44 #include "usbd_hid_core.h"
45 #include "usbd_desc.h"
46 #include "usbd_req.h"
47
48
49 /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
50   * @{
51   */
52
53
54 /** @defgroup USBD_HID 
55   * @brief usbd core module
56   * @{
57   */ 
58
59 /** @defgroup USBD_HID_Private_TypesDefinitions
60   * @{
61   */ 
62 /**
63   * @}
64   */ 
65
66
67 /** @defgroup USBD_HID_Private_Defines
68   * @{
69   */ 
70
71 /**
72   * @}
73   */ 
74
75
76 /** @defgroup USBD_HID_Private_Macros
77   * @{
78   */ 
79 /**
80   * @}
81   */ 
82
83
84
85
86 /** @defgroup USBD_HID_Private_FunctionPrototypes
87   * @{
88   */
89
90
91 static uint8_t  USBD_HID_Init (void  *pdev, 
92                                uint8_t cfgidx);
93
94 static uint8_t  USBD_HID_DeInit (void  *pdev, 
95                                  uint8_t cfgidx);
96
97 static uint8_t  USBD_HID_Setup (void  *pdev, 
98                                 USB_SETUP_REQ *req);
99
100 static uint8_t  *USBD_HID_GetCfgDesc (uint8_t speed, uint16_t *length);
101
102 static uint8_t  USBD_HID_DataIn (void  *pdev, uint8_t epnum);
103 /**
104   * @}
105   */ 
106
107 /** @defgroup USBD_HID_Private_Variables
108   * @{
109   */ 
110
111 USBD_Class_cb_TypeDef  USBD_HID_cb = 
112 {
113   USBD_HID_Init,
114   USBD_HID_DeInit,
115   USBD_HID_Setup,
116   NULL, /*EP0_TxSent*/  
117   NULL, /*EP0_RxReady*/
118   USBD_HID_DataIn, /*DataIn*/
119   NULL, /*DataOut*/
120   NULL, /*SOF */
121   NULL,
122   NULL,      
123   USBD_HID_GetCfgDesc,
124 #ifdef USB_OTG_HS_CORE  
125   USBD_HID_GetCfgDesc, /* use same config as per FS */
126 #endif  
127 };
128
129 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
130   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
131     #pragma data_alignment=4   
132   #endif
133 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */        
134 __ALIGN_BEGIN static uint32_t  USBD_HID_AltSet  __ALIGN_END = 0;
135
136 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
137   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
138     #pragma data_alignment=4   
139   #endif
140 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */      
141 __ALIGN_BEGIN static uint32_t  USBD_HID_Protocol  __ALIGN_END = 0;
142
143 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
144   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
145     #pragma data_alignment=4   
146   #endif
147 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */  
148 __ALIGN_BEGIN static uint32_t  USBD_HID_IdleState __ALIGN_END = 0;
149
150 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
151   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
152     #pragma data_alignment=4   
153   #endif
154 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ 
155 /* USB HID device Configuration Descriptor */
156 __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
157 {
158   0x09, /* bLength: Configuration Descriptor size */
159   USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
160   USB_HID_CONFIG_DESC_SIZ,
161   /* wTotalLength: Bytes returned */
162   0x00,
163   0x01,         /*bNumInterfaces: 1 interface*/
164   0x01,         /*bConfigurationValue: Configuration value*/
165   0x00,         /*iConfiguration: Index of string descriptor describing
166   the configuration*/
167   0xE0,         /*bmAttributes: bus powered and Support Remote Wake-up */
168   0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/
169   
170   /************** Descriptor of Joystick Mouse interface ****************/
171   /* 09 */
172   0x09,         /*bLength: Interface Descriptor size*/
173   USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/
174   0x00,         /*bInterfaceNumber: Number of Interface*/
175   0x00,         /*bAlternateSetting: Alternate setting*/
176   0x01,         /*bNumEndpoints*/
177   0x03,         /*bInterfaceClass: HID*/
178   0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
179   0x02,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
180   0,            /*iInterface: Index of string descriptor*/
181   /******************** Descriptor of Joystick Mouse HID ********************/
182   /* 18 */
183   0x09,         /*bLength: HID Descriptor size*/
184   HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
185   0x11,         /*bcdHID: HID Class Spec release number*/
186   0x01,
187   0x00,         /*bCountryCode: Hardware target country*/
188   0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/
189   0x22,         /*bDescriptorType*/
190   HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
191   0x00,
192   /******************** Descriptor of Mouse endpoint ********************/
193   /* 27 */
194   0x07,          /*bLength: Endpoint Descriptor size*/
195   USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
196   
197   HID_IN_EP,     /*bEndpointAddress: Endpoint Address (IN)*/
198   0x03,          /*bmAttributes: Interrupt endpoint*/
199   HID_IN_PACKET, /*wMaxPacketSize: 4 Byte max */
200   0x00,
201   0x0A,          /*bInterval: Polling Interval (10 ms)*/
202   /* 34 */
203 } ;
204
205 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
206   #if defined ( __ICCARM__ ) /*!< IAR Compiler */
207     #pragma data_alignment=4   
208   #endif
209 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */  
210 __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
211 {
212   0x05,   0x01,
213   0x09,   0x02,
214   0xA1,   0x01,
215   0x09,   0x01,
216   
217   0xA1,   0x00,
218   0x05,   0x09,
219   0x19,   0x01,
220   0x29,   0x03,
221   
222   0x15,   0x00,
223   0x25,   0x01,
224   0x95,   0x03,
225   0x75,   0x01,
226   
227   0x81,   0x02,
228   0x95,   0x01,
229   0x75,   0x05,
230   0x81,   0x01,
231   
232   0x05,   0x01,
233   0x09,   0x30,
234   0x09,   0x31,
235   0x09,   0x38,
236   
237   0x15,   0x81,
238   0x25,   0x7F,
239   0x75,   0x08,
240   0x95,   0x03,
241   
242   0x81,   0x06,
243   0xC0,   0x09,
244   0x3c,   0x05,
245   0xff,   0x09,
246   
247   0x01,   0x15,
248   0x00,   0x25,
249   0x01,   0x75,
250   0x01,   0x95,
251   
252   0x02,   0xb1,
253   0x22,   0x75,
254   0x06,   0x95,
255   0x01,   0xb1,
256   
257   0x01,   0xc0
258 }; 
259
260 /**
261   * @}
262   */ 
263
264 /** @defgroup USBD_HID_Private_Functions
265   * @{
266   */ 
267
268 /**
269   * @brief  USBD_HID_Init
270   *         Initialize the HID interface
271   * @param  pdev: device instance
272   * @param  cfgidx: Configuration index
273   * @retval status
274   */
275 static uint8_t  USBD_HID_Init (void  *pdev, 
276                                uint8_t cfgidx)
277 {
278   
279   /* Open EP IN */
280   DCD_EP_Open(pdev,
281               HID_IN_EP,
282               HID_IN_PACKET,
283               USB_OTG_EP_INT);
284   
285   /* Open EP OUT */
286   DCD_EP_Open(pdev,
287               HID_OUT_EP,
288               HID_OUT_PACKET,
289               USB_OTG_EP_INT);
290   
291   return USBD_OK;
292 }
293
294 /**
295   * @brief  USBD_HID_Init
296   *         DeInitialize the HID layer
297   * @param  pdev: device instance
298   * @param  cfgidx: Configuration index
299   * @retval status
300   */
301 static uint8_t  USBD_HID_DeInit (void  *pdev, 
302                                  uint8_t cfgidx)
303 {
304   /* Close HID EPs */
305   DCD_EP_Close (pdev , HID_IN_EP);
306   DCD_EP_Close (pdev , HID_OUT_EP);
307   
308   
309   return USBD_OK;
310 }
311
312 /**
313   * @brief  USBD_HID_Setup
314   *         Handle the HID specific requests
315   * @param  pdev: instance
316   * @param  req: usb requests
317   * @retval status
318   */
319 static uint8_t  USBD_HID_Setup (void  *pdev, 
320                                 USB_SETUP_REQ *req)
321 {
322   uint16_t len = 0;
323   uint8_t  *pbuf = NULL;
324   
325   switch (req->bmRequest & USB_REQ_TYPE_MASK)
326   {
327   case USB_REQ_TYPE_CLASS :  
328     switch (req->bRequest)
329     {
330       
331       
332     case HID_REQ_SET_PROTOCOL:
333       USBD_HID_Protocol = (uint8_t)(req->wValue);
334       break;
335       
336     case HID_REQ_GET_PROTOCOL:
337       USBD_CtlSendData (pdev, 
338                         (uint8_t *)&USBD_HID_Protocol,
339                         1);    
340       break;
341       
342     case HID_REQ_SET_IDLE:
343       USBD_HID_IdleState = (uint8_t)(req->wValue >> 8);
344       break;
345       
346     case HID_REQ_GET_IDLE:
347       USBD_CtlSendData (pdev, 
348                         (uint8_t *)&USBD_HID_IdleState,
349                         1);        
350       break;      
351       
352     default:
353       USBD_CtlError (pdev, req);
354       return USBD_FAIL; 
355     }
356     break;
357     
358   case USB_REQ_TYPE_STANDARD:
359     switch (req->bRequest)
360     {
361     case USB_REQ_GET_DESCRIPTOR: 
362       if( req->wValue >> 8 == HID_REPORT_DESC)
363       {
364         len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength);
365         pbuf = HID_MOUSE_ReportDesc;
366       }
367       else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE)
368       {
369         
370 //#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
371 //        pbuf = USBD_HID_Desc;   
372 //#else
373         pbuf = USBD_HID_CfgDesc + 0x12;
374 //#endif 
375         len = MIN(USB_HID_DESC_SIZ , req->wLength);
376       }
377       
378       USBD_CtlSendData (pdev, 
379                         pbuf,
380                         len);
381       
382       break;
383       
384     case USB_REQ_GET_INTERFACE :
385       USBD_CtlSendData (pdev,
386                         (uint8_t *)&USBD_HID_AltSet,
387                         1);
388       break;
389       
390     case USB_REQ_SET_INTERFACE :
391       USBD_HID_AltSet = (uint8_t)(req->wValue);
392       break;
393     }
394   }
395   return USBD_OK;
396 }
397
398 /**
399   * @brief  USBD_HID_SendReport 
400   *         Send HID Report
401   * @param  pdev: device instance
402   * @param  buff: pointer to report
403   * @retval status
404   */
405 uint8_t USBD_HID_SendReport     (USB_OTG_CORE_HANDLE  *pdev, 
406                                  uint8_t *report,
407                                  uint16_t len)
408 {
409   if (pdev->dev.device_status == USB_OTG_CONFIGURED )
410   {
411     DCD_EP_Tx (pdev, HID_IN_EP, report, len);
412   }
413   return USBD_OK;
414 }
415
416 /**
417   * @brief  USBD_HID_GetCfgDesc 
418   *         return configuration descriptor
419   * @param  speed : current device speed
420   * @param  length : pointer data length
421   * @retval pointer to descriptor buffer
422   */
423 static uint8_t  *USBD_HID_GetCfgDesc (uint8_t speed, uint16_t *length)
424 {
425   *length = sizeof (USBD_HID_CfgDesc);
426   return USBD_HID_CfgDesc;
427 }
428
429 /**
430   * @brief  USBD_HID_DataIn
431   *         handle data IN Stage
432   * @param  pdev: device instance
433   * @param  epnum: endpoint index
434   * @retval status
435   */
436 static uint8_t  USBD_HID_DataIn (void  *pdev, 
437                               uint8_t epnum)
438 {
439   
440   /* Ensure that the FIFO is empty before a new transfer, this condition could 
441   be caused by  a new transfer before the end of the previous transfer */
442   DCD_EP_Flush(pdev, HID_IN_EP);
443   return USBD_OK;
444 }
445
446 /**
447   * @}
448   */ 
449
450
451 /**
452   * @}
453   */ 
454
455
456 /**
457   * @}
458   */ 
459
460 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/