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

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

ライブラリとOS及びベーシックなサンプルの追加.

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