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) */