root / arduino-1.0 / hardware / arduino / cores / arduino / HID.cpp @ 58d82c77
History | View | Annotate | Download (11.2 KB)
1 | 58d82c77 | Tom Mullins | |
---|---|---|---|
2 | |||
3 | /* Copyright (c) 2011, Peter Barrett
|
||
4 | **
|
||
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.
|
||
8 | **
|
||
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
|
||
16 | ** SOFTWARE.
|
||
17 | */
|
||
18 | |||
19 | #include "Platform.h" |
||
20 | #include "USBAPI.h" |
||
21 | #include "USBDesc.h" |
||
22 | |||
23 | #if defined(USBCON)
|
||
24 | #ifdef HID_ENABLED
|
||
25 | |||
26 | //#define RAWHID_ENABLED
|
||
27 | |||
28 | // Singletons for mouse and keyboard
|
||
29 | |||
30 | Mouse_ Mouse; |
||
31 | Keyboard_ Keyboard; |
||
32 | |||
33 | //================================================================================
|
||
34 | //================================================================================
|
||
35 | |||
36 | // HID report descriptor
|
||
37 | |||
38 | #define LSB(_x) ((_x) & 0xFF) |
||
39 | #define MSB(_x) ((_x) >> 8) |
||
40 | |||
41 | #define RAWHID_USAGE_PAGE 0xFFC0 |
||
42 | #define RAWHID_USAGE 0x0C00 |
||
43 | #define RAWHID_TX_SIZE 64 |
||
44 | #define RAWHID_RX_SIZE 64 |
||
45 | |||
46 | extern const u8 _hidReportDescriptor[] PROGMEM; |
||
47 | const u8 _hidReportDescriptor[] = {
|
||
48 | |||
49 | // Mouse
|
||
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 |
||
78 | |||
79 | // Keyboard
|
||
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) |
||
85 | |||
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) |
||
91 | |||
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) |
||
97 | |||
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) |
||
103 | |||
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 |
||
108 | |||
109 | #if RAWHID_ENABLED
|
||
110 | // RAW HID
|
||
111 | 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 |
||
112 | 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||
113 | |||
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 |
||
119 | |||
120 | 0x95, 64, // report count TX |
||
121 | 0x09, 0x01, // usage |
||
122 | 0x81, 0x02, // Input (array) |
||
123 | |||
124 | 0x95, 64, // report count RX |
||
125 | 0x09, 0x02, // usage |
||
126 | 0x91, 0x02, // Output (array) |
||
127 | 0xC0 // end collection |
||
128 | #endif
|
||
129 | }; |
||
130 | |||
131 | extern const HIDDescriptor _hidInterface PROGMEM; |
||
132 | const HIDDescriptor _hidInterface =
|
||
133 | { |
||
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) |
||
137 | }; |
||
138 | |||
139 | //================================================================================
|
||
140 | //================================================================================
|
||
141 | // Driver
|
||
142 | |||
143 | u8 _hid_protocol = 1;
|
||
144 | u8 _hid_idle = 1;
|
||
145 | |||
146 | #define WEAK __attribute__ ((weak))
|
||
147 | #define WEAK
|
||
148 | |||
149 | int WEAK HID_GetInterface(u8* interfaceNum)
|
||
150 | { |
||
151 | interfaceNum[0] += 1; // uses 1 |
||
152 | return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface)); |
||
153 | } |
||
154 | |||
155 | int WEAK HID_GetDescriptor(int i) |
||
156 | { |
||
157 | return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor)); |
||
158 | } |
||
159 | |||
160 | void WEAK HID_SendReport(u8 id, const void* data, int len) |
||
161 | { |
||
162 | USB_Send(HID_TX, &id, 1);
|
||
163 | USB_Send(HID_TX | TRANSFER_RELEASE,data,len); |
||
164 | } |
||
165 | |||
166 | bool WEAK HID_Setup(Setup& setup)
|
||
167 | { |
||
168 | u8 r = setup.bRequest; |
||
169 | u8 requestType = setup.bmRequestType; |
||
170 | if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
|
||
171 | { |
||
172 | if (HID_GET_REPORT == r)
|
||
173 | { |
||
174 | //HID_GetReport();
|
||
175 | return true; |
||
176 | } |
||
177 | if (HID_GET_PROTOCOL == r)
|
||
178 | { |
||
179 | //Send8(_hid_protocol); // TODO
|
||
180 | return true; |
||
181 | } |
||
182 | } |
||
183 | |||
184 | if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
|
||
185 | { |
||
186 | if (HID_SET_PROTOCOL == r)
|
||
187 | { |
||
188 | _hid_protocol = setup.wValueL; |
||
189 | return true; |
||
190 | } |
||
191 | |||
192 | if (HID_SET_IDLE == r)
|
||
193 | { |
||
194 | _hid_idle = setup.wValueL; |
||
195 | return true; |
||
196 | } |
||
197 | } |
||
198 | return false; |
||
199 | } |
||
200 | |||
201 | //================================================================================
|
||
202 | //================================================================================
|
||
203 | // Mouse
|
||
204 | |||
205 | Mouse_::Mouse_() : _buttons(0)
|
||
206 | { |
||
207 | } |
||
208 | |||
209 | void Mouse_::click(uint8_t b)
|
||
210 | { |
||
211 | _buttons = b; |
||
212 | move(0,0,0); |
||
213 | _buttons = 0;
|
||
214 | move(0,0,0); |
||
215 | } |
||
216 | |||
217 | void Mouse_::move(signed char x, signed char y, signed char wheel) |
||
218 | { |
||
219 | u8 m[4];
|
||
220 | m[0] = _buttons;
|
||
221 | m[1] = x;
|
||
222 | m[2] = y;
|
||
223 | m[3] = wheel;
|
||
224 | HID_SendReport(1,m,4); |
||
225 | } |
||
226 | |||
227 | void Mouse_::buttons(uint8_t b)
|
||
228 | { |
||
229 | if (b != _buttons)
|
||
230 | { |
||
231 | _buttons = b; |
||
232 | move(0,0,0); |
||
233 | } |
||
234 | } |
||
235 | |||
236 | void Mouse_::press(uint8_t b)
|
||
237 | { |
||
238 | buttons(_buttons | b); |
||
239 | } |
||
240 | |||
241 | void Mouse_::release(uint8_t b)
|
||
242 | { |
||
243 | buttons(_buttons & ~b); |
||
244 | } |
||
245 | |||
246 | bool Mouse_::isPressed(uint8_t b)
|
||
247 | { |
||
248 | if (b & _buttons > 0) |
||
249 | return true; |
||
250 | return false; |
||
251 | } |
||
252 | |||
253 | //================================================================================
|
||
254 | //================================================================================
|
||
255 | // Keyboard
|
||
256 | |||
257 | Keyboard_::Keyboard_() : _keyMap(0)
|
||
258 | { |
||
259 | } |
||
260 | |||
261 | void Keyboard_::sendReport(KeyReport* keys)
|
||
262 | { |
||
263 | HID_SendReport(2,keys,sizeof(KeyReport)); |
||
264 | } |
||
265 | |||
266 | void Keyboard_::setKeyMap(KeyMap* keyMap)
|
||
267 | { |
||
268 | _keyMap = keyMap; |
||
269 | } |
||
270 | |||
271 | extern
|
||
272 | const uint8_t _asciimap[128] PROGMEM; |
||
273 | |||
274 | #define SHIFT 0x80 |
||
275 | const uint8_t _asciimap[128] = |
||
276 | { |
||
277 | 0x00, // NUL |
||
278 | 0x00, // SOH |
||
279 | 0x00, // STX |
||
280 | 0x00, // ETX |
||
281 | 0x00, // EOT |
||
282 | 0x00, // ENQ |
||
283 | 0x00, // ACK |
||
284 | 0x00, // BEL |
||
285 | 0x2a, // BS Backspace |
||
286 | 0x2b, // TAB Tab |
||
287 | 0x28, // LF Enter |
||
288 | 0x00, // VT |
||
289 | 0x00, // FF |
||
290 | 0x00, // CR |
||
291 | 0x00, // SO |
||
292 | 0x00, // SI |
||
293 | 0x00, // DEL |
||
294 | 0x00, // DC1 |
||
295 | 0x00, // DC2 |
||
296 | 0x00, // DC3 |
||
297 | 0x00, // DC4 |
||
298 | 0x00, // NAK |
||
299 | 0x00, // SYN |
||
300 | 0x00, // ETB |
||
301 | 0x00, // CAN |
||
302 | 0x00, // EM |
||
303 | 0x00, // SUB |
||
304 | 0x00, // ESC |
||
305 | 0x00, // FS |
||
306 | 0x00, // GS |
||
307 | 0x00, // RS |
||
308 | 0x00, // US |
||
309 | |||
310 | 0x2c, // ' ' |
||
311 | 0x1e|SHIFT, // ! |
||
312 | 0x34|SHIFT, // " |
||
313 | 0x20|SHIFT, // # |
||
314 | 0x21|SHIFT, // $ |
||
315 | 0x22|SHIFT, // % |
||
316 | 0x24|SHIFT, // & |
||
317 | 0x34, // ' |
||
318 | 0x26|SHIFT, // ( |
||
319 | 0x27|SHIFT, // ) |
||
320 | 0x25|SHIFT, // * |
||
321 | 0x2e|SHIFT, // + |
||
322 | 0x36, // , |
||
323 | 0x2d, // - |
||
324 | 0x37, // . |
||
325 | 0x38, // / |
||
326 | 0x27, // 0 |
||
327 | 0x1e, // 1 |
||
328 | 0x1f, // 2 |
||
329 | 0x20, // 3 |
||
330 | 0x21, // 4 |
||
331 | 0x22, // 5 |
||
332 | 0x23, // 6 |
||
333 | 0x24, // 7 |
||
334 | 0x25, // 8 |
||
335 | 0x26, // 9 |
||
336 | 0x33|SHIFT, // : |
||
337 | 0x33, // ; |
||
338 | 0x36|SHIFT, // < |
||
339 | 0x2e, // = |
||
340 | 0x37|SHIFT, // > |
||
341 | 0x38|SHIFT, // ? |
||
342 | 0x1f|SHIFT, // @ |
||
343 | 0x04|SHIFT, // A |
||
344 | 0x05|SHIFT, // B |
||
345 | 0x06|SHIFT, // C |
||
346 | 0x07|SHIFT, // D |
||
347 | 0x08|SHIFT, // E |
||
348 | 0x09|SHIFT, // F |
||
349 | 0x0a|SHIFT, // G |
||
350 | 0x0b|SHIFT, // H |
||
351 | 0x0c|SHIFT, // I |
||
352 | 0x0d|SHIFT, // J |
||
353 | 0x0e|SHIFT, // K |
||
354 | 0x0f|SHIFT, // L |
||
355 | 0x10|SHIFT, // M |
||
356 | 0x11|SHIFT, // N |
||
357 | 0x12|SHIFT, // O |
||
358 | 0x13|SHIFT, // P |
||
359 | 0x14|SHIFT, // Q |
||
360 | 0x15|SHIFT, // R |
||
361 | 0x16|SHIFT, // S |
||
362 | 0x17|SHIFT, // T |
||
363 | 0x18|SHIFT, // U |
||
364 | 0x19|SHIFT, // V |
||
365 | 0x1a|SHIFT, // W |
||
366 | 0x1b|SHIFT, // X |
||
367 | 0x1c|SHIFT, // Y |
||
368 | 0x1d|SHIFT, // Z |
||
369 | 0x2f, // [ |
||
370 | 0x31, // bslash |
||
371 | 0x30, // ] |
||
372 | 0x23|SHIFT, // ^ |
||
373 | 0x2d|SHIFT, // _ |
||
374 | 0x35, // ` |
||
375 | 0x04, // a |
||
376 | 0x05, // b |
||
377 | 0x06, // c |
||
378 | 0x07, // d |
||
379 | 0x08, // e |
||
380 | 0x09, // f |
||
381 | 0x0a, // g |
||
382 | 0x0b, // h |
||
383 | 0x0c, // i |
||
384 | 0x0d, // j |
||
385 | 0x0e, // k |
||
386 | 0x0f, // l |
||
387 | 0x10, // m |
||
388 | 0x11, // n |
||
389 | 0x12, // o |
||
390 | 0x13, // p |
||
391 | 0x14, // q |
||
392 | 0x15, // r |
||
393 | 0x16, // s |
||
394 | 0x17, // t |
||
395 | 0x18, // u |
||
396 | 0x19, // v |
||
397 | 0x1a, // w |
||
398 | 0x1b, // x |
||
399 | 0x1c, // y |
||
400 | 0x1d, // z |
||
401 | 0x2f|SHIFT, // |
||
402 | 0x31|SHIFT, // | |
||
403 | 0x30|SHIFT, // } |
||
404 | 0x35|SHIFT, // ~ |
||
405 | 0 // DEL |
||
406 | }; |
||
407 | |||
408 | uint8_t USBPutChar(uint8_t c); |
||
409 | size_t Keyboard_::write(uint8_t c) |
||
410 | { |
||
411 | // Keydown
|
||
412 | { |
||
413 | KeyReport keys = {0};
|
||
414 | if (_keyMap)
|
||
415 | _keyMap->charToKey(c,&keys); |
||
416 | else
|
||
417 | { |
||
418 | if (c >= 128) { |
||
419 | setWriteError(); |
||
420 | return 0; |
||
421 | } |
||
422 | c = pgm_read_byte(_asciimap + c); |
||
423 | if (!c) {
|
||
424 | setWriteError(); |
||
425 | return 0; |
||
426 | } |
||
427 | if (c & 0x80) |
||
428 | { |
||
429 | keys.modifiers |= KEY_MODIFIER_LEFT_SHIFT; |
||
430 | c &= 0x7F;
|
||
431 | } |
||
432 | keys.keys[0] = c;
|
||
433 | } |
||
434 | sendReport(&keys); |
||
435 | } |
||
436 | // Keyup
|
||
437 | { |
||
438 | KeyReport keys = {0};
|
||
439 | sendReport(&keys); |
||
440 | } |
||
441 | return 1; |
||
442 | } |
||
443 | |||
444 | #endif
|
||
445 | |||
446 | #endif /* if defined(USBCON) */ |