mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Improved hidboot, now supports composite keyboard mouse devices.
This commit is contained in:
parent
a88933ea3e
commit
2432379a27
1 changed files with 78 additions and 56 deletions
134
hidboot.h
134
hidboot.h
|
@ -107,9 +107,9 @@ struct KBDLEDS {
|
||||||
uint8_t bmReserved : 3;
|
uint8_t bmReserved : 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KEY_NUM_LOCK 0x53
|
#define KEY_NUM_LOCK 0x53
|
||||||
#define KEY_CAPS_LOCK 0x39
|
#define KEY_CAPS_LOCK 0x39
|
||||||
#define KEY_SCROLL_LOCK 0x47
|
#define KEY_SCROLL_LOCK 0x47
|
||||||
|
|
||||||
class KeyboardReportParser : public HIDReportParser {
|
class KeyboardReportParser : public HIDReportParser {
|
||||||
static const uint8_t numKeys[];
|
static const uint8_t numKeys[];
|
||||||
|
@ -142,26 +142,25 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key);
|
virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key);
|
||||||
|
|
||||||
virtual void OnControlKeysChanged(uint8_t before, uint8_t after) {
|
virtual void OnControlKeysChanged(uint8_t before, uint8_t after) {
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void OnKeyDown(uint8_t mod, uint8_t key) {
|
virtual void OnKeyDown(uint8_t mod, uint8_t key) {
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void OnKeyUp(uint8_t mod, uint8_t key) {
|
virtual void OnKeyUp(uint8_t mod, uint8_t key) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#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);
|
||||||
|
|
||||||
for(uint8_t i = 0; i < num_of_conf; i++) {
|
// GCC will optimize unused stuff away.
|
||||||
ConfigDescParser<
|
if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
|
||||||
USB_CLASS_HID,
|
for(uint8_t i = 0; i < num_of_conf; i++) {
|
||||||
HID_BOOT_INTF_SUBCLASS,
|
ConfigDescParser<
|
||||||
BOOT_PROTOCOL,
|
USB_CLASS_HID,
|
||||||
CP_MASK_COMPARE_ALL> confDescrParser(this);
|
HID_BOOT_INTF_SUBCLASS,
|
||||||
|
HID_PROTOCOL_KEYBOARD,
|
||||||
|
CP_MASK_COMPARE_ALL> confDescrParserA(this);
|
||||||
|
|
||||||
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
|
if(bNumEP == totalEndpoints)
|
||||||
|
break;
|
||||||
|
pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(bNumEP > 1)
|
// GCC will optimize unused stuff away.
|
||||||
break;
|
if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) {
|
||||||
} // for
|
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;
|
||||||
|
|
||||||
if(bNumEP < 2) {
|
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;
|
||||||
|
|
||||||
const uint8_t const_buff_len = 16;
|
// To-do: optimize manually, getting rid of the loop
|
||||||
uint8_t buf[const_buff_len];
|
for(uint8_t i = 0; i < epMUL; i++) {
|
||||||
|
const uint8_t const_buff_len = 16;
|
||||||
|
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;
|
||||||
|
|
||||||
if(rcode) {
|
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf);
|
||||||
if(rcode != hrNAK)
|
if(!rcode) {
|
||||||
USBTRACE2("Poll:", rcode);
|
if(pRptParser[i])
|
||||||
return rcode;
|
pRptParser[i]->Parse((HID*)this, 0, (uint8_t) read, buf);
|
||||||
|
|
||||||
|
//for (uint8_t i=0; i<read; i++)
|
||||||
|
// PrintHex<uint8_t>(buf[i]);
|
||||||
|
//if (read)
|
||||||
|
// USB_HOST_SERIAL.println("");
|
||||||
|
} else {
|
||||||
|
if(rcode != hrNAK) {
|
||||||
|
USBTRACE2("Poll:", rcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//for (uint8_t i=0; i<read; i++)
|
|
||||||
// PrintHex<uint8_t>(buf[i]);
|
|
||||||
//if (read)
|
|
||||||
// USB_HOST_SERIAL.println("");
|
|
||||||
|
|
||||||
if(pRptParser)
|
|
||||||
pRptParser->Parse((HID*)this, 0, (uint8_t) read, buf);
|
|
||||||
}
|
}
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // __HIDBOOTMOUSE_H__
|
||||||
#endif // __HIDBOOTMOUSE_H__
|
|
||||||
|
|
Loading…
Reference in a new issue