From c298e349ae01717b798b382b81e344c2d2007f75 Mon Sep 17 00:00:00 2001 From: "Andrew J. Kroll" Date: Mon, 23 Dec 2013 14:12:29 -0500 Subject: [PATCH] HID_BOOT fixes. Fix Keyboard init issue. Set boot protocol and idle on all interfaces. TO-DO: Investagate mouse init issue. There are many devices with quirks that can not be worked around easily on such a small platform. These need to be addressed. Note! This commit does not fully fix mouse problems on all mouse adaptors, but more of them should start working. --- hidboot.h | 85 ++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/hidboot.h b/hidboot.h index 0d9a338d..700c2e4b 100644 --- a/hidboot.h +++ b/hidboot.h @@ -184,6 +184,7 @@ class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter uint8_t bNumEP; // total number of EP in the configuration uint32_t qNextPollTime; // next poll time bool bPollEnable; // poll enable flag + uint8_t bInterval; // largest interval void Initialize(); @@ -256,12 +257,13 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed AddressPool &addrPool = pUsb->GetAddressPool(); USBTRACE("BM Init\r\n"); - USBTRACE2("totalEndpoints:", (uint8_t)(totalEndpoints(BOOT_PROTOCOL))); - USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL)); + //USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL))); + //USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL)); if(bAddress) return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + bInterval = 0; // Get pointer to pseudo device with address 0 assigned p = addrPool.GetUsbDevicePtr(0); @@ -337,19 +339,8 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; - // Assign epInfo to epinfo pointer - //rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + USBTRACE2("NC:", num_of_conf); - //if(rcode) - // goto FailSetDevTblEntry; - - //USBTRACE2("NC:", num_of_conf); - // GCC will optimize unused stuff away. - //if((totalEndpoints(BOOT_PROTOCOL)) != 3) { - // bNumEP = 0; - //} - - USBTRACE2("bNumEP:", bNumEP); // GCC will optimize unused stuff away. if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { USBTRACE("HID_PROTOCOL_KEYBOARD\r\n"); @@ -361,7 +352,7 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed CP_MASK_COMPARE_ALL> confDescrParserA(this); pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA); - if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) + if(bNumEP == (uint8_t) (totalEndpoints(BOOT_PROTOCOL))) break; } } @@ -377,24 +368,22 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed CP_MASK_COMPARE_ALL> confDescrParserB(this); pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB); - if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL)))) + if(bNumEP == ((uint8_t) (totalEndpoints(BOOT_PROTOCOL)))) break; } } - - USBTRACE2("bAddr:", bAddress); USBTRACE2("bNumEP:", bNumEP); - if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) { - rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; - goto Fail; - } + if(bNumEP != (uint8_t) (totalEndpoints(BOOT_PROTOCOL))) { + rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + goto Fail; + } // Assign epInfo to epinfo pointer rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); - USBTRACE2("setEpInfoEntry returned ", rcode); + //USBTRACE2("setEpInfoEntry returned ", rcode); USBTRACE2("Cnf:", bConfNum); delay(1000); @@ -407,19 +396,28 @@ uint8_t HIDBoot::Init(uint8_t parent, uint8_t port, bool lowspeed delay(1000); - USBTRACE2("If:", bIfaceNum); + USBTRACE2("bIfaceNum:", bIfaceNum); + USBTRACE2("bNumIface:", bNumIface); - rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL); + // Yes, mouse wants SetProtocol and SetIdle too! + for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) { + USBTRACE2("\r\nInterface:", i); + rcode = SetProtocol(i, HID_BOOT_PROTOCOL); + if(rcode) goto FailSetProtocol; + USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode); + rcode = SetIdle(i, 0, 0); + USBTRACE2("SET_IDLE rcode:", rcode); + if(rcode) goto FailSetIdle; + } - if(rcode) - goto FailSetProtocol; - - // GCC will optimize unused stuff away. if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) { - rcode = SetIdle(0/* bIfaceNum*/, 0, 0); - - if(rcode) - goto FailSetIdle; + // Wake keyboard interface by twinkling up to 7 LEDs + rcode = 0x80; // Reuse rcode. + while(rcode) { + rcode >>= 1; + SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off) + delay(25); + } } USBTRACE("BM configured\r\n"); @@ -472,6 +470,7 @@ Fail: template void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { + // If the first configuration satisfies, the others are not considered. if(bNumEP > 1 && conf != bConfNum) return; @@ -480,14 +479,13 @@ void HIDBoot::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t bIfaceNum = iface; if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { - - uint8_t index = bNumEP; //epInterruptInIndex; //+ bNumEP; + if(pep->bInterval > bInterval) bInterval = pep->bInterval; // Fill in the endpoint info structure - epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); - epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; - epInfo[index].bmNakPower = USB_NAK_NOWAIT; + epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[bNumEP].maxPktSize = (uint8_t) pep->wMaxPacketSize; + epInfo[bNumEP].epAttribs = 0; + epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; bNumEP++; } @@ -511,11 +509,7 @@ template uint8_t HIDBoot::Poll() { uint8_t rcode = 0; - if(!bPollEnable) - return 0; - - if(qNextPollTime <= millis()) { - qNextPollTime = millis() + 10; + if(bPollEnable && qNextPollTime <= millis()) { // To-do: optimize manually, getting rid of the loop for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) { @@ -543,10 +537,11 @@ uint8_t HIDBoot::Poll() { } else { if(rcode != hrNAK) { USBTRACE3("(hidboot.h) Poll:", rcode, 0x81); - break; + //break; } } } + qNextPollTime = millis() + bInterval; } return rcode; }