3 /* Copyright (c) 2011, Peter Barrett
5 ** Permission to use, copy, modify, and/or distribute this software for
6 ** any purpose with or without fee is hereby granted, provided that the
7 ** above copyright notice and this permission notice appear in all copies.
9 ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 ** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 ** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
12 ** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
13 ** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
14 ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
15 ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 //#define RAWHID_ENABLED
28 // Singletons for mouse and keyboard
33 //================================================================================
34 //================================================================================
36 // HID report descriptor
38 #define LSB(_x) ((_x) & 0xFF)
39 #define MSB(_x) ((_x) >> 8)
41 #define RAWHID_USAGE_PAGE 0xFFC0
42 #define RAWHID_USAGE 0x0C00
43 #define RAWHID_TX_SIZE 64
44 #define RAWHID_RX_SIZE 64
46 extern const u8 _hidReportDescriptor[] PROGMEM;
47 const u8 _hidReportDescriptor[] = {
50 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
51 0x09, 0x02, // USAGE (Mouse)
52 0xa1, 0x01, // COLLECTION (Application)
53 0x09, 0x01, // USAGE (Pointer)
54 0xa1, 0x00, // COLLECTION (Physical)
55 0x85, 0x01, // REPORT_ID (1)
56 0x05, 0x09, // USAGE_PAGE (Button)
57 0x19, 0x01, // USAGE_MINIMUM (Button 1)
58 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
59 0x15, 0x00, // LOGICAL_MINIMUM (0)
60 0x25, 0x01, // LOGICAL_MAXIMUM (1)
61 0x95, 0x03, // REPORT_COUNT (3)
62 0x75, 0x01, // REPORT_SIZE (1)
63 0x81, 0x02, // INPUT (Data,Var,Abs)
64 0x95, 0x01, // REPORT_COUNT (1)
65 0x75, 0x05, // REPORT_SIZE (5)
66 0x81, 0x03, // INPUT (Cnst,Var,Abs)
67 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
68 0x09, 0x30, // USAGE (X)
69 0x09, 0x31, // USAGE (Y)
70 0x09, 0x38, // USAGE (Wheel)
71 0x15, 0x81, // LOGICAL_MINIMUM (-127)
72 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
73 0x75, 0x08, // REPORT_SIZE (8)
74 0x95, 0x03, // REPORT_COUNT (3)
75 0x81, 0x06, // INPUT (Data,Var,Rel)
76 0xc0, // END_COLLECTION
77 0xc0, // END_COLLECTION
80 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
81 0x09, 0x06, // USAGE (Keyboard)
82 0xa1, 0x01, // COLLECTION (Application)
83 0x85, 0x02, // REPORT_ID (2)
84 0x05, 0x07, // USAGE_PAGE (Keyboard)
86 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
87 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
88 0x15, 0x00, // LOGICAL_MINIMUM (0)
89 0x25, 0x01, // LOGICAL_MAXIMUM (1)
90 0x75, 0x01, // REPORT_SIZE (1)
92 0x95, 0x08, // REPORT_COUNT (8)
93 0x81, 0x02, // INPUT (Data,Var,Abs)
94 0x95, 0x01, // REPORT_COUNT (1)
95 0x75, 0x08, // REPORT_SIZE (8)
96 0x81, 0x03, // INPUT (Cnst,Var,Abs)
98 0x95, 0x06, // REPORT_COUNT (6)
99 0x75, 0x08, // REPORT_SIZE (8)
100 0x15, 0x00, // LOGICAL_MINIMUM (0)
101 0x25, 0x65, // LOGICAL_MAXIMUM (101)
102 0x05, 0x07, // USAGE_PAGE (Keyboard)
104 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
105 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
106 0x81, 0x00, // INPUT (Data,Ary,Abs)
107 0xc0, // END_COLLECTION
111 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
112 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
114 0xA1, 0x01, // Collection 0x01
115 0x85, 0x03, // REPORT_ID (3)
116 0x75, 0x08, // report size = 8 bits
117 0x15, 0x00, // logical minimum = 0
118 0x26, 0xFF, 0x00, // logical maximum = 255
120 0x95, 64, // report count TX
122 0x81, 0x02, // Input (array)
124 0x95, 64, // report count RX
126 0x91, 0x02, // Output (array)
127 0xC0 // end collection
131 extern const HIDDescriptor _hidInterface PROGMEM;
132 const HIDDescriptor _hidInterface =
134 D_INTERFACE(HID_INTERFACE,1,3,0,0),
135 D_HIDREPORT(sizeof(_hidReportDescriptor)),
136 D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
139 //================================================================================
140 //================================================================================
143 u8 _hid_protocol = 1;
146 #define WEAK __attribute__ ((weak))
148 int WEAK HID_GetInterface(u8* interfaceNum)
150 interfaceNum[0] += 1; // uses 1
151 return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface));
154 int WEAK HID_GetDescriptor(int i)
156 return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor));
159 void WEAK HID_SendReport(u8 id, const void* data, int len)
161 USB_Send(HID_TX, &id, 1);
162 USB_Send(HID_TX | TRANSFER_RELEASE,data,len);
165 bool WEAK HID_Setup(Setup& setup)
167 u8 r = setup.bRequest;
168 u8 requestType = setup.bmRequestType;
169 if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
171 if (HID_GET_REPORT == r)
176 if (HID_GET_PROTOCOL == r)
178 //Send8(_hid_protocol); // TODO
183 if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
185 if (HID_SET_PROTOCOL == r)
187 _hid_protocol = setup.wValueL;
191 if (HID_SET_IDLE == r)
193 _hid_idle = setup.wValueL;
200 //================================================================================
201 //================================================================================
204 Mouse_::Mouse_(void) : _buttons(0)
208 void Mouse_::begin(void)
212 void Mouse_::end(void)
216 void Mouse_::click(uint8_t b)
224 void Mouse_::move(signed char x, signed char y, signed char wheel)
231 HID_SendReport(1,m,4);
234 void Mouse_::buttons(uint8_t b)
243 void Mouse_::press(uint8_t b)
245 buttons(_buttons | b);
248 void Mouse_::release(uint8_t b)
250 buttons(_buttons & ~b);
253 bool Mouse_::isPressed(uint8_t b)
255 if ((b & _buttons) > 0)
260 //================================================================================
261 //================================================================================
264 Keyboard_::Keyboard_(void)
268 void Keyboard_::begin(void)
272 void Keyboard_::end(void)
276 void Keyboard_::sendReport(KeyReport* keys)
278 HID_SendReport(2,keys,sizeof(KeyReport));
282 const uint8_t _asciimap[128] PROGMEM;
285 const uint8_t _asciimap[128] =
295 0x2a, // BS Backspace
418 uint8_t USBPutChar(uint8_t c);
420 // press() adds the specified key (printing, non-printing, or modifier)
421 // to the persistent key report and sends the report. Because of the way
422 // USB HID works, the host acts like the key remains pressed until we
423 // call release(), releaseAll(), or otherwise clear the report and resend.
424 size_t Keyboard_::press(uint8_t k)
427 if (k >= 136) { // it's a non-printing key (not a modifier)
429 } else if (k >= 128) { // it's a modifier key
430 _keyReport.modifiers |= (1<<(k-128));
432 } else { // it's a printing key
433 k = pgm_read_byte(_asciimap + k);
438 if (k & 0x80) { // it's a capital letter or other character reached with shift
439 _keyReport.modifiers |= 0x02; // the left shift modifier
444 // Add k to the key report only if it's not already present
445 // and if there is an empty slot.
446 if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
447 _keyReport.keys[2] != k && _keyReport.keys[3] != k &&
448 _keyReport.keys[4] != k && _keyReport.keys[5] != k) {
450 for (i=0; i<6; i++) {
451 if (_keyReport.keys[i] == 0x00) {
452 _keyReport.keys[i] = k;
461 sendReport(&_keyReport);
465 // release() takes the specified key out of the persistent key report and
466 // sends the report. This tells the OS the key is no longer pressed and that
467 // it shouldn't be repeated any more.
468 size_t Keyboard_::release(uint8_t k)
471 if (k >= 136) { // it's a non-printing key (not a modifier)
473 } else if (k >= 128) { // it's a modifier key
474 _keyReport.modifiers &= ~(1<<(k-128));
476 } else { // it's a printing key
477 k = pgm_read_byte(_asciimap + k);
481 if (k & 0x80) { // it's a capital letter or other character reached with shift
482 _keyReport.modifiers &= ~(0x02); // the left shift modifier
487 // Test the key report to see if k is present. Clear it if it exists.
488 // Check all positions in case the key is present more than once (which it shouldn't be)
489 for (i=0; i<6; i++) {
490 if (0 != k && _keyReport.keys[i] == k) {
491 _keyReport.keys[i] = 0x00;
495 sendReport(&_keyReport);
499 void Keyboard_::releaseAll(void)
501 _keyReport.keys[0] = 0;
502 _keyReport.keys[1] = 0;
503 _keyReport.keys[2] = 0;
504 _keyReport.keys[3] = 0;
505 _keyReport.keys[4] = 0;
506 _keyReport.keys[5] = 0;
507 _keyReport.modifiers = 0;
508 sendReport(&_keyReport);
511 size_t Keyboard_::write(uint8_t c)
513 uint8_t p = press(c); // Keydown
514 uint8_t r = release(c); // Keyup
515 return (p); // just return the result of press() since release() almost always returns 1
520 #endif /* if defined(USBCON) */