Stripped down arduino host shield library
This commit is contained in:
@@ -32,17 +32,11 @@ e-mail : support@circuitsathome.com
|
||||
|
||||
// None of these should ever be included by a driver, or a user's sketch.
|
||||
#include "../lib/hostshield/settings.h"
|
||||
#include "../lib/hostshield/printhex.h"
|
||||
#include "../lib/hostshield/message.h"
|
||||
#include "../lib/hostshield/hexdump.h"
|
||||
#include "../lib/hostshield/sink_parser.h"
|
||||
#include "../lib/hostshield/max3421e.h"
|
||||
#include "../lib/hostshield/address.h"
|
||||
#include "../lib/hostshield/avrpins.h"
|
||||
#include "../lib/hostshield/usb_ch9.h"
|
||||
#include "../lib/hostshield/usbhost.h"
|
||||
#include "../lib/hostshield/UsbCore.h"
|
||||
#include "../lib/hostshield/parsetools.h"
|
||||
#include "../lib/hostshield/confdescparser.h"
|
||||
|
||||
#endif //_usb_h_
|
||||
|
||||
@@ -243,12 +243,9 @@ uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t*
|
||||
|
||||
uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
|
||||
|
||||
if(rcode) {
|
||||
USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
|
||||
USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
|
||||
USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
|
||||
if(rcode)
|
||||
return rcode;
|
||||
}
|
||||
|
||||
return InTransfer(pep, nak_limit, nbytesptr, data, bInterval);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)
|
||||
#error "Never include confdescparser.h directly; include Usb.h instead"
|
||||
#else
|
||||
|
||||
#define __CONFDESCPARSER_H__
|
||||
|
||||
class UsbConfigXtracter {
|
||||
public:
|
||||
//virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
|
||||
//virtual void InterfaceXtract(uint8_t conf, const USB_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_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_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(void) {
|
||||
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_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
|
||||
USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_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)
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#endif // __CONFDESCPARSER_H__
|
||||
@@ -1,69 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
|
||||
#if !defined(_usb_h_) || defined(__HEXDUMP_H__)
|
||||
#error "Never include hexdump.h directly; include Usb.h instead"
|
||||
#else
|
||||
#define __HEXDUMP_H__
|
||||
|
||||
extern int UsbDEBUGlvl;
|
||||
|
||||
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
|
||||
class HexDumper : public BASE_CLASS {
|
||||
uint8_t byteCount;
|
||||
OFFSET_TYPE byteTotal;
|
||||
|
||||
public:
|
||||
|
||||
HexDumper() : byteCount(0), byteTotal(0) {
|
||||
};
|
||||
|
||||
void Initialize() {
|
||||
byteCount = 0;
|
||||
byteTotal = 0;
|
||||
};
|
||||
|
||||
void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset);
|
||||
};
|
||||
|
||||
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
|
||||
void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset __attribute__((unused))) {
|
||||
if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug.
|
||||
for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {
|
||||
if(!byteCount) {
|
||||
PrintHex<OFFSET_TYPE > (byteTotal, 0x80);
|
||||
E_Notify(PSTR(": "), 0x80);
|
||||
}
|
||||
PrintHex<uint8_t > (pbuf[j], 0x80);
|
||||
E_Notify(PSTR(" "), 0x80);
|
||||
|
||||
if(byteCount == 15) {
|
||||
E_Notify(PSTR("\r\n"), 0x80);
|
||||
byteCount = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __HEXDUMP_H__
|
||||
@@ -1,89 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
|
||||
#if !defined(_usb_h_) || defined(MACROS_H)
|
||||
#error "Never include macros.h directly; include Usb.h instead"
|
||||
#else
|
||||
#define MACROS_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HANDY MACROS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h)))
|
||||
#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h)))
|
||||
#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el)
|
||||
#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el);
|
||||
|
||||
#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
|
||||
#ifndef __BYTE_GRABBING_DEFINED__
|
||||
#define __BYTE_GRABBING_DEFINED__ 1
|
||||
#ifdef BROKEN_OPTIMIZER_LITTLE_ENDIAN
|
||||
// Note: Use this if your compiler generates horrible assembler!
|
||||
#define BGRAB0(__usi__) (((uint8_t *)&(__usi__))[0])
|
||||
#define BGRAB1(__usi__) (((uint8_t *)&(__usi__))[1])
|
||||
#define BGRAB2(__usi__) (((uint8_t *)&(__usi__))[2])
|
||||
#define BGRAB3(__usi__) (((uint8_t *)&(__usi__))[3])
|
||||
#define BGRAB4(__usi__) (((uint8_t *)&(__usi__))[4])
|
||||
#define BGRAB5(__usi__) (((uint8_t *)&(__usi__))[5])
|
||||
#define BGRAB6(__usi__) (((uint8_t *)&(__usi__))[6])
|
||||
#define BGRAB7(__usi__) (((uint8_t *)&(__usi__))[7])
|
||||
#else
|
||||
// Note: The cast alone to uint8_t is actually enough.
|
||||
// GCC throws out the "& 0xff", and the size is no different.
|
||||
// Some compilers need it.
|
||||
#define BGRAB0(__usi__) ((uint8_t)((__usi__) & 0xff ))
|
||||
#define BGRAB1(__usi__) ((uint8_t)(((__usi__) >> 8) & 0xff))
|
||||
#define BGRAB2(__usi__) ((uint8_t)(((__usi__) >> 16) & 0xff))
|
||||
#define BGRAB3(__usi__) ((uint8_t)(((__usi__) >> 24) & 0xff))
|
||||
#define BGRAB4(__usi__) ((uint8_t)(((__usi__) >> 32) & 0xff))
|
||||
#define BGRAB5(__usi__) ((uint8_t)(((__usi__) >> 40) & 0xff))
|
||||
#define BGRAB6(__usi__) ((uint8_t)(((__usi__) >> 48) & 0xff))
|
||||
#define BGRAB7(__usi__) ((uint8_t)(((__usi__) >> 56) & 0xff))
|
||||
#endif
|
||||
#define BOVER1(__usi__) ((uint16_t)(__usi__) << 8)
|
||||
#define BOVER2(__usi__) ((uint32_t)(__usi__) << 16)
|
||||
#define BOVER3(__usi__) ((uint32_t)(__usi__) << 24)
|
||||
#define BOVER4(__usi__) ((uint64_t)(__usi__) << 32)
|
||||
#define BOVER5(__usi__) ((uint64_t)(__usi__) << 40)
|
||||
#define BOVER6(__usi__) ((uint64_t)(__usi__) << 48)
|
||||
#define BOVER7(__usi__) ((uint64_t)(__usi__) << 56)
|
||||
|
||||
// These are the smallest and fastest ways I have found so far in pure C/C++.
|
||||
#define BMAKE16(__usc1__,__usc0__) ((uint16_t)((uint16_t)(__usc0__) | (uint16_t)BOVER1(__usc1__)))
|
||||
#define BMAKE32(__usc3__,__usc2__,__usc1__,__usc0__) ((uint32_t)((uint32_t)(__usc0__) | (uint32_t)BOVER1(__usc1__) | (uint32_t)BOVER2(__usc2__) | (uint32_t)BOVER3(__usc3__)))
|
||||
#define BMAKE64(__usc7__,__usc6__,__usc5__,__usc4__,__usc3__,__usc2__,__usc1__,__usc0__) ((uint64_t)((uint64_t)__usc0__ | (uint64_t)BOVER1(__usc1__) | (uint64_t)BOVER2(__usc2__) | (uint64_t)BOVER3(__usc3__) | (uint64_t)BOVER4(__usc4__) | (uint64_t)BOVER5(__usc5__) | (uint64_t)BOVER6(__usc6__) | (uint64_t)BOVER1(__usc7__)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Debug macros: Strings are stored in progmem (flash) instead of RAM.
|
||||
*/
|
||||
#define USBTRACE(s) (Notify(PSTR(s), 0x80))
|
||||
#define USBTRACE1(s,l) (Notify(PSTR(s), l))
|
||||
#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80))
|
||||
#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l))
|
||||
|
||||
|
||||
#endif /* MACROS_H */
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
|
||||
#include "../../include/Usb.h"
|
||||
// 0x80 is the default (i.e. trace) to turn off set this global to something lower.
|
||||
// this allows for 126 other debugging levels.
|
||||
// TO-DO: Allow assignment to a different serial port by software
|
||||
int UsbDEBUGlvl = 0x80;
|
||||
|
||||
void E_Notifyc(char c, int lvl) {
|
||||
if(UsbDEBUGlvl < lvl) return;
|
||||
#if defined(ARDUINO) && ARDUINO >=100
|
||||
USB_HOST_SERIAL.print(c);
|
||||
#else
|
||||
USB_HOST_SERIAL.print(c, BYTE);
|
||||
#endif
|
||||
//USB_HOST_SERIAL.flush();
|
||||
}
|
||||
|
||||
void E_Notify(char const * msg, int lvl) {
|
||||
if(UsbDEBUGlvl < lvl) return;
|
||||
if(!msg) return;
|
||||
char c;
|
||||
|
||||
while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl);
|
||||
}
|
||||
|
||||
void E_NotifyStr(char const * msg, int lvl) {
|
||||
if(UsbDEBUGlvl < lvl) return;
|
||||
if(!msg) return;
|
||||
char c;
|
||||
|
||||
while((c = *msg++)) E_Notifyc(c, lvl);
|
||||
}
|
||||
|
||||
void E_Notify(uint8_t b, int lvl) {
|
||||
if(UsbDEBUGlvl < lvl) return;
|
||||
#if defined(ARDUINO) && ARDUINO >=100
|
||||
USB_HOST_SERIAL.print(b);
|
||||
#else
|
||||
USB_HOST_SERIAL.print(b, DEC);
|
||||
#endif
|
||||
//USB_HOST_SERIAL.flush();
|
||||
}
|
||||
|
||||
void E_Notify(double d, int lvl) {
|
||||
if(UsbDEBUGlvl < lvl) return;
|
||||
USB_HOST_SERIAL.print(d);
|
||||
//USB_HOST_SERIAL.flush();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_USB_HOST
|
||||
|
||||
void NotifyFailGetDevDescr(void) {
|
||||
Notify(PSTR("\r\ngetDevDescr "), 0x80);
|
||||
}
|
||||
|
||||
void NotifyFailSetDevTblEntry(void) {
|
||||
Notify(PSTR("\r\nsetDevTblEn "), 0x80);
|
||||
}
|
||||
|
||||
void NotifyFailGetConfDescr(void) {
|
||||
Notify(PSTR("\r\ngetConf "), 0x80);
|
||||
}
|
||||
|
||||
void NotifyFailSetConfDescr(void) {
|
||||
Notify(PSTR("\r\nsetConf "), 0x80);
|
||||
}
|
||||
|
||||
void NotifyFailGetDevDescr(uint8_t reason) {
|
||||
NotifyFailGetDevDescr();
|
||||
NotifyFail(reason);
|
||||
}
|
||||
|
||||
void NotifyFailSetDevTblEntry(uint8_t reason) {
|
||||
NotifyFailSetDevTblEntry();
|
||||
NotifyFail(reason);
|
||||
|
||||
}
|
||||
|
||||
void NotifyFailGetConfDescr(uint8_t reason) {
|
||||
NotifyFailGetConfDescr();
|
||||
NotifyFail(reason);
|
||||
}
|
||||
|
||||
void NotifyFailSetConfDescr(uint8_t reason) {
|
||||
NotifyFailSetConfDescr();
|
||||
NotifyFail(reason);
|
||||
}
|
||||
|
||||
void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) {
|
||||
Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80);
|
||||
D_PrintHex<uint16_t > (VID, 0x80);
|
||||
Notify(PSTR(" PID: "), 0x80);
|
||||
D_PrintHex<uint16_t > (PID, 0x80);
|
||||
}
|
||||
|
||||
void NotifyFail(uint8_t rcode) {
|
||||
D_PrintHex<uint8_t > (rcode, 0x80);
|
||||
Notify(PSTR("\r\n"), 0x80);
|
||||
}
|
||||
#endif
|
||||
@@ -1,85 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
#if !defined(_usb_h_) || defined(__MESSAGE_H__)
|
||||
#error "Never include message.h directly; include Usb.h instead"
|
||||
#else
|
||||
#define __MESSAGE_H__
|
||||
|
||||
extern int UsbDEBUGlvl;
|
||||
|
||||
void E_Notify(char const * msg, int lvl);
|
||||
void E_Notify(uint8_t b, int lvl);
|
||||
void E_NotifyStr(char const * msg, int lvl);
|
||||
void E_Notifyc(char c, int lvl);
|
||||
|
||||
#ifdef DEBUG_USB_HOST
|
||||
#define Notify E_Notify
|
||||
#define NotifyStr E_NotifyStr
|
||||
#define Notifyc E_Notifyc
|
||||
void NotifyFailGetDevDescr(uint8_t reason);
|
||||
void NotifyFailSetDevTblEntry(uint8_t reason);
|
||||
void NotifyFailGetConfDescr(uint8_t reason);
|
||||
void NotifyFailSetConfDescr(uint8_t reason);
|
||||
void NotifyFailGetDevDescr(void);
|
||||
void NotifyFailSetDevTblEntry(void);
|
||||
void NotifyFailGetConfDescr(void);
|
||||
void NotifyFailSetConfDescr(void);
|
||||
void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID);
|
||||
void NotifyFail(uint8_t rcode);
|
||||
#else
|
||||
#define Notify(...) ((void)0)
|
||||
#define NotifyStr(...) ((void)0)
|
||||
#define Notifyc(...) ((void)0)
|
||||
#define NotifyFailGetDevDescr(...) ((void)0)
|
||||
#define NotifyFailSetDevTblEntry(...) ((void)0)
|
||||
#define NotifyFailGetConfDescr(...) ((void)0)
|
||||
#define NotifyFailGetDevDescr(...) ((void)0)
|
||||
#define NotifyFailSetDevTblEntry(...) ((void)0)
|
||||
#define NotifyFailGetConfDescr(...) ((void)0)
|
||||
#define NotifyFailSetConfDescr(...) ((void)0)
|
||||
#define NotifyFailUnknownDevice(...) ((void)0)
|
||||
#define NotifyFail(...) ((void)0)
|
||||
#endif
|
||||
|
||||
template <class ERROR_TYPE>
|
||||
void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(msg, level);
|
||||
Notify(PSTR(": "), level);
|
||||
D_PrintHex<ERROR_TYPE > (rcode, level);
|
||||
Notify(PSTR("\r\n"), level);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class ERROR_TYPE>
|
||||
void ErrorMessage(char const * msg __attribute__((unused)), ERROR_TYPE rcode __attribute__((unused)) = 0) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
Notify(msg, 0x80);
|
||||
Notify(PSTR(": "), 0x80);
|
||||
D_PrintHex<ERROR_TYPE > (rcode, 0x80);
|
||||
Notify(PSTR("\r\n"), 0x80);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __MESSAGE_H__
|
||||
@@ -1,74 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
#include "../../include/Usb.h"
|
||||
|
||||
bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) {
|
||||
if(!pBuf) {
|
||||
Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
|
||||
return false;
|
||||
}
|
||||
for(; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
|
||||
pBuf[valueSize - countDown] = (**pp);
|
||||
|
||||
if(countDown)
|
||||
return false;
|
||||
|
||||
countDown = valueSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {
|
||||
switch(nStage) {
|
||||
case 0:
|
||||
pBuf->valueSize = lenSize;
|
||||
theParser.Initialize(pBuf);
|
||||
nStage = 1;
|
||||
|
||||
case 1:
|
||||
if(!theParser.Parse(pp, pcntdn))
|
||||
return false;
|
||||
|
||||
arLen = 0;
|
||||
arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
|
||||
arLenCntdn = arLen;
|
||||
nStage = 2;
|
||||
|
||||
case 2:
|
||||
pBuf->valueSize = valSize;
|
||||
theParser.Initialize(pBuf);
|
||||
nStage = 3;
|
||||
|
||||
case 3:
|
||||
for(; arLenCntdn; arLenCntdn--) {
|
||||
if(!theParser.Parse(pp, pcntdn))
|
||||
return false;
|
||||
|
||||
if(pf)
|
||||
pf(pBuf, (arLen - arLenCntdn), me);
|
||||
}
|
||||
|
||||
nStage = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
|
||||
#if !defined(_usb_h_) || defined(__PARSETOOLS_H__)
|
||||
#error "Never include parsetools.h directly; include Usb.h instead"
|
||||
#else
|
||||
#define __PARSETOOLS_H__
|
||||
|
||||
struct MultiValueBuffer {
|
||||
uint8_t valueSize;
|
||||
void *pValue;
|
||||
|
||||
public:
|
||||
|
||||
MultiValueBuffer() : valueSize(0), pValue(NULL) {
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
class MultiByteValueParser {
|
||||
uint8_t * pBuf;
|
||||
uint8_t countDown;
|
||||
uint8_t valueSize;
|
||||
|
||||
public:
|
||||
|
||||
MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {
|
||||
};
|
||||
|
||||
const uint8_t* GetBuffer() {
|
||||
return pBuf;
|
||||
};
|
||||
|
||||
void Initialize(MultiValueBuffer * const pbuf) {
|
||||
pBuf = (uint8_t*)pbuf->pValue;
|
||||
countDown = valueSize = pbuf->valueSize;
|
||||
};
|
||||
|
||||
bool Parse(uint8_t **pp, uint16_t *pcntdn);
|
||||
};
|
||||
|
||||
class ByteSkipper {
|
||||
uint8_t *pBuf;
|
||||
uint8_t nStage;
|
||||
uint16_t countDown;
|
||||
|
||||
public:
|
||||
|
||||
ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {
|
||||
};
|
||||
|
||||
void Initialize(MultiValueBuffer *pbuf) {
|
||||
pBuf = (uint8_t*)pbuf->pValue;
|
||||
countDown = 0;
|
||||
};
|
||||
|
||||
bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) {
|
||||
switch(nStage) {
|
||||
case 0:
|
||||
countDown = bytes_to_skip;
|
||||
nStage++;
|
||||
case 1:
|
||||
for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
|
||||
|
||||
if(!countDown)
|
||||
nStage = 0;
|
||||
};
|
||||
return (!countDown);
|
||||
};
|
||||
};
|
||||
|
||||
// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
|
||||
typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);
|
||||
|
||||
class PTPListParser {
|
||||
public:
|
||||
|
||||
enum ParseMode {
|
||||
modeArray, modeRange/*, modeEnum*/
|
||||
};
|
||||
|
||||
private:
|
||||
uint8_t nStage;
|
||||
uint8_t enStage;
|
||||
|
||||
uint32_t arLen;
|
||||
uint32_t arLenCntdn;
|
||||
|
||||
uint8_t lenSize; // size of the array length field in bytes
|
||||
uint8_t valSize; // size of the array element in bytes
|
||||
|
||||
MultiValueBuffer *pBuf;
|
||||
|
||||
// The only parser for both size and array element parsing
|
||||
MultiByteValueParser theParser;
|
||||
|
||||
uint8_t /*ParseMode*/ prsMode;
|
||||
|
||||
public:
|
||||
|
||||
PTPListParser() :
|
||||
nStage(0),
|
||||
enStage(0),
|
||||
arLen(0),
|
||||
arLenCntdn(0),
|
||||
lenSize(0),
|
||||
valSize(0),
|
||||
pBuf(NULL),
|
||||
prsMode(modeArray) {
|
||||
};
|
||||
|
||||
void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) {
|
||||
pBuf = p;
|
||||
lenSize = len_size;
|
||||
valSize = val_size;
|
||||
prsMode = mode;
|
||||
|
||||
if(prsMode == modeRange) {
|
||||
arLenCntdn = arLen = 3;
|
||||
nStage = 2;
|
||||
} else {
|
||||
arLenCntdn = arLen = 0;
|
||||
nStage = 0;
|
||||
}
|
||||
enStage = 0;
|
||||
theParser.Initialize(p);
|
||||
};
|
||||
|
||||
bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);
|
||||
};
|
||||
|
||||
#endif // __PARSETOOLS_H__
|
||||
@@ -1,91 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
|
||||
#if !defined(_usb_h_) || defined(__PRINTHEX_H__)
|
||||
#error "Never include printhex.h directly; include Usb.h instead"
|
||||
#else
|
||||
#define __PRINTHEX_H__
|
||||
|
||||
void E_Notifyc(char c, int lvl);
|
||||
|
||||
template <class T>
|
||||
void PrintHex(T val, int lvl) {
|
||||
int num_nibbles = sizeof (T) * 2;
|
||||
|
||||
do {
|
||||
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
|
||||
if(v > 57) v += 7;
|
||||
E_Notifyc(v, lvl);
|
||||
} while(--num_nibbles);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PrintBin(T val, int lvl) {
|
||||
for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1)
|
||||
if(val & mask)
|
||||
E_Notifyc('1', lvl);
|
||||
else
|
||||
E_Notifyc('0', lvl);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void SerialPrintHex(T val) {
|
||||
int num_nibbles = sizeof (T) * 2;
|
||||
|
||||
do {
|
||||
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
|
||||
if(v > 57) v += 7;
|
||||
USB_HOST_SERIAL.print(v);
|
||||
} while(--num_nibbles);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PrintHex2(Print *prn, T val) {
|
||||
T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2));
|
||||
|
||||
while(mask > 1) {
|
||||
if(val < mask)
|
||||
prn->print("0");
|
||||
|
||||
mask >>= 4;
|
||||
}
|
||||
prn->print((T)val, HEX);
|
||||
}
|
||||
|
||||
template <class T> void D_PrintHex(T val __attribute__((unused)), int lvl __attribute__((unused))) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
PrintHex<T > (val, lvl);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void D_PrintBin(T val, int lvl) {
|
||||
#ifdef DEBUG_USB_HOST
|
||||
PrintBin<T > (val, lvl);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // __PRINTHEX_H__
|
||||
@@ -24,7 +24,6 @@ e-mail : support@circuitsathome.com
|
||||
|
||||
#ifndef USB_HOST_SHIELD_SETTINGS_H
|
||||
#define USB_HOST_SHIELD_SETTINGS_H
|
||||
#include "macros.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI Configuration
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/* 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 : http://www.circuitsathome.com
|
||||
e-mail : support@circuitsathome.com
|
||||
*/
|
||||
|
||||
#if !defined(_usb_h_) || defined(__SINK_PARSER_H__)
|
||||
#error "Never include hexdump.h directly; include Usb.h instead"
|
||||
#else
|
||||
#define __SINK_PARSER_H__
|
||||
|
||||
extern int UsbDEBUGlvl;
|
||||
|
||||
// This parser does absolutely nothing with the data, just swallows it.
|
||||
|
||||
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
|
||||
class SinkParser : public BASE_CLASS {
|
||||
public:
|
||||
|
||||
SinkParser() {
|
||||
};
|
||||
|
||||
void Initialize() {
|
||||
};
|
||||
|
||||
void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif // __HEXDUMP_H__
|
||||
@@ -1,427 +0,0 @@
|
||||
/* 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
|
||||
*/
|
||||
#include "usbhub.h"
|
||||
|
||||
bool USBHub::bResetInitiated = false;
|
||||
|
||||
USBHub::USBHub(USB *p) :
|
||||
pUsb(p),
|
||||
bAddress(0),
|
||||
bNbrPorts(0),
|
||||
//bInitState(0),
|
||||
qNextPollTime(0),
|
||||
bPollEnable(false) {
|
||||
epInfo[0].epAddr = 0;
|
||||
epInfo[0].maxPktSize = 8;
|
||||
epInfo[0].bmSndToggle = 0;
|
||||
epInfo[0].bmRcvToggle = 0;
|
||||
epInfo[0].bmNakPower = USB_NAK_MAX_POWER;
|
||||
|
||||
epInfo[1].epAddr = 1;
|
||||
epInfo[1].maxPktSize = 8; //kludge
|
||||
epInfo[1].bmSndToggle = 0;
|
||||
epInfo[1].bmRcvToggle = 0;
|
||||
epInfo[1].bmNakPower = USB_NAK_NOWAIT;
|
||||
|
||||
if(pUsb)
|
||||
pUsb->RegisterDeviceClass(this);
|
||||
}
|
||||
|
||||
uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
|
||||
uint8_t buf[32];
|
||||
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
|
||||
HubDescriptor* hd = reinterpret_cast<HubDescriptor*>(buf);
|
||||
USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(buf);
|
||||
uint8_t rcode;
|
||||
UsbDevice *p = NULL;
|
||||
EpInfo *oldep_ptr = NULL;
|
||||
uint8_t len = 0;
|
||||
uint16_t cd_len = 0;
|
||||
|
||||
//USBTRACE("\r\nHub Init Start ");
|
||||
//D_PrintHex<uint8_t > (bInitState, 0x80);
|
||||
|
||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||
|
||||
//switch (bInitState) {
|
||||
// case 0:
|
||||
if(bAddress)
|
||||
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
||||
|
||||
// Get pointer to pseudo device with address 0 assigned
|
||||
p = addrPool.GetUsbDevicePtr(0);
|
||||
|
||||
if(!p)
|
||||
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||
|
||||
if(!p->epinfo)
|
||||
return USB_ERROR_EPINFO_IS_NULL;
|
||||
|
||||
// Save old pointer to EP_RECORD of address 0
|
||||
oldep_ptr = p->epinfo;
|
||||
|
||||
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
|
||||
p->epinfo = epInfo;
|
||||
|
||||
p->lowspeed = lowspeed;
|
||||
|
||||
// Get device descriptor
|
||||
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
|
||||
|
||||
p->lowspeed = false;
|
||||
|
||||
if(!rcode)
|
||||
len = (buf[0] > 32) ? 32 : buf[0];
|
||||
|
||||
if(rcode) {
|
||||
// Restore p->epinfo
|
||||
p->epinfo = oldep_ptr;
|
||||
return rcode;
|
||||
}
|
||||
|
||||
// Extract device class from device descriptor
|
||||
// If device class is not a hub return
|
||||
if(udd->bDeviceClass != 0x09)
|
||||
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||
|
||||
// Allocate new address according to device class
|
||||
bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port);
|
||||
|
||||
if(!bAddress)
|
||||
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
|
||||
|
||||
// Extract Max Packet Size from the device descriptor
|
||||
epInfo[0].maxPktSize = udd->bMaxPacketSize0;
|
||||
|
||||
// Assign new address to the device
|
||||
rcode = pUsb->setAddr(0, 0, bAddress);
|
||||
|
||||
if(rcode) {
|
||||
// Restore p->epinfo
|
||||
p->epinfo = oldep_ptr;
|
||||
addrPool.FreeAddress(bAddress);
|
||||
bAddress = 0;
|
||||
return rcode;
|
||||
}
|
||||
|
||||
//USBTRACE2("\r\nHub address: ", bAddress );
|
||||
|
||||
// Restore p->epinfo
|
||||
p->epinfo = oldep_ptr;
|
||||
|
||||
if(len)
|
||||
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
|
||||
|
||||
if(rcode)
|
||||
goto FailGetDevDescr;
|
||||
|
||||
// Assign epInfo to epinfo pointer
|
||||
rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);
|
||||
|
||||
if(rcode)
|
||||
goto FailSetDevTblEntry;
|
||||
|
||||
// bInitState = 1;
|
||||
|
||||
// case 1:
|
||||
// Get hub descriptor
|
||||
rcode = GetHubDescriptor(0, 8, buf);
|
||||
|
||||
if(rcode)
|
||||
goto FailGetHubDescr;
|
||||
|
||||
// Save number of ports for future use
|
||||
bNbrPorts = hd->bNbrPorts;
|
||||
|
||||
// bInitState = 2;
|
||||
|
||||
// case 2:
|
||||
// Read configuration Descriptor in Order To Obtain Proper Configuration Value
|
||||
rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);
|
||||
|
||||
if(!rcode) {
|
||||
cd_len = ucd->wTotalLength;
|
||||
rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
|
||||
}
|
||||
if(rcode)
|
||||
goto FailGetConfDescr;
|
||||
|
||||
// The following code is of no practical use in real life applications.
|
||||
// It only intended for the usb protocol sniffer to properly parse hub-class requests.
|
||||
{
|
||||
uint8_t buf2[24];
|
||||
|
||||
rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2);
|
||||
|
||||
if(rcode)
|
||||
goto FailGetConfDescr;
|
||||
}
|
||||
|
||||
// Set Configuration Value
|
||||
rcode = pUsb->setConf(bAddress, 0, buf[5]);
|
||||
|
||||
if(rcode)
|
||||
goto FailSetConfDescr;
|
||||
|
||||
// bInitState = 3;
|
||||
|
||||
// case 3:
|
||||
// Power on all ports
|
||||
for(uint8_t j = 1; j <= bNbrPorts; j++)
|
||||
SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j);
|
||||
|
||||
pUsb->SetHubPreMask();
|
||||
bPollEnable = true;
|
||||
// bInitState = 0;
|
||||
//}
|
||||
//bInitState = 0;
|
||||
//USBTRACE("...OK\r\n");
|
||||
return 0;
|
||||
|
||||
// Oleg, No debugging?? -- xxxajk
|
||||
FailGetDevDescr:
|
||||
goto Fail;
|
||||
|
||||
FailSetDevTblEntry:
|
||||
goto Fail;
|
||||
|
||||
FailGetHubDescr:
|
||||
goto Fail;
|
||||
|
||||
FailGetConfDescr:
|
||||
goto Fail;
|
||||
|
||||
FailSetConfDescr:
|
||||
goto Fail;
|
||||
|
||||
Fail:
|
||||
USBTRACE("...FAIL\r\n");
|
||||
return rcode;
|
||||
}
|
||||
|
||||
uint8_t USBHub::Release() {
|
||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||
|
||||
if(bAddress == 0x41)
|
||||
pUsb->SetHubPreMask();
|
||||
|
||||
bAddress = 0;
|
||||
bNbrPorts = 0;
|
||||
qNextPollTime = 0;
|
||||
bPollEnable = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t USBHub::Poll() {
|
||||
uint8_t rcode = 0;
|
||||
|
||||
if(!bPollEnable)
|
||||
return 0;
|
||||
|
||||
if(((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L)) {
|
||||
rcode = CheckHubStatus();
|
||||
qNextPollTime = (uint32_t)millis() + 100;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
uint8_t USBHub::CheckHubStatus() {
|
||||
uint8_t rcode;
|
||||
uint8_t buf[8];
|
||||
uint16_t read = 1;
|
||||
|
||||
rcode = pUsb->inTransfer(bAddress, 1, &read, buf);
|
||||
|
||||
if(rcode)
|
||||
return rcode;
|
||||
|
||||
//if (buf[0] & 0x01) // Hub Status Change
|
||||
//{
|
||||
// pUsb->PrintHubStatus(addr);
|
||||
// rcode = GetHubStatus(1, 0, 1, 4, buf);
|
||||
// if (rcode)
|
||||
// {
|
||||
// USB_HOST_SERIAL.print("GetHubStatus Error");
|
||||
// USB_HOST_SERIAL.println(rcode, HEX);
|
||||
// return rcode;
|
||||
// }
|
||||
//}
|
||||
for(uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) {
|
||||
if(buf[0] & mask) {
|
||||
HubEvent evt;
|
||||
evt.bmEvent = 0;
|
||||
|
||||
rcode = GetPortStatus(port, 4, evt.evtBuff);
|
||||
|
||||
if(rcode)
|
||||
continue;
|
||||
|
||||
rcode = PortStatusChange(port, evt);
|
||||
|
||||
if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
|
||||
return 0;
|
||||
|
||||
if(rcode)
|
||||
return rcode;
|
||||
}
|
||||
} // for
|
||||
|
||||
for(uint8_t port = 1; port <= bNbrPorts; port++) {
|
||||
HubEvent evt;
|
||||
evt.bmEvent = 0;
|
||||
|
||||
rcode = GetPortStatus(port, 4, evt.evtBuff);
|
||||
|
||||
if(rcode)
|
||||
continue;
|
||||
|
||||
if((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED)
|
||||
continue;
|
||||
|
||||
// Emulate connection event for the port
|
||||
evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION;
|
||||
|
||||
rcode = PortStatusChange(port, evt);
|
||||
|
||||
if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
|
||||
return 0;
|
||||
|
||||
if(rcode)
|
||||
return rcode;
|
||||
} // for
|
||||
return 0;
|
||||
}
|
||||
|
||||
void USBHub::ResetHubPort(uint8_t port) {
|
||||
HubEvent evt;
|
||||
evt.bmEvent = 0;
|
||||
uint8_t rcode;
|
||||
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
|
||||
SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);
|
||||
|
||||
|
||||
for(int i = 0; i < 3; i++) {
|
||||
rcode = GetPortStatus(port, 4, evt.evtBuff);
|
||||
if(rcode) break; // Some kind of error, bail.
|
||||
if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) {
|
||||
break;
|
||||
}
|
||||
delay(100); // simulate polling.
|
||||
}
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
|
||||
delay(20);
|
||||
}
|
||||
|
||||
uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) {
|
||||
switch(evt.bmEvent) {
|
||||
// Device connected event
|
||||
case bmHUB_PORT_EVENT_CONNECT:
|
||||
case bmHUB_PORT_EVENT_LS_CONNECT:
|
||||
if(bResetInitiated)
|
||||
return 0;
|
||||
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
|
||||
SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);
|
||||
bResetInitiated = true;
|
||||
return HUB_ERROR_PORT_HAS_BEEN_RESET;
|
||||
|
||||
// Device disconnected event
|
||||
case bmHUB_PORT_EVENT_DISCONNECT:
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
|
||||
bResetInitiated = false;
|
||||
|
||||
UsbDeviceAddress a;
|
||||
a.devAddress = 0;
|
||||
a.bmHub = 0;
|
||||
a.bmParent = bAddress;
|
||||
a.bmAddress = port;
|
||||
pUsb->ReleaseDevice(a.devAddress);
|
||||
return 0;
|
||||
|
||||
// Reset complete event
|
||||
case bmHUB_PORT_EVENT_RESET_COMPLETE:
|
||||
case bmHUB_PORT_EVENT_LS_RESET_COMPLETE:
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);
|
||||
ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
|
||||
|
||||
delay(20);
|
||||
|
||||
a.devAddress = bAddress;
|
||||
|
||||
pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED));
|
||||
bResetInitiated = false;
|
||||
break;
|
||||
|
||||
} // switch (evt.bmEvent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrintHubPortStatus(USBHub *hubptr, uint8_t addr __attribute__((unused)), uint8_t port, bool print_changes) {
|
||||
uint8_t rcode = 0;
|
||||
HubEvent evt;
|
||||
|
||||
rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff);
|
||||
|
||||
if(rcode) {
|
||||
USB_HOST_SERIAL.println("ERROR!");
|
||||
return;
|
||||
}
|
||||
USB_HOST_SERIAL.print("\r\nPort ");
|
||||
USB_HOST_SERIAL.println(port, DEC);
|
||||
|
||||
USB_HOST_SERIAL.println("Status");
|
||||
USB_HOST_SERIAL.print("CONNECTION:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("ENABLE:\t\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("SUSPEND:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("OVER_CURRENT:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("RESET:\t\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("POWER:\t\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("LOW_SPEED:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("HIGH_SPEED:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("TEST:\t\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("INDICATOR:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC);
|
||||
|
||||
if(!print_changes)
|
||||
return;
|
||||
|
||||
USB_HOST_SERIAL.println("\r\nChange");
|
||||
USB_HOST_SERIAL.print("CONNECTION:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("ENABLE:\t\t");
|
||||
USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("SUSPEND:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("OVER_CURRENT:\t");
|
||||
USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC);
|
||||
USB_HOST_SERIAL.print("RESET:\t\t");
|
||||
USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC);
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
/* 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
|
||||
*/
|
||||
#if !defined(__USBHUB_H__)
|
||||
#define __USBHUB_H__
|
||||
|
||||
#include "../../include/Usb.h"
|
||||
|
||||
#define USB_DESCRIPTOR_HUB 0x09 // Hub descriptor type
|
||||
|
||||
// Hub Requests
|
||||
#define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||
#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||
|
||||
// Hub Class Requests
|
||||
#define HUB_REQUEST_CLEAR_TT_BUFFER 8
|
||||
#define HUB_REQUEST_RESET_TT 9
|
||||
#define HUB_REQUEST_GET_TT_STATE 10
|
||||
#define HUB_REQUEST_STOP_TT 11
|
||||
|
||||
// Hub Features
|
||||
#define HUB_FEATURE_C_HUB_LOCAL_POWER 0
|
||||
#define HUB_FEATURE_C_HUB_OVER_CURRENT 1
|
||||
#define HUB_FEATURE_PORT_CONNECTION 0
|
||||
#define HUB_FEATURE_PORT_ENABLE 1
|
||||
#define HUB_FEATURE_PORT_SUSPEND 2
|
||||
#define HUB_FEATURE_PORT_OVER_CURRENT 3
|
||||
#define HUB_FEATURE_PORT_RESET 4
|
||||
#define HUB_FEATURE_PORT_POWER 8
|
||||
#define HUB_FEATURE_PORT_LOW_SPEED 9
|
||||
#define HUB_FEATURE_C_PORT_CONNECTION 16
|
||||
#define HUB_FEATURE_C_PORT_ENABLE 17
|
||||
#define HUB_FEATURE_C_PORT_SUSPEND 18
|
||||
#define HUB_FEATURE_C_PORT_OVER_CURRENT 19
|
||||
#define HUB_FEATURE_C_PORT_RESET 20
|
||||
#define HUB_FEATURE_PORT_TEST 21
|
||||
#define HUB_FEATURE_PORT_INDICATOR 22
|
||||
|
||||
// Hub Port Test Modes
|
||||
#define HUB_PORT_TEST_MODE_J 1
|
||||
#define HUB_PORT_TEST_MODE_K 2
|
||||
#define HUB_PORT_TEST_MODE_SE0_NAK 3
|
||||
#define HUB_PORT_TEST_MODE_PACKET 4
|
||||
#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5
|
||||
|
||||
// Hub Port Indicator Color
|
||||
#define HUB_PORT_INDICATOR_AUTO 0
|
||||
#define HUB_PORT_INDICATOR_AMBER 1
|
||||
#define HUB_PORT_INDICATOR_GREEN 2
|
||||
#define HUB_PORT_INDICATOR_OFF 3
|
||||
|
||||
// Hub Port Status Bitmasks
|
||||
#define bmHUB_PORT_STATUS_PORT_CONNECTION 0x0001
|
||||
#define bmHUB_PORT_STATUS_PORT_ENABLE 0x0002
|
||||
#define bmHUB_PORT_STATUS_PORT_SUSPEND 0x0004
|
||||
#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008
|
||||
#define bmHUB_PORT_STATUS_PORT_RESET 0x0010
|
||||
#define bmHUB_PORT_STATUS_PORT_POWER 0x0100
|
||||
#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200
|
||||
#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400
|
||||
#define bmHUB_PORT_STATUS_PORT_TEST 0x0800
|
||||
#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000
|
||||
|
||||
// Hub Port Status Change Bitmasks (used one byte instead of two)
|
||||
#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001
|
||||
#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002
|
||||
#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004
|
||||
#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008
|
||||
#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010
|
||||
|
||||
// Hub Status Bitmasks (used one byte instead of two)
|
||||
#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01
|
||||
#define bmHUB_STATUS_OVER_CURRENT 0x12
|
||||
|
||||
// Hub Status Change Bitmasks (used one byte instead of two)
|
||||
#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01
|
||||
#define bmHUB_STATUS_C_OVER_CURRENT 0x12
|
||||
|
||||
|
||||
// Hub Port Configuring Substates
|
||||
#define USB_STATE_HUB_PORT_CONFIGURING 0xb0
|
||||
#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1
|
||||
#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2
|
||||
#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3
|
||||
#define USB_STATE_HUB_PORT_DISABLED 0xb4
|
||||
#define USB_STATE_HUB_PORT_RESETTING 0xb5
|
||||
#define USB_STATE_HUB_PORT_ENABLED 0xb6
|
||||
|
||||
// Additional Error Codes
|
||||
#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1
|
||||
|
||||
// The bit mask to check for all necessary state bits
|
||||
#define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
|
||||
|
||||
// Bit mask to check for DISABLED state in HubEvent::bmStatus field
|
||||
#define bmHUB_PORT_STATE_CHECK_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
|
||||
|
||||
// Hub Port States
|
||||
#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||
|
||||
// Hub Port Events
|
||||
#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||
#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER)
|
||||
#define bmHUB_PORT_EVENT_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||
|
||||
#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
|
||||
#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
|
||||
#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
|
||||
|
||||
struct HubDescriptor {
|
||||
uint8_t bDescLength; // descriptor length
|
||||
uint8_t bDescriptorType; // descriptor type
|
||||
uint8_t bNbrPorts; // number of ports a hub equiped with
|
||||
|
||||
struct {
|
||||
uint16_t LogPwrSwitchMode : 2;
|
||||
uint16_t CompoundDevice : 1;
|
||||
uint16_t OverCurrentProtectMode : 2;
|
||||
uint16_t TTThinkTime : 2;
|
||||
uint16_t PortIndicatorsSupported : 1;
|
||||
uint16_t Reserved : 8;
|
||||
} __attribute__((packed));
|
||||
|
||||
uint8_t bPwrOn2PwrGood;
|
||||
uint8_t bHubContrCurrent;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HubEvent {
|
||||
|
||||
union {
|
||||
|
||||
struct {
|
||||
uint16_t bmStatus; // port status bits
|
||||
uint16_t bmChange; // port status change bits
|
||||
} __attribute__((packed));
|
||||
uint32_t bmEvent;
|
||||
uint8_t evtBuff[4];
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
class USBHub : USBDeviceConfig {
|
||||
static bool bResetInitiated; // True when reset is triggered
|
||||
|
||||
USB *pUsb; // USB class instance pointer
|
||||
|
||||
EpInfo epInfo[2]; // interrupt endpoint info structure
|
||||
|
||||
uint8_t bAddress; // address
|
||||
uint8_t bNbrPorts; // number of ports
|
||||
// uint8_t bInitState; // initialization state variable
|
||||
uint32_t qNextPollTime; // next poll time
|
||||
bool bPollEnable; // poll enable flag
|
||||
|
||||
uint8_t CheckHubStatus();
|
||||
uint8_t PortStatusChange(uint8_t port, HubEvent &evt);
|
||||
|
||||
public:
|
||||
USBHub(USB *p);
|
||||
|
||||
uint8_t ClearHubFeature(uint8_t fid);
|
||||
uint8_t ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0);
|
||||
uint8_t GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr);
|
||||
uint8_t GetHubStatus(uint16_t nbytes, uint8_t* dataptr);
|
||||
uint8_t GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr);
|
||||
uint8_t SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr);
|
||||
uint8_t SetHubFeature(uint8_t fid);
|
||||
uint8_t SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0);
|
||||
|
||||
void PrintHubStatus();
|
||||
|
||||
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||
uint8_t Release();
|
||||
uint8_t Poll();
|
||||
void ResetHubPort(uint8_t port);
|
||||
|
||||
virtual uint8_t GetAddress() {
|
||||
return bAddress;
|
||||
};
|
||||
|
||||
virtual bool DEVCLASSOK(uint8_t klass) {
|
||||
return (klass == 0x09);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Clear Hub Feature
|
||||
|
||||
inline uint8_t USBHub::ClearHubFeature(uint8_t fid) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
|
||||
}
|
||||
// Clear Port Feature
|
||||
|
||||
inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));
|
||||
}
|
||||
// Get Hub Descriptor
|
||||
|
||||
inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));
|
||||
}
|
||||
// Get Hub Status
|
||||
|
||||
inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));
|
||||
}
|
||||
// Get Port Status
|
||||
|
||||
inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));
|
||||
}
|
||||
// Set Hub Descriptor
|
||||
|
||||
inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));
|
||||
}
|
||||
// Set Hub Feature
|
||||
|
||||
inline uint8_t USBHub::SetHubFeature(uint8_t fid) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
|
||||
}
|
||||
// Set Port Feature
|
||||
|
||||
inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
|
||||
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));
|
||||
}
|
||||
|
||||
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false);
|
||||
|
||||
#endif // __USBHUB_H__
|
||||
@@ -1,7 +1,7 @@
|
||||
project(checkm8_remote C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_FLAGS -g)
|
||||
set(CMAKE_C_FLAGS "-g -Wall")
|
||||
|
||||
include_directories(include)
|
||||
add_executable(checkm8_remote main.c src/usb_helpers.c src/exploit.c src/payload.c src/command.c)
|
||||
|
||||
@@ -291,7 +291,8 @@ struct pwned_device *exploit_device()
|
||||
|
||||
void free_device(struct pwned_device *dev)
|
||||
{
|
||||
close_device_session(dev);
|
||||
checkm8_debug_indent("free_device(dev = %p)\n", dev);
|
||||
if(is_device_session_open(dev)) close_device_session(dev);
|
||||
#ifndef WITH_ARDUINO
|
||||
free(dev->bundle);
|
||||
#endif
|
||||
|
||||
@@ -105,6 +105,12 @@ int open_device_session(struct pwned_device *dev)
|
||||
close(ard_fd);
|
||||
return CHECKM8_FAIL_NOTDONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkm8_debug_indent("\tunexpected response %X\n", buf);
|
||||
close(ard_fd);
|
||||
return CHECKM8_FAIL_PROT;
|
||||
}
|
||||
#else
|
||||
int i, usb_dev_count, ret = CHECKM8_FAIL_NODEV;
|
||||
libusb_device **usb_device_list = NULL;
|
||||
|
||||
Reference in New Issue
Block a user