M480 BSP  V3.05.001
The Board Support Package for M480 Series
hid_driver.c
Go to the documentation of this file.
1 /**************************************************************************/
10 #include <stdio.h>
11 #include <string.h>
12 
13 #include "NuMicro.h"
14 
15 #include "usb.h"
16 #include "usbh_lib.h"
17 #include "usbh_hid.h"
18 
19 
21 
22 extern int hid_parse_report_descriptor(HID_DEV_T *hdev, IFACE_T *iface);
23 
24 static HID_DEV_T g_hid_dev[CONFIG_HID_MAX_DEV];
25 
26 static HID_DEV_T *g_hdev_list = NULL;
27 
28 static HID_DEV_T *alloc_hid_device(void)
29 {
30  int i;
31 
32  for (i = 0; i < CONFIG_HID_MAX_DEV; i++)
33  {
34  if (g_hid_dev[i].iface == NULL)
35  {
36  memset((char *)&g_hid_dev[i], 0, sizeof(HID_DEV_T));
37  g_hid_dev[i].uid = get_ticks();
38  return &g_hid_dev[i];
39  }
40  }
41  return NULL;
42 }
43 
44 void free_hid_device(HID_DEV_T *hid_dev)
45 {
46  hid_dev->iface = NULL;
47  memset((char *)hid_dev, 0, sizeof(HID_DEV_T));
48 }
49 
50 
51 static int hid_probe(IFACE_T *iface)
52 {
53  UDEV_T *udev = iface->udev;
54  ALT_IFACE_T *aif = iface->aif;
55  DESC_IF_T *ifd;
56  EP_INFO_T *ep;
57  HID_DEV_T *hdev, *p;
58  int i;
59 
60  ifd = aif->ifd;
61 
62  /* Is this interface HID class? */
63  if (ifd->bInterfaceClass != USB_CLASS_HID)
64  return USBH_ERR_NOT_MATCHED;
65 
66  HID_DBGMSG("hid_probe - device (vid=0x%x, pid=0x%x), interface %d, subclass 0x%x, protocol 0x%x.\n",
67  udev->descriptor.idVendor, udev->descriptor.idProduct, ifd->bInterfaceNumber,
68  ifd->bInterfaceSubClass, ifd->bInterfaceProtocol);
69 
70  /*
71  * Try to find any interrupt endpoints
72  */
73  for (i = 0; i < aif->ifd->bNumEndpoints; i++)
74  {
75  if ((aif->ep[i].bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_INT)
76  {
77  ep = &aif->ep[i];
78  break;
79  }
80  }
81 
82  if (ep == NULL)
83  return USBH_ERR_NOT_MATCHED; // No endpoints, Ignore this interface
84 
85  hdev = alloc_hid_device();
86  if (hdev == NULL)
87  return HID_RET_OUT_OF_MEMORY;
88 
89  hdev->iface = iface;
90  hdev->idVendor = udev->descriptor.idVendor;
91  hdev->idProduct = udev->descriptor.idProduct;
92  hdev->bSubClassCode = ifd->bInterfaceSubClass;
93  hdev->bProtocolCode = ifd->bInterfaceProtocol;
94  hdev->next = NULL;
95  iface->context = (void *)hdev;
96 
97  hid_parse_report_descriptor(hdev, iface);
98 
99  /*
100  * Chaining newly found HID device to end of HID device list.
101  */
102  if (g_hdev_list == NULL)
103  g_hdev_list = hdev;
104  else
105  {
106  for (p = g_hdev_list; p->next != NULL; p = p->next)
107  ;
108  p->next = hdev;
109  }
110 
111  HID_DBGMSG("usbhid_probe OK. hdev=0x%x\n", (int)hdev);
112 
113  return 0;
114 }
115 
116 
117 static void hid_disconnect(IFACE_T *iface)
118 {
119  HID_DEV_T *hdev, *p;
120  UTR_T *utr;
121  RP_INFO_T *rp, *next_rp;
122  int i;
123 
124  hdev = (HID_DEV_T *)(iface->context);
125 
126  for (i = 0; i < iface->aif->ifd->bNumEndpoints; i++)
127  {
128  iface->udev->hc_driver->quit_xfer(NULL, &(iface->aif->ep[i]));
129  }
130 
131  /*
132  * Abort all UTR of this HID device (interface)
133  */
134  for (i = 0; i < CONFIG_HID_DEV_MAX_PIPE; i++)
135  {
136  utr = hdev->utr_list[i];
137  if (utr != NULL)
138  {
139  usbh_quit_utr(utr); /* Quit the UTR */
140  usbh_free_mem(utr->buff, utr->ep->wMaxPacketSize);
141  free_utr(utr);
142  }
143  }
144 
145  if (hdev->rpd.utr_led != NULL)
146  {
147  usbh_quit_utr(hdev->rpd.utr_led); /* Quit the UTR */
148  free_utr(hdev->rpd.utr_led);
149  }
150 
151  if (hdev->rpd.report != NULL)
152  {
153  for (rp = hdev->rpd.report; rp != NULL; )
154  {
155  next_rp = rp->next;
156  usbh_free_mem(rp, sizeof(RP_INFO_T));
157  rp = next_rp;
158  };
159  }
160 
161  /*
162  * remove it from HID device list
163  */
164  for (i = 0; i < CONFIG_HID_MAX_DEV; i++)
165  {
166  if (g_hid_dev[i].iface == iface)
167  {
168  hdev = &g_hid_dev[i];
169 
170  if (hdev == g_hdev_list)
171  {
172  g_hdev_list = g_hdev_list->next;
173  }
174  else
175  {
176  for (p = g_hdev_list; p != NULL; p = p->next)
177  {
178  if (p->next == hdev)
179  {
180  p->next = hdev->next;
181  break;
182  }
183  }
184  }
185  HID_DBGMSG("hid_disconnect - device (vid=0x%x, pid=0x%x), interface %d.\n",
186  hdev->idVendor, hdev->idProduct, iface->if_num);
187  free_hid_device(hdev);
188  }
189  }
190 }
191 
192 
193 UDEV_DRV_T hid_driver =
194 {
195  hid_probe,
196  hid_disconnect,
197  NULL, /* suspend */
198  NULL, /* resume */
199 };
200 
201 
203 
204 
209 void usbh_hid_init(void)
210 {
211  memset((char *)&g_hid_dev[0], 0, sizeof(g_hid_dev));
212  g_hdev_list = NULL;
213  usbh_register_driver(&hid_driver);
214 }
215 
216 
226 {
227  return g_hdev_list;
228 }
229 
230 
231 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
232 
HID_DEV_T * usbh_hid_get_device_list(void)
Get a list of currently connected USB Hid devices.
Definition: hid_driver.c:225
NuMicro peripheral access layer header file.
void usbh_hid_init(void)
Initialize USB Host HID driver.
Definition: hid_driver.c:209
USB Host HID class driver header file.
USB Host library exported header file.
uint32_t get_ticks(void)
A function return current tick count.
UDEV_T * udev
Definition: usbh_uac.h:111
USB Host library header file.
#define HID_RET_OUT_OF_MEMORY
Definition: usbh_lib.h:89
#define CONFIG_HID_DEV_MAX_PIPE
Definition: usbh_hid.h:53
#define NULL
NULL pointer.
Definition: M480.h:604
#define USBH_ERR_NOT_MATCHED
Definition: usbh_lib.h:36
#define CONFIG_HID_MAX_DEV
Definition: usbh_hid.h:52
HIDDEN_SYMBOLS struct usbhid_dev HID_DEV_T