Improved hidboot, now supports composite keyboard mouse devices.

This commit is contained in:
Andrew J. Kroll 2013-09-29 16:08:20 -04:00
parent a88933ea3e
commit 2432379a27

100
hidboot.h
View file

@ -152,16 +152,15 @@ protected:
}; };
}; };
#define totalEndpoints 2 #define totalEndpoints (((BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD)? 2 : 0)+((BOOT_PROTOCOL & HID_PROTOCOL_MOUSE)? 1 : 0))
#define epMUL (((BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD)? 1 : 0)+((BOOT_PROTOCOL & HID_PROTOCOL_MOUSE)? 1 : 0))
#define HID_MAX_HID_CLASS_DESCRIPTORS 5 #define HID_MAX_HID_CLASS_DESCRIPTORS 5
template <const uint8_t BOOT_PROTOCOL> template <const uint8_t BOOT_PROTOCOL>
class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter
{ {
EpInfo epInfo[totalEndpoints]; EpInfo epInfo[totalEndpoints];
HIDReportParser *pRptParser[epMUL];
HIDReportParser *pRptParser;
uint8_t bConfNum; // configuration number uint8_t bConfNum; // configuration number
uint8_t bIfaceNum; // Interface Number uint8_t bIfaceNum; // Interface Number
@ -173,14 +172,14 @@ class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter
void Initialize(); void Initialize();
virtual HIDReportParser* GetReportParser(uint8_t id) { virtual HIDReportParser* GetReportParser(uint8_t id) {
return pRptParser; return pRptParser[id];
}; };
public: public:
HIDBoot(USB *p); HIDBoot(USB *p);
virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) { virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {
pRptParser = prs; pRptParser[id] = prs;
return true; return true;
}; };
@ -201,10 +200,12 @@ template <const uint8_t BOOT_PROTOCOL>
HIDBoot<BOOT_PROTOCOL>::HIDBoot(USB *p) : HIDBoot<BOOT_PROTOCOL>::HIDBoot(USB *p) :
HID(p), HID(p),
qNextPollTime(0), qNextPollTime(0),
bPollEnable(false), bPollEnable(false) {
pRptParser(NULL) {
Initialize(); Initialize();
for(uint8_t i = 0; i < epMUL; i++) {
pRptParser[i] = NULL;
}
if(pUsb) if(pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
} }
@ -231,10 +232,10 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
UsbDevice *p = NULL; UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL; EpInfo *oldep_ptr = NULL;
uint8_t len = 0; uint8_t len = 0;
uint16_t cd_len = 0; //uint16_t cd_len = 0;
uint8_t num_of_conf; // number of configurations uint8_t num_of_conf; // number of configurations
uint8_t num_of_intf; // number of interfaces //uint8_t num_of_intf; // number of interfaces
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
@ -325,30 +326,48 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
//USBTRACE2("NC:", num_of_conf); //USBTRACE2("NC:", num_of_conf);
// GCC will optimize unused stuff away.
if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
for(uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser< ConfigDescParser<
USB_CLASS_HID, USB_CLASS_HID,
HID_BOOT_INTF_SUBCLASS, HID_BOOT_INTF_SUBCLASS,
BOOT_PROTOCOL, HID_PROTOCOL_KEYBOARD,
CP_MASK_COMPARE_ALL> confDescrParser(this); CP_MASK_COMPARE_ALL> confDescrParserA(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); if(bNumEP == totalEndpoints)
if(bNumEP > 1)
break; break;
} // for pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);
}
}
if(bNumEP < 2) { // GCC will optimize unused stuff away.
if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) {
for(uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser<
USB_CLASS_HID,
HID_BOOT_INTF_SUBCLASS,
HID_PROTOCOL_MOUSE,
CP_MASK_COMPARE_ALL> confDescrParserB(this);
if(bNumEP == totalEndpoints)
break;
pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB);
}
}
USBTRACE2("\r\nbAddr:", bAddress);
USBTRACE2("\r\nbNumEP:", bNumEP);
USBTRACE2("\r\ntotalEndpoints:", totalEndpoints);
if(bNumEP != totalEndpoints) {
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
goto Fail; goto Fail;
} }
//USBTRACE2("\r\nbAddr:", bAddress);
//USBTRACE2("\r\nbNumEP:", bNumEP);
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
//USBTRACE2("\r\nCnf:", bConfNum); USBTRACE2("\r\nCnf:", bConfNum);
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
@ -356,15 +375,16 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
if(rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
//USBTRACE2("\r\nIf:", bIfaceNum); USBTRACE2("\r\nIf:", bIfaceNum);
rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL); rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL);
if(rcode) if(rcode)
goto FailSetProtocol; goto FailSetProtocol;
if(BOOT_PROTOCOL == 1) { // GCC will optimize unused stuff away.
rcode = SetIdle(bIfaceNum, 0, 0); if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
rcode = SetIdle(0/* bIfaceNum*/, 0, 0);
if(rcode) if(rcode)
goto FailSetIdle; goto FailSetIdle;
@ -419,25 +439,23 @@ Fail:
template <const uint8_t BOOT_PROTOCOL> template <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { void HIDBoot<BOOT_PROTOCOL>::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 concidered. // If the first configuration satisfies, the others are not considered.
if(bNumEP > 1 && conf != bConfNum) if(bNumEP > 1 && conf != bConfNum)
return; return;
bConfNum = conf; bConfNum = conf;
bIfaceNum = iface; bIfaceNum = iface;
uint8_t index;
if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) {
index = epInterruptInIndex; uint8_t index = bNumEP;//epInterruptInIndex; //+ bNumEP;
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize;
epInfo[index].epAttribs = 0; epInfo[index].epAttribs = 0;
epInfo[index].bmNakPower = USB_NAK_NOWAIT; epInfo[index].bmNakPower = USB_NAK_NOWAIT;
bNumEP++; bNumEP++;
} }
} }
@ -464,28 +482,32 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
if(qNextPollTime <= millis()) { if(qNextPollTime <= millis()) {
qNextPollTime = millis() + 10; qNextPollTime = millis() + 10;
// To-do: optimize manually, getting rid of the loop
for(uint8_t i = 0; i < epMUL; i++) {
const uint8_t const_buff_len = 16; const uint8_t const_buff_len = 16;
uint8_t buf[const_buff_len]; uint8_t buf[const_buff_len];
uint16_t read = (uint16_t) epInfo[epInterruptInIndex].maxPktSize;
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); uint16_t read = (uint16_t) epInfo[epInterruptInIndex + i].maxPktSize;
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf);
if(!rcode) {
if(pRptParser[i])
pRptParser[i]->Parse((HID*)this, 0, (uint8_t) read, buf);
if(rcode) {
if(rcode != hrNAK)
USBTRACE2("Poll:", rcode);
return rcode;
}
//for (uint8_t i=0; i<read; i++) //for (uint8_t i=0; i<read; i++)
// PrintHex<uint8_t>(buf[i]); // PrintHex<uint8_t>(buf[i]);
//if (read) //if (read)
// USB_HOST_SERIAL.println(""); // USB_HOST_SERIAL.println("");
} else {
if(pRptParser) if(rcode != hrNAK) {
pRptParser->Parse((HID*)this, 0, (uint8_t) read, buf); USBTRACE2("Poll:", rcode);
break;
}
}
}
} }
return rcode; return rcode;
} }
#endif // __HIDBOOTMOUSE_H__ #endif // __HIDBOOTMOUSE_H__