1 /*
2  * File      : hid.c
3  * COPYRIGHT (C) 2006 - 2021, RT-Thread Development Team
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * Change Logs:
8  * Date           Author       Notes
9  * 2017-03-13     Urey         the first version
10  * 2017-11-16     ZYH          Update to common hid
11  */
12 
13 #include <rthw.h>
14 #include <rtdevice.h>
15 #include "drivers/usb_common.h"
16 #include "drivers/usb_device.h"
17 #include "hid.h"
18 
19 #ifdef RT_USB_DEVICE_HID
20 
21 #define DBG_TAG           "usbdevice.hid"
22 #define DBG_LVL           DBG_INFO
23 #include <rtdbg.h>
24 
25 #define HID_INTF_STR_INDEX 7
26 struct hid_s
27 {
28     struct rt_device parent;
29     struct ufunction *func;
30     uep_t ep_in;
31     uep_t ep_out;
32     int status;
33     rt_uint8_t protocol;
34     rt_uint8_t report_buf[MAX_REPORT_SIZE];
35     struct rt_messagequeue hid_mq;
36 };
37 
38 /* CustomHID_ConfigDescriptor */
39 rt_align(4)
40 const rt_uint8_t _report_desc[]=
41 {
42 #ifdef RT_USB_DEVICE_HID_KEYBOARD
43     USAGE_PAGE(1),      0x01,
44     USAGE(1),           0x06,
45     COLLECTION(1),      0x01,
46     REPORT_ID(1),       HID_REPORT_ID_KEYBOARD1,
47 
48     USAGE_PAGE(1),      0x07,
49     USAGE_MINIMUM(1),   0xE0,
50     USAGE_MAXIMUM(1),   0xE7,
51     LOGICAL_MINIMUM(1), 0x00,
52     LOGICAL_MAXIMUM(1), 0x01,
53     REPORT_SIZE(1),     0x01,
54     REPORT_COUNT(1),    0x08,
55     INPUT(1),           0x02,
56     REPORT_COUNT(1),    0x01,
57     REPORT_SIZE(1),     0x08,
58     INPUT(1),           0x01,
59 
60 
61     REPORT_COUNT(1),    0x05,
62     REPORT_SIZE(1),     0x01,
63     USAGE_PAGE(1),      0x08,
64     USAGE_MINIMUM(1),   0x01,
65     USAGE_MAXIMUM(1),   0x05,
66     OUTPUT(1),          0x02,
67     REPORT_COUNT(1),    0x01,
68     REPORT_SIZE(1),     0x03,
69     OUTPUT(1),          0x01,
70 
71 
72     REPORT_COUNT(1),    0x06,
73     REPORT_SIZE(1),     0x08,
74     LOGICAL_MINIMUM(1), 0x00,
75     LOGICAL_MAXIMUM(1), 0x65,
76     USAGE_PAGE(1),      0x07,
77     USAGE_MINIMUM(1),   0x00,
78     USAGE_MAXIMUM(1),   0x65,
79     INPUT(1),           0x00,
80     END_COLLECTION(0),
81 #if RT_USB_DEVICE_HID_KEYBOARD_NUMBER>1
82     /****keyboard2*****/
83     USAGE_PAGE(1),      0x01,
84     USAGE(1),           0x06,
85     COLLECTION(1),      0x01,
86     REPORT_ID(1),       HID_REPORT_ID_KEYBOARD2,
87 
88     USAGE_PAGE(1),      0x07,
89     USAGE_MINIMUM(1),   0xE0,
90     USAGE_MAXIMUM(1),   0xE7,
91     LOGICAL_MINIMUM(1), 0x00,
92     LOGICAL_MAXIMUM(1), 0x01,
93     REPORT_SIZE(1),     0x01,
94     REPORT_COUNT(1),    0x08,
95     INPUT(1),           0x02,
96     REPORT_COUNT(1),    0x01,
97     REPORT_SIZE(1),     0x08,
98     INPUT(1),           0x01,
99 
100     REPORT_COUNT(1),    0x06,
101     REPORT_SIZE(1),     0x08,
102     LOGICAL_MINIMUM(1), 0x00,
103     LOGICAL_MAXIMUM(1), 0x65,
104     USAGE_PAGE(1),      0x07,
105     USAGE_MINIMUM(1),   0x00,
106     USAGE_MAXIMUM(1),   0x65,
107     INPUT(1),           0x00,
108     END_COLLECTION(0),
109 #if RT_USB_DEVICE_HID_KEYBOARD_NUMBER>2
110     USAGE_PAGE(1),      0x01,
111     USAGE(1),           0x06,
112     COLLECTION(1),      0x01,
113     REPORT_ID(1),       HID_REPORT_ID_KEYBOARD3,
114 
115     USAGE_PAGE(1),      0x07,
116     USAGE_MINIMUM(1),   0xE0,
117     USAGE_MAXIMUM(1),   0xE7,
118     LOGICAL_MINIMUM(1), 0x00,
119     LOGICAL_MAXIMUM(1), 0x01,
120     REPORT_SIZE(1),     0x01,
121     REPORT_COUNT(1),    0x08,
122     INPUT(1),           0x02,
123     REPORT_COUNT(1),    0x01,
124     REPORT_SIZE(1),     0x08,
125     INPUT(1),           0x01,
126 
127     REPORT_COUNT(1),    0x06,
128     REPORT_SIZE(1),     0x08,
129     LOGICAL_MINIMUM(1), 0x00,
130     LOGICAL_MAXIMUM(1), 0x65,
131     USAGE_PAGE(1),      0x07,
132     USAGE_MINIMUM(1),   0x00,
133     USAGE_MAXIMUM(1),   0x65,
134     INPUT(1),           0x00,
135     END_COLLECTION(0),
136 #if RT_USB_DEVICE_HID_KEYBOARD_NUMBER>3
137     USAGE_PAGE(1),      0x01,
138     USAGE(1),           0x06,
139     COLLECTION(1),      0x01,
140     REPORT_ID(1),       HID_REPORT_ID_KEYBOARD4,
141 
142     USAGE_PAGE(1),      0x07,
143     USAGE_MINIMUM(1),   0xE0,
144     USAGE_MAXIMUM(1),   0xE7,
145     LOGICAL_MINIMUM(1), 0x00,
146     LOGICAL_MAXIMUM(1), 0x01,
147     REPORT_SIZE(1),     0x01,
148     REPORT_COUNT(1),    0x08,
149     INPUT(1),           0x02,
150     REPORT_COUNT(1),    0x01,
151     REPORT_SIZE(1),     0x08,
152     INPUT(1),           0x01,
153 
154     REPORT_COUNT(1),    0x06,
155     REPORT_SIZE(1),     0x08,
156     LOGICAL_MINIMUM(1), 0x00,
157     LOGICAL_MAXIMUM(1), 0x65,
158     USAGE_PAGE(1),      0x07,
159     USAGE_MINIMUM(1),   0x00,
160     USAGE_MAXIMUM(1),   0x65,
161     INPUT(1),           0x00,
162     END_COLLECTION(0),
163 #endif
164 #endif
165 #endif
166 #endif
167     // Media Control
168 #ifdef RT_USB_DEVICE_HID_MEDIA
169     USAGE_PAGE(1),      0x0C,
170     USAGE(1),           0x01,
171     COLLECTION(1),      0x01,
172     REPORT_ID(1),       HID_REPORT_ID_MEDIA,
173     USAGE_PAGE(1),      0x0C,
174     LOGICAL_MINIMUM(1), 0x00,
175     LOGICAL_MAXIMUM(1), 0x01,
176     REPORT_SIZE(1),     0x01,
177     REPORT_COUNT(1),    0x07,
178     USAGE(1),           0xB5,             // Next Track
179     USAGE(1),           0xB6,             // Previous Track
180     USAGE(1),           0xB7,             // Stop
181     USAGE(1),           0xCD,             // Play / Pause
182     USAGE(1),           0xE2,             // Mute
183     USAGE(1),           0xE9,             // Volume Up
184     USAGE(1),           0xEA,             // Volume Down
185     INPUT(1),           0x02,             // Input (Data, Variable, Absolute)
186     REPORT_COUNT(1),    0x01,
187     INPUT(1),           0x01,
188     END_COLLECTION(0),
189 #endif
190 
191 #ifdef RT_USB_DEVICE_HID_GENERAL
192     USAGE_PAGE(1),      0x8c,
193     USAGE(1),           0x01,
194     COLLECTION(1),      0x01,
195     REPORT_ID(1),       HID_REPORT_ID_GENERAL,
196 
197     REPORT_COUNT(1),    RT_USB_DEVICE_HID_GENERAL_IN_REPORT_LENGTH,
198     USAGE(1),           0x03,
199     REPORT_SIZE(1),     0x08,
200     LOGICAL_MINIMUM(1), 0x00,
201     LOGICAL_MAXIMUM(1), 0xFF,
202     INPUT(1),           0x02,
203 
204     REPORT_COUNT(1),    RT_USB_DEVICE_HID_GENERAL_OUT_REPORT_LENGTH,
205     USAGE(1),           0x04,
206     REPORT_SIZE(1),     0x08,
207     LOGICAL_MINIMUM(1), 0x00,
208     LOGICAL_MAXIMUM(1), 0xFF,
209     OUTPUT(1),          0x02,
210     END_COLLECTION(0),
211 #endif
212 #ifdef RT_USB_DEVICE_HID_MOUSE
213     USAGE_PAGE(1),      0x01,           // Generic Desktop
214     USAGE(1),           0x02,           // Mouse
215     COLLECTION(1),      0x01,           // Application
216     USAGE(1),           0x01,           // Pointer
217     COLLECTION(1),      0x00,           // Physical
218     REPORT_ID(1),       HID_REPORT_ID_MOUSE,
219     REPORT_COUNT(1),    0x03,
220     REPORT_SIZE(1),     0x01,
221     USAGE_PAGE(1),      0x09,           // Buttons
222     USAGE_MINIMUM(1),   0x1,
223     USAGE_MAXIMUM(1),   0x3,
224     LOGICAL_MINIMUM(1), 0x00,
225     LOGICAL_MAXIMUM(1), 0x01,
226     INPUT(1),           0x02,
227     REPORT_COUNT(1),    0x01,
228     REPORT_SIZE(1),     0x05,
229     INPUT(1),           0x01,
230     REPORT_COUNT(1),    0x03,
231     REPORT_SIZE(1),     0x08,
232     USAGE_PAGE(1),      0x01,
233     USAGE(1),           0x30,           // X
234     USAGE(1),           0x31,           // Y
235     USAGE(1),           0x38,           // scroll
236     LOGICAL_MINIMUM(1), 0x81,
237     LOGICAL_MAXIMUM(1), 0x7f,
238     INPUT(1),           0x06,
239     END_COLLECTION(0),
240     END_COLLECTION(0),
241 #endif
242 }; /* CustomHID_ReportDescriptor */
243 
244 rt_align(4)
245 static struct udevice_descriptor _dev_desc =
246 {
247     USB_DESC_LENGTH_DEVICE,     //bLength;
248     USB_DESC_TYPE_DEVICE,       //type;
249     USB_BCD_VERSION,            //bcdUSB;
250     0x0,                        //bDeviceClass;
251     0x00,                       //bDeviceSubClass;
252     0x00,                       //bDeviceProtocol;
253     64,                         //bMaxPacketSize0;
254     _VENDOR_ID,                 //idVendor;
255     _PRODUCT_ID,                //idProduct;
256     USB_BCD_DEVICE,             //bcdDevice;
257     USB_STRING_MANU_INDEX,      //iManufacturer;
258     USB_STRING_PRODUCT_INDEX,   //iProduct;
259     USB_STRING_SERIAL_INDEX,    //iSerialNumber;
260     USB_DYNAMIC,                //bNumConfigurations;
261 };
262 
263 //FS and HS needed
264 rt_align(4)
265 static struct usb_qualifier_descriptor dev_qualifier =
266 {
267     sizeof(dev_qualifier),          //bLength
268     USB_DESC_TYPE_DEVICEQUALIFIER,  //bDescriptorType
269     0x0200,                         //bcdUSB
270     0x0,                            //bDeviceClass
271     0x0,                            //bDeviceSubClass
272     0x50,                           //bDeviceProtocol
273     64,                             //bMaxPacketSize0
274     0x01,                           //bNumConfigurations
275     0,
276 };
277 
278 
279 /* hid interface descriptor */
280 rt_align(4)
281 const static struct uhid_comm_descriptor _hid_comm_desc =
282 {
283 #ifdef RT_USB_DEVICE_COMPOSITE
284     /* Interface Association Descriptor */
285     {
286         USB_DESC_LENGTH_IAD,
287         USB_DESC_TYPE_IAD,
288         USB_DYNAMIC,
289         0x01,
290         0x03,                       /* bInterfaceClass: HID */
291 #if defined(RT_USB_DEVICE_HID_KEYBOARD)||defined(RT_USB_DEVICE_HID_MOUSE)
292         USB_HID_SUBCLASS_BOOT,    /* bInterfaceSubClass : 1=BOOT, 0=no boot */
293 #else
294         USB_HID_SUBCLASS_NOBOOT,    /* bInterfaceSubClass : 1=BOOT, 0=no boot */
295 #endif
296 #if !defined(RT_USB_DEVICE_HID_KEYBOARD)||!defined(RT_USB_DEVICE_HID_MOUSE)||!defined(RT_USB_DEVICE_HID_MEDIA)
297         USB_HID_PROTOCOL_NONE,      /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
298 #elif !defined(RT_USB_DEVICE_HID_MOUSE)
299         USB_HID_PROTOCOL_KEYBOARD,  /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
300 #else
301         USB_HID_PROTOCOL_MOUSE,     /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
302 #endif
303         0x00,
304     },
305 #endif
306     /* Interface Descriptor */
307     {
308         USB_DESC_LENGTH_INTERFACE,
309         USB_DESC_TYPE_INTERFACE,
310         USB_DYNAMIC,                /* bInterfaceNumber: Number of Interface */
311         0x00,                       /* bAlternateSetting: Alternate setting */
312         0x02,                       /* bNumEndpoints */
313         0x03,                       /* bInterfaceClass: HID */
314 #if defined(RT_USB_DEVICE_HID_KEYBOARD)||defined(RT_USB_DEVICE_HID_MOUSE)
315         USB_HID_SUBCLASS_BOOT,    /* bInterfaceSubClass : 1=BOOT, 0=no boot */
316 #else
317         USB_HID_SUBCLASS_NOBOOT,    /* bInterfaceSubClass : 1=BOOT, 0=no boot */
318 #endif
319 #if !defined(RT_USB_DEVICE_HID_KEYBOARD)||!defined(RT_USB_DEVICE_HID_MOUSE)||!defined(RT_USB_DEVICE_HID_MEDIA)
320         USB_HID_PROTOCOL_NONE,      /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
321 #elif !defined(RT_USB_DEVICE_HID_MOUSE)
322         USB_HID_PROTOCOL_KEYBOARD,  /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
323 #else
324         USB_HID_PROTOCOL_MOUSE,     /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
325 #endif
326 #ifdef RT_USB_DEVICE_COMPOSITE
327         HID_INTF_STR_INDEX,         /* iInterface: Index of string descriptor */
328 #else
329         0,
330 #endif
331     },
332 
333     /* HID Descriptor */
334     {
335         HID_DESCRIPTOR_SIZE,        /* bLength: HID Descriptor size */
336         HID_DESCRIPTOR_TYPE,        /* bDescriptorType: HID */
337         0x0110,                     /* bcdHID: HID Class Spec release number */
338         0x00,                       /* bCountryCode: Hardware target country */
339         0x01,                       /* bNumDescriptors: Number of HID class descriptors to follow */
340         {
341             {
342                 0x22,                       /* bDescriptorType */
343                 sizeof(_report_desc),       /* wItemLength: Total length of Report descriptor */
344             },
345         },
346     },
347 
348     /* Endpoint Descriptor IN */
349     {
350         USB_DESC_LENGTH_ENDPOINT,
351         USB_DESC_TYPE_ENDPOINT,
352         USB_DYNAMIC | USB_DIR_IN,
353         USB_EP_ATTR_INT,
354         0x40,
355         0x0A,
356     },
357 
358     /* Endpoint Descriptor OUT */
359     {
360         USB_DESC_LENGTH_ENDPOINT,
361         USB_DESC_TYPE_ENDPOINT,
362         USB_DYNAMIC | USB_DIR_OUT,
363         USB_EP_ATTR_INT,
364         0x40,
365         0x01,
366     },
367 };
368 
369 rt_align(4)
370 const static char* _ustring[] =
371 {
372     "Language",
373     "RT-Thread Team.",
374     "RTT HID-Device",
375     "32021919830108",
376     "Configuration",
377     "Interface",
378 };
379 
dump_data(rt_uint8_t * data,rt_size_t size)380 static void dump_data(rt_uint8_t *data, rt_size_t size)
381 {
382     rt_size_t i;
383     for (i = 0; i < size; i++)
384     {
385         rt_kprintf("%02x ", *data++);
386         if ((i + 1) % 8 == 0)
387         {
388             rt_kprintf("\n");
389         }else if ((i + 1) % 4 == 0){
390             rt_kprintf(" ");
391         }
392     }
393 }
dump_report(struct hid_report * report)394 static void dump_report(struct hid_report * report)
395 {
396     rt_kprintf("\nHID Recived:");
397     rt_kprintf("\nReport ID %02x \n", report->report_id);
398     dump_data(report->report,report->size);
399 }
400 
_ep_out_handler(ufunction_t func,rt_size_t size)401 static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
402 {
403     struct hid_s *data;
404     struct hid_report report;
405     RT_ASSERT(func != RT_NULL);
406     RT_ASSERT(func->device != RT_NULL);
407     data = (struct hid_s *) func->user_data;
408 
409     if(size != 0)
410     {
411         rt_memcpy((void *)&report,(void*)data->ep_out->buffer,size);
412         report.size = size-1;
413         rt_mq_send(&data->hid_mq,(void *)&report,sizeof(report));
414     }
415 
416     data->ep_out->request.buffer = data->ep_out->buffer;
417     data->ep_out->request.size = EP_MAXPACKET(data->ep_out);
418     data->ep_out->request.req_type = UIO_REQUEST_READ_BEST;
419     rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
420     return RT_EOK;
421 }
422 
_ep_in_handler(ufunction_t func,rt_size_t size)423 static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
424 {
425     struct hid_s *data;
426     RT_ASSERT(func != RT_NULL);
427     RT_ASSERT(func->device != RT_NULL);
428 
429     data = (struct hid_s *) func->user_data;
430     if(data->parent.tx_complete != RT_NULL)
431     {
432         data->parent.tx_complete(&data->parent,RT_NULL);
433     }
434     return RT_EOK;
435 }
436 
_hid_set_report_callback(udevice_t device,rt_size_t size)437 static rt_err_t _hid_set_report_callback(udevice_t device, rt_size_t size)
438 {
439     LOG_D("_hid_set_report_callback");
440 
441     if(size != 0)
442     {
443     }
444 
445     dcd_ep0_send_status(device->dcd);
446 
447     return RT_EOK;
448 }
449 
450 /**
451  * This function will handle hid interface bRequest.
452  *
453  * @param device the usb device object.
454  * @param setup the setup bRequest.
455  *
456  * @return RT_EOK on successful.
457  */
_interface_handler(ufunction_t func,ureq_t setup)458 static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
459 {
460     RT_ASSERT(func != RT_NULL);
461     RT_ASSERT(func->device != RT_NULL);
462     RT_ASSERT(setup != RT_NULL);
463 
464     struct hid_s *data = (struct hid_s *) func->user_data;
465 
466 
467     switch (setup->bRequest)
468     {
469     case USB_REQ_GET_DESCRIPTOR:
470         if((setup->wValue >> 8) == USB_DESC_TYPE_REPORT)
471         {
472             rt_usbd_ep0_write(func->device, (void *)(&_report_desc[0]), sizeof(_report_desc));
473         }
474         else if((setup->wValue >> 8) == USB_DESC_TYPE_HID)
475         {
476 
477             rt_usbd_ep0_write(func->device, (void *)(&_hid_comm_desc.hid_desc), sizeof(struct uhid_descriptor));
478         }
479         break;
480     case USB_HID_REQ_GET_REPORT:
481         if(setup->wLength == 0)
482         {
483             rt_usbd_ep0_set_stall(func->device);
484             break;
485         }
486         if((setup->wLength == 0) || (setup->wLength > MAX_REPORT_SIZE))
487             setup->wLength = MAX_REPORT_SIZE;
488         rt_usbd_ep0_write(func->device, data->report_buf,setup->wLength);
489         break;
490     case USB_HID_REQ_GET_IDLE:
491 
492         dcd_ep0_send_status(func->device->dcd);
493         break;
494     case USB_HID_REQ_GET_PROTOCOL:
495         rt_usbd_ep0_write(func->device, &data->protocol,1);
496         break;
497     case USB_HID_REQ_SET_REPORT:
498 
499         if((setup->wLength == 0) || (setup->wLength > MAX_REPORT_SIZE))
500             rt_usbd_ep0_set_stall(func->device);
501 
502         rt_usbd_ep0_read(func->device, data->report_buf, setup->wLength, _hid_set_report_callback);
503         break;
504     case USB_HID_REQ_SET_IDLE:
505         dcd_ep0_send_status(func->device->dcd);
506         break;
507     case USB_HID_REQ_SET_PROTOCOL:
508         data->protocol = setup->wValue;
509 
510         dcd_ep0_send_status(func->device->dcd);
511         break;
512     }
513 
514     return RT_EOK;
515 }
516 
517 
518 /**
519  * This function will run cdc function, it will be called on handle set configuration bRequest.
520  *
521  * @param func the usb function object.
522  *
523  * @return RT_EOK on successful.
524  */
_function_enable(ufunction_t func)525 static rt_err_t _function_enable(ufunction_t func)
526 {
527     struct hid_s *data;
528 
529     RT_ASSERT(func != RT_NULL);
530     RT_ASSERT(func->device != RT_NULL);
531     data = (struct hid_s *) func->user_data;
532 
533     LOG_D("hid function enable");
534 //
535 //    _vcom_reset_state(func);
536 //
537     if(data->ep_out->buffer == RT_NULL)
538     {
539         data->ep_out->buffer        = rt_malloc(HID_RX_BUFSIZE);
540     }
541     data->ep_out->request.buffer    = data->ep_out->buffer;
542     data->ep_out->request.size      = EP_MAXPACKET(data->ep_out);
543     data->ep_out->request.req_type  = UIO_REQUEST_READ_BEST;
544 
545     rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
546 
547     return RT_EOK;
548 }
549 
550 /**
551  * This function will stop cdc function, it will be called on handle set configuration bRequest.
552  *
553  * @param func the usb function object.
554  *
555  * @return RT_EOK on successful.
556  */
_function_disable(ufunction_t func)557 static rt_err_t _function_disable(ufunction_t func)
558 {
559     struct hid_s *data;
560 
561     RT_ASSERT(func != RT_NULL);
562     RT_ASSERT(func->device != RT_NULL);
563     data = (struct hid_s *) func->user_data;
564 
565     LOG_D("hid function disable");
566 
567     if(data->ep_out->buffer != RT_NULL)
568     {
569         rt_free(data->ep_out->buffer);
570         data->ep_out->buffer = RT_NULL;
571     }
572 
573     return RT_EOK;
574 }
575 
576 static struct ufunction_ops ops =
577 {
578     _function_enable,
579     _function_disable,
580     RT_NULL,
581 };
582 
583 
584 
585 
586 /**
587  * This function will configure hid descriptor.
588  *
589  * @param comm the communication interface number.
590  * @param data the data interface number.
591  *
592  * @return RT_EOK on successful.
593  */
_hid_descriptor_config(uhid_comm_desc_t hid,rt_uint8_t cintf_nr)594 static rt_err_t _hid_descriptor_config(uhid_comm_desc_t hid, rt_uint8_t cintf_nr)
595 {
596 #ifdef RT_USB_DEVICE_COMPOSITE
597     hid->iad_desc.bFirstInterface = cintf_nr;
598 #endif
599 
600     return RT_EOK;
601 }
_hid_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)602 static rt_ssize_t _hid_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
603 {
604     struct hid_s *hiddev = (struct hid_s *)dev;
605     struct hid_report report;
606     if (hiddev->func->device->state == USB_STATE_CONFIGURED)
607     {
608         report.report_id = pos;
609         rt_memcpy((void *)report.report,(void *)buffer,size);
610         report.size = size;
611         hiddev->ep_in->request.buffer = (void *)&report;
612         hiddev->ep_in->request.size = (size+1) > 64 ? 64 : size+1;
613         hiddev->ep_in->request.req_type = UIO_REQUEST_WRITE;
614         rt_usbd_io_request(hiddev->func->device, hiddev->ep_in, &hiddev->ep_in->request);
615         return size;
616     }
617 
618     return 0;
619 }
HID_Report_Received(hid_report_t report)620 rt_weak void HID_Report_Received(hid_report_t report)
621 {
622     dump_report(report);
623 }
624 rt_align(RT_ALIGN_SIZE)
625 static rt_uint8_t hid_thread_stack[512];
626 static struct rt_thread hid_thread;
627 
hid_thread_entry(void * parameter)628 static void hid_thread_entry(void* parameter)
629 {
630     struct hid_report report;
631     struct hid_s *hiddev;
632     hiddev = (struct hid_s *)parameter;
633     while(1)
634     {
635         if(rt_mq_recv(&hiddev->hid_mq, &report, sizeof(report),RT_WAITING_FOREVER) < 0)
636             continue;
637         HID_Report_Received(&report);
638     }
639 }
640 
641 #ifdef RT_USING_DEVICE_OPS
642 const static struct rt_device_ops hid_device_ops =
643 {
644     RT_NULL,
645     RT_NULL,
646     RT_NULL,
647     RT_NULL,
648     _hid_write,
649     RT_NULL,
650 };
651 #endif
652 
653 static rt_uint8_t hid_mq_pool[(sizeof(struct hid_report)+sizeof(void*))*8];
rt_usb_hid_init(struct ufunction * func)654 static void rt_usb_hid_init(struct ufunction *func)
655 {
656     struct hid_s *hiddev;
657     hiddev = (struct hid_s *)func->user_data;
658     rt_memset(&hiddev->parent, 0, sizeof(hiddev->parent));
659 
660 #ifdef RT_USING_DEVICE_OPS
661     hiddev->parent.ops   = &hid_device_ops;
662 #else
663     hiddev->parent.write = _hid_write;
664 #endif
665     hiddev->func = func;
666 
667     rt_device_register(&hiddev->parent, "hidd", RT_DEVICE_FLAG_RDWR);
668     rt_mq_init(&hiddev->hid_mq, "hiddmq", hid_mq_pool, sizeof(struct hid_report),
669                             sizeof(hid_mq_pool), RT_IPC_FLAG_FIFO);
670 
671     rt_thread_init(&hid_thread, "hidd", hid_thread_entry, hiddev,
672             hid_thread_stack, sizeof(hid_thread_stack), RT_USBD_THREAD_PRIO, 20);
673     rt_thread_startup(&hid_thread);
674 }
675 
676 
677 /**
678  * This function will create a hid function instance.
679  *
680  * @param device the usb device object.
681  *
682  * @return RT_EOK on successful.
683  */
rt_usbd_function_hid_create(udevice_t device)684 ufunction_t rt_usbd_function_hid_create(udevice_t device)
685 {
686     ufunction_t     func;
687     struct hid_s   *data;
688 
689     uintf_t         hid_intf;
690     ualtsetting_t   hid_setting;
691     uhid_comm_desc_t hid_desc;
692 
693     /* parameter check */
694     RT_ASSERT(device != RT_NULL);
695 
696     /* set usb device string description */
697 #ifdef RT_USB_DEVICE_COMPOSITE
698     rt_usbd_device_set_interface_string(device, HID_INTF_STR_INDEX, _ustring[2]);
699 #else
700     rt_usbd_device_set_string(device, _ustring);
701 #endif
702     /* create a cdc function */
703     func = rt_usbd_function_new(device, &_dev_desc, &ops);
704 
705     /* For high speed mode supporting */
706     rt_usbd_device_set_qualifier(device, &dev_qualifier);
707 
708     /* allocate memory for cdc vcom data */
709     data = (struct hid_s*)rt_malloc(sizeof(struct hid_s));
710     rt_memset(data, 0, sizeof(struct hid_s));
711     func->user_data = (void*)data;
712 
713     /* create an interface object */
714     hid_intf = rt_usbd_interface_new(device, _interface_handler);
715 
716     /* create an alternate setting object */
717     hid_setting = rt_usbd_altsetting_new(sizeof(struct uhid_comm_descriptor));
718 
719     /* config desc in alternate setting */
720     rt_usbd_altsetting_config_descriptor(hid_setting, &_hid_comm_desc, (rt_off_t)&((uhid_comm_desc_t)0)->intf_desc);
721 
722     /* configure the hid interface descriptor */
723     _hid_descriptor_config(hid_setting->desc, hid_intf->intf_num);
724 
725     /* create endpoint */
726     hid_desc = (uhid_comm_desc_t)hid_setting->desc;
727     data->ep_out = rt_usbd_endpoint_new(&hid_desc->ep_out_desc, _ep_out_handler);
728     data->ep_in  = rt_usbd_endpoint_new(&hid_desc->ep_in_desc, _ep_in_handler);
729 
730     /* add the int out and int in endpoint to the alternate setting */
731     rt_usbd_altsetting_add_endpoint(hid_setting, data->ep_out);
732     rt_usbd_altsetting_add_endpoint(hid_setting, data->ep_in);
733 
734     /* add the alternate setting to the interface, then set default setting */
735     rt_usbd_interface_add_altsetting(hid_intf, hid_setting);
736     rt_usbd_set_altsetting(hid_intf, 0);
737 
738     /* add the interface to the mass storage function */
739     rt_usbd_function_add_interface(func, hid_intf);
740 
741     /* initilize hid */
742     rt_usb_hid_init(func);
743     return func;
744 }
745 struct udclass hid_class =
746 {
747     .rt_usbd_function_create = rt_usbd_function_hid_create
748 };
749 
rt_usbd_hid_class_register(void)750 int rt_usbd_hid_class_register(void)
751 {
752     rt_usbd_class_register(&hid_class);
753     return 0;
754 }
755 INIT_PREV_EXPORT(rt_usbd_hid_class_register);
756 #endif /* RT_USB_DEVICE_HID */
757