source: rtos_arduino/trunk/arduino_lib/libraries/USBHost/src/hidboot.h@ 136

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

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

File size: 12.6 KB
Line 
1/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2
3This software may be distributed and modified under the terms of the GNU
4General Public License version 2 (GPL2) as published by the Free Software
5Foundation and appearing in the file GPL2.TXT included in the packaging of
6this file. Please note that GPL2 Section 2[b] requires that all works based
7on this software must also be made publicly available under the terms of
8the GPL2 ("Copyleft").
9
10Contact information
11-------------------
12
13Circuits At Home, LTD
14Web : http://www.circuitsathome.com
15e-mail : support@circuitsathome.com
16*/
17
18#ifndef HIDBOOT_H_INCLUDED
19#define HIDBOOT_H_INCLUDED
20
21#include <stdint.h>
22#include "usb_ch9.h"
23#include "Usb.h"
24#include "hid.h"
25#include "Arduino.h"
26#include "confdescparser.h"
27
28#define KEY_SPACE 0x2c
29#define KEY_ZERO 0x27
30#define KEY_ZERO2 0x62
31#define KEY_ENTER 0x28
32#define KEY_PERIOD 0x63
33
34/**
35 * \brief MOUSEINFO definition.
36 */
37struct MOUSEINFO
38{
39 struct
40 {
41 uint8_t bmLeftButton : 1;
42 uint8_t bmRightButton : 1;
43 uint8_t bmMiddleButton : 1;
44 uint8_t bmDummy : 1;
45 };
46 int8_t dX;
47 int8_t dY;
48};
49
50/**
51 * \class MouseReportParser definition.
52 */
53class MouseReportParser : public HIDReportParser
54{
55 union
56 {
57 MOUSEINFO mouseInfo;
58 uint8_t bInfo[3];
59 } prevState;
60
61public:
62 virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf);
63
64protected:
65 virtual void OnMouseMove (MOUSEINFO *mi) {};
66 virtual void OnLeftButtonUp (MOUSEINFO *mi) {};
67 virtual void OnLeftButtonDown (MOUSEINFO *mi) {};
68 virtual void OnRightButtonUp (MOUSEINFO *mi) {};
69 virtual void OnRightButtonDown (MOUSEINFO *mi) {};
70 virtual void OnMiddleButtonUp (MOUSEINFO *mi) {};
71 virtual void OnMiddleButtonDown (MOUSEINFO *mi) {};
72};
73
74/**
75 * \brief MODIFIERKEYS definition.
76 */
77struct MODIFIERKEYS
78{
79 uint8_t bmLeftCtrl : 1;
80 uint8_t bmLeftShift : 1;
81 uint8_t bmLeftAlt : 1;
82 uint8_t bmLeftGUI : 1;
83 uint8_t bmRightCtrl : 1;
84 uint8_t bmRightShift : 1;
85 uint8_t bmRightAlt : 1;
86 uint8_t bmRightGUI : 1;
87};
88
89/**
90 * \brief KBDINFO definition.
91 */
92struct KBDINFO
93{
94 struct
95 {
96 uint8_t bmLeftCtrl : 1;
97 uint8_t bmLeftShift : 1;
98 uint8_t bmLeftAlt : 1;
99 uint8_t bmLeftGUI : 1;
100 uint8_t bmRightCtrl : 1;
101 uint8_t bmRightShift : 1;
102 uint8_t bmRightAlt : 1;
103 uint8_t bmRightGUI : 1;
104 };
105 uint8_t bReserved;
106 uint8_t Keys[6];
107};
108
109/**
110 * \brief KBDLEDS definition.
111 */
112struct KBDLEDS
113{
114 uint8_t bmNumLock : 1;
115 uint8_t bmCapsLock : 1;
116 uint8_t bmScrollLock : 1;
117 uint8_t bmCompose : 1;
118 uint8_t bmKana : 1;
119 uint8_t bmReserved : 3;
120};
121
122#define KEY_NUM_LOCK 0x53
123
124// Clear compiler warning
125#ifdef KEY_CAPS_LOCK
126#undef KEY_CAPS_LOCK
127#endif
128
129#define KEY_CAPS_LOCK 0x39
130#define KEY_SCROLL_LOCK 0x47
131
132/**
133 * \class KeyboardReportParser definition.
134 */
135class KeyboardReportParser : public HIDReportParser
136{
137 static const uint8_t numKeys[];
138 static const uint8_t symKeysUp[];
139 static const uint8_t symKeysLo[];
140 static const uint8_t padKeys[];
141
142protected:
143 union
144 {
145 KBDINFO kbdInfo;
146 uint8_t bInfo[sizeof(KBDINFO)];
147 } prevState;
148
149 union
150 {
151 KBDLEDS kbdLeds;
152 uint8_t bLeds;
153 } kbdLockingKeys;
154
155 uint8_t OemToAscii(uint8_t mod, uint8_t key);
156
157public:
158 KeyboardReportParser() { kbdLockingKeys.bLeds = 0; };
159
160 virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf);
161
162protected:
163 uint8_t HandleLockingKeys(HID* hid, uint8_t key);
164
165 virtual void OnKeyDown (uint8_t mod, uint8_t key) {};
166 virtual void OnKeyUp (uint8_t mod, uint8_t key) {};
167};
168
169#define totalEndpoints 2
170
171#define HID_MAX_HID_CLASS_DESCRIPTORS 5
172
173/**
174 * \class HIDBoot definition.
175 */
176template <const uint8_t BOOT_PROTOCOL>
177class HIDBoot : public HID
178{
179 EpInfo epInfo[totalEndpoints];
180
181 HIDReportParser *pRptParser;
182
183 uint32_t bConfNum; // configuration number
184 uint32_t bIfaceNum; // Interface Number
185 uint32_t bNumIface; // number of interfaces in the configuration
186 uint32_t bNumEP; // total number of EP in the configuration
187 uint32_t qNextPollTime; // next poll time
188 bool bPollEnable; // poll enable flag
189
190 void Initialize();
191
192 virtual HIDReportParser* GetReportParser(uint32_t id) { return pRptParser; };
193
194public:
195 HIDBoot(USBHost *p);
196
197 virtual bool SetReportParser(uint32_t id, HIDReportParser *prs) { pRptParser = prs; return true; };
198
199 // USBDeviceConfig implementation
200 virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
201 virtual uint32_t Release();
202 virtual uint32_t Poll();
203 virtual uint32_t GetAddress() { return bAddress; };
204
205 // UsbConfigXtracter implementation
206 virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
207};
208
209/**
210 * \brief HIDBoot class constructor.
211 */
212template <const uint8_t BOOT_PROTOCOL>
213HIDBoot<BOOT_PROTOCOL>::HIDBoot(USBHost *p) :
214 HID(p),
215 pRptParser(NULL),
216 qNextPollTime(0),
217 bPollEnable(false)
218{
219 Initialize();
220
221 if (pUsb)
222 pUsb->RegisterDeviceClass(this);
223}
224
225/**
226 * \brief Initialize HIDBoot class.
227 */
228template <const uint8_t BOOT_PROTOCOL>
229void HIDBoot<BOOT_PROTOCOL>::Initialize()
230{
231 for (uint32_t i = 0; i < totalEndpoints; ++i)
232 {
233 epInfo[i].deviceEpNum = 0;
234 epInfo[i].hostPipeNum = 0;
235 epInfo[i].maxPktSize = (i) ? 0 : 8;
236 epInfo[i].epAttribs = 0;
237 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
238 }
239
240 bNumEP = 1;
241 bNumIface = 0;
242 bConfNum = 0;
243}
244
245/**
246 * \brief Initialize connection to an HID device.
247 *
248 * \param parent USB device address of the Parent device.
249 * \param port USB device base address.
250 * \param lowspeed USB device speed.
251 *
252 * \return 0 on success, error code otherwise.
253 */
254template <const uint8_t BOOT_PROTOCOL>
255uint32_t HIDBoot<BOOT_PROTOCOL>::Init(uint32_t parent, uint32_t port, uint32_t lowspeed)
256{
257 const uint32_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR);
258
259 uint8_t buf[constBufSize];
260 uint32_t rcode = 0;
261 UsbDevice *p = 0;
262 EpInfo *oldep_ptr = 0;
263 uint32_t len = 0;
264
265 uint32_t num_of_conf = 0; // number of configurations
266
267 AddressPool &addrPool = pUsb->GetAddressPool();
268
269 TRACE_USBHOST(printf("HIDBoot::Init\r\n");)
270
271 if (bAddress)
272 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
273
274 // Get pointer to pseudo device with address 0 assigned
275 p = addrPool.GetUsbDevicePtr(0);
276
277 if (!p)
278 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
279
280 if (!p->epinfo)
281 {
282 TRACE_USBHOST(printf("HIDBoot::Init : epinfo is null!\r\n");)
283 return USB_ERROR_EPINFO_IS_NULL;
284 }
285
286 // Save old pointer to EP_RECORD of address 0
287 oldep_ptr = p->epinfo;
288
289 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
290 p->epinfo = epInfo;
291
292 p->lowspeed = lowspeed;
293
294 // Get device descriptor
295 rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
296
297 if (!rcode)
298 len = (buf[0] > constBufSize) ? constBufSize : buf[0];
299
300 if (rcode)
301 {
302 // Restore p->epinfo
303 p->epinfo = oldep_ptr;
304
305 goto FailGetDevDescr;
306 }
307
308 // Restore p->epinfo
309 p->epinfo = oldep_ptr;
310
311 // Allocate new address according to device class
312 bAddress = addrPool.AllocAddress(parent, false, port);
313
314 if (!bAddress)
315 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
316
317 // Extract Max Packet Size from the device descriptor
318 epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
319
320 // Assign new address to the device
321 rcode = pUsb->setAddr(0, 0, bAddress);
322
323 if (rcode)
324 {
325 p->lowspeed = false;
326 addrPool.FreeAddress(bAddress);
327 bAddress = 0;
328 TRACE_USBHOST(printf("HIDBoot::Init : setAddr failed with rcode %lu\r\n", rcode);)
329 return rcode;
330 }
331
332 TRACE_USBHOST(printf("HIDBoot::Init : device address is now %lu\r\n", bAddress);)
333
334 p->lowspeed = false;
335
336 p = addrPool.GetUsbDevicePtr(bAddress);
337
338 if (!p)
339 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
340
341 p->lowspeed = lowspeed;
342
343 if (len)
344 rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
345
346 if(rcode)
347 goto FailGetDevDescr;
348
349 num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
350
351 // Assign epInfo to epinfo pointer
352 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
353
354 if (rcode)
355 goto FailSetDevTblEntry;
356
357 TRACE_USBHOST(printf("HIDBoot::Init : number of configuration is %lu\r\n", num_of_conf);)
358
359 for (uint32_t i = 0; i < num_of_conf; ++i)
360 {
361 ConfigDescParser<
362 USB_CLASS_HID,
363 HID_BOOT_INTF_SUBCLASS,
364 BOOT_PROTOCOL,
365 CP_MASK_COMPARE_ALL> confDescrParser(this);
366
367 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
368
369 if (bNumEP > 1)
370 break;
371 }
372
373 if (bNumEP < 2)
374 return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
375
376 TRACE_USBHOST(printf("HIDBoot::Init : bAddress: %lu\r\n", bAddress);)
377 TRACE_USBHOST(printf("HIDBoot::Init : bNumEP: %lu\r\n", bNumEP);)
378
379 // Assign epInfo to epinfo pointer
380 rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
381
382 TRACE_USBHOST(printf("HIDBoot::Init : bConfNum: %lu\r\n", bConfNum);)
383
384 // Set Configuration Value
385 rcode = pUsb->setConf(bAddress, 0, bConfNum);
386
387 if (rcode)
388 goto FailSetConfDescr;
389
390 TRACE_USBHOST(printf("HIDBoot::Init : bIfaceNum: %lu\r\n", bIfaceNum);)
391
392 rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL);
393
394 if (rcode)
395 goto FailSetProtocol;
396
397 if (BOOT_PROTOCOL == 1)
398 {
399 rcode = SetIdle(bIfaceNum, 0, 0);
400
401 if (rcode)
402 goto FailSetIdle;
403 }
404
405 TRACE_USBHOST(printf("HIDBoot::Init : HID device configured successfully\r\n");)
406
407 bPollEnable = true;
408 return 0;
409
410FailGetDevDescr:
411 TRACE_USBHOST(printf("HIDBoot::Init getDevDescr : ");)
412 goto Fail;
413
414FailSetDevTblEntry:
415 TRACE_USBHOST(printf("HIDBoot::Init setDevTblEn : ");)
416 goto Fail;
417
418FailSetProtocol:
419 TRACE_USBHOST(printf("HIDBoot::Init SetProto : ");)
420 goto Fail;
421
422FailSetIdle:
423 TRACE_USBHOST(printf("HIDBoot::Init SetIdle : ");)
424 goto Fail;
425
426FailSetConfDescr:
427 TRACE_USBHOST(printf("HIDBoot::Init setConf : ");)
428 goto Fail;
429
430Fail:
431 TRACE_USBHOST(printf("error code: %lu\r\n", rcode);)
432 Release();
433 return rcode;
434}
435
436/**
437 * \brief Extract interrupt-IN endpoint information from configuration
438 * descriptor.
439 *
440 * \param conf Configuration number.
441 * \param iface Interface number.
442 * \param alt Alternate setting.
443 * \param proto Protocol version used.
444 * \param pep Pointer to endpoint descriptor.
445 */
446template <const uint8_t BOOT_PROTOCOL>
447void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
448{
449 // If the first configuration satisfies, the others are not considered.
450 if (bNumEP > 1 && conf != bConfNum)
451 return;
452
453 bConfNum = conf;
454 bIfaceNum = iface;
455
456 uint32_t index = 0;
457 uint32_t pipe = 0;
458
459 if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
460 {
461 index = epInterruptInIndex;
462
463 // Fill in the endpoint info structure
464 epInfo[index].deviceEpNum = (pep->bEndpointAddress & 0x0F);
465 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
466 epInfo[index].epAttribs = 0;
467
468 TRACE_USBHOST(printf("HIDBoot::EndpointXtract : Found new endpoint\r\n");)
469 TRACE_USBHOST(printf("HIDBoot::EndpointXtract : deviceEpNum: %lu\r\n", epInfo[index].deviceEpNum);)
470 TRACE_USBHOST(printf("HIDBoot::EndpointXtract : maxPktSize: %lu\r\n", epInfo[index].maxPktSize);)
471 TRACE_USBHOST(printf("HIDBoot::EndpointXtract : index: %lu\r\n", index);)
472
473 // Ensure pipe allocation is okay
474 pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_INTRPT, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 10, UOTGHS_HSTPIPCFG_PBK_1_BANK);
475 if (pipe == 0)
476 {
477 TRACE_USBHOST(printf("HIDBoot::EndpointXtract : Pipe allocation failure\r\n");)
478 // Enumeration failed
479 return;
480 }
481
482 epInfo[index].hostPipeNum = pipe;
483
484 bNumEP++;
485 }
486}
487
488/**
489 * \brief Release USB allocated resources (pipes and address).
490 *
491 * \note Release call is made from USBHost.task() on disconnection events.
492 * \note Release call is made from Init() on enumeration failure.
493 *
494 * \return Always 0.
495 */
496template <const uint8_t BOOT_PROTOCOL>
497uint32_t HIDBoot<BOOT_PROTOCOL>::Release()
498{
499 // Free allocated host pipes
500 UHD_Pipe_Free(epInfo[epInterruptInIndex].hostPipeNum);
501
502 // Free allocated USB address
503 pUsb->GetAddressPool().FreeAddress(bAddress);
504
505 bConfNum = 0;
506 bIfaceNum = 0;
507 bNumEP = 1;
508 bAddress = 0;
509 qNextPollTime = 0;
510 bPollEnable = false;
511
512 return 0;
513}
514
515/**
516 * \brief Poll USB device activity.
517 *
518 * \note Poll call is periodically made from USBHost.task().
519 *
520 * \return 0 on success, error code otherwise.
521 */
522template <const uint8_t BOOT_PROTOCOL>
523uint32_t HIDBoot<BOOT_PROTOCOL>::Poll()
524{
525 uint32_t rcode = 0;
526
527 if (!bPollEnable)
528 return 0;
529
530 if (qNextPollTime <= millis())
531 {
532 qNextPollTime = millis() + 10;
533
534 const uint32_t const_buff_len = 16;
535 uint8_t buf[const_buff_len];
536
537 uint32_t read = epInfo[epInterruptInIndex].maxPktSize;
538
539 rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].deviceEpNum, &read, buf);
540
541 if (rcode)
542 {
543 return rcode;
544 }
545
546 if (pRptParser)
547 pRptParser->Parse((HID*)this, 0, (uint32_t)read, buf);
548 }
549
550 return rcode;
551}
552
553#endif /* HIDBOOT_H_INCLUDED */
Note: See TracBrowser for help on using the repository browser.