Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Committer:
hudakz
Date:
Sun Jul 12 20:39:26 2020 +0000
Revision:
0:84353c479782
Child:
1:2263e77400e9
MAX3421E-based USB Host Shield Library

Who changed what in which revision?

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