source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/HID.cpp@ 224

Last change on this file since 224 was 224, checked in by ertl-honda, 8 years ago

1.7.10のファイルに更新

File size: 14.0 KB
Line 
1/* Copyright (c) 2011, Peter Barrett
2**
3** Permission to use, copy, modify, and/or distribute this software for
4** any purpose with or without fee is hereby granted, provided that the
5** above copyright notice and this permission notice appear in all copies.
6**
7** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
8** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
9** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
10** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
11** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
12** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
13** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
14** SOFTWARE.
15*/
16
17
18#include "USBAPI.h"
19#include "Reset.h"
20#include "USBCore.h"
21#include "USBDesc.h"
22#include "sam.h"
23
24
25#ifdef HID_ENABLED
26
27//#define RAWHID_ENABLED
28
29// Singletons for mouse and keyboard
30Mouse_ Mouse;
31Keyboard_ Keyboard;
32
33//================================================================================
34//================================================================================
35
36#define LSB(_x) ((_x) & 0xFF)
37#define MSB(_x) ((_x) >> 8)
38
39#define RAWHID_USAGE_PAGE 0xFFC0
40#define RAWHID_USAGE 0x0C00
41#define RAWHID_TX_SIZE 64
42#define RAWHID_RX_SIZE 64
43
44// HID report descriptor
45_Pragma("pack(1)")
46extern const uint32_t _hidReportDescriptor[] = {
47 // Mouse
48 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
49 0x09, 0x02, // USAGE (Mouse)
50 0xa1, 0x01, // COLLECTION (Application)
51 0x09, 0x01, // USAGE (Pointer)
52 0xa1, 0x00, // COLLECTION (Physical)
53 0x85, 0x01, // REPORT_ID (1)
54 0x05, 0x09, // USAGE_PAGE (Button)
55 0x19, 0x01, // USAGE_MINIMUM (Button 1)
56 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
57 0x15, 0x00, // LOGICAL_MINIMUM (0)
58 0x25, 0x01, // LOGICAL_MAXIMUM (1)
59 0x95, 0x03, // REPORT_COUNT (3)
60 0x75, 0x01, // REPORT_SIZE (1)
61 0x81, 0x02, // INPUT (Data,Var,Abs)
62 0x95, 0x01, // REPORT_COUNT (1)
63 0x75, 0x05, // REPORT_SIZE (5)
64 0x81, 0x03, // INPUT (Cnst,Var,Abs)
65 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
66 0x09, 0x30, // USAGE (X)
67 0x09, 0x31, // USAGE (Y)
68 0x09, 0x38, // USAGE (Wheel)
69 0x15, 0x81, // LOGICAL_MINIMUM (-127)
70 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
71 0x75, 0x08, // REPORT_SIZE (8)
72 0x95, 0x03, // REPORT_COUNT (3)
73 0x81, 0x06, // INPUT (Data,Var,Rel)
74 0xc0, // END_COLLECTION
75 0xc0, // END_COLLECTION
76
77 // Keyboard
78 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
79 0x09, 0x06, // USAGE (Keyboard)
80 0xa1, 0x01, // COLLECTION (Application)
81 0x85, 0x02, // REPORT_ID (2)
82 0x05, 0x07, // USAGE_PAGE (Keyboard)
83
84 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
85 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
86 0x15, 0x00, // LOGICAL_MINIMUM (0)
87 0x25, 0x01, // LOGICAL_MAXIMUM (1)
88 0x75, 0x01, // REPORT_SIZE (1)
89
90 0x95, 0x08, // REPORT_COUNT (8)
91 0x81, 0x02, // INPUT (Data,Var,Abs)
92 0x95, 0x01, // REPORT_COUNT (1)
93 0x75, 0x08, // REPORT_SIZE (8)
94 0x81, 0x03, // INPUT (Cnst,Var,Abs)
95
96 0x95, 0x06, // REPORT_COUNT (6)
97 0x75, 0x08, // REPORT_SIZE (8)
98 0x15, 0x00, // LOGICAL_MINIMUM (0)
99 0x25, 0x65, // LOGICAL_MAXIMUM (101)
100 0x05, 0x07, // USAGE_PAGE (Keyboard)
101
102 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
103 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
104 0x81, 0x00, // INPUT (Data,Ary,Abs)
105 0xc0, // END_COLLECTION
106
107#ifdef RAWHID_ENABLED
108 // RAW HID
109 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
110 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
111
112 0xA1, 0x01, // Collection 0x01
113 0x85, 0x03, // REPORT_ID (3)
114 0x75, 0x08, // report size = 8 bits
115 0x15, 0x00, // logical minimum = 0
116 0x26, 0xFF, 0x00, // logical maximum = 255
117
118 0x95, 64, // report count TX
119 0x09, 0x01, // usage
120 0x81, 0x02, // Input (array)
121
122 0x95, 64, // report count RX
123 0x09, 0x02, // usage
124 0x91, 0x02, // Output (array)
125 0xC0 // end collection
126#endif
127};
128
129extern const HIDDescriptor _hidInterface =
130{
131 D_INTERFACE(HID_INTERFACE,1,3,0,0),
132 D_HIDREPORT(sizeof(_hidReportDescriptor)),
133 D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
134};
135_Pragma("pack()")
136
137//================================================================================
138//================================================================================
139// Driver
140
141uint8_t _hid_protocol = 1;
142uint8_t _hid_idle = 1;
143
144#define WEAK __attribute__ ((weak))
145
146const void* WEAK HID_GetInterface(void)
147{
148 return &_hidInterface;
149}
150
151uint32_t WEAK HID_GetInterfaceLength(void)
152{
153 return sizeof( _hidInterface );
154}
155
156uint32_t HID_SizeReportDescriptor(void)
157{
158 return sizeof(_hidReportDescriptor);
159}
160
161uint32_t WEAK HID_GetDescriptor(void)
162{
163 return USBD_SendControl(_hidReportDescriptor,sizeof(_hidReportDescriptor));
164}
165
166void WEAK HID_SendReport(uint8_t id, const void* data, uint32_t len)
167{
168 uint8_t p[8];
169 const uint8_t *d = reinterpret_cast<const uint8_t *>(data);
170
171 p[0] = id;
172 for (uint32_t i=0; i<len; i++)
173 {
174 p[i+1] = d[i];
175 }
176 USBD_Send(HID_ENDPOINT_INT, p, len+1);
177}
178
179bool WEAK HID_Setup(Setup& setup)
180{
181 uint8_t r = setup.bRequest;
182 uint8_t requestType = setup.bmRequestType;
183
184 if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
185 {
186 if (HID_GET_REPORT == r)
187 {
188 //HID_GetReport();
189 return true;
190 }
191 if (HID_GET_PROTOCOL == r)
192 {
193 //Send8(_hid_protocol);
194 return true;
195 }
196 if (HID_GET_IDLE == r)
197 {
198 USBD_Send(0, &_hid_idle, 1);
199 USB->DEVICE.DeviceEndpoint[EP0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
200 return true;
201 }
202 }
203
204 if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
205 {
206 if (HID_SET_PROTOCOL == r)
207 {
208 _hid_protocol = setup.wValueL;
209 return true;
210 }
211
212 if (HID_SET_IDLE == r)
213 {
214 _hid_idle = setup.wValueH;
215 return true;
216 }
217 }
218 return false;
219}
220
221//================================================================================
222//================================================================================
223// Mouse
224
225Mouse_::Mouse_(void) : _buttons(0)
226{
227}
228
229void Mouse_::begin(void)
230{
231}
232
233void Mouse_::end(void)
234{
235}
236
237void Mouse_::click(uint8_t b)
238{
239 _buttons = b;
240 move(0,0,0);
241 _buttons = 0;
242 move(0,0,0);
243}
244
245void Mouse_::move(signed char x, signed char y, signed char wheel)
246{
247 uint8_t m[4];
248 m[0] = _buttons;
249 m[1] = x;
250 m[2] = y;
251 m[3] = wheel;
252 HID_SendReport(1,m,4);
253}
254
255void Mouse_::buttons(uint8_t b)
256{
257 if (b != _buttons)
258 {
259 _buttons = b;
260 move(0,0,0);
261 }
262}
263
264void Mouse_::press(uint8_t b)
265{
266 buttons(_buttons | b);
267}
268
269void Mouse_::release(uint8_t b)
270{
271 buttons(_buttons & ~b);
272}
273
274bool Mouse_::isPressed(uint8_t b)
275{
276 if ((b & _buttons) > 0)
277 return true;
278 return false;
279}
280
281//================================================================================
282//================================================================================
283// Keyboard
284
285Keyboard_::Keyboard_(void)
286{
287}
288
289void Keyboard_::begin(void)
290{
291}
292
293void Keyboard_::end(void)
294{
295}
296
297void Keyboard_::sendReport(KeyReport* keys)
298{
299 HID_SendReport(2,keys,sizeof(KeyReport));
300}
301
302#define SHIFT 0x80
303extern const uint8_t _asciimap[128] =
304{
305 0x00, // NUL
306 0x00, // SOH
307 0x00, // STX
308 0x00, // ETX
309 0x00, // EOT
310 0x00, // ENQ
311 0x00, // ACK
312 0x00, // BEL
313 0x2a, // BS Backspace
314 0x2b, // TAB Tab
315 0x28, // LF Enter
316 0x00, // VT
317 0x00, // FF
318 0x00, // CR
319 0x00, // SO
320 0x00, // SI
321 0x00, // DEL
322 0x00, // DC1
323 0x00, // DC2
324 0x00, // DC3
325 0x00, // DC4
326 0x00, // NAK
327 0x00, // SYN
328 0x00, // ETB
329 0x00, // CAN
330 0x00, // EM
331 0x00, // SUB
332 0x00, // ESC
333 0x00, // FS
334 0x00, // GS
335 0x00, // RS
336 0x00, // US
337
338 0x2c, // ' '
339 0x1e|SHIFT, // !
340 0x34|SHIFT, // "
341 0x20|SHIFT, // #
342 0x21|SHIFT, // $
343 0x22|SHIFT, // %
344 0x24|SHIFT, // &
345 0x34, // '
346 0x26|SHIFT, // (
347 0x27|SHIFT, // )
348 0x25|SHIFT, // *
349 0x2e|SHIFT, // +
350 0x36, // ,
351 0x2d, // -
352 0x37, // .
353 0x38, // /
354 0x27, // 0
355 0x1e, // 1
356 0x1f, // 2
357 0x20, // 3
358 0x21, // 4
359 0x22, // 5
360 0x23, // 6
361 0x24, // 7
362 0x25, // 8
363 0x26, // 9
364 0x33|SHIFT, // :
365 0x33, // ;
366 0x36|SHIFT, // <
367 0x2e, // =
368 0x37|SHIFT, // >
369 0x38|SHIFT, // ?
370 0x1f|SHIFT, // @
371 0x04|SHIFT, // A
372 0x05|SHIFT, // B
373 0x06|SHIFT, // C
374 0x07|SHIFT, // D
375 0x08|SHIFT, // E
376 0x09|SHIFT, // F
377 0x0a|SHIFT, // G
378 0x0b|SHIFT, // H
379 0x0c|SHIFT, // I
380 0x0d|SHIFT, // J
381 0x0e|SHIFT, // K
382 0x0f|SHIFT, // L
383 0x10|SHIFT, // M
384 0x11|SHIFT, // N
385 0x12|SHIFT, // O
386 0x13|SHIFT, // P
387 0x14|SHIFT, // Q
388 0x15|SHIFT, // R
389 0x16|SHIFT, // S
390 0x17|SHIFT, // T
391 0x18|SHIFT, // U
392 0x19|SHIFT, // V
393 0x1a|SHIFT, // W
394 0x1b|SHIFT, // X
395 0x1c|SHIFT, // Y
396 0x1d|SHIFT, // Z
397 0x2f, // [
398 0x31, // bslash
399 0x30, // ]
400 0x23|SHIFT, // ^
401 0x2d|SHIFT, // _
402 0x35, // `
403 0x04, // a
404 0x05, // b
405 0x06, // c
406 0x07, // d
407 0x08, // e
408 0x09, // f
409 0x0a, // g
410 0x0b, // h
411 0x0c, // i
412 0x0d, // j
413 0x0e, // k
414 0x0f, // l
415 0x10, // m
416 0x11, // n
417 0x12, // o
418 0x13, // p
419 0x14, // q
420 0x15, // r
421 0x16, // s
422 0x17, // t
423 0x18, // u
424 0x19, // v
425 0x1a, // w
426 0x1b, // x
427 0x1c, // y
428 0x1d, // z
429 0x2f|SHIFT, //
430 0x31|SHIFT, // |
431 0x30|SHIFT, // }
432 0x35|SHIFT, // ~
433 0 // DEL
434} ;
435
436// press() adds the specified key (printing, non-printing, or modifier)
437// to the persistent key report and sends the report. Because of the way
438// USB HID works, the host acts like the key remains pressed until we
439// call release(), releaseAll(), or otherwise clear the report and resend.
440size_t Keyboard_::press(uint8_t k)
441{
442 uint8_t i;
443 if (k >= 136) { // it's a non-printing key (not a modifier)
444 k = k - 136;
445 } else if (k >= 128) { // it's a modifier key
446 _keyReport.modifiers |= (1<<(k-128));
447 k = 0;
448 } else { // it's a printing key
449 k = _asciimap[k];
450 if (!k) {
451 setWriteError();
452 return 0;
453 }
454 if (k & 0x80) { // it's a capital letter or other character reached with shift
455 _keyReport.modifiers |= 0x02; // the left shift modifier
456 k &= 0x7F;
457 }
458 }
459
460 // Add k to the key report only if it's not already present
461 // and if there is an empty slot.
462 if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
463 _keyReport.keys[2] != k && _keyReport.keys[3] != k &&
464 _keyReport.keys[4] != k && _keyReport.keys[5] != k) {
465
466 for (i=0; i<6; i++) {
467 if (_keyReport.keys[i] == 0x00) {
468 _keyReport.keys[i] = k;
469 break;
470 }
471 }
472 if (i == 6) {
473 setWriteError();
474 return 0;
475 }
476 }
477 sendReport(&_keyReport);
478 return 1;
479}
480
481// release() takes the specified key out of the persistent key report and
482// sends the report. This tells the OS the key is no longer pressed and that
483// it shouldn't be repeated any more.
484
485size_t Keyboard_::release(uint8_t k)
486{
487 uint8_t i;
488 if (k >= 136) { // it's a non-printing key (not a modifier)
489 k = k - 136;
490 } else if (k >= 128) { // it's a modifier key
491 _keyReport.modifiers &= ~(1<<(k-128));
492 k = 0;
493 } else { // it's a printing key
494 k = _asciimap[k];
495 if (!k) {
496 return 0;
497 }
498 if (k & 0x80) { // it's a capital letter or other character reached with shift
499 _keyReport.modifiers &= ~(0x02); // the left shift modifier
500 k &= 0x7F;
501 }
502 }
503
504 // Test the key report to see if k is present. Clear it if it exists.
505 // Check all positions in case the key is present more than once (which it shouldn't be)
506 for (i=0; i<6; i++) {
507 if (0 != k && _keyReport.keys[i] == k) {
508 _keyReport.keys[i] = 0x00;
509 }
510 }
511
512 sendReport(&_keyReport);
513 return 1;
514}
515
516void Keyboard_::releaseAll(void)
517{
518 _keyReport.keys[0] = 0;
519 _keyReport.keys[1] = 0;
520 _keyReport.keys[2] = 0;
521 _keyReport.keys[3] = 0;
522 _keyReport.keys[4] = 0;
523 _keyReport.keys[5] = 0;
524 _keyReport.modifiers = 0;
525 sendReport(&_keyReport);
526}
527
528size_t Keyboard_::write(uint8_t c)
529{
530 uint8_t p = 0;
531
532 p = press(c); // Keydown
533 release(c); // Keyup
534
535 return (p); // Just return the result of press() since release() almost always returns 1
536}
537
538#endif
Note: See TracBrowser for help on using the repository browser.