diff options
Diffstat (limited to 'Marlin/src/sd/usb_flashdrive/lib-uhs2/confdescparser.h')
-rw-r--r-- | Marlin/src/sd/usb_flashdrive/lib-uhs2/confdescparser.h | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/Marlin/src/sd/usb_flashdrive/lib-uhs2/confdescparser.h b/Marlin/src/sd/usb_flashdrive/lib-uhs2/confdescparser.h new file mode 100644 index 0000000..9ed35ff --- /dev/null +++ b/Marlin/src/sd/usb_flashdrive/lib-uhs2/confdescparser.h @@ -0,0 +1,201 @@ +/** + * Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Contact information + * ------------------- + * + * Circuits At Home, LTD + * Web : https://www.circuitsathome.com + * e-mail : support@circuitsathome.com + */ +#pragma once + +#ifndef _usb_h_ + #error "Never include confdescparser.h directly; include Usb.h instead" +#endif + +class UsbConfigXtracter { +public: + //virtual void ConfigXtract(const USB_FD_CONFIGURATION_DESCRIPTOR *conf) = 0; + //virtual void InterfaceXtract(uint8_t conf, const USB_FD_INTERFACE_DESCRIPTOR *iface) = 0; + + virtual void EndpointXtract(uint8_t conf __attribute__((unused)), uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_FD_ENDPOINT_DESCRIPTOR *ep __attribute__((unused))) { + } +}; + +#define CP_MASK_COMPARE_CLASS 1 +#define CP_MASK_COMPARE_SUBCLASS 2 +#define CP_MASK_COMPARE_PROTOCOL 4 +#define CP_MASK_COMPARE_ALL 7 + +// Configuration Descriptor Parser Class Template + +template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> +class ConfigDescParser : public USBReadParser { + UsbConfigXtracter *theXtractor; + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[16 /*sizeof(USB_FD_CONFIGURATION_DESCRIPTOR)*/]; + + uint8_t stateParseDescr; // ParseDescriptor state + + uint8_t dscrLen; // Descriptor length + uint8_t dscrType; // Descriptor type + + bool isGoodInterface; // Apropriate interface flag + uint8_t confValue; // Configuration value + uint8_t protoValue; // Protocol value + uint8_t ifaceNumber; // Interface number + uint8_t ifaceAltSet; // Interface alternate settings + + bool UseOr; + bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + +public: + + void SetOR() { UseOr = true; } + ConfigDescParser(UsbConfigXtracter *xtractor); + void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); +}; + +template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> +ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) : + theXtractor(xtractor), + stateParseDescr(0), + dscrLen(0), + dscrType(0), + UseOr(false) { + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); + }; + +template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> +void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) { + uint16_t cntdn = (uint16_t)len; + uint8_t *p = (uint8_t*)pbuf; + while (cntdn) if (!ParseDescriptor(&p, &cntdn)) return; +} + +/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and + compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ +template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> +bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { + USB_FD_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_FD_CONFIGURATION_DESCRIPTOR*>(varBuffer); + USB_FD_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_FD_INTERFACE_DESCRIPTOR*>(varBuffer); + switch (stateParseDescr) { + case 0: + theBuffer.valueSize = 2; + valParser.Initialize(&theBuffer); + stateParseDescr = 1; + case 1: + if (!valParser.Parse(pp, pcntdn)) return false; + dscrLen = *((uint8_t*)theBuffer.pValue); + dscrType = *((uint8_t*)theBuffer.pValue + 1); + stateParseDescr = 2; + case 2: + // This is a sort of hack. Assuming that two bytes are all ready in the buffer + // the pointer is positioned two bytes ahead in order for the rest of descriptor + // to be read right after the size and the type fields. + // This should be used carefully. varBuffer should be used directly to handle data + // in the buffer. + theBuffer.pValue = varBuffer + 2; + stateParseDescr = 3; + case 3: + switch (dscrType) { + case USB_DESCRIPTOR_INTERFACE: + isGoodInterface = false; + break; + case USB_DESCRIPTOR_CONFIGURATION: + case USB_DESCRIPTOR_ENDPOINT: + case HID_DESCRIPTOR_HID: + break; + } + theBuffer.valueSize = dscrLen - 2; + valParser.Initialize(&theBuffer); + stateParseDescr = 4; + case 4: + switch (dscrType) { + case USB_DESCRIPTOR_CONFIGURATION: + if (!valParser.Parse(pp, pcntdn)) return false; + confValue = ucd->bConfigurationValue; + break; + case USB_DESCRIPTOR_INTERFACE: + if (!valParser.Parse(pp, pcntdn)) return false; + if ((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) + break; + if (UseOr) { + if ((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) break; + } + else if ((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID) + break; + isGoodInterface = true; + ifaceNumber = uid->bInterfaceNumber; + ifaceAltSet = uid->bAlternateSetting; + protoValue = uid->bInterfaceProtocol; + break; + case USB_DESCRIPTOR_ENDPOINT: + if (!valParser.Parse(pp, pcntdn)) return false; + if (isGoodInterface && theXtractor) + theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_FD_ENDPOINT_DESCRIPTOR*)varBuffer); + break; + //case HID_DESCRIPTOR_HID: + // if (!valParser.Parse(pp, pcntdn)) return false; + // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); + // break; + default: + if (!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) return false; + } + theBuffer.pValue = varBuffer; + stateParseDescr = 0; + } + return true; +} + +template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> +void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); + Notify(PSTR("bDescLength:\t\t"), 0x80); + PrintHex<uint8_t > (pDesc->bLength, 0x80); + + Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); + PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80); + + Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); + PrintHex<uint16_t > (pDesc->bcdHID, 0x80); + + Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); + PrintHex<uint8_t > (pDesc->bCountryCode, 0x80); + + Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); + PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80); + + for (uint8_t i = 0; i < pDesc->bNumDescriptors; i++) { + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); + + Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); + PrintHex<uint8_t > (pLT[i].bDescrType, 0x80); + + Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); + PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80); + } + Notify(PSTR("\r\n"), 0x80); +} |