Wixel SDK
usb_hid.c
1 // TODO: Add a function for converting chars to keycodes. The test_hid app
2 // contains the start of such a function.
3 // TODO: Don't use double-buffered USB endpoints. It just increases latency.
4 
5 #include <usb_hid.h>
6 #include <usb.h>
7 #include <board.h>
8 #include <time.h>
9 
10 /* HID Library Configuration **************************************************/
11 
12 #define HID_IN_KEYBOARD_PACKET_SIZE 8
13 #define HID_IN_MOUSE_PACKET_SIZE 4
14 #define HID_IN_JOYSTICK_PACKET_SIZE 20
15 
16 #define HID_KEYBOARD_INTERFACE_NUMBER 0
17 #define HID_MOUSE_INTERFACE_NUMBER 1
18 #define HID_JOYSTICK_INTERFACE_NUMBER 2
19 
20 #define HID_KEYBOARD_ENDPOINT 1
21 #define HID_KEYBOARD_FIFO USBF1 // This must match HID_KEYBOARD_ENDPOINT!
22 
23 #define HID_MOUSE_ENDPOINT 2
24 #define HID_MOUSE_FIFO USBF2 // This must match HID_MOUSE_ENDPOINT!
25 
26 #define HID_JOYSTICK_ENDPOINT 3
27 #define HID_JOYSTICK_FIFO USBF3 // This must match HID_JOYSTICK_ENDPOINT!
28 
29 /* HID Constants **************************************************************/
30 
31 // USB Class Code from HID 1.11 Section 4.1: The HID Class
32 #define HID_CLASS 3
33 
34 // USB Subclass Code from HID 1.11 Section 4.2: Subclass
35 #define HID_SUBCLASS_BOOT 1
36 
37 // USB Protocol Codes from HID 1.11 Section 4.3: Protocols
38 #define HID_PROTOCOL_KEYBOARD 1
39 #define HID_PROTOCOL_MOUSE 2
40 
41 // USB Descriptor types from HID 1.11 Section 7.1
42 #define HID_DESCRIPTOR_TYPE_HID 0x21
43 #define HID_DESCRIPTOR_TYPE_REPORT 0x22
44 
45 // Country Codes from HID 1.11 Section 6.2.1
46 #define HID_COUNTRY_NOT_LOCALIZED 0
47 
48 // HID Report Items from HID 1.11 Section 6.2.2
49 #define HID_USAGE_PAGE 0x05
50 #define HID_USAGE 0x09
51 #define HID_COLLECTION 0xA1
52 #define HID_END_COLLECTION 0xC0
53 #define HID_REPORT_COUNT 0x95
54 #define HID_REPORT_SIZE 0x75
55 #define HID_USAGE_MIN 0x19
56 #define HID_USAGE_MAX 0x29
57 #define HID_LOGICAL_MIN 0x15
58 #define HID_LOGICAL_MIN_2 0x16 // 2-byte data
59 #define HID_LOGICAL_MAX 0x25
60 #define HID_LOGICAL_MAX_2 0x26 // 2-byte data
61 #define HID_INPUT 0x81
62 #define HID_OUTPUT 0x91
63 
64 // HID Report Usage Pages from HID Usage Tables 1.12 Section 3, Table 1
65 #define HID_USAGE_PAGE_GENERIC_DESKTOP 0x01
66 #define HID_USAGE_PAGE_KEY_CODES 0x07
67 #define HID_USAGE_PAGE_LEDS 0x08
68 #define HID_USAGE_PAGE_BUTTONS 0x09
69 
70 // HID Report Usages from HID Usage Tables 1.12 Section 4, Table 6
71 #define HID_USAGE_POINTER 0x01
72 #define HID_USAGE_MOUSE 0x02
73 #define HID_USAGE_JOYSTICK 0x04
74 #define HID_USAGE_KEYBOARD 0x06
75 #define HID_USAGE_X 0x30
76 #define HID_USAGE_Y 0x31
77 #define HID_USAGE_Z 0x32
78 #define HID_USAGE_RX 0x33
79 #define HID_USAGE_RY 0x34
80 #define HID_USAGE_RZ 0x35
81 #define HID_USAGE_SLIDER 0x36
82 #define HID_USAGE_DIAL 0x37
83 #define HID_USAGE_WHEEL 0x38
84 
85 // HID Report Collection Types from HID 1.12 6.2.2.6
86 #define HID_COLLECTION_PHYSICAL 0
87 #define HID_COLLECTION_APPLICATION 1
88 
89 // HID Input/Output/Feature Item Data (attributes) from HID 1.11 6.2.2.5
90 #define HID_ITEM_CONSTANT 0x1
91 #define HID_ITEM_VARIABLE 0x2
92 #define HID_ITEM_RELATIVE 0x4
93 
94 // Request Codes from HID 1.11 Section 7.2
95 #define HID_REQUEST_GET_REPORT 0x1
96 #define HID_REQUEST_GET_IDLE 0x2
97 #define HID_REQUEST_GET_PROTOCOL 0x3
98 #define HID_REQUEST_SET_REPORT 0x9
99 #define HID_REQUEST_SET_IDLE 0xA
100 #define HID_REQUEST_SET_PROTOCOL 0xB
101 
102 // Report Types from HID 1.11 Section 7.2.1
103 #define HID_REPORT_TYPE_INPUT 1
104 #define HID_REPORT_TYPE_OUTPUT 2
105 #define HID_REPORT_TYPE_FEATURE 3
106 
107 // Protocols from HID 1.11 Section 7.2.5
108 #define HID_PROTOCOL_BOOT 0
109 #define HID_PROTOCOL_REPORT 1
110 
111 /* HID USB Descriptors ****************************************************/
112 
114 {
115  sizeof(USB_DESCRIPTOR_DEVICE),
116  USB_DESCRIPTOR_TYPE_DEVICE,
117  0x0200, // USB Spec Release Number in BCD format
118  0, // Class Code: undefined (use class code info from Interface Descriptors)
119  0, // Subclass code
120  0, // Protocol
121  USB_EP0_PACKET_SIZE, // Max packet size for Endpoint 0
122  USB_VENDOR_ID_POLOLU, // Vendor ID
123  0x2201, // Product ID
124  0x0000, // Device release number in BCD format
125  1, // Index of Manufacturer String Descriptor
126  2, // Index of Product String Descriptor
127  3, // Index of Serial Number String Descriptor
128  1 // Number of possible configurations.
129 };
130 
131 // keyboard report descriptor
132 // HID 1.11 Section 6.2.2: Report Descriptor
133 // Uses format compatible with keyboard boot interface report descriptor - see HID 1.11 Appendix B.1
134 uint8 CODE keyboardReportDescriptor[]
135 =
136 {
137  HID_USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DESKTOP,
138  HID_USAGE, HID_USAGE_KEYBOARD,
139  HID_COLLECTION, HID_COLLECTION_APPLICATION,
140 
141  HID_REPORT_COUNT, 8, // 8 Modifier Keys
142  HID_REPORT_SIZE, 1,
143  HID_USAGE_PAGE, HID_USAGE_PAGE_KEY_CODES,
144  HID_USAGE_MIN, 0xE0, // Left Control
145  HID_USAGE_MAX, 0xE7, // Right GUI (Windows key) (highest defined usage ID)
146  HID_LOGICAL_MIN, 0,
147  HID_LOGICAL_MAX, 1,
148  HID_INPUT, HID_ITEM_VARIABLE,
149 
150  HID_REPORT_COUNT, 1, // Reserved (1 byte)
151  HID_REPORT_SIZE, 8,
152  HID_INPUT, HID_ITEM_CONSTANT,
153 
154  HID_REPORT_COUNT, 8, // 8 LEDs
155  HID_REPORT_SIZE, 1,
156  HID_USAGE_PAGE, HID_USAGE_PAGE_LEDS,
157  HID_USAGE_MIN, 0x1, // Num Lock
158  HID_USAGE_MAX, 0x8, // Do Not Disturb (TODO: use this as a bootloader signal?)
159  HID_OUTPUT, HID_ITEM_VARIABLE,
160 
161  HID_REPORT_COUNT, 6, // 6 Key Codes
162  HID_REPORT_SIZE, 8,
163  HID_USAGE_PAGE, HID_USAGE_PAGE_KEY_CODES,
164  HID_USAGE_MIN, 0,
165  HID_USAGE_MAX, 231,
166  HID_LOGICAL_MIN, 0,
167  HID_LOGICAL_MAX_2, 231, 0, // Logical Maximum is signed, so we need to use an extra byte to make sure the highest bit is 0
168  HID_INPUT, 0,
169 
170  HID_END_COLLECTION,
171 };
172 
173 // mouse report descriptor
174 // HID 1.11 Section 6.2.2: Report Descriptor
175 // Uses format compatible with mouse boot interface report descriptor - see HID 1.11 Appendix B.2
176 uint8 CODE mouseReportDescriptor[]
177 =
178 {
179  HID_USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DESKTOP,
180  HID_USAGE, HID_USAGE_MOUSE,
181  HID_COLLECTION, HID_COLLECTION_APPLICATION,
182 
183  HID_USAGE, HID_USAGE_POINTER,
184  HID_COLLECTION, HID_COLLECTION_PHYSICAL,
185 
186  HID_REPORT_COUNT, 8, // 8 Mouse Buttons
187  HID_REPORT_SIZE, 1,
188  HID_USAGE_PAGE, HID_USAGE_PAGE_BUTTONS,
189  HID_USAGE_MIN, 1,
190  HID_USAGE_MAX, 8,
191  HID_LOGICAL_MIN, 0,
192  HID_LOGICAL_MAX, 1,
193  HID_INPUT, HID_ITEM_VARIABLE,
194 
195  HID_REPORT_COUNT, 3, // 3 Axes (X, Y, wheel)
196  HID_REPORT_SIZE, 8,
197  HID_USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DESKTOP,
198  HID_USAGE, HID_USAGE_X,
199  HID_USAGE, HID_USAGE_Y,
200  HID_USAGE, HID_USAGE_WHEEL,
201  HID_LOGICAL_MIN, -127,
202  HID_LOGICAL_MAX, 127,
203  HID_INPUT, (HID_ITEM_VARIABLE | HID_ITEM_RELATIVE),
204 
205  HID_END_COLLECTION,
206 
207  HID_END_COLLECTION,
208 };
209 
210 // joystick report descriptor
211 // HID 1.11 Section 6.2.2: Report Descriptor
212 uint8 CODE joystickReportDescriptor[]
213 =
214 {
215  HID_USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DESKTOP,
216  HID_USAGE, HID_USAGE_JOYSTICK,
217  HID_COLLECTION, HID_COLLECTION_APPLICATION,
218 
219  HID_USAGE, HID_USAGE_POINTER,
220  HID_COLLECTION, HID_COLLECTION_PHYSICAL,
221 
222  HID_REPORT_COUNT, 8, // 8 Axes (X, Y, Z, Rx, Ry, Rz, Slider, Dial)
223  HID_REPORT_SIZE, 16,
224  HID_USAGE, HID_USAGE_X,
225  HID_USAGE, HID_USAGE_Y,
226  HID_USAGE, HID_USAGE_Z,
227  HID_USAGE, HID_USAGE_RX,
228  HID_USAGE, HID_USAGE_RY,
229  HID_USAGE, HID_USAGE_RZ,
230  HID_USAGE, HID_USAGE_SLIDER,
231  HID_USAGE, HID_USAGE_DIAL,
232  HID_LOGICAL_MIN_2, 0x01, 0x80, // -32767
233  HID_LOGICAL_MAX_2, 0xFF, 0x7F, // 32767
234  HID_INPUT, HID_ITEM_VARIABLE,
235 
236  HID_END_COLLECTION,
237 
238  HID_REPORT_COUNT, 32, // 32 Joystick Buttons
239  HID_REPORT_SIZE, 1,
240  HID_USAGE_PAGE, HID_USAGE_PAGE_BUTTONS,
241  HID_USAGE_MIN, 1,
242  HID_USAGE_MAX, 32,
243  HID_LOGICAL_MIN, 0,
244  HID_LOGICAL_MAX, 1,
245  HID_INPUT, HID_ITEM_VARIABLE,
246 
247  HID_END_COLLECTION,
248 };
249 
250 CODE struct CONFIG1 {
251  USB_DESCRIPTOR_CONFIGURATION configuration;
252 
253  USB_DESCRIPTOR_INTERFACE keyboard_interface;
254  uint8 keyboard_hid[9]; // HID Descriptor
255  USB_DESCRIPTOR_ENDPOINT keyboard_in;
256 
257  USB_DESCRIPTOR_INTERFACE mouse_interface;
258  uint8 mouse_hid[9]; // HID Descriptor
259  USB_DESCRIPTOR_ENDPOINT mouse_in;
260 
261  USB_DESCRIPTOR_INTERFACE joystick_interface;
262  uint8 joystick_hid[9]; // HID Descriptor
263  USB_DESCRIPTOR_ENDPOINT joystick_in;
264 } usbConfigurationDescriptor
265 =
266 {
267  { // Configuration Descriptor
269  USB_DESCRIPTOR_TYPE_CONFIGURATION,
270  sizeof(struct CONFIG1), // wTotalLength
271  3, // bNumInterfaces
272  1, // bConfigurationValue
273  0, // iConfiguration
274  0xC0, // bmAttributes: self powered (but may use bus power)
275  50, // bMaxPower
276  },
277  { // Keyboard Interface
278  sizeof(USB_DESCRIPTOR_INTERFACE),
279  USB_DESCRIPTOR_TYPE_INTERFACE,
280  HID_KEYBOARD_INTERFACE_NUMBER, // bInterfaceNumber
281  0, // bAlternateSetting
282  1, // bNumEndpoints
283  HID_CLASS, // bInterfaceClass
284  HID_SUBCLASS_BOOT, // bInterfaceSubClass
285  HID_PROTOCOL_KEYBOARD, // bInterfaceProtocol
286  4 // iInterface
287  },
288  {
289  sizeof(usbConfigurationDescriptor.keyboard_hid), // 9-byte HID Descriptor for keyboard (HID 1.11 Section 6.2.1)
290  HID_DESCRIPTOR_TYPE_HID,
291  0x11, 0x01, // bcdHID. We conform to HID 1.11.
292  HID_COUNTRY_NOT_LOCALIZED, // bCountryCode
293  1, // bNumDescriptors
294  HID_DESCRIPTOR_TYPE_REPORT, // bDescriptorType
295  sizeof(keyboardReportDescriptor), 0 // wDescriptorLength
296  },
297  { // Keyboard IN Endpoint
298  sizeof(USB_DESCRIPTOR_ENDPOINT),
299  USB_DESCRIPTOR_TYPE_ENDPOINT,
300  USB_ENDPOINT_ADDRESS_IN | HID_KEYBOARD_ENDPOINT, // bEndpointAddress
301  USB_TRANSFER_TYPE_INTERRUPT, // bmAttributes
302  HID_IN_KEYBOARD_PACKET_SIZE, // wMaxPacketSize
303  10, // bInterval
304  },
305  { // Mouse Interface
306  sizeof(USB_DESCRIPTOR_INTERFACE),
307  USB_DESCRIPTOR_TYPE_INTERFACE,
308  HID_MOUSE_INTERFACE_NUMBER, // bInterfaceNumber
309  0, // bAlternateSetting
310  1, // bNumEndpoints
311  HID_CLASS, // bInterfaceClass
312  HID_SUBCLASS_BOOT, // bInterfaceSubClass
313  HID_PROTOCOL_MOUSE, // bInterfaceProtocol
314  5 // iInterface
315  },
316  {
317  sizeof(usbConfigurationDescriptor.mouse_hid), // 9-byte HID Descriptor for mouse (HID 1.11 Section 6.2.1)
318  HID_DESCRIPTOR_TYPE_HID,
319  0x11, 0x01, // bcdHID. We conform to HID 1.11.
320  HID_COUNTRY_NOT_LOCALIZED, // bCountryCode
321  1, // bNumDescriptors
322  HID_DESCRIPTOR_TYPE_REPORT, // bDescriptorType
323  sizeof(mouseReportDescriptor), 0 // wDescriptorLength
324  },
325  { // Mouse IN Endpoint
326  sizeof(USB_DESCRIPTOR_ENDPOINT),
327  USB_DESCRIPTOR_TYPE_ENDPOINT,
328  USB_ENDPOINT_ADDRESS_IN | HID_MOUSE_ENDPOINT, // bEndpointAddress
329  USB_TRANSFER_TYPE_INTERRUPT, // bmAttributes
330  HID_IN_MOUSE_PACKET_SIZE, // wMaxPacketSize
331  10, // bInterval
332  },
333  { // Joystick Interface
334  sizeof(USB_DESCRIPTOR_INTERFACE),
335  USB_DESCRIPTOR_TYPE_INTERFACE,
336  HID_JOYSTICK_INTERFACE_NUMBER, // bInterfaceNumber
337  0, // bAlternateSetting
338  1, // bNumEndpoints
339  HID_CLASS, // bInterfaceClass
340  0, // bInterfaceSubClass
341  0, // bInterfaceProtocol
342  6 // iInterface
343  },
344  {
345  sizeof(usbConfigurationDescriptor.joystick_hid), // 9-byte HID Descriptor for joystick (HID 1.11 Section 6.2.1)
346  HID_DESCRIPTOR_TYPE_HID,
347  0x11, 0x01, // bcdHID. We conform to HID 1.11.
348  HID_COUNTRY_NOT_LOCALIZED, // bCountryCode
349  1, // bNumDescriptors
350  HID_DESCRIPTOR_TYPE_REPORT, // bDescriptorType
351  sizeof(joystickReportDescriptor), 0 // wDescriptorLength
352  },
353  { // Joystick IN Endpoint
354  sizeof(USB_DESCRIPTOR_ENDPOINT),
355  USB_DESCRIPTOR_TYPE_ENDPOINT,
356  USB_ENDPOINT_ADDRESS_IN | HID_JOYSTICK_ENDPOINT, // bEndpointAddress
357  USB_TRANSFER_TYPE_INTERRUPT, // bmAttributes
358  HID_IN_JOYSTICK_PACKET_SIZE, // wMaxPacketSize
359  10, // bInterval
360  },
361 };
362 
365 DEFINE_STRING_DESCRIPTOR(manufacturer, 18, 'P','o','l','o','l','u',' ','C','o','r','p','o','r','a','t','i','o','n')
366 DEFINE_STRING_DESCRIPTOR(product, 5, 'W','i','x','e','l')
367 DEFINE_STRING_DESCRIPTOR(keyboardName, 14, 'W','i','x','e','l',' ','K','e','y','b','o','a','r','d')
368 DEFINE_STRING_DESCRIPTOR(mouseName, 11, 'W','i','x','e','l',' ','M','o','u','s','e')
369 DEFINE_STRING_DESCRIPTOR(joystickName, 14, 'W','i','x','e','l',' ','J','o','y','s','t','i','c','k')
370 uint16 CODE * CODE usbStringDescriptors[] = { languages, manufacturer, product, serialNumberStringDescriptor, keyboardName, mouseName, joystickName };
371 
372 /* HID structs and global variables *******************************************/
373 
377 HID_JOYSTICK_IN_REPORT XDATA usbHidJoystickInput = {0, 0, 0, 0, 0, 0, 0, 0, 0};
378 
382 
383 uint16 XDATA hidKeyboardIdleDuration = 500; // 0 to 1020 ms
384 
385 BIT hidKeyboardProtocol = HID_PROTOCOL_REPORT;
386 BIT hidMouseProtocol = HID_PROTOCOL_REPORT;
387 
388 /* HID USB callbacks **********************************************************/
389 // These functions are called by the low-level USB module (usb.c) when a USB
390 // event happens that requires higher-level code to make a decision.
391 
392 void usbCallbackInitEndpoints(void)
393 {
394  usbInitEndpointIn(HID_KEYBOARD_ENDPOINT, HID_IN_KEYBOARD_PACKET_SIZE);
395  usbInitEndpointIn(HID_MOUSE_ENDPOINT, HID_IN_MOUSE_PACKET_SIZE);
396  usbInitEndpointIn(HID_JOYSTICK_ENDPOINT, HID_IN_JOYSTICK_PACKET_SIZE);
397 }
398 
399 // Implements all the control transfers that are required by Appendix G of HID 1.11.
400 void usbCallbackSetupHandler(void)
401 {
402  static XDATA uint8 response;
403 
404  if ((usbSetupPacket.bmRequestType & 0x7F) != 0x21) // Require Type==Class and Recipient==Interface.
405  return;
406 
407  switch(usbSetupPacket.bRequest)
408  {
409  // required
410  case HID_REQUEST_GET_REPORT:
411  if ((usbSetupPacket.wValue >> 8) != HID_REPORT_TYPE_INPUT)
412  return;
413 
414  switch (usbSetupPacket.wIndex)
415  {
416  case HID_KEYBOARD_INTERFACE_NUMBER:
417  usbControlRead(sizeof(usbHidKeyboardInput), (uint8 XDATA *)&usbHidKeyboardInput);
418  return;
419 
420  case HID_MOUSE_INTERFACE_NUMBER:
421  usbControlRead(sizeof(usbHidMouseInput), (uint8 XDATA *)&usbHidMouseInput);
422  return;
423 
424  case HID_JOYSTICK_INTERFACE_NUMBER:
425  usbControlRead(sizeof(usbHidJoystickInput), (uint8 XDATA *)&usbHidJoystickInput);
426  return;
427  }
428  // unrecognized interface - stall
429  return;
430 
431  // required for devices with Output reports
432  case HID_REQUEST_SET_REPORT:
433  if (usbSetupPacket.wIndex == HID_KEYBOARD_INTERFACE_NUMBER)
434  {
435  usbControlWrite(sizeof(usbHidKeyboardOutput), (uint8 XDATA *)&usbHidKeyboardOutput);
436  }
437  return;
438 
439  // required for keyboards
440  case HID_REQUEST_GET_IDLE:
441  if (usbSetupPacket.wIndex == HID_KEYBOARD_INTERFACE_NUMBER)
442  {
443  response = hidKeyboardIdleDuration / 4; // value in request is in units of 4 ms
444  usbControlRead(1, (uint8 XDATA *)&response);
445  }
446  return;
447 
448  // required for keyboards
449  case HID_REQUEST_SET_IDLE:
450  if (usbSetupPacket.wIndex == HID_KEYBOARD_INTERFACE_NUMBER)
451  {
452  hidKeyboardIdleDuration = (usbSetupPacket.wValue >> 8) * 4; // value in request is in units of 4 ms
454  }
455  return;
456 
457 
458  // required for boot devices
459  case HID_REQUEST_GET_PROTOCOL:
460  switch (usbSetupPacket.wIndex)
461  {
462  case HID_KEYBOARD_INTERFACE_NUMBER:
463  response = hidKeyboardProtocol;
464  usbControlRead(1, (uint8 XDATA *)&response);
465  return;
466 
467  case HID_MOUSE_INTERFACE_NUMBER:
468  response = hidMouseProtocol;
469  usbControlRead(1, (uint8 XDATA *)&response);
470  return;
471  }
472  // unrecognized interface - stall
473  return;
474 
475  // required for boot devices
476  case HID_REQUEST_SET_PROTOCOL:
477  switch (usbSetupPacket.wIndex)
478  {
479  case HID_KEYBOARD_INTERFACE_NUMBER:
480  hidKeyboardProtocol = usbSetupPacket.wValue;
481  break;
482 
483  case HID_MOUSE_INTERFACE_NUMBER:
484  hidMouseProtocol = usbSetupPacket.wValue;
485  break;
486 
487  default:
488  // unrecognized interface - stall
489  return;
490  }
492  return;
493 
494  default:
495  // unrecognized request - stall
496  return;
497  }
498 }
499 
501 {
502  // Require Direction==Device-to-Host, Type==Standard, and Recipient==Interface. (HID 1.11 Section 7.1.1)
503  if (usbSetupPacket.bmRequestType != 0x81)
504  {
505  return;
506  }
507 
508  switch (usbSetupPacket.wValue >> 8)
509  {
510  case HID_DESCRIPTOR_TYPE_HID:
511  // The host has requested the HID descriptor of a particular interface.
512  switch (usbSetupPacket.wIndex)
513  {
514  case HID_KEYBOARD_INTERFACE_NUMBER:
515  usbControlRead(sizeof(usbConfigurationDescriptor.keyboard_hid), (uint8 XDATA *)&usbConfigurationDescriptor.keyboard_hid);
516  return;
517 
518  case HID_MOUSE_INTERFACE_NUMBER:
519  usbControlRead(sizeof(usbConfigurationDescriptor.mouse_hid), (uint8 XDATA *)&usbConfigurationDescriptor.mouse_hid);
520  return;
521 
522  case HID_JOYSTICK_INTERFACE_NUMBER:
523  usbControlRead(sizeof(usbConfigurationDescriptor.joystick_hid), (uint8 XDATA *)&usbConfigurationDescriptor.joystick_hid);
524  return;
525  }
526  return;
527 
528  case HID_DESCRIPTOR_TYPE_REPORT:
529  // The host has requested the Report Descriptor of a particular interface.
530  switch (usbSetupPacket.wIndex)
531  {
532  case HID_KEYBOARD_INTERFACE_NUMBER:
533  usbControlRead(sizeof(keyboardReportDescriptor), (uint8 XDATA *)&keyboardReportDescriptor);
534  return;
535 
536  case HID_MOUSE_INTERFACE_NUMBER:
537  usbControlRead(sizeof(mouseReportDescriptor), (uint8 XDATA *)&mouseReportDescriptor);
538  return;
539 
540  case HID_JOYSTICK_INTERFACE_NUMBER:
541  usbControlRead(sizeof(joystickReportDescriptor), (uint8 XDATA *)&joystickReportDescriptor);
542  return;
543  }
544  return;
545  }
546 }
547 
549 {
550  // not used by usb_hid
551 }
552 
553 /* Other HID Functions ********************************************************/
554 
555 void usbHidService(void)
556 {
557  static uint16 XDATA hidKeyboardLastReportTime = 0;
558 
559  usbPoll();
560 
561  if (usbDeviceState != USB_STATE_CONFIGURED)
562  {
563  // We have not reached the Configured state yet, so we should not be touching the non-zero endpoints.
564  return;
565  }
566 
567  USBINDEX = HID_KEYBOARD_ENDPOINT;
568  // Check if keyboard input has been updated OR if the idle period is nonzero and has expired.
569  if ((usbHidKeyboardInputUpdated || (hidKeyboardIdleDuration && ((uint16)(getMs() - hidKeyboardLastReportTime) > hidKeyboardIdleDuration))) && !(USBCSIL & USBCSIL_INPKT_RDY))
570  {
571  usbWriteFifo(HID_KEYBOARD_ENDPOINT, sizeof(usbHidKeyboardInput), (uint8 XDATA *)&usbHidKeyboardInput);
572  USBCSIL |= USBCSIL_INPKT_RDY;
573  usbHidKeyboardInputUpdated = 0; // reset updated flag
574  hidKeyboardLastReportTime = getMs();
575  }
576 
577  USBINDEX = HID_MOUSE_ENDPOINT;
578  // Check if mouse input has been updated.
579  if (usbHidMouseInputUpdated && !(USBCSIL & USBCSIL_INPKT_RDY)) {
580  usbWriteFifo(HID_MOUSE_ENDPOINT, sizeof(usbHidMouseInput), (uint8 XDATA *)&usbHidMouseInput);
581  USBCSIL |= USBCSIL_INPKT_RDY;
582  usbHidMouseInputUpdated = 0; // reset updated flag
583  }
584 
585  USBINDEX = HID_JOYSTICK_ENDPOINT;
586  // Check if joystick input has been updated.
587  if (usbHidJoystickInputUpdated && !(USBCSIL & USBCSIL_INPKT_RDY)) {
588  usbWriteFifo(HID_JOYSTICK_ENDPOINT, sizeof(usbHidJoystickInput), (uint8 XDATA *)&usbHidJoystickInput);
589  USBCSIL |= USBCSIL_INPKT_RDY;
590  usbHidJoystickInputUpdated = 0; // reset updated flag
591  }
592 }
593 
594 // Look-up table stored in code memory that we use to convert from ASCII
595 // characters to HID key codes.
596 uint8 CODE hidKeyCode[128] =
597 {
598  0, // 0x00 Null
599  0, // 0x01
600  0, // 0x02
601  0, // 0x03
602  0, // 0x04
603  0, // 0x05
604  0, // 0x06
605  0, // 0x07
606  KEY_BACKSPACE, // 0x08 Backspace
607  KEY_TAB, // 0x09 Horizontal Tab
608  KEY_RETURN, // 0x0A Line Feed
609  0, // 0x0B
610  0, // 0x0C
611  KEY_RETURN, // 0x0D Carriage return
612  0, // 0x0E
613  0, // 0x0F
614  0, // 0x10
615  0, // 0x11
616  0, // 0x12
617  0, // 0x13
618  0, // 0x14
619  0, // 0x15
620  0, // 0x16
621  0, // 0x17
622  0, // 0x18
623  0, // 0x19
624  0, // 0x1A
625  KEY_ESCAPE, // 0x1B Escape
626  0, // 0x1C
627  0, // 0x1D
628  0, // 0x1E
629  0, // 0x1F
630 
631  KEY_SPACE, // 0x20
632  KEY_1, // 0x21 !
633  KEY_APOSTROPHE, // 0x22 "
634  KEY_3, // 0x23 #
635  KEY_4, // 0x24 $
636  KEY_5, // 0x25 %
637  KEY_7, // 0x26 &
638  KEY_APOSTROPHE, // 0x27 '
639  KEY_9, // 0x28 (
640  KEY_0, // 0x29 )
641  KEY_8, // 0x2A *
642  KEY_EQUAL, // 0x2B +
643  KEY_COMMA, // 0x2C ,
644  KEY_MINUS, // 0x2D -
645  KEY_PERIOD, // 0x2E .
646  KEY_SLASH, // 0x2F /
647  KEY_0, // 0x30 0
648  KEY_1, // 0x31 1
649  KEY_2, // 0x32 2
650  KEY_3, // 0x33 3
651  KEY_4, // 0x34 4
652  KEY_5, // 0x35 5
653  KEY_6, // 0x36 6
654  KEY_7, // 0x37 7
655  KEY_8, // 0x38 8
656  KEY_9, // 0x39 9
657  KEY_SEMICOLON, // 0x3A :
658  KEY_SEMICOLON, // 0x3B ;
659  KEY_COMMA, // 0x3C <
660  KEY_EQUAL, // 0x3D =
661  KEY_PERIOD, // 0x3E >
662  KEY_SLASH, // 0x3F ?
663 
664  KEY_2, // 0x40 @
665  KEY_A, // 0x41 A
666  KEY_B, // 0x42 B
667  KEY_C, // 0x43 C
668  KEY_D, // 0x44 D
669  KEY_E, // 0x45 E
670  KEY_F, // 0x46 F
671  KEY_G, // 0x47 G
672  KEY_H, // 0x48 H
673  KEY_I, // 0x49 I
674  KEY_J, // 0x4A J
675  KEY_K, // 0x4B K
676  KEY_L, // 0x4C L
677  KEY_M, // 0x4D M
678  KEY_N, // 0x4E N
679  KEY_O, // 0x4F O
680  KEY_P, // 0x50 P
681  KEY_Q, // 0x51 Q
682  KEY_R, // 0x52 R
683  KEY_S, // 0x53 S
684  KEY_T, // 0x55 T
685  KEY_U, // 0x55 U
686  KEY_V, // 0x56 V
687  KEY_W, // 0x57 W
688  KEY_X, // 0x58 X
689  KEY_Y, // 0x59 Y
690  KEY_Z, // 0x5A Z
691  KEY_BRACKET_LEFT, // 0x5B [
692  KEY_BACKSLASH, // 0x5C '\'
693  KEY_BRACKET_RIGHT, // 0x5D ]
694  KEY_6, // 0x5E ^
695  KEY_MINUS, // 0x5F _
696 
697  KEY_GRAVE, // 0x60 `
698  KEY_A, // 0x61 a
699  KEY_B, // 0x62 b
700  KEY_C, // 0x63 c
701  KEY_D, // 0x66 d
702  KEY_E, // 0x65 e
703  KEY_F, // 0x66 f
704  KEY_G, // 0x67 g
705  KEY_H, // 0x68 h
706  KEY_I, // 0x69 i
707  KEY_J, // 0x6A j
708  KEY_K, // 0x6B k
709  KEY_L, // 0x6C l
710  KEY_M, // 0x6D m
711  KEY_N, // 0x6E n
712  KEY_O, // 0x6F o
713  KEY_P, // 0x70 p
714  KEY_Q, // 0x71 q
715  KEY_R, // 0x72 r
716  KEY_S, // 0x73 s
717  KEY_T, // 0x75 t
718  KEY_U, // 0x75 u
719  KEY_V, // 0x76 v
720  KEY_W, // 0x77 w
721  KEY_X, // 0x78 x
722  KEY_Y, // 0x79 y
723  KEY_Z, // 0x7A z
724  KEY_BRACKET_LEFT, // 0x7B {
725  KEY_BACKSLASH, // 0x7C |
726  KEY_BRACKET_RIGHT, // 0x7D }
727  KEY_GRAVE, // 0x7E ~
728  KEY_DELETE // 0x7F Delete
729 };
730 
732 {
733  if (asciiChar & 0x80){ return 0; }
734  return hidKeyCode[asciiChar];
735 }
HID_KEYBOARD_IN_REPORT XDATA usbHidKeyboardInput
Definition: usb_hid.c:375
HID_KEYBOARD_OUT_REPORT XDATA usbHidKeyboardOutput
Definition: usb_hid.c:374
struct USB_DESCRIPTOR_DEVICE USB_DESCRIPTOR_DEVICE
void usbCallbackInitEndpoints(void)
Definition: usb_cdc_acm.c:234
uint8 CODE usbStringDescriptorCount
Definition: usb_cdc_acm.c:224
#define XDATA
Definition: cc2511_types.h:65
#define USB_LANGUAGE_EN_US
Definition: usb.h:113
#define USB_EP0_PACKET_SIZE
Definition: usb.h:34
enum USB_DEVICE_STATES XDATA usbDeviceState
Definition: usb.c:18
void usbControlWrite(uint16 bytesCount, uint8 XDATA *source)
Definition: usb.c:617
USB_DESCRIPTOR_DEVICE CODE usbDeviceDescriptor
Definition: usb_cdc_acm.c:109
struct USB_DESCRIPTOR_CONFIGURATION USB_DESCRIPTOR_CONFIGURATION
BIT usbHidMouseInputUpdated
Definition: usb_hid.c:380
struct USB_DESCRIPTOR_INTERFACE USB_DESCRIPTOR_INTERFACE
struct USB_DESCRIPTOR_ENDPOINT USB_DESCRIPTOR_ENDPOINT
USB_SETUP_PACKET XDATA usbSetupPacket
Definition: usb.c:17
#define USB_VENDOR_ID_POLOLU
Definition: usb.h:30
void usbHidService(void)
Definition: usb_hid.c:555
void usbWriteFifo(uint8 endpointNumber, uint8 count, const uint8 XDATA *buffer)
Definition: usb.c:46
uint16 CODE serialNumberStringDescriptor[]
void usbInitEndpointIn(uint8 endpointNumber, uint8 maxPacketSize)
Definition: usb.c:635
__bit BIT
Definition: cc2511_types.h:32
void usbPoll(void)
Definition: usb.c:73
unsigned short uint16
Definition: cc2511_types.h:15
HID_MOUSE_IN_REPORT XDATA usbHidMouseInput
Definition: usb_hid.c:376
void usbCallbackSetupHandler(void)
Definition: usb_cdc_acm.c:246
unsigned char uint8
Definition: cc2511_types.h:9
HID_JOYSTICK_IN_REPORT XDATA usbHidJoystickInput
Definition: usb_hid.c:377
void usbControlAcknowledge(void)
Definition: usb.c:624
BIT usbHidJoystickInputUpdated
Definition: usb_hid.c:381
uint32 getMs()
Definition: time.c:19
BIT usbHidKeyboardInputUpdated
Definition: usb_hid.c:379
void usbCallbackControlWriteHandler(void)
Definition: usb_cdc_acm.c:281
void usbControlRead(uint16 bytesCount, uint8 XDATA *source)
Definition: usb.c:610
#define DEFINE_STRING_DESCRIPTOR(name, char_count,...)
Definition: usb.h:230
void usbCallbackClassDescriptorHandler(void)
Definition: usb_cdc_acm.c:271
uint16 CODE *CODE usbStringDescriptors[]
Definition: usb_cdc_acm.c:228
uint8 usbHidKeyCodeFromAsciiChar(char asciiChar)
Definition: usb_hid.c:731
#define CODE
Definition: cc2511_types.h:39