root / arduino-1.0 / hardware / arduino / cores / arduino / HID.cpp @ 58d82c77
History | View | Annotate | Download (11.2 KB)
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 |
#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) */ |