You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

hidboot.h 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
  2. This software may be distributed and modified under the terms of the GNU
  3. General Public License version 2 (GPL2) as published by the Free Software
  4. Foundation and appearing in the file GPL2.TXT included in the packaging of
  5. this file. Please note that GPL2 Section 2[b] requires that all works based
  6. on this software must also be made publicly available under the terms of
  7. the GPL2 ("Copyleft").
  8. Contact information
  9. -------------------
  10. Circuits At Home, LTD
  11. Web : http://www.circuitsathome.com
  12. e-mail : [email protected]
  13. */
  14. #if !defined(__HIDBOOT_H__)
  15. #define __HIDBOOT_H__
  16. #include "hid.h"
  17. #define UHS_HID_BOOT_KEY_ZERO 0x27
  18. #define UHS_HID_BOOT_KEY_ENTER 0x28
  19. #define UHS_HID_BOOT_KEY_SPACE 0x2c
  20. #define UHS_HID_BOOT_KEY_CAPS_LOCK 0x39
  21. #define UHS_HID_BOOT_KEY_SCROLL_LOCK 0x47
  22. #define UHS_HID_BOOT_KEY_NUM_LOCK 0x53
  23. #define UHS_HID_BOOT_KEY_ZERO2 0x62
  24. #define UHS_HID_BOOT_KEY_PERIOD 0x63
  25. // Don't worry, GCC will optimize the result to a final value.
  26. #define bitsEndpoints(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & HID_PROTOCOL_MOUSE)? 1 : 0))
  27. #define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2)
  28. #define epMUL(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & HID_PROTOCOL_MOUSE)? 1 : 0))
  29. // Already defined in hid.h
  30. // #define HID_MAX_HID_CLASS_DESCRIPTORS 5
  31. struct MOUSEINFO {
  32. struct {
  33. uint8_t bmLeftButton : 1;
  34. uint8_t bmRightButton : 1;
  35. uint8_t bmMiddleButton : 1;
  36. uint8_t bmDummy : 5;
  37. };
  38. int8_t dX;
  39. int8_t dY;
  40. };
  41. class MouseReportParser : public HIDReportParser {
  42. union {
  43. MOUSEINFO mouseInfo;
  44. uint8_t bInfo[sizeof (MOUSEINFO)];
  45. } prevState;
  46. public:
  47. void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
  48. protected:
  49. virtual void OnMouseMove(MOUSEINFO *mi) {
  50. };
  51. virtual void OnLeftButtonUp(MOUSEINFO *mi) {
  52. };
  53. virtual void OnLeftButtonDown(MOUSEINFO *mi) {
  54. };
  55. virtual void OnRightButtonUp(MOUSEINFO *mi) {
  56. };
  57. virtual void OnRightButtonDown(MOUSEINFO *mi) {
  58. };
  59. virtual void OnMiddleButtonUp(MOUSEINFO *mi) {
  60. };
  61. virtual void OnMiddleButtonDown(MOUSEINFO *mi) {
  62. };
  63. };
  64. struct MODIFIERKEYS {
  65. uint8_t bmLeftCtrl : 1;
  66. uint8_t bmLeftShift : 1;
  67. uint8_t bmLeftAlt : 1;
  68. uint8_t bmLeftGUI : 1;
  69. uint8_t bmRightCtrl : 1;
  70. uint8_t bmRightShift : 1;
  71. uint8_t bmRightAlt : 1;
  72. uint8_t bmRightGUI : 1;
  73. };
  74. struct KBDINFO {
  75. struct {
  76. uint8_t bmLeftCtrl : 1;
  77. uint8_t bmLeftShift : 1;
  78. uint8_t bmLeftAlt : 1;
  79. uint8_t bmLeftGUI : 1;
  80. uint8_t bmRightCtrl : 1;
  81. uint8_t bmRightShift : 1;
  82. uint8_t bmRightAlt : 1;
  83. uint8_t bmRightGUI : 1;
  84. };
  85. uint8_t bReserved;
  86. uint8_t Keys[6];
  87. };
  88. struct KBDLEDS {
  89. uint8_t bmNumLock : 1;
  90. uint8_t bmCapsLock : 1;
  91. uint8_t bmScrollLock : 1;
  92. uint8_t bmCompose : 1;
  93. uint8_t bmKana : 1;
  94. uint8_t bmReserved : 3;
  95. };
  96. class KeyboardReportParser : public HIDReportParser {
  97. static const uint8_t numKeys[10];
  98. static const uint8_t symKeysUp[12];
  99. static const uint8_t symKeysLo[12];
  100. static const uint8_t padKeys[5];
  101. protected:
  102. union {
  103. KBDINFO kbdInfo;
  104. uint8_t bInfo[sizeof (KBDINFO)];
  105. } prevState;
  106. union {
  107. KBDLEDS kbdLeds;
  108. uint8_t bLeds;
  109. } kbdLockingKeys;
  110. uint8_t OemToAscii(uint8_t mod, uint8_t key);
  111. public:
  112. KeyboardReportParser() {
  113. kbdLockingKeys.bLeds = 0;
  114. };
  115. void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
  116. protected:
  117. virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key) {
  118. uint8_t old_keys = kbdLockingKeys.bLeds;
  119. switch(key) {
  120. case UHS_HID_BOOT_KEY_NUM_LOCK:
  121. kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;
  122. break;
  123. case UHS_HID_BOOT_KEY_CAPS_LOCK:
  124. kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock;
  125. break;
  126. case UHS_HID_BOOT_KEY_SCROLL_LOCK:
  127. kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock;
  128. break;
  129. }
  130. if(old_keys != kbdLockingKeys.bLeds && hid)
  131. return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds));
  132. return 0;
  133. };
  134. virtual void OnControlKeysChanged(uint8_t before, uint8_t after) {
  135. };
  136. virtual void OnKeyDown(uint8_t mod, uint8_t key) {
  137. };
  138. virtual void OnKeyUp(uint8_t mod, uint8_t key) {
  139. };
  140. virtual const uint8_t *getNumKeys() {
  141. return numKeys;
  142. };
  143. virtual const uint8_t *getSymKeysUp() {
  144. return symKeysUp;
  145. };
  146. virtual const uint8_t *getSymKeysLo() {
  147. return symKeysLo;
  148. };
  149. virtual const uint8_t *getPadKeys() {
  150. return padKeys;
  151. };
  152. };
  153. template <const uint8_t BOOT_PROTOCOL>
  154. class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter
  155. {
  156. EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)];
  157. HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)];
  158. uint8_t bConfNum; // configuration number
  159. uint8_t bIfaceNum; // Interface Number
  160. uint8_t bNumIface; // number of interfaces in the configuration
  161. uint8_t bNumEP; // total number of EP in the configuration
  162. uint32_t qNextPollTime; // next poll time
  163. bool bPollEnable; // poll enable flag
  164. uint8_t bInterval; // largest interval
  165. void Initialize();
  166. virtual HIDReportParser* GetReportParser(uint8_t id) {
  167. return pRptParser[id];
  168. };
  169. public:
  170. HIDBoot(USB *p);
  171. virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {
  172. pRptParser[id] = prs;
  173. return true;
  174. };
  175. // USBDeviceConfig implementation
  176. uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
  177. uint8_t Release();
  178. uint8_t Poll();
  179. virtual uint8_t GetAddress() {
  180. return bAddress;
  181. };
  182. virtual bool isReady() {
  183. return bPollEnable;
  184. };
  185. // UsbConfigXtracter implementation
  186. // Method should be defined here if virtual.
  187. virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
  188. virtual bool DEVCLASSOK(uint8_t klass) {
  189. return (klass == USB_CLASS_HID);
  190. }
  191. virtual bool DEVSUBCLASSOK(uint8_t subklass) {
  192. return (subklass == BOOT_PROTOCOL);
  193. }
  194. };
  195. template <const uint8_t BOOT_PROTOCOL>
  196. HIDBoot<BOOT_PROTOCOL>::HIDBoot(USB *p) :
  197. HID(p),
  198. qNextPollTime(0),
  199. bPollEnable(false) {
  200. Initialize();
  201. for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
  202. pRptParser[i] = NULL;
  203. }
  204. if(pUsb)
  205. pUsb->RegisterDeviceClass(this);
  206. }
  207. template <const uint8_t BOOT_PROTOCOL>
  208. void HIDBoot<BOOT_PROTOCOL>::Initialize() {
  209. for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); i++) {
  210. epInfo[i].epAddr = 0;
  211. epInfo[i].maxPktSize = (i) ? 0 : 8;
  212. epInfo[i].epAttribs = 0;
  213. epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
  214. }
  215. bNumEP = 1;
  216. bNumIface = 0;
  217. bConfNum = 0;
  218. }
  219. template <const uint8_t BOOT_PROTOCOL>
  220. uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed) {
  221. const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
  222. uint8_t buf[constBufSize];
  223. uint8_t rcode;
  224. UsbDevice *p = NULL;
  225. EpInfo *oldep_ptr = NULL;
  226. uint8_t len = 0;
  227. //uint16_t cd_len = 0;
  228. uint8_t num_of_conf; // number of configurations
  229. //uint8_t num_of_intf; // number of interfaces
  230. AddressPool &addrPool = pUsb->GetAddressPool();
  231. USBTRACE("BM Init\r\n");
  232. //USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL)));
  233. //USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL));
  234. if(bAddress)
  235. return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
  236. bInterval = 0;
  237. // Get pointer to pseudo device with address 0 assigned
  238. p = addrPool.GetUsbDevicePtr(0);
  239. if(!p)
  240. return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
  241. if(!p->epinfo) {
  242. USBTRACE("epinfo\r\n");
  243. return USB_ERROR_EPINFO_IS_NULL;
  244. }
  245. // Save old pointer to EP_RECORD of address 0
  246. oldep_ptr = p->epinfo;
  247. // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
  248. p->epinfo = epInfo;
  249. p->lowspeed = lowspeed;
  250. // Get device descriptor
  251. rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
  252. if(!rcode)
  253. len = (buf[0] > constBufSize) ? constBufSize : buf[0];
  254. if(rcode) {
  255. // Restore p->epinfo
  256. p->epinfo = oldep_ptr;
  257. goto FailGetDevDescr;
  258. }
  259. // Restore p->epinfo
  260. p->epinfo = oldep_ptr;
  261. // Allocate new address according to device class
  262. bAddress = addrPool.AllocAddress(parent, false, port);
  263. if(!bAddress)
  264. return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
  265. // Extract Max Packet Size from the device descriptor
  266. epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
  267. // Assign new address to the device
  268. rcode = pUsb->setAddr(0, 0, bAddress);
  269. if(rcode) {
  270. p->lowspeed = false;
  271. addrPool.FreeAddress(bAddress);
  272. bAddress = 0;
  273. USBTRACE2("setAddr:", rcode);
  274. return rcode;
  275. }
  276. //delay(2); //per USB 2.0 sect.9.2.6.3
  277. USBTRACE2("Addr:", bAddress);
  278. p->lowspeed = false;
  279. p = addrPool.GetUsbDevicePtr(bAddress);
  280. if(!p)
  281. return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
  282. p->lowspeed = lowspeed;
  283. if(len)
  284. rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
  285. if(rcode)
  286. goto FailGetDevDescr;
  287. num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
  288. USBTRACE2("NC:", num_of_conf);
  289. // GCC will optimize unused stuff away.
  290. if((BOOT_PROTOCOL & (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) == (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) {
  291. USBTRACE("HID_PROTOCOL_KEYBOARD AND MOUSE\r\n");
  292. ConfigDescParser<
  293. USB_CLASS_HID,
  294. HID_BOOT_INTF_SUBCLASS,
  295. HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE,
  296. CP_MASK_COMPARE_ALL > confDescrParser(this);
  297. confDescrParser.SetOR(); // Use the OR variant.
  298. for(uint8_t i = 0; i < num_of_conf; i++) {
  299. pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
  300. if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))
  301. break;
  302. }
  303. } else {
  304. // GCC will optimize unused stuff away.
  305. if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
  306. USBTRACE("HID_PROTOCOL_KEYBOARD\r\n");
  307. for(uint8_t i = 0; i < num_of_conf; i++) {
  308. ConfigDescParser<
  309. USB_CLASS_HID,
  310. HID_BOOT_INTF_SUBCLASS,
  311. HID_PROTOCOL_KEYBOARD,
  312. CP_MASK_COMPARE_ALL> confDescrParserA(this);
  313. pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);
  314. if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))
  315. break;
  316. }
  317. }
  318. // GCC will optimize unused stuff away.
  319. if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) {
  320. USBTRACE("HID_PROTOCOL_MOUSE\r\n");
  321. for(uint8_t i = 0; i < num_of_conf; i++) {
  322. ConfigDescParser<
  323. USB_CLASS_HID,
  324. HID_BOOT_INTF_SUBCLASS,
  325. HID_PROTOCOL_MOUSE,
  326. CP_MASK_COMPARE_ALL> confDescrParserB(this);
  327. pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB);
  328. if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL))))
  329. break;
  330. }
  331. }
  332. }
  333. USBTRACE2("bNumEP:", bNumEP);
  334. if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) {
  335. rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
  336. goto Fail;
  337. }
  338. // Assign epInfo to epinfo pointer
  339. rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
  340. //USBTRACE2("setEpInfoEntry returned ", rcode);
  341. USBTRACE2("Cnf:", bConfNum);
  342. delay(1000);
  343. // Set Configuration Value
  344. rcode = pUsb->setConf(bAddress, 0, bConfNum);
  345. if(rcode)
  346. goto FailSetConfDescr;
  347. delay(1000);
  348. USBTRACE2("bIfaceNum:", bIfaceNum);
  349. USBTRACE2("bNumIface:", bNumIface);
  350. // Yes, mouse wants SetProtocol and SetIdle too!
  351. for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
  352. USBTRACE2("\r\nInterface:", i);
  353. rcode = SetProtocol(i, HID_BOOT_PROTOCOL);
  354. if(rcode) goto FailSetProtocol;
  355. USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode);
  356. rcode = SetIdle(i, 0, 0);
  357. USBTRACE2("SET_IDLE rcode:", rcode);
  358. // if(rcode) goto FailSetIdle; This can fail.
  359. // Get the RPIPE and just throw it away.
  360. SinkParser<USBReadParser, uint16_t, uint16_t> sink;
  361. rcode = GetReportDescr(i, &sink);
  362. USBTRACE2("RPIPE rcode:", rcode);
  363. }
  364. // Get RPIPE and throw it away.
  365. if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
  366. // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec.
  367. // kana, compose, scroll, caps, num
  368. rcode = 0x20; // Reuse rcode.
  369. while(rcode) {
  370. rcode >>= 1;
  371. // Ignore any error returned, we don't care if LED is not supported
  372. SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off)
  373. delay(25);
  374. }
  375. }
  376. USBTRACE("BM configured\r\n");
  377. bPollEnable = true;
  378. return 0;
  379. FailGetDevDescr:
  380. #ifdef DEBUG_USB_HOST
  381. NotifyFailGetDevDescr();
  382. goto Fail;
  383. #endif
  384. //FailSetDevTblEntry:
  385. //#ifdef DEBUG_USB_HOST
  386. // NotifyFailSetDevTblEntry();
  387. // goto Fail;
  388. //#endif
  389. //FailGetConfDescr:
  390. //#ifdef DEBUG_USB_HOST
  391. // NotifyFailGetConfDescr();
  392. // goto Fail;
  393. //#endif
  394. FailSetConfDescr:
  395. #ifdef DEBUG_USB_HOST
  396. NotifyFailSetConfDescr();
  397. goto Fail;
  398. #endif
  399. FailSetProtocol:
  400. #ifdef DEBUG_USB_HOST
  401. USBTRACE("SetProto:");
  402. goto Fail;
  403. #endif
  404. //FailSetIdle:
  405. //#ifdef DEBUG_USB_HOST
  406. // USBTRACE("SetIdle:");
  407. //#endif
  408. Fail:
  409. #ifdef DEBUG_USB_HOST
  410. NotifyFail(rcode);
  411. #endif
  412. Release();
  413. return rcode;
  414. }
  415. template <const uint8_t BOOT_PROTOCOL>
  416. void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
  417. // If the first configuration satisfies, the others are not considered.
  418. //if(bNumEP > 1 && conf != bConfNum)
  419. if(bNumEP == totalEndpoints(BOOT_PROTOCOL))
  420. return;
  421. bConfNum = conf;
  422. bIfaceNum = iface;
  423. if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) {
  424. if(pep->bInterval > bInterval) bInterval = pep->bInterval;
  425. // Fill in the endpoint info structure
  426. epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
  427. epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
  428. epInfo[bNumEP].epAttribs = 0;
  429. epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
  430. bNumEP++;
  431. }
  432. }
  433. template <const uint8_t BOOT_PROTOCOL>
  434. uint8_t HIDBoot<BOOT_PROTOCOL>::Release() {
  435. pUsb->GetAddressPool().FreeAddress(bAddress);
  436. bConfNum = 0;
  437. bIfaceNum = 0;
  438. bNumEP = 1;
  439. bAddress = 0;
  440. qNextPollTime = 0;
  441. bPollEnable = false;
  442. return 0;
  443. }
  444. template <const uint8_t BOOT_PROTOCOL>
  445. uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
  446. uint8_t rcode = 0;
  447. if(bPollEnable && ((long)(millis() - qNextPollTime) >= 0L)) {
  448. // To-do: optimize manually, using the for loop only if needed.
  449. for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
  450. const uint16_t const_buff_len = 16;
  451. uint8_t buf[const_buff_len];
  452. USBTRACE3("(hidboot.h) i=", i, 0x81);
  453. USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=", epInfo[epInterruptInIndex + i].epAddr, 0x81);
  454. USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=", epInfo[epInterruptInIndex + i].maxPktSize, 0x81);
  455. uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize;
  456. rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf);
  457. // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint.
  458. // Since keyboard and mice must report at least 3 bytes, we ignore the extra data.
  459. if(!rcode && read > 2) {
  460. if(pRptParser[i])
  461. pRptParser[i]->Parse((HID*)this, 0, (uint8_t)read, buf);
  462. #ifdef DEBUG_USB_HOST
  463. // We really don't care about errors and anomalies unless we are debugging.
  464. } else {
  465. if(rcode != hrNAK) {
  466. USBTRACE3("(hidboot.h) Poll:", rcode, 0x81);
  467. }
  468. if(!rcode && read) {
  469. USBTRACE3("(hidboot.h) Strange read count: ", read, 0x80);
  470. USBTRACE3("(hidboot.h) Interface:", i, 0x80);
  471. }
  472. }
  473. if(!rcode && read && (UsbDEBUGlvl > 0x7f)) {
  474. for(uint8_t i = 0; i < read; i++) {
  475. PrintHex<uint8_t > (buf[i], 0x80);
  476. USBTRACE1(" ", 0x80);
  477. }
  478. if(read)
  479. USBTRACE1("\r\n", 0x80);
  480. #endif
  481. }
  482. }
  483. qNextPollTime = millis() + bInterval;
  484. }
  485. return rcode;
  486. }
  487. #endif // __HIDBOOTMOUSE_H__