sanguino/cores/arduino/HID.cpp

changeset 2
b373b0288715
equal deleted inserted replaced
1:b584642d4f58 2:b373b0288715
1
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
148 int WEAK HID_GetInterface(u8* interfaceNum)
149 {
150 interfaceNum[0] += 1; // uses 1
151 return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface));
152 }
153
154 int WEAK HID_GetDescriptor(int i)
155 {
156 return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor));
157 }
158
159 void WEAK HID_SendReport(u8 id, const void* data, int len)
160 {
161 USB_Send(HID_TX, &id, 1);
162 USB_Send(HID_TX | TRANSFER_RELEASE,data,len);
163 }
164
165 bool WEAK HID_Setup(Setup& setup)
166 {
167 u8 r = setup.bRequest;
168 u8 requestType = setup.bmRequestType;
169 if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
170 {
171 if (HID_GET_REPORT == r)
172 {
173 //HID_GetReport();
174 return true;
175 }
176 if (HID_GET_PROTOCOL == r)
177 {
178 //Send8(_hid_protocol); // TODO
179 return true;
180 }
181 }
182
183 if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
184 {
185 if (HID_SET_PROTOCOL == r)
186 {
187 _hid_protocol = setup.wValueL;
188 return true;
189 }
190
191 if (HID_SET_IDLE == r)
192 {
193 _hid_idle = setup.wValueL;
194 return true;
195 }
196 }
197 return false;
198 }
199
200 //================================================================================
201 //================================================================================
202 // Mouse
203
204 Mouse_::Mouse_(void) : _buttons(0)
205 {
206 }
207
208 void Mouse_::begin(void)
209 {
210 }
211
212 void Mouse_::end(void)
213 {
214 }
215
216 void Mouse_::click(uint8_t b)
217 {
218 _buttons = b;
219 move(0,0,0);
220 _buttons = 0;
221 move(0,0,0);
222 }
223
224 void Mouse_::move(signed char x, signed char y, signed char wheel)
225 {
226 u8 m[4];
227 m[0] = _buttons;
228 m[1] = x;
229 m[2] = y;
230 m[3] = wheel;
231 HID_SendReport(1,m,4);
232 }
233
234 void Mouse_::buttons(uint8_t b)
235 {
236 if (b != _buttons)
237 {
238 _buttons = b;
239 move(0,0,0);
240 }
241 }
242
243 void Mouse_::press(uint8_t b)
244 {
245 buttons(_buttons | b);
246 }
247
248 void Mouse_::release(uint8_t b)
249 {
250 buttons(_buttons & ~b);
251 }
252
253 bool Mouse_::isPressed(uint8_t b)
254 {
255 if ((b & _buttons) > 0)
256 return true;
257 return false;
258 }
259
260 //================================================================================
261 //================================================================================
262 // Keyboard
263
264 Keyboard_::Keyboard_(void)
265 {
266 }
267
268 void Keyboard_::begin(void)
269 {
270 }
271
272 void Keyboard_::end(void)
273 {
274 }
275
276 void Keyboard_::sendReport(KeyReport* keys)
277 {
278 HID_SendReport(2,keys,sizeof(KeyReport));
279 }
280
281 extern
282 const uint8_t _asciimap[128] PROGMEM;
283
284 #define SHIFT 0x80
285 const uint8_t _asciimap[128] =
286 {
287 0x00, // NUL
288 0x00, // SOH
289 0x00, // STX
290 0x00, // ETX
291 0x00, // EOT
292 0x00, // ENQ
293 0x00, // ACK
294 0x00, // BEL
295 0x2a, // BS Backspace
296 0x2b, // TAB Tab
297 0x28, // LF Enter
298 0x00, // VT
299 0x00, // FF
300 0x00, // CR
301 0x00, // SO
302 0x00, // SI
303 0x00, // DEL
304 0x00, // DC1
305 0x00, // DC2
306 0x00, // DC3
307 0x00, // DC4
308 0x00, // NAK
309 0x00, // SYN
310 0x00, // ETB
311 0x00, // CAN
312 0x00, // EM
313 0x00, // SUB
314 0x00, // ESC
315 0x00, // FS
316 0x00, // GS
317 0x00, // RS
318 0x00, // US
319
320 0x2c, // ' '
321 0x1e|SHIFT, // !
322 0x34|SHIFT, // "
323 0x20|SHIFT, // #
324 0x21|SHIFT, // $
325 0x22|SHIFT, // %
326 0x24|SHIFT, // &
327 0x34, // '
328 0x26|SHIFT, // (
329 0x27|SHIFT, // )
330 0x25|SHIFT, // *
331 0x2e|SHIFT, // +
332 0x36, // ,
333 0x2d, // -
334 0x37, // .
335 0x38, // /
336 0x27, // 0
337 0x1e, // 1
338 0x1f, // 2
339 0x20, // 3
340 0x21, // 4
341 0x22, // 5
342 0x23, // 6
343 0x24, // 7
344 0x25, // 8
345 0x26, // 9
346 0x33|SHIFT, // :
347 0x33, // ;
348 0x36|SHIFT, // <
349 0x2e, // =
350 0x37|SHIFT, // >
351 0x38|SHIFT, // ?
352 0x1f|SHIFT, // @
353 0x04|SHIFT, // A
354 0x05|SHIFT, // B
355 0x06|SHIFT, // C
356 0x07|SHIFT, // D
357 0x08|SHIFT, // E
358 0x09|SHIFT, // F
359 0x0a|SHIFT, // G
360 0x0b|SHIFT, // H
361 0x0c|SHIFT, // I
362 0x0d|SHIFT, // J
363 0x0e|SHIFT, // K
364 0x0f|SHIFT, // L
365 0x10|SHIFT, // M
366 0x11|SHIFT, // N
367 0x12|SHIFT, // O
368 0x13|SHIFT, // P
369 0x14|SHIFT, // Q
370 0x15|SHIFT, // R
371 0x16|SHIFT, // S
372 0x17|SHIFT, // T
373 0x18|SHIFT, // U
374 0x19|SHIFT, // V
375 0x1a|SHIFT, // W
376 0x1b|SHIFT, // X
377 0x1c|SHIFT, // Y
378 0x1d|SHIFT, // Z
379 0x2f, // [
380 0x31, // bslash
381 0x30, // ]
382 0x23|SHIFT, // ^
383 0x2d|SHIFT, // _
384 0x35, // `
385 0x04, // a
386 0x05, // b
387 0x06, // c
388 0x07, // d
389 0x08, // e
390 0x09, // f
391 0x0a, // g
392 0x0b, // h
393 0x0c, // i
394 0x0d, // j
395 0x0e, // k
396 0x0f, // l
397 0x10, // m
398 0x11, // n
399 0x12, // o
400 0x13, // p
401 0x14, // q
402 0x15, // r
403 0x16, // s
404 0x17, // t
405 0x18, // u
406 0x19, // v
407 0x1a, // w
408 0x1b, // x
409 0x1c, // y
410 0x1d, // z
411 0x2f|SHIFT, //
412 0x31|SHIFT, // |
413 0x30|SHIFT, // }
414 0x35|SHIFT, // ~
415 0 // DEL
416 };
417
418 uint8_t USBPutChar(uint8_t c);
419
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)
425 {
426 uint8_t i;
427 if (k >= 136) { // it's a non-printing key (not a modifier)
428 k = k - 136;
429 } else if (k >= 128) { // it's a modifier key
430 _keyReport.modifiers |= (1<<(k-128));
431 k = 0;
432 } else { // it's a printing key
433 k = pgm_read_byte(_asciimap + k);
434 if (!k) {
435 setWriteError();
436 return 0;
437 }
438 if (k & 0x80) { // it's a capital letter or other character reached with shift
439 _keyReport.modifiers |= 0x02; // the left shift modifier
440 k &= 0x7F;
441 }
442 }
443
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) {
449
450 for (i=0; i<6; i++) {
451 if (_keyReport.keys[i] == 0x00) {
452 _keyReport.keys[i] = k;
453 break;
454 }
455 }
456 if (i == 6) {
457 setWriteError();
458 return 0;
459 }
460 }
461 sendReport(&_keyReport);
462 return 1;
463 }
464
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)
469 {
470 uint8_t i;
471 if (k >= 136) { // it's a non-printing key (not a modifier)
472 k = k - 136;
473 } else if (k >= 128) { // it's a modifier key
474 _keyReport.modifiers &= ~(1<<(k-128));
475 k = 0;
476 } else { // it's a printing key
477 k = pgm_read_byte(_asciimap + k);
478 if (!k) {
479 return 0;
480 }
481 if (k & 0x80) { // it's a capital letter or other character reached with shift
482 _keyReport.modifiers &= ~(0x02); // the left shift modifier
483 k &= 0x7F;
484 }
485 }
486
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;
492 }
493 }
494
495 sendReport(&_keyReport);
496 return 1;
497 }
498
499 void Keyboard_::releaseAll(void)
500 {
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);
509 }
510
511 size_t Keyboard_::write(uint8_t c)
512 {
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
516 }
517
518 #endif
519
520 #endif /* if defined(USBCON) */

mercurial