USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
hidboot.h
Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9 
10 Contact information
11 -------------------
12 
13 Circuits At Home, LTD
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
16  */
17 #if !defined(__HIDBOOT_H__)
18 #define __HIDBOOT_H__
19 
20 #include "hid.h"
21 
22 #define KEY_SPACE 0x2c
23 #define KEY_ZERO 0x27
24 #define KEY_ZERO2 0x62
25 #define KEY_ENTER 0x28
26 #define KEY_PERIOD 0x63
27 
28 struct MOUSEINFO {
29 
30  struct {
31  uint8_t bmLeftButton : 1;
32  uint8_t bmRightButton : 1;
33  uint8_t bmMiddleButton : 1;
34  uint8_t bmDummy : 1;
35  };
36  int8_t dX;
37  int8_t dY;
38 };
39 
41 
42  union {
44  uint8_t bInfo[sizeof(MOUSEINFO)];
45  } prevState;
46 
47 public:
48  virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
49 
50 protected:
51 
52  virtual void OnMouseMove(MOUSEINFO *mi) {
53  };
54 
55  virtual void OnLeftButtonUp(MOUSEINFO *mi) {
56  };
57 
58  virtual void OnLeftButtonDown(MOUSEINFO *mi) {
59  };
60 
61  virtual void OnRightButtonUp(MOUSEINFO *mi) {
62  };
63 
64  virtual void OnRightButtonDown(MOUSEINFO *mi) {
65  };
66 
67  virtual void OnMiddleButtonUp(MOUSEINFO *mi) {
68  };
69 
70  virtual void OnMiddleButtonDown(MOUSEINFO *mi) {
71  };
72 };
73 
74 struct MODIFIERKEYS {
75  uint8_t bmLeftCtrl : 1;
76  uint8_t bmLeftShift : 1;
77  uint8_t bmLeftAlt : 1;
78  uint8_t bmLeftGUI : 1;
79  uint8_t bmRightCtrl : 1;
80  uint8_t bmRightShift : 1;
81  uint8_t bmRightAlt : 1;
82  uint8_t bmRightGUI : 1;
83 };
84 
85 struct KBDINFO {
86 
87  struct {
88  uint8_t bmLeftCtrl : 1;
89  uint8_t bmLeftShift : 1;
90  uint8_t bmLeftAlt : 1;
91  uint8_t bmLeftGUI : 1;
92  uint8_t bmRightCtrl : 1;
93  uint8_t bmRightShift : 1;
94  uint8_t bmRightAlt : 1;
95  uint8_t bmRightGUI : 1;
96  };
97  uint8_t bReserved;
98  uint8_t Keys[6];
99 };
100 
101 struct KBDLEDS {
102  uint8_t bmNumLock : 1;
103  uint8_t bmCapsLock : 1;
104  uint8_t bmScrollLock : 1;
105  uint8_t bmCompose : 1;
106  uint8_t bmKana : 1;
107  uint8_t bmReserved : 3;
108 };
109 
110 #define KEY_NUM_LOCK 0x53
111 #define KEY_CAPS_LOCK 0x39
112 #define KEY_SCROLL_LOCK 0x47
113 
115  static const uint8_t numKeys[];
116  static const uint8_t symKeysUp[];
117  static const uint8_t symKeysLo[];
118  static const uint8_t padKeys[];
119 
120 protected:
121 
122  union {
124  uint8_t bInfo[sizeof(KBDINFO)];
125  } prevState;
126 
127  union {
129  uint8_t bLeds;
130  } kbdLockingKeys;
131 
132  uint8_t OemToAscii(uint8_t mod, uint8_t key);
133 
134 public:
135 
137  kbdLockingKeys.bLeds = 0;
138  };
139 
140  virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
141 
142 protected:
143  virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key);
144 
145  virtual void OnControlKeysChanged(uint8_t before, uint8_t after) {
146  };
147 
148  virtual void OnKeyDown(uint8_t mod, uint8_t key) {
149  };
150 
151  virtual void OnKeyUp(uint8_t mod, uint8_t key) {
152  };
153 };
154 
155 #define totalEndpoints (((BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD)? 2 : 0)+((BOOT_PROTOCOL & HID_PROTOCOL_MOUSE)? 1 : 0))
156 #define epMUL (((BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD)? 1 : 0)+((BOOT_PROTOCOL & HID_PROTOCOL_MOUSE)? 1 : 0))
157 #define HID_MAX_HID_CLASS_DESCRIPTORS 5
158 
159 template <const uint8_t BOOT_PROTOCOL>
160 class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter
161 {
162  EpInfo epInfo[totalEndpoints];
163  HIDReportParser *pRptParser[epMUL];
164 
165  uint8_t bConfNum; // configuration number
166  uint8_t bIfaceNum; // Interface Number
167  uint8_t bNumIface; // number of interfaces in the configuration
168  uint8_t bNumEP; // total number of EP in the configuration
169  uint32_t qNextPollTime; // next poll time
170  bool bPollEnable; // poll enable flag
171 
172  void Initialize();
173 
174  virtual HIDReportParser* GetReportParser(uint8_t id) {
175  return pRptParser[id];
176  };
177 
178 public:
179  HIDBoot(USB *p);
180 
181  virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {
182  pRptParser[id] = prs;
183  return true;
184  };
185 
186  // USBDeviceConfig implementation
187  virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
188  virtual uint8_t Release();
189  virtual uint8_t Poll();
190 
191  virtual uint8_t GetAddress() {
192  return bAddress;
193  };
194 
195  // UsbConfigXtracter implementation
196  virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
197 };
198 
199 template <const uint8_t BOOT_PROTOCOL>
201 HID(p),
202 qNextPollTime(0),
203 bPollEnable(false) {
204  Initialize();
205 
206  for(uint8_t i = 0; i < epMUL; i++) {
207  pRptParser[i] = NULL;
208  }
209  if(pUsb)
210  pUsb->RegisterDeviceClass(this);
211 }
212 
213 template <const uint8_t BOOT_PROTOCOL>
215  for(uint8_t i = 0; i < totalEndpoints; i++) {
216  epInfo[i].epAddr = 0;
217  epInfo[i].maxPktSize = (i) ? 0 : 8;
218  epInfo[i].epAttribs = 0;
219  epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
220  }
221  bNumEP = 1;
222  bNumIface = 0;
223  bConfNum = 0;
224 }
225 
226 template <const uint8_t BOOT_PROTOCOL>
227 uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed) {
228  const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR);
229 
230  uint8_t buf[constBufSize];
231  uint8_t rcode;
232  UsbDevice *p = NULL;
233  EpInfo *oldep_ptr = NULL;
234  uint8_t len = 0;
235  //uint16_t cd_len = 0;
236 
237  uint8_t num_of_conf; // number of configurations
238  //uint8_t num_of_intf; // number of interfaces
239 
240  AddressPool &addrPool = pUsb->GetAddressPool();
241 
242  USBTRACE("BM Init\r\n");
243 
244  if(bAddress)
246 
247  // Get pointer to pseudo device with address 0 assigned
248  p = addrPool.GetUsbDevicePtr(0);
249 
250  if(!p)
252 
253  if(!p->epinfo) {
254  USBTRACE("epinfo\r\n");
256  }
257 
258  // Save old pointer to EP_RECORD of address 0
259  oldep_ptr = p->epinfo;
260 
261  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
262  p->epinfo = epInfo;
263 
264  p->lowspeed = lowspeed;
265 
266  // Get device descriptor
267  rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf);
268 
269  if(!rcode)
270  len = (buf[0] > constBufSize) ? constBufSize : buf[0];
271 
272  if(rcode) {
273  // Restore p->epinfo
274  p->epinfo = oldep_ptr;
275 
276  goto FailGetDevDescr;
277  }
278 
279  // Restore p->epinfo
280  p->epinfo = oldep_ptr;
281 
282  // Allocate new address according to device class
283  bAddress = addrPool.AllocAddress(parent, false, port);
284 
285  if(!bAddress)
287 
288  // Extract Max Packet Size from the device descriptor
289  epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0;
290 
291  // Assign new address to the device
292  rcode = pUsb->setAddr(0, 0, bAddress);
293 
294  if(rcode) {
295  p->lowspeed = false;
296  addrPool.FreeAddress(bAddress);
297  bAddress = 0;
298  USBTRACE2("setAddr:", rcode);
299  return rcode;
300  }
301 
302  USBTRACE2("Addr:", bAddress);
303 
304  p->lowspeed = false;
305 
306  p = addrPool.GetUsbDevicePtr(bAddress);
307 
308  if(!p)
310 
311  p->lowspeed = lowspeed;
312 
313  if(len)
314  rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf);
315 
316  if(rcode)
317  goto FailGetDevDescr;
318 
319  num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations;
320 
321  // Assign epInfo to epinfo pointer
322  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
323 
324  if(rcode)
325  goto FailSetDevTblEntry;
326 
327  //USBTRACE2("NC:", num_of_conf);
328 
329  // GCC will optimize unused stuff away.
330  if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
331  for(uint8_t i = 0; i < num_of_conf; i++) {
336  CP_MASK_COMPARE_ALL> confDescrParserA(this);
337 
338  if(bNumEP == totalEndpoints)
339  break;
340  pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);
341  }
342  }
343 
344  // GCC will optimize unused stuff away.
345  if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) {
346  for(uint8_t i = 0; i < num_of_conf; i++) {
351  CP_MASK_COMPARE_ALL> confDescrParserB(this);
352  if(bNumEP == totalEndpoints)
353  break;
354 
355  pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB);
356  }
357  }
358 
359  USBTRACE2("\r\nbAddr:", bAddress);
360  USBTRACE2("\r\nbNumEP:", bNumEP);
361  USBTRACE2("\r\ntotalEndpoints:", totalEndpoints);
362  if(bNumEP != totalEndpoints) {
364  goto Fail;
365  }
366 
367  // Assign epInfo to epinfo pointer
368  rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
369 
370  USBTRACE2("\r\nCnf:", bConfNum);
371 
372  // Set Configuration Value
373  rcode = pUsb->setConf(bAddress, 0, bConfNum);
374 
375  if(rcode)
376  goto FailSetConfDescr;
377 
378  USBTRACE2("\r\nIf:", bIfaceNum);
379 
380  rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL);
381 
382  if(rcode)
383  goto FailSetProtocol;
384 
385  // GCC will optimize unused stuff away.
386  if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
387  rcode = SetIdle(0/* bIfaceNum*/, 0, 0);
388 
389  if(rcode)
390  goto FailSetIdle;
391  }
392  USBTRACE("BM configured\r\n");
393 
394  bPollEnable = true;
395  return 0;
396 
397 FailGetDevDescr:
398 #ifdef DEBUG_USB_HOST
400  goto Fail;
401 #endif
402 
403 FailSetDevTblEntry:
404 #ifdef DEBUG_USB_HOST
406  goto Fail;
407 #endif
408 
409 FailGetConfDescr:
410 #ifdef DEBUG_USB_HOST
412  goto Fail;
413 #endif
414 
415 FailSetConfDescr:
416 #ifdef DEBUG_USB_HOST
418  goto Fail;
419 #endif
420 
421 FailSetProtocol:
422 #ifdef DEBUG_USB_HOST
423  USBTRACE("SetProto:");
424  goto Fail;
425 #endif
426 
427 FailSetIdle:
428 #ifdef DEBUG_USB_HOST
429  USBTRACE("SetIdle:");
430 #endif
431 
432 Fail:
433 #ifdef DEBUG_USB_HOST
434  NotifyFail(rcode);
435 #endif
436  Release();
437  return rcode;
438 }
439 
440 template <const uint8_t BOOT_PROTOCOL>
441 void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
442  // If the first configuration satisfies, the others are not considered.
443  if(bNumEP > 1 && conf != bConfNum)
444  return;
445 
446  bConfNum = conf;
447  bIfaceNum = iface;
448 
449  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) {
450  uint8_t index = bNumEP;//epInterruptInIndex; //+ bNumEP;
451 
452  // Fill in the endpoint info structure
453  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
454  epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize;
455  epInfo[index].epAttribs = 0;
456  epInfo[index].bmNakPower = USB_NAK_NOWAIT;
457  bNumEP++;
458 
459  }
460 }
461 
462 template <const uint8_t BOOT_PROTOCOL>
464  pUsb->GetAddressPool().FreeAddress(bAddress);
465 
466  bConfNum = 0;
467  bIfaceNum = 0;
468  bNumEP = 1;
469  bAddress = 0;
470  qNextPollTime = 0;
471  bPollEnable = false;
472  return 0;
473 }
474 
475 template <const uint8_t BOOT_PROTOCOL>
477  uint8_t rcode = 0;
478 
479  if(!bPollEnable)
480  return 0;
481 
482  if(qNextPollTime <= millis()) {
483  qNextPollTime = millis() + 10;
484 
485  // To-do: optimize manually, getting rid of the loop
486  for(uint8_t i = 0; i < epMUL; i++) {
487  const uint8_t const_buff_len = 16;
488  uint8_t buf[const_buff_len];
489 
490 
491  uint16_t read = (uint16_t) epInfo[epInterruptInIndex + i].maxPktSize;
492 
493  uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf);
494  if(!rcode) {
495  if(pRptParser[i])
496  pRptParser[i]->Parse((HID*)this, 0, (uint8_t) read, buf);
497 
498  //for (uint8_t i=0; i<read; i++)
499  // PrintHex<uint8_t>(buf[i]);
500  //if (read)
501  // USB_HOST_SERIAL.println("");
502  } else {
503  if(rcode != hrNAK) {
504  USBTRACE2("Poll:", rcode);
505  break;
506  }
507  }
508  }
509  }
510  return rcode;
511 }
512 
513 #endif // __HIDBOOTMOUSE_H__
#define CP_MASK_COMPARE_ALL
uint8_t bmLeftShift
Definition: hidboot.h:76
EpInfo * epinfo
Definition: address.h:76
uint8_t bmKana
Definition: hidboot.h:106
uint8_t bmRightButton
Definition: hidboot.h:32
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:67
virtual void OnRightButtonDown(MOUSEINFO *mi)
Definition: hidboot.h:64
virtual void OnKeyDown(uint8_t mod, uint8_t key)
Definition: hidboot.h:148
virtual uint8_t Poll()
Definition: hidboot.h:476
uint8_t bmLeftCtrl
Definition: hidboot.h:88
uint8_t bmRightShift
Definition: hidboot.h:93
#define NotifyFail(...)
Definition: message.h:55
virtual void OnMiddleButtonUp(MOUSEINFO *mi)
Definition: hidboot.h:67
virtual uint8_t HandleLockingKeys(HID *hid, uint8_t key)
Definition: hidboot.cpp:81
MOUSEINFO mouseInfo
Definition: hidboot.h:43
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
Definition: hidboot.cpp:19
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: hidboot.h:441
uint8_t bmCapsLock
Definition: hidboot.h:103
uint8_t bmNumLock
Definition: hidboot.h:102
union KeyboardReportParser::@14 kbdLockingKeys
#define NotifyFailGetDevDescr(...)
Definition: message.h:50
uint8_t bAddress
Definition: hid.h:146
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: hidboot.h:227
union KeyboardReportParser::@13 prevState
virtual bool SetReportParser(uint8_t id, HIDReportParser *prs)
Definition: hidboot.h:181
virtual void OnKeyUp(uint8_t mod, uint8_t key)
Definition: hidboot.h:151
uint8_t bmLeftGUI
Definition: hidboot.h:91
#define USB_CLASS_HID
Definition: UsbCore.h:43
virtual void FreeAddress(uint8_t addr)=0
#define HID_PROTOCOL_KEYBOARD
Definition: hid.h:90
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
Definition: hidboot.cpp:48
uint8_t bmReserved
Definition: hidboot.h:107
#define HID_BOOT_PROTOCOL
Definition: hid.h:79
#define USBTRACE2(s, r)
Definition: macros.h:61
uint8_t bmMiddleButton
Definition: hidboot.h:33
#define NotifyFailGetConfDescr(...)
Definition: message.h:52
virtual void OnLeftButtonUp(MOUSEINFO *mi)
Definition: hidboot.h:55
uint8_t bmDummy
Definition: hidboot.h:34
uint8_t bmLeftAlt
Definition: hidboot.h:77
virtual uint8_t GetAddress()
Definition: hidboot.h:191
HIDBoot(USB *p)
Definition: hidboot.h:200
#define USB_NAK_MAX_POWER
Definition: address.h:27
#define HID_BOOT_INTF_SUBCLASS
Definition: hid.h:86
uint8_t bInfo[sizeof(KBDINFO)]
Definition: hidboot.h:124
uint8_t bmRightCtrl
Definition: hidboot.h:92
uint8_t bInfo[sizeof(MOUSEINFO)]
Definition: hidboot.h:44
Definition: address.h:32
virtual void OnMouseMove(MOUSEINFO *mi)
Definition: hidboot.h:52
#define hrNAK
Definition: max3421e.h:216
virtual void OnRightButtonUp(MOUSEINFO *mi)
Definition: hidboot.h:61
uint8_t bmLeftGUI
Definition: hidboot.h:78
uint16_t wMaxPacketSize
Definition: usb_ch9.h:146
Definition: hid.h:143
virtual void OnMiddleButtonDown(MOUSEINFO *mi)
Definition: hidboot.h:70
uint8_t bmRightCtrl
Definition: hidboot.h:79
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
uint8_t bEndpointAddress
Definition: usb_ch9.h:144
uint8_t bmRightGUI
Definition: hidboot.h:82
uint8_t bmScrollLock
Definition: hidboot.h:104
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:69
uint8_t bmLeftShift
Definition: hidboot.h:89
uint8_t bmRightShift
Definition: hidboot.h:80
#define USB_NAK_NOWAIT
Definition: address.h:29
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:66
int8_t dX
Definition: hidboot.h:36
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:61
virtual void OnControlKeysChanged(uint8_t before, uint8_t after)
Definition: hidboot.h:145
USB * pUsb
Definition: hid.h:145
virtual uint8_t Release()
Definition: hidboot.h:463
uint8_t bmRightGUI
Definition: hidboot.h:95
virtual void OnLeftButtonDown(MOUSEINFO *mi)
Definition: hidboot.h:58
#define HID_PROTOCOL_MOUSE
Definition: hid.h:91
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:64
uint8_t bmLeftCtrl
Definition: hidboot.h:75
uint8_t bmRightAlt
Definition: hidboot.h:81
int8_t dY
Definition: hidboot.h:37
#define totalEndpoints
Definition: hidboot.h:155
Definition: UsbCore.h:152
#define epMUL
Definition: hidboot.h:156
uint8_t bmRightAlt
Definition: hidboot.h:94
uint8_t Keys[6]
Definition: hidboot.h:98
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:172
static const uint8_t totalEndpoints
Definition: hid.h:154
#define NotifyFailSetConfDescr(...)
Definition: message.h:53
uint8_t bmCompose
Definition: hidboot.h:105
uint8_t bmLeftButton
Definition: hidboot.h:31
uint8_t bmLeftAlt
Definition: hidboot.h:90
uint8_t bReserved
Definition: hidboot.h:97
#define USBTRACE(s)
Definition: macros.h:60
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:51
uint8_t OemToAscii(uint8_t mod, uint8_t key)
Definition: hidboot.cpp:107