mirror of
https://github.com/esp8266/Arduino.git
synced 2025-08-12 20:49:16 +03:00
USBHost library to new format
This commit is contained in:
241
libraries/USBHost/src/confdescparser.h
Normal file
241
libraries/USBHost/src/confdescparser.h
Normal file
@@ -0,0 +1,241 @@
|
||||
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
|
||||
|
||||
This software may be distributed and modified under the terms of the GNU
|
||||
General Public License version 2 (GPL2) as published by the Free Software
|
||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||
on this software must also be made publicly available under the terms of
|
||||
the GPL2 ("Copyleft").
|
||||
|
||||
Contact information
|
||||
-------------------
|
||||
|
||||
Circuits At Home, LTD
|
||||
Web : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
|
||||
#ifndef CONFDESCPARSER_H_INCLUDED
|
||||
#define CONFDESCPARSER_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
#include "parsetools.h"
|
||||
|
||||
/**
|
||||
* \class Abstract UsbConfigXtracter definition.
|
||||
*
|
||||
* \note This class is used for extracting USB endpoint descriptors.
|
||||
*/
|
||||
class UsbConfigXtracter
|
||||
{
|
||||
public:
|
||||
virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0;
|
||||
};
|
||||
|
||||
#define CP_MASK_COMPARE_CLASS 1
|
||||
#define CP_MASK_COMPARE_SUBCLASS 2
|
||||
#define CP_MASK_COMPARE_PROTOCOL 4
|
||||
#define CP_MASK_COMPARE_ALL 7
|
||||
|
||||
/**
|
||||
* \class ConfigDescParser definition.
|
||||
*
|
||||
* \note This class is used for parsing configuration descriptors.
|
||||
*/
|
||||
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_CONFIGURATION_DESCRIPTOR)*/];
|
||||
|
||||
uint32_t stateParseDescr; // ParseDescriptor state
|
||||
|
||||
uint32_t dscrLen; // Descriptor length
|
||||
uint32_t dscrType; // Descriptor type
|
||||
|
||||
bool isGoodInterface; // Apropriate interface flag
|
||||
uint32_t confValue; // Configuration value
|
||||
uint32_t protoValue; // Protocol value
|
||||
uint32_t ifaceNumber; // Interface number
|
||||
uint32_t ifaceAltSet; // Interface alternate settings
|
||||
|
||||
bool ParseDescriptor(uint8_t **pp, uint32_t *pcntdn);
|
||||
|
||||
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
|
||||
|
||||
public:
|
||||
ConfigDescParser(UsbConfigXtracter *xtractor);
|
||||
virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief ConfigDescParser class constructor.
|
||||
*
|
||||
* \param xtractor Is saved as ConfigDescParser attribute and later used as a
|
||||
* callback for parsing the endpoint descriptors.
|
||||
*
|
||||
* \note During enumeration stage, all supported USB classes invoke
|
||||
* ConfigDescParser with "this" as parameter, meaning that one class is also
|
||||
* responsible for parsing its endpoint descriptors. This makes sense since
|
||||
* each USB class handles different number of endpoints and configurations.
|
||||
* For instance see ADK::Init from ADK class.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
theBuffer.pValue = varBuffer;
|
||||
valParser.Initialize(&theBuffer);
|
||||
theSkipper.Initialize(&theBuffer);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Parse a complete USB configuration descriptor.
|
||||
*
|
||||
* \param len Buffer length.
|
||||
* \param pbuf Buffer containing the configuration descriptor.
|
||||
* \param offset Current offset position.
|
||||
*/
|
||||
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 uint32_t len, const uint8_t *pbuf, const uint32_t &offset)
|
||||
{
|
||||
uint32_t cntdn = len;
|
||||
uint8_t *p = (uint8_t*)pbuf;
|
||||
|
||||
while (cntdn)
|
||||
if (!ParseDescriptor(&p, &cntdn))
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Parse a USB 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.
|
||||
*
|
||||
* \note This method should not be called directly, use Parse() instead.
|
||||
*
|
||||
* \param pcntdn Buffer length.
|
||||
* \param pp Buffer containing the configuration descriptor.
|
||||
*
|
||||
* \return true if data remains in the buffer for parsing, false otherwise.
|
||||
*/
|
||||
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, uint32_t *pcntdn)
|
||||
{
|
||||
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 already 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 carefuly. 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;
|
||||
case USB_DESCRIPTOR_CONFIGURATION:
|
||||
theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2;
|
||||
break;
|
||||
case USB_DESCRIPTOR_ENDPOINT:
|
||||
theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2;
|
||||
break;
|
||||
case HID_DESCRIPTOR_HID:
|
||||
theBuffer.valueSize = dscrLen - 2;
|
||||
break;
|
||||
}
|
||||
valParser.Initialize(&theBuffer);
|
||||
stateParseDescr = 4;
|
||||
case 4:
|
||||
switch (dscrType)
|
||||
{
|
||||
case USB_DESCRIPTOR_CONFIGURATION:
|
||||
if (!valParser.Parse(pp, pcntdn))
|
||||
return false;
|
||||
confValue = ((USB_CONFIGURATION_DESCRIPTOR*)varBuffer)->bConfigurationValue;
|
||||
break;
|
||||
case USB_DESCRIPTOR_INTERFACE:
|
||||
if (!valParser.Parse(pp, pcntdn))
|
||||
return false;
|
||||
if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceClass != CLASS_ID)
|
||||
break;
|
||||
if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceSubClass != SUBCLASS_ID)
|
||||
break;
|
||||
if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol != PROTOCOL_ID)
|
||||
break;
|
||||
|
||||
isGoodInterface = true;
|
||||
ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceNumber;
|
||||
ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bAlternateSetting;
|
||||
protoValue = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol;
|
||||
break;
|
||||
case USB_DESCRIPTOR_ENDPOINT:
|
||||
if (!valParser.Parse(pp, pcntdn))
|
||||
return false;
|
||||
if (isGoodInterface)
|
||||
if (theXtractor)
|
||||
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Print HID descriptor.
|
||||
*
|
||||
* \note TRACE_USBHOST macro must be enabled. See Usb.h for reference.
|
||||
*
|
||||
* \param pDesc Pointer to HID descriptor.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescLength: %d\r\n", pDesc->bLength);)
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescriptorType: %d\r\n", pDesc->bDescriptorType);)
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bcdHID: %d\r\n", pDesc->bcdHID);)
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bCountryCode: %d\r\n", pDesc->bCountryCode);)
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bNumDescriptors: %d\r\n", pDesc->bNumDescriptors);)
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescrType: %d\r\n", pDesc->bDescrType);)
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : wDescriptorLength: %d\r\n", pDesc->wDescriptorLength);)
|
||||
|
||||
for (uint32_t i = 0; i < pDesc->bNumDescriptors; ++i)
|
||||
{
|
||||
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
|
||||
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescrType: %d\r\n", pLT[i].bDescrType);)
|
||||
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : wDescriptorLength: %d\r\n", pLT[i].wDescriptorLength);)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFDESCPARSER_H_INCLUDED */
|
Reference in New Issue
Block a user