From 2e52a1dfa66680d6e1a770c9b9840ffc3150b27d Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Wed, 18 May 2011 20:24:13 -0600 Subject: [PATCH 1/6] inTransfer with pointer to nbytes --- Usb.cpp | 162 +++++++++++------------ Usb.h | 80 +++++------- cdcacm.cpp | 330 +++++++++++++++++++++++++++++++++++++++++++++++ cdcacm.h | 166 ++++++++++++++++++++++++ cdcftdi.cpp | 330 +++++++++++++++++++++++++++++++++++++++++++++++ cdcftdi.h | 119 +++++++++++++++++ cdcprolific.cpp | 189 +++++++++++++++++++++++++++ cdcprolific.h | 134 +++++++++++++++++++ confdescparser.h | 148 +++++++++++++++++++++ max_LCD.h | 5 +- usb_ch9.h | 66 ++-------- usbhub.cpp | 5 +- usbhub.h | 35 ++--- 13 files changed, 1560 insertions(+), 209 deletions(-) create mode 100644 cdcacm.cpp create mode 100644 cdcacm.h create mode 100644 cdcftdi.cpp create mode 100644 cdcftdi.h create mode 100644 cdcprolific.cpp create mode 100644 cdcprolific.h create mode 100644 confdescparser.h diff --git a/Usb.cpp b/Usb.cpp index 653a4334..6da62e4b 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -106,78 +106,7 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_l /* 00 = success */ /* 01-0f = non-zero HRSLT */ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - unsigned int wInd, unsigned int nbytes, uint8_t* dataptr ) -{ - return ctrlReq(addr, ep, bmReqType, bRequest, wValLo, wValHi, wInd, nbytes, nbytes, dataptr, NULL); -} - -//uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, -// uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBREADCALLBACK pf) -//{ -// boolean direction = false; //request direction, IN or OUT -// uint8_t rcode; -// SETUP_PKT setup_pkt; -// -// EpInfo *pep = NULL; -// uint16_t nak_limit; -// -// rcode = SetAddress(addr, ep, &pep, nak_limit); -// -// if (rcode) -// return rcode; -// -// direction = (( bmReqType & 0x80 ) > 0); -// -// /* fill in setup packet */ -// setup_pkt.ReqType_u.bmRequestType = bmReqType; -// setup_pkt.bRequest = bRequest; -// setup_pkt.wVal_u.wValueLo = wValLo; -// setup_pkt.wVal_u.wValueHi = wValHi; -// setup_pkt.wIndex = wInd; -// setup_pkt.wLength = total; -// -// bytesWr( rSUDFIFO, 8, (uint8_t*)&setup_pkt ); //transfer to setup packet FIFO -// -// rcode = dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet -// -// if( rcode ) //return HRSLT if not zero -// return( rcode ); -// -// if( dataptr != NULL ) //data stage, if present -// { -// if( direction ) //IN transfer -// { -// uint16_t left = total; -// -// while (left) -// { -// pep->bmRcvToggle = 1; //bmRCVTOG1; -// rcode = InTransfer( pep, nak_limit, nbytes, dataptr ); -// -// // Bytes read into buffer -// uint16_t read = (left < nbytes) ? left : nbytes; -// -// // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified -// if (!rcode && pf) -// pf( read, dataptr, total - left ); -// -// left -= read; -// } -// } -// else //OUT transfer -// { -// pep->bmSndToggle = 1; //bmSNDTOG1; -// rcode = OutTransfer( pep, nak_limit, nbytes, dataptr ); -// } -// if( rcode ) //return error -// return( rcode ); -// } -// // Status stage -// return dispatchPkt( (direction) ? tokOUTHS : tokINHS, ep, nak_limit ); //GET if direction -//} - -uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, UsbReadParser *p) + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) { boolean direction = false; //request direction, IN or OUT uint8_t rcode; @@ -214,17 +143,22 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ { uint16_t left = total; + pep->bmRcvToggle = 1; //bmRCVTOG1; + while (left) { - pep->bmRcvToggle = 1; //bmRCVTOG1; - rcode = InTransfer( pep, nak_limit, nbytes, dataptr ); - // Bytes read into buffer - uint16_t read = (left < nbytes) ? left : nbytes; + uint16_t read = nbytes; + //uint16_t read = (leftParse( read, dataptr, total - left ); + ((USBReadParser*)p)->Parse( read, dataptr, total - left ); left -= read; } @@ -245,7 +179,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ /* Keep sending INs and writes data to memory area pointed by 'data' */ /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, fe USB xfer timeout */ -uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ) +uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) { EpInfo *pep = NULL; uint16_t nak_limit = 0; @@ -255,17 +189,18 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* if (rcode) return rcode; - return InTransfer(pep, nak_limit, nbytes, data); + return InTransfer(pep, nak_limit, nbytesptr, data); } -uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t* data ) +uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { uint8_t rcode; uint8_t pktsize; - uint8_t maxpktsize = pep->maxPktSize; + uint16_t nbytes = *nbytesptr; + uint8_t maxpktsize = pep->maxPktSize; - unsigned int xfrlen = 0; + *nbytesptr = 0; regWr( rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0 ); //set toggle value while( 1 ) // use a 'return' to exit this loop @@ -281,13 +216,20 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, ui return ( 0xf0 ); //receive error } pktsize = regRd( rRCVBC ); //number of received bytes - data = bytesRd( rRCVFIFO, pktsize, data ); + + int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); + + if (mem_left < 0) + mem_left = 0; + + data = bytesRd( rRCVFIFO, (pktsize > mem_left) ? mem_left : pktsize, data ); + regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer - xfrlen += pktsize; // add this packet's byte count to total transfer length + *nbytesptr += pktsize; // add this packet's byte count to total transfer length /* The transfer is complete under two conditions: */ /* 1. The device sent a short packet (L.T. maxPacketSize) */ /* 2. 'nbytes' have been transferred. */ - if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) // have we transferred 'nbytes' bytes? + if (( pktsize < maxpktsize ) || (*nbytesptr >= nbytes )) // have we transferred 'nbytes' bytes? { // Save toggle value pep->bmRcvToggle = ( regRd( rHRSL ) & bmRCVTOGRD ) ? 1 : 0; @@ -301,7 +243,7 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, ui /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */ /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ /* major part of this function borrowed from code shared by Richard Ibbotson */ -uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ) +uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data ) { EpInfo *pep = NULL; uint16_t nak_limit; @@ -314,7 +256,7 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t return OutTransfer(pep, nak_limit, nbytes, data); } -uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t *data) +uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) { uint8_t rcode, retry_count; uint8_t *data_p = data; //local copy of the data pointer @@ -618,4 +560,50 @@ uint8_t USB::ReleaseDevice(uint8_t addr) return devConfig[i]->Release(); } +#if 1 //!defined(USB_METHODS_INLINE) +//get device descriptor +uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) +{ + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL )); +} +//get configuration descriptor +uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr ) +{ + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL )); +} + +uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p ) +{ + const uint8_t bufSize = 64; + uint8_t buf[bufSize]; + + uint8_t ret = getConfDescr( addr, ep, 8, conf, buf ); + + if (ret) + return ret; + + uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength; + + USBTRACE2("total:", total); + + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p )); +} + +//get string descriptor +uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr ) +{ + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL )); +} +//set address +uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr ) +{ + return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL )); +} +//set configuration +uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ) +{ + return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL )); +} + +#endif // defined(USB_METHODS_INLINE) diff --git a/Usb.h b/Usb.h index 2c762179..0f054621 100644 --- a/Usb.h +++ b/Usb.h @@ -12,23 +12,23 @@ #include "address.h" #include +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#define USBTRACE(s) (Serial.print((s))) +#define USBTRACE2(s,r) (Serial.print((s)), Serial.println((r),HEX)) + + /* Common setup data constant combinations */ #define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type #define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type -/* HID requests */ -#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE - - - // D7 data transfer direction (0 - host-to-device, 1 - device-to-host) // D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved) // D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved) - // USB Device Classes #define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors #define USB_CLASS_AUDIO 0x01 // Audio @@ -114,28 +114,28 @@ typedef struct { }ReqType_u; uint8_t bRequest; // 1 Request union { - unsigned int wValue; // 2 Depends on bRequest + uint16_t wValue; // 2 Depends on bRequest struct { uint8_t wValueLo; uint8_t wValueHi; }; }wVal_u; - unsigned int wIndex; // 4 Depends on bRequest - unsigned int wLength; // 6 Depends on bRequest + uint16_t wIndex; // 4 Depends on bRequest + uint16_t wLength; // 6 Depends on bRequest } SETUP_PKT, *PSETUP_PKT; // Base class for incomming data parser -class UsbReadParser +class USBReadParser { public: - virtual void Parse(const uint8_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; }; -//typedef MAX3421e MAX3421E; // Black Widdow -typedef MAX3421e MAX3421E; // Duemielanove +typedef MAX3421e MAX3421E; // Black Widdow +//typedef MAX3421e MAX3421E; // Duemielanove class USB : public MAX3421E { @@ -176,22 +176,22 @@ class USB : public MAX3421E EpInfo* getEpInfoEntry( uint8_t addr, uint8_t ep ); uint8_t setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr ); - uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, unsigned int wInd, unsigned int nbytes, uint8_t* dataptr); + //uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t nbytes, uint8_t* dataptr); /* Control requests */ - uint8_t getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ); - uint8_t getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr ); - uint8_t getStrDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t index, unsigned int langid, uint8_t* dataptr ); + uint8_t getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ); + uint8_t getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr ); + + uint8_t getConfDescr( uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p ); + + uint8_t getStrDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr ); uint8_t setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr ); uint8_t setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ); /**/ - uint8_t setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol ); - uint8_t getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr ); - /**/ - uint8_t ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction ); + uint8_t ctrlData( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, boolean direction ); uint8_t ctrlStatus( uint8_t ep, boolean direction, uint16_t nak_limit ); - uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ); - uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ); + uint8_t inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data ); + uint8_t outTransfer( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data ); uint8_t dispatchPkt( uint8_t token, uint8_t ep, uint16_t nak_limit ); void Task( void ); @@ -200,34 +200,29 @@ class USB : public MAX3421E uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed); uint8_t ReleaseDevice(uint8_t addr); - //typedef void (*USBREADCALLBACK)(uint16_t nbytes, uint8_t *data, uint16_t offset); - - //uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - // uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBREADCALLBACK pf); - uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, UsbReadParser *p); + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p); private: void init(); uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit); - uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t *data); - uint8_t InTransfer (EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t* data); + uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); + uint8_t InTransfer (EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data); }; -//#if defined(USB_METHODS_INLINE) +#if 0 //defined(USB_METHODS_INLINE) //get device descriptor -inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ) +inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) { return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr )); } //get configuration descriptor -inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr ) +inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr ) { return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr )); } //get string descriptor -inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t index, unsigned int langid, uint8_t* dataptr ) +inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr ) { return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr )); } @@ -241,16 +236,7 @@ inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ) { return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL )); } -//class requests -inline uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol ) -{ - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL )); -} -inline uint8_t USB::getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr ) -{ - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr )); -} -//#endif // defined(USB_METHODS_INLINE) +#endif // defined(USB_METHODS_INLINE) #endif //_usb_h_ \ No newline at end of file diff --git a/cdcacm.cpp b/cdcacm.cpp new file mode 100644 index 00000000..b911dda2 --- /dev/null +++ b/cdcacm.cpp @@ -0,0 +1,330 @@ +#include "cdcacm.h" + +const uint8_t ACM::epDataInIndex = 1; +const uint8_t ACM::epDataOutIndex = 2; +const uint8_t ACM::epInterruptInIndex = 3; + +ACM::ACM(USB *p, CDCAsyncOper *pasync) : + pUsb(p), + pAsync(pasync), + bAddress(0), + qNextPollTime(0), + bPollEnable(false), + bControlIface(0), + bDataIface(0), + bNumEP(1) +{ + for(uint8_t i=0; iRegisterDeviceClass(this); +} + +uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) +{ + const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("ACM Init\r\n"); + + 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) + { + USBTRACE("epinfo\r\n"); + 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, constBufSize, (uint8_t*)buf ); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if( rcode ) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i CdcControlParser(this); + + ConfigDescParser CdcDataParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 4) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConf; + + rcode = pAsync->OnInit(this); + + if (rcode) + goto FailOnInit; + + USBTRACE("ACM configured\r\n"); + + //bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConf: + USBTRACE("setConf:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + + +void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) +{ + ErrorMessage(PSTR("Conf.Val"), conf); + ErrorMessage(PSTR("Iface Num"),iface); + ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP ++; + + PrintEndpointDescriptor(pep); +} + +uint8_t ACM::Release() +{ + pUsb->GetAddressPool().FreeAddress(bAddress); + + bControlIface = 0; + bDataIface = 0; + bNumEP = 1; + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t ACM::Poll() +{ + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + uint32_t time_now = millis(); + + if (qNextPollTime <= time_now) + { + qNextPollTime = time_now + 100; + + uint8_t rcode; + const uint8_t constBufSize = 16; + uint8_t buf[constBufSize]; + + for (uint8_t i=0; iinTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); + + if (rcode) + return rcode; + + for (uint8_t i=0; i(buf[i]); + Serial.print(" "); + } + USBTRACE("\r\n"); + } + return rcode; +} + +uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) +{ + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) +{ + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL )); +} + +uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL )); +} + +uint8_t ACM::ClearCommFeature(uint16_t fid) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL )); +} + +uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof(LINE_CODING), sizeof(LINE_CODING), (uint8_t*)dataptr, NULL )); +} + +uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof(LINE_CODING), sizeof(LINE_CODING), (uint8_t*)dataptr, NULL )); +} + +uint8_t ACM::SetControlLineState(uint8_t state) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL )); +} + +uint8_t ACM::SendBreak(uint16_t duration) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL )); +} + + +void ACM::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) +{ + Notify(PSTR("Endpoint descriptor:")); + Notify(PSTR("\r\nLength:\t\t")); + PrintHex(ep_ptr->bLength); + Notify(PSTR("\r\nType:\t\t")); + PrintHex(ep_ptr->bDescriptorType); + Notify(PSTR("\r\nAddress:\t")); + PrintHex(ep_ptr->bEndpointAddress); + Notify(PSTR("\r\nAttributes:\t")); + PrintHex(ep_ptr->bmAttributes); + Notify(PSTR("\r\nMaxPktSize:\t")); + PrintHex(ep_ptr->wMaxPacketSize); + Notify(PSTR("\r\nPoll Intrv:\t")); + PrintHex(ep_ptr->bInterval); + Notify(PSTR("\r\n")); +} diff --git a/cdcacm.h b/cdcacm.h new file mode 100644 index 00000000..fc63b587 --- /dev/null +++ b/cdcacm.h @@ -0,0 +1,166 @@ +#if !defined(__CDCACM_H__) +#define __CDCACM_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" + +#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +// CDC Subclass Constants +#define CDC_SUBCLASS_DLCM 0x01 // Direct Line Control Model +#define CDC_SUBCLASS_ACM 0x02 // Abstract Control Model +#define CDC_SUBCLASS_TCM 0x03 // Telephone Control Model +#define CDC_SUBCLASS_MCCM 0x04 // Multi Channel Control Model +#define CDC_SUBCLASS_CAPI 0x05 // CAPI Control Model +#define CDC_SUBCLASS_ETHERNET 0x06 // Ethernet Network Control Model +#define CDC_SUBCLASS_ATM 0x07 // ATM Network Control Model +#define CDC_SUBCLASS_WIRELESS_HANDSET 0x08 // Wireless Handset Control Model +#define CDC_SUBCLASS_DEVICE_MANAGEMENT 0x09 // Device Management +#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A // Mobile Direct Line Model +#define CDC_SUBCLASS_OBEX 0x0B // OBEX +#define CDC_SUBCLASS_ETHERNET_EMU 0x0C // Ethernet Emulation Model + +// Communication Interface Class Control Protocol Codes +#define CDC_PROTOCOL_ITU_T_V_250 0x01 // AT Commands defined by ITU-T V.250 +#define CDC_PROTOCOL_PCCA_101 0x02 // AT Commands defined by PCCA-101 +#define CDC_PROTOCOL_PCCA_101_O 0x03 // AT Commands defined by PCCA-101 & Annex O +#define CDC_PROTOCOL_GSM_7_07 0x04 // AT Commands defined by GSM 7.07 +#define CDC_PROTOCOL_3GPP_27_07 0x05 // AT Commands defined by 3GPP 27.007 +#define CDC_PROTOCOL_C_S0017_0 0x06 // AT Commands defined by TIA for CDMA +#define CDC_PROTOCOL_USB_EEM 0x07 // Ethernet Emulation Model + +// CDC Commands defined by CDC 1.2 +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 + +// CDC Commands defined by PSTN 1.2 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_AUX_LINE_STATE 0x10 +#define CDC_SET_HOOK_STATE 0x11 +#define CDC_PULSE_SETUP 0x12 +#define CDC_SEND_PULSE 0x13 +#define CDC_SET_PULSE_TIME 0x14 +#define CDC_RING_AUX_JACK 0x15 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 +#define CDC_SET_RINGER_PARMS 0x30 +#define CDC_GET_RINGER_PARMS 0x31 +#define CDC_SET_OPERATION_PARMS 0x32 +#define CDC_GET_OPERATION_PARMS 0x33 +#define CDC_SET_LINE_PARMS 0x34 +#define CDC_GET_LINE_PARMS 0x35 +#define CDC_DIAL_DIGITS 0x36 + +// CDC Functional Descriptor Structures +typedef struct +{ + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} CALL_MGMNT_FUNC_DESCR; + +typedef struct +{ + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR, + TEL_CALL_STATE_REP_CPBL_FUNC_DESCR; + +typedef struct +{ + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bRingerVolSteps; + uint8_t bNumRingerPatterns; +} TEL_RINGER_FUNC_DESCR; + +typedef struct +{ + uint32_t dwDTERate; // Data Terminal Rate in bits per second + uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits + uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space + uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16) +} LINE_CODING; + +class ACM; + +class CDCAsyncOper +{ +public: + virtual uint8_t OnInit(ACM *pacm) = 0; + //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; + //virtual void OnDisconnected(ACM *pacm) = 0; +}; + + +#define ACM_MAX_ENDPOINTS 4 + +class ACM : public USBDeviceConfig, public UsbConfigXtracter +{ +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + CDCAsyncOper *pAsync; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bControlIface; // Control interface value + uint8_t bDataIface; // Data interface value + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + EpInfo epInfo[ACM_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + ACM(USB *pusb, CDCAsyncOper *pasync); + + uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t ClearCommFeature(uint16_t fid); + uint8_t SetLineCoding(const LINE_CODING *dataptr); + uint8_t GetLineCoding(LINE_CODING *dataptr); + uint8_t SetControlLineState(uint8_t state); + uint8_t SendBreak(uint16_t duration); + + // Methods for recieving and sending data + uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __CDCACM_H__ \ No newline at end of file diff --git a/cdcftdi.cpp b/cdcftdi.cpp new file mode 100644 index 00000000..76076f89 --- /dev/null +++ b/cdcftdi.cpp @@ -0,0 +1,330 @@ +#include "cdcftdi.h" + +const uint8_t FTDI::epDataInIndex = 1; +const uint8_t FTDI::epDataOutIndex = 2; +const uint8_t FTDI::epInterruptInIndex = 3; + +FTDI::FTDI(USB *p) : + pUsb(p), + bAddress(0), + wFTDIType(0) +{ + for(uint8_t i=0; iRegisterDeviceClass(this); +} + +uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) +{ + const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + uint16_t cd_len = 0; + + uint8_t num_of_conf; // number of configurations + uint8_t num_of_intf; // number of interfaces + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("FTDI Init\r\n"); + + 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) + { + USBTRACE("epinfo\r\n"); + 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, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf ); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if( rcode ) + goto FailGetDevDescr; + + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != FTDI_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of FTDI chip + wFTDIType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i HexDump; + ConfigDescParser<0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + rcode = SetBaudRate(115200); + + if (rcode) + goto FailSetBaudRate; + + rcode = SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL); + //rcode = SetFlowControl(FTDI_SIO_SET_DTR_HIGH); + + if (rcode) + goto FailSetFlowControl; + + + USBTRACE("FTDI configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailSetBaudRate: + USBTRACE("SetBaudRate:"); + goto Fail; + +FailSetFlowControl: + USBTRACE("SetFlowControl:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + + +void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) +{ + ErrorMessage(PSTR("Conf.Val"), conf); + ErrorMessage(PSTR("Iface Num"),iface); + ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP ++; + + PrintEndpointDescriptor(pep); +} + +uint8_t FTDI::Release() +{ + pUsb->GetAddressPool().FreeAddress(bAddress); + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t FTDI::Poll() +{ + uint8_t rcode = 0; + + //if (!bPollEnable) + // return 0; + + //if (qNextPollTime <= millis()) + //{ + // Serial.println(bAddress, HEX); + + // qNextPollTime = millis() + 100; + //} + return rcode; +} + +uint8_t FTDI::SetBaudRate(uint32_t baud) +{ + uint16_t baud_value, baud_index = 0; + uint32_t divisor3; + + divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left + + if (wFTDIType == FT232AM) + { + if ((divisor3 & 0x7) == 7) + divisor3 ++; // round x.7/8 up to x+1 + + baud_value = divisor3 >> 3; + divisor3 &= 0x7; + + if (divisor3 == 1) baud_value |= 0xc000; else // 0.125 + if (divisor3 >= 4) baud_value |= 0x4000; else // 0.5 + if (divisor3 != 0) baud_value |= 0x8000; // 0.25 + if (baud_value == 1) baud_value = 0; /* special case for maximum baud rate */ + } + else + { + static const unsigned char divfrac [8] = { 0, 3, 2, 0, 1, 1, 2, 3 }; + static const unsigned char divindex[8] = { 0, 0, 0, 1, 0, 1, 1, 1 }; + + baud_value = divisor3 >> 3; + baud_value |= divfrac [divisor3 & 0x7] << 14; + baud_index = divindex[divisor3 & 0x7]; + + /* Deal with special cases for highest baud rates. */ + if (baud_value == 1) baud_value = 0; else // 1.0 + if (baud_value == 0x4001) baud_value = 1; // 1.5 + } + USBTRACE2("baud_value:", baud_value); + USBTRACE2("baud_index:", baud_index); + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL ); +} + +uint8_t FTDI::SetModemControl(uint16_t signal) +{ + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL); +} + +uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) +{ + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL); +} + +uint8_t FTDI::SetData(uint16_t databm) +{ + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL); +} + +uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) +{ + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) +{ + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +void FTDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) +{ + Notify(PSTR("Endpoint descriptor:")); + Notify(PSTR("\r\nLength:\t\t")); + PrintHex(ep_ptr->bLength); + Notify(PSTR("\r\nType:\t\t")); + PrintHex(ep_ptr->bDescriptorType); + Notify(PSTR("\r\nAddress:\t")); + PrintHex(ep_ptr->bEndpointAddress); + Notify(PSTR("\r\nAttributes:\t")); + PrintHex(ep_ptr->bmAttributes); + Notify(PSTR("\r\nMaxPktSize:\t")); + PrintHex(ep_ptr->wMaxPacketSize); + Notify(PSTR("\r\nPoll Intrv:\t")); + PrintHex(ep_ptr->bInterval); + Notify(PSTR("\r\n")); +} diff --git a/cdcftdi.h b/cdcftdi.h new file mode 100644 index 00000000..0bb81792 --- /dev/null +++ b/cdcftdi.h @@ -0,0 +1,119 @@ +#if !defined(__CDCFTDI_H__) +#define __CDCFTDI_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" + +#define bmREQ_FTDI_OUT 0x40 +#define bmREQ_FTDI_IN 0xc0 + +//#define bmREQ_FTDI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +//#define bmREQ_FTDI_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +#define FTDI_VID 0x0403 // FTDI VID +#define FTDI_PID 0x6001 // FTDI PID + +#define FT232AM 0x0200 +#define FT232BM 0x0400 +#define FT2232 0x0500 +#define FT232R 0x0600 + +// Commands +#define FTDI_SIO_RESET 0 /* Reset the port */ +#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ +#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ +#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ +#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ +#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ +#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ +#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ + +#define FTDI_SIO_RESET_SIO 0 +#define FTDI_SIO_RESET_PURGE_RX 1 +#define FTDI_SIO_RESET_PURGE_TX 2 + +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 ) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) + +#define FTDI_SIO_SET_DTR_MASK 0x1 +#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_RTS_MASK 0x2 +#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) +#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) + +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) +#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) +#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) + +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 + +// Only single port chips are currently supported by the library, +// so only three endpoints are allocated. +#define FTDI_MAX_ENDPOINTS 3 + +class FTDI : public USBDeviceConfig, public UsbConfigXtracter +{ + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + uint16_t wFTDIType; // Type of FTDI chip + + EpInfo epInfo[FTDI_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + FTDI(USB *pusb); + + uint8_t SetBaudRate(uint32_t baud); + uint8_t SetModemControl(uint16_t control); + uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13); + uint8_t SetData(uint16_t databm); + + // Methods for recieving and sending data + uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __CDCFTDI_H__ \ No newline at end of file diff --git a/cdcprolific.cpp b/cdcprolific.cpp new file mode 100644 index 00000000..3d0fd4c7 --- /dev/null +++ b/cdcprolific.cpp @@ -0,0 +1,189 @@ +#include "cdcprolific.h" + +PL::PL(USB *p, CDCAsyncOper *pasync) : + ACM(p, pasync), + wPLType(0) +{ +} + +uint8_t PL::Init(uint8_t parent, uint8_t port, bool lowspeed) +{ + const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("PL Init\r\n"); + + 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) + { + USBTRACE("epinfo\r\n"); + 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, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf ); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if( rcode ) + goto FailGetDevDescr; + + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of PL chip + wPLType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i HexDump; + ConfigDescParser<0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + rcode = pAsync->OnInit(this); + + if (rcode) + goto FailOnInit; + + USBTRACE("PL configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailSetControlLineState: + USBTRACE("SetControlLineState:"); + goto Fail; + +FailSetLineCoding: + USBTRACE("SetLineCoding:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + +//uint8_t PL::Poll() +//{ +// uint8_t rcode = 0; +// +// //if (!bPollEnable) +// // return 0; +// +// //if (qNextPollTime <= millis()) +// //{ +// // Serial.println(bAddress, HEX); +// +// // qNextPollTime = millis() + 100; +// //} +// return rcode; +//} + + diff --git a/cdcprolific.h b/cdcprolific.h new file mode 100644 index 00000000..c2a7bfd0 --- /dev/null +++ b/cdcprolific.h @@ -0,0 +1,134 @@ +#if !defined(__CDCPROLIFIC_H__) +#define __CDCPROLIFIC_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" +#include "cdcacm.h" + +#define PL_VID 0x067B +#define PL_PID 0x2303 + +#define PROLIFIC_REV_H 0x0202 +#define PROLIFIC_REV_X 0x0300 +#define PROLIFIC_REV_HX_CHIP_D 0x0400 +#define PROLIFIC_REV_1 0x0001 + +#define kXOnChar '\x11' +#define kXOffChar '\x13' + +#define SPECIAL_SHIFT (5) +#define SPECIAL_MASK ((1< +#include "..\ParseTools\parsetools.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, uint8_t iface, uint8_t alt, uint8_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 + +// Configuration Descriptor Parser Class Template +template +class ConfigDescParser : public USBReadParser +{ + UsbConfigXtracter *theXtractor; + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[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 ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); + +public: + ConfigDescParser(UsbConfigXtracter *xtractor); + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); +}; + +template +ConfigDescParser::ConfigDescParser(UsbConfigXtracter *xtractor) : + stateParseDescr(0), + dscrLen(0), + dscrType(0), + theXtractor(xtractor) +{ + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); +}; + +template +void ConfigDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) +{ + uint16_t cntdn = (uint16_t)len; + uint8_t *p = (uint8_t*)pbuf; + + while(cntdn) + if (!ParseDescriptor(&p, &cntdn)) + return; +} + +template +bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint16_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 allready 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; + } + 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; + default: + if (!theSkipper.Skip(pp, pcntdn, dscrLen-2)) + return false; + } + theBuffer.pValue = varBuffer; + stateParseDescr = 0; + } + return true; +} + +#endif // __CONFDESCPARSER_H__ \ No newline at end of file diff --git a/max_LCD.h b/max_LCD.h index e746b6d3..718162c3 100644 --- a/max_LCD.h +++ b/max_LCD.h @@ -49,7 +49,7 @@ #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 -class Max_LCD : public Print +class Max_LCD //: public Print { USB *pUsb; @@ -85,7 +85,4 @@ private: uint8_t _numlines,_currline; }; - - - #endif \ No newline at end of file diff --git a/usb_ch9.h b/usb_ch9.h index 33bc2f61..150a077b 100644 --- a/usb_ch9.h +++ b/usb_ch9.h @@ -70,51 +70,24 @@ #define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient #define USB_FEATURE_TEST_MODE 2 // Device recipient -/* HID constants. Not part of chapter 9 */ -/* Class-Specific Requests */ -#define HID_REQUEST_GET_REPORT 0x01 -#define HID_REQUEST_GET_IDLE 0x02 -#define HID_REQUEST_GET_PROTOCOL 0x03 -#define HID_REQUEST_SET_REPORT 0x09 -#define HID_REQUEST_SET_IDLE 0x0A -#define HID_REQUEST_SET_PROTOCOL 0x0B - -/* Class Descriptor Types */ -#define HID_DESCRIPTOR_HID 0x21 -#define HID_DESCRIPTOR_REPORT 0x22 -#define HID_DESRIPTOR_PHY 0x23 - -/* Protocol Selection */ -#define BOOT_PROTOCOL 0x00 -#define RPT_PROTOCOL 0x01 -/* HID Interface Class Code */ -#define HID_INTF 0x03 -/* HID Interface Class SubClass Codes */ -#define BOOT_INTF_SUBCLASS 0x01 -/* HID Interface Class Protocol Codes */ -#define HID_PROTOCOL_NONE 0x00 -#define HID_PROTOCOL_KEYBOARD 0x01 -#define HID_PROTOCOL_MOUSE 0x02 - - /* descriptor data structures */ /* Device descriptor structure */ typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). - uint16_t bcdUSB; // USB Spec Release Number (BCD). - uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). - uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. - uint16_t idVendor; // Vendor ID (assigned by the USB-IF). - uint16_t idProduct; // Product ID (assigned by the manufacturer). - uint16_t bcdDevice; // Device release number (BCD). - uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. - uint8_t iProduct; // Index of String Descriptor describing the product. - uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. - uint8_t bNumConfigurations; // Number of possible configurations. + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + uint8_t iProduct; // Index of String Descriptor describing the product. + uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. + uint8_t bNumConfigurations; // Number of possible configurations. } USB_DEVICE_DESCRIPTOR; /* Configuration descriptor structure */ @@ -155,15 +128,4 @@ typedef struct uint8_t bInterval; // Polling interval in frames. } USB_ENDPOINT_DESCRIPTOR; -/* HID descriptor */ -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bDescrType; - uint16_t wDescriptorLength; -} USB_HID_DESCRIPTOR; - #endif // _ch9_h_ diff --git a/usbhub.cpp b/usbhub.cpp index 64efaafc..405d2ffb 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -55,7 +55,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence p->epinfo = epInfo; - p->lowspeed = lowspeed; + p->lowspeed = lowspeed; // Get device descriptor rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); @@ -225,8 +225,9 @@ uint8_t USBHub::CheckHubStatus() { uint8_t rcode; uint8_t buf[8]; + uint16_t read = 1; - rcode = pUsb->inTransfer(bAddress, 1, 1, buf); + rcode = pUsb->inTransfer(bAddress, 1, &read, buf); if (rcode) return rcode; diff --git a/usbhub.h b/usbhub.h index cb03f228..7a113883 100644 --- a/usbhub.h +++ b/usbhub.h @@ -10,6 +10,8 @@ #include "Usb.h" #include +#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 @@ -90,16 +92,16 @@ // 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 +#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 +#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) @@ -153,7 +155,6 @@ struct HubEvent }; }; - class USBHub : USBDeviceConfig { static bool bResetInitiated; // True when reset is triggered @@ -194,42 +195,42 @@ public: // 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, NULL )); + 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, NULL )); + 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, 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, 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, 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, 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, NULL )); + 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, NULL )); + 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); From b30f62d931e1855f91d379def8d82abdf3de22cd Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Fri, 20 May 2011 21:39:35 -0600 Subject: [PATCH 2/6] minor --- README | 2 +- Usb.h | 4 ++-- cdcacm.cpp | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README b/README index 7328e500..9424dafe 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ This is Rev.2.0 of MAX3421E-based USB Host Library for Arduino. At the moment, this repo contains current development copy -of the code facilitating developer's exchange. For those not involved in the project, the code in its' current state doesn't bear any value. +of the code facilitating developer's exchange. For those not involved in the project, the code in its current state doesn't bear any value. In other words, nothing works yet. The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects \ No newline at end of file diff --git a/Usb.h b/Usb.h index 0f054621..95854700 100644 --- a/Usb.h +++ b/Usb.h @@ -134,8 +134,8 @@ public: }; -typedef MAX3421e MAX3421E; // Black Widdow -//typedef MAX3421e MAX3421E; // Duemielanove +//typedef MAX3421e MAX3421E; // Black Widdow +typedef MAX3421e MAX3421E; // Duemielanove class USB : public MAX3421E { diff --git a/cdcacm.cpp b/cdcacm.cpp index b911dda2..c0c254da 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -249,7 +249,8 @@ uint8_t ACM::Poll() for (uint8_t i=0; i epInfo[epInterruptInIndex].maxPktSize) + ? epInfo[epInterruptInIndex].maxPktSize : constBufSize; rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); if (rcode) From cf1611cb483c6e87baa811578c58d66b0fb6894c Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Sun, 5 Jun 2011 21:22:39 -0600 Subject: [PATCH 3/6] FTDI fixed --- README | 2 +- Usb.cpp | 8 +- Usb.h | 6 +- cdcacm.cpp | 40 +- cdcftdi.cpp | 22 +- cdcftdi.h | 30 +- confdescparser.h | 62 +- hid.cpp | 1879 ++++++++++++++++++++++++++++++++++++++++++++++ hid.h | 1180 +++++++++++++++++++++++++++++ masstorage.h | 97 +++ usb_ch9.h | 23 + 11 files changed, 3298 insertions(+), 51 deletions(-) create mode 100644 hid.cpp create mode 100644 hid.h create mode 100644 masstorage.h diff --git a/README b/README index 9424dafe..7328e500 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ This is Rev.2.0 of MAX3421E-based USB Host Library for Arduino. At the moment, this repo contains current development copy -of the code facilitating developer's exchange. For those not involved in the project, the code in its current state doesn't bear any value. +of the code facilitating developer's exchange. For those not involved in the project, the code in its' current state doesn't bear any value. In other words, nothing works yet. The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects \ No newline at end of file diff --git a/Usb.cpp b/Usb.cpp index 6da62e4b..6cc60fe3 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -153,7 +153,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ rcode = InTransfer( pep, nak_limit, &read, dataptr ); - if (rcode) + if (rcode /*&& rcode != hrSTALL*/) return rcode; // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified @@ -194,7 +194,7 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { - uint8_t rcode; + uint8_t rcode = 0; uint8_t pktsize; uint16_t nbytes = *nbytesptr; @@ -212,9 +212,9 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui /* check for RCVDAVIRQ and generate error if not present */ /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ - if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) { + if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) return ( 0xf0 ); //receive error - } + pktsize = regRd( rRCVBC ); //number of received bytes int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); diff --git a/Usb.h b/Usb.h index 95854700..a584f1ba 100644 --- a/Usb.h +++ b/Usb.h @@ -67,9 +67,9 @@ class USBDeviceConfig { public: virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0; - virtual uint8_t Release() = 0; - virtual uint8_t Poll() = 0; - virtual uint8_t GetAddress() = 0; + virtual uint8_t Release() = 0; + virtual uint8_t Poll() = 0; + virtual uint8_t GetAddress() = 0; }; #define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec diff --git a/cdcacm.cpp b/cdcacm.cpp index c0c254da..8bef335d 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -238,31 +238,31 @@ uint8_t ACM::Poll() uint32_t time_now = millis(); - if (qNextPollTime <= time_now) - { - qNextPollTime = time_now + 100; + //if (qNextPollTime <= time_now) + //{ + // qNextPollTime = time_now + 100; - uint8_t rcode; - const uint8_t constBufSize = 16; - uint8_t buf[constBufSize]; + // uint8_t rcode; + // const uint8_t constBufSize = 16; + // uint8_t buf[constBufSize]; - for (uint8_t i=0; i epInfo[epInterruptInIndex].maxPktSize) - ? epInfo[epInterruptInIndex].maxPktSize : constBufSize; - rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); + // uint16_t read = (constBufSize > epInfo[epInterruptInIndex].maxPktSize) + // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize; + // rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); - if (rcode) - return rcode; + // if (rcode) + // return rcode; - for (uint8_t i=0; i(buf[i]); - Serial.print(" "); - } - USBTRACE("\r\n"); - } + // for (uint8_t i=0; i(buf[i]); + // Serial.print(" "); + // } + // USBTRACE("\r\n"); + //} return rcode; } diff --git a/cdcftdi.cpp b/cdcftdi.cpp index 76076f89..10386262 100644 --- a/cdcftdi.cpp +++ b/cdcftdi.cpp @@ -4,9 +4,11 @@ const uint8_t FTDI::epDataInIndex = 1; const uint8_t FTDI::epDataOutIndex = 2; const uint8_t FTDI::epInterruptInIndex = 3; -FTDI::FTDI(USB *p) : +FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) : + pAsync(pasync), pUsb(p), bAddress(0), + bNumEP(1), wFTDIType(0) { for(uint8_t i=0; isetEpInfoEntry(bAddress, bNumEP, epInfo); @@ -146,17 +150,10 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) if (rcode) goto FailSetConfDescr; - rcode = SetBaudRate(115200); + rcode = pAsync->OnInit(this); if (rcode) - goto FailSetBaudRate; - - rcode = SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL); - //rcode = SetFlowControl(FTDI_SIO_SET_DTR_HIGH); - - if (rcode) - goto FailSetFlowControl; - + goto FailOnInit; USBTRACE("FTDI configured\r\n"); @@ -187,6 +184,10 @@ FailSetFlowControl: USBTRACE("SetFlowControl:"); goto Fail; +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + Fail: Serial.println(rcode, HEX); Release(); @@ -227,6 +228,7 @@ uint8_t FTDI::Release() pUsb->GetAddressPool().FreeAddress(bAddress); bAddress = 0; + bNumEP = 1; qNextPollTime = 0; bPollEnable = false; return 0; diff --git a/cdcftdi.h b/cdcftdi.h index 0bb81792..7ebea5f7 100644 --- a/cdcftdi.h +++ b/cdcftdi.h @@ -71,6 +71,15 @@ #define FTDI_SIO_RI_MASK 0x40 #define FTDI_SIO_RLSD_MASK 0x80 +class FTDI; + +class FTDIAsyncOper +{ +public: + virtual uint8_t OnInit(FTDI *pftdi) = 0; +}; + + // Only single port chips are currently supported by the library, // so only three endpoints are allocated. #define FTDI_MAX_ENDPOINTS 3 @@ -81,21 +90,22 @@ class FTDI : public USBDeviceConfig, public UsbConfigXtracter static const uint8_t epDataOutIndex; // DataOUT endpoint index static const uint8_t epInterruptInIndex; // InterruptIN endpoint index - USB *pUsb; - uint8_t bAddress; - uint8_t bConfNum; // configuration number - uint8_t bNumIface; // number of interfaces in the configuration - uint8_t bNumEP; // total number of EP in the configuration - uint32_t qNextPollTime; // next poll time - bool bPollEnable; // poll enable flag - uint16_t wFTDIType; // Type of FTDI chip + FTDIAsyncOper *pAsync; + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + uint16_t wFTDIType; // Type of FTDI chip - EpInfo epInfo[FTDI_MAX_ENDPOINTS]; + EpInfo epInfo[FTDI_MAX_ENDPOINTS]; void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); public: - FTDI(USB *pusb); + FTDI(USB *pusb, FTDIAsyncOper *pasync); uint8_t SetBaudRate(uint32_t baud); uint8_t SetModemControl(uint16_t control); diff --git a/confdescparser.h b/confdescparser.h index 4d4dba76..a17a6dac 100644 --- a/confdescparser.h +++ b/confdescparser.h @@ -4,6 +4,13 @@ #include #include "..\ParseTools\parsetools.h" +#include +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +//#include "hid.h" + class UsbConfigXtracter { public: @@ -25,7 +32,7 @@ class ConfigDescParser : public USBReadParser MultiValueBuffer theBuffer; MultiByteValueParser valParser; ByteSkipper theSkipper; - uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; + uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; uint8_t stateParseDescr; // ParseDescriptor state @@ -40,6 +47,8 @@ class ConfigDescParser : public USBReadParser bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + public: ConfigDescParser(UsbConfigXtracter *xtractor); virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); @@ -97,10 +106,13 @@ bool ConfigDescParser::ParseDescriptor case USB_DESCRIPTOR_INTERFACE: isGoodInterface = false; case USB_DESCRIPTOR_CONFIGURATION: - theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR)-2; + theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2; break; case USB_DESCRIPTOR_ENDPOINT: - theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR)-2; + theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2; + break; + case HID_DESCRIPTOR_HID: + theBuffer.valueSize = dscrLen - 2; break; } valParser.Initialize(&theBuffer); @@ -135,6 +147,11 @@ bool ConfigDescParser::ParseDescriptor 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; @@ -145,4 +162,43 @@ bool ConfigDescParser::ParseDescriptor return true; } +template +void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) +{ + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n")); + Notify(PSTR("bDescLength:\t\t")); + PrintHex(pDesc->bLength); + + Notify(PSTR("\r\nbDescriptorType:\t")); + PrintHex(pDesc->bDescriptorType); + + Notify(PSTR("\r\nbcdHID:\t\t\t")); + PrintHex(pDesc->bcdHID); + + Notify(PSTR("\r\nbCountryCode:\t\t")); + PrintHex(pDesc->bCountryCode); + + Notify(PSTR("\r\nbNumDescriptors:\t")); + PrintHex(pDesc->bNumDescriptors); + + //Notify(PSTR("\r\nbDescrType:\t\t")); + //PrintHex(pDesc->bDescrType); + // + //Notify(PSTR("\r\nwDescriptorLength:\t")); + //PrintHex(pDesc->wDescriptorLength); + + for (uint8_t i=0; ibNumDescriptors; i++) + { + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); + + Notify(PSTR("\r\nbDescrType:\t\t")); + PrintHex(pLT[i].bDescrType); + + Notify(PSTR("\r\nwDescriptorLength:\t")); + PrintHex(pLT[i].wDescriptorLength); + } + Notify(PSTR("\r\n")); +} + + #endif // __CONFDESCPARSER_H__ \ No newline at end of file diff --git a/hid.cpp b/hid.cpp new file mode 100644 index 00000000..5b756453 --- /dev/null +++ b/hid.cpp @@ -0,0 +1,1879 @@ +#include "hid.h" + +//const uint16_t HID::maxHidInterfaces = 3; +//const uint16_t HID::maxEpPerInterface = 2; +const uint8_t HID::epInterruptInIndex = 0; +const uint8_t HID::epInterruptOutIndex = 1; + +HID::HID(USB *p) : + pUsb(p), + bAddress(0), + qNextPollTime(0), + bPollEnable(false) +{ + Initialize(); + + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +uint16_t HID::GetHidClassDescrLen(uint8_t type, uint8_t num) +{ + for (uint8_t i=0, n=0; iGetAddressPool(); + + USBTRACE("HID Init\r\n"); + + 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) + { + USBTRACE("epinfo\r\n"); + 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 ); + + if (!rcode) + len = (buf[0] > constBufSize) ? constBufSize : buf[0]; + + if( rcode ) + { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + goto FailGetDevDescr; + } + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + if (len) + rcode = pUsb->getDevDescr( bAddress, 0, len, (uint8_t*)buf ); + + if(rcode) + goto FailGetDevDescr; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i HexDump; + ConfigDescParser confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("\r\nCnf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + USBTRACE("HID configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + +HID::HIDInterface* HID::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) +{ + for (uint8_t i=0; i 1 && conf != bConfNum) + return; + + ErrorMessage(PSTR("\r\nConf.Val"), conf); + ErrorMessage(PSTR("Iface Num"), iface); + ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + HIDInterface *piface = FindInterface(iface, alt, proto); + + // Fill in interface structure in case of new interface + if (!piface) + { + piface = hidInterfaces + bNumIface; + piface->bmInterface = iface; + piface->bmAltSet = alt; + piface->bmProtocol = proto; + bNumIface ++; + } + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + index = epInterruptOutIndex; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + // Fill in the endpoint index list + piface->epIndex[index] = (pep->bEndpointAddress & 0x0F); + + bNumEP ++; + + PrintEndpointDescriptor(pep); +} + + +uint8_t HID::Release() +{ + pUsb->GetAddressPool().FreeAddress(bAddress); + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t HID::Poll() +{ + uint8_t rcode = 0; + + //if (!bPollEnable) + // return 0; + + //if (qNextPollTime <= millis()) + //{ + // Serial.println(bAddress, HEX); + + // qNextPollTime = millis() + 100; + //} + return rcode; +} + +//get HID report descriptor +uint8_t HID::getReportDescr( uint8_t ep, USBReadParser *parser ) +{ + const uint8_t constBufLen = 64; + uint8_t buf[constBufLen]; + + //HexDumper HexDump; + + //return( pUsb->ctrlReq( bAddress, ep, /*bmREQ_HIDREPORT*/0x81, USB_REQUEST_GET_DESCRIPTOR, 0x00, + // HID_DESCRIPTOR_REPORT, 0x0000, constBufLen, constBufLen, buf, NULL )); + + uint8_t rcode = pUsb->ctrlReq( bAddress, ep, /*bmREQ_HIDREPORT*/0x81, USB_REQUEST_GET_DESCRIPTOR, 0x00, + HID_DESCRIPTOR_REPORT, 0x0000, constBufLen, constBufLen, buf, (USBReadParser*)parser ); + + //return ((rcode != hrSTALL) ? rcode : 0); + return rcode; +} +//uint8_t HID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) +//{ +// return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr )); +//} +uint8_t HID::setReport( uint8_t ep, uint16_t nbytes, uint8_t iface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ) +{ + return( pUsb->ctrlReq( bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL )); +} +uint8_t HID::getReport( uint8_t ep, uint16_t nbytes, uint8_t iface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ) +{ + return( pUsb->ctrlReq( bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL )); +} +uint8_t HID::getIdle( uint8_t ep, uint8_t iface, uint8_t reportID, uint8_t* dataptr ) +{ + return( pUsb->ctrlReq( bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL )); +} +uint8_t HID::setIdle( uint8_t ep, uint8_t iface, uint8_t reportID, uint8_t duration ) +{ + return( pUsb->ctrlReq( bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL )); +} +uint8_t HID::setProto( uint8_t ep, uint8_t iface, uint8_t protocol ) +{ + return( pUsb->ctrlReq( bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL )); +} +uint8_t HID::getProto( uint8_t ep, uint8_t iface, uint8_t* dataptr ) +{ + return( pUsb->ctrlReq( bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL )); +} + +//ReportDescParser::UsagePageFunc usagePageFunctions[] /*PROGMEM*/ = +//{ +// ReportDescParser::PrintGenericDesktopPageUsage, +// ReportDescParser::PrintSimulationControlsPageUsage, +// ReportDescParser::PrintVRControlsPageUsage, +// ReportDescParser::PrintSportsControlsPageUsage, +// ReportDescParser::PrintGameControlsPageUsage, +// ReportDescParser::PrintGenericDeviceControlsPageUsage, +// ReportDescParser::PrintLEDPageUsage, +// ReportDescParser::PrintTelephonyPageUsage, +// ReportDescParser::PrintConsumerPageUsage, +// ReportDescParser::PrintDigitizerPageUsage, +// ReportDescParser::PrintAlphanumDisplayPageUsage, +// ReportDescParser::PrintMedicalInstrumentPageUsage +//}; + +void ReportDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) +{ + uint16_t cntdn = (uint16_t)len; + uint8_t *p = (uint8_t*)pbuf; + + Serial.print("\r\nL:"); + Serial.println(len, HEX); + + while(cntdn) + { + //Serial.print("CDN:"); + //Serial.println(cntdn, HEX); + + if (ParseItem(&p, &cntdn)) + return; + } +} + +uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) +{ + switch (itemParseState) + { + case 0: + //if (**pp == HID_LONG_ITEM_PREFIX) + //{ + // *pp ++; + // pcntdn --; + + // if (!(*pcntdn)) + // return enErrorIncomplete; + + // itemSize = **pp + 3; // bDataSize + sizeof(bLongItemTag) + sizeof(bDataSize) + 1 + //} + //else + { + uint8_t size = ((**pp) & DATA_SIZE_MASK); + itemPrefix = (**pp); + itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size); + + //USBTRACE2("Sz1:", size); + //Serial.print("\r\nSz:"); + //Serial.print(itemSize,DEC); + + switch (itemPrefix & (TYPE_MASK | TAG_MASK)) + { + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + Notify(PSTR("\r\nPush")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + Notify(PSTR("\r\nPop")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + Notify(PSTR("\r\nUsage Page")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + Notify(PSTR("\r\nLogical Min")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + Notify(PSTR("\r\nLogical Max")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + Notify(PSTR("\r\nPhysical Min")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + Notify(PSTR("\r\nPhysical Max")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + Notify(PSTR("\r\nUnit Exp")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + Notify(PSTR("\r\nUnit")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + Notify(PSTR("\r\nReport Size")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + Notify(PSTR("\r\nReport Count")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + Notify(PSTR("\r\nReport Id")); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + Notify(PSTR("\r\nUsage")); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + Notify(PSTR("\r\nUsage Min")); + break; + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + Notify(PSTR("\r\nUsage Max")); + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + Notify(PSTR("\r\nCollection")); + break; + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + Notify(PSTR("\r\nEnd Collection")); + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + Notify(PSTR("\r\nInput")); + break; + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + Notify(PSTR("\r\nOutput")); + break; + case (TYPE_MAIN | TAG_MAIN_FEATURE): + Notify(PSTR("\r\nFeature")); + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) + } + (*pp) ++; + (*pcntdn) --; + itemSize --; + itemParseState = 1; + case 1: + if (!itemSize) + break; + + if (!pcntdn) + { + if (itemSize) + return enErrorIncomplete; + + break; + } + switch (itemPrefix & (TYPE_MASK | TAG_MASK)) + { + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): + case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): + case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE): + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT): + case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID): + case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN): + case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): + case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): + case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + //PrintGenericDesktopPageUsage((**pp)); + //PrintSimulationControlsPageUsage((**pp)); + //PrintVRControlsPageUsage((**pp)); + //PrintSportsControlsPageUsage((**pp)); + //PrintGameControlsPageUsage((**pp)); + //PrintGenericDeviceControlsPageUsage((**pp)); + //PrintLEDPageUsage((**pp)); + //PrintTelephonyPageUsage((**pp)); + //PrintConsumerPageUsage((**pp)); + //PrintDigitizerPageUsage((**pp)); + //PrintAlphanumDisplayPageUsage((**pp)); + //PrintMedicalInstrumentPageUsage((**pp)); + Notify(PSTR("(")); + PrintHex((**pp)); + Notify(PSTR(")")); + break; + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + PrintUsagePage((**pp)); + break; + case (TYPE_MAIN | TAG_MAIN_COLLECTION): + case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): + switch ((**pp)) + { + case 0x00: + Notify(PSTR(" Physical")); + break; + case 0x01: + Notify(PSTR(" Application")); + break; + case 0x02: + Notify(PSTR(" Logical")); + break; + case 0x03: + Notify(PSTR(" Report")); + break; + case 0x04: + Notify(PSTR(" Named Array")); + break; + case 0x05: + Notify(PSTR(" Usage Switch")); + break; + case 0x06: + Notify(PSTR(" Usage Modifier")); + break; + default: + Notify(PSTR(" Vendor Defined(")); + PrintHex((**pp)); + Notify(PSTR(")")); + } + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + case (TYPE_MAIN | TAG_MAIN_FEATURE): + Notify(PSTR("(")); + PrintBin((**pp)); + Notify(PSTR(")")); + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) + (*pp) ++; + (*pcntdn) --; + itemSize --; + itemParseState = 2; + case 2: + if (itemSize > 1 && !theSkipper.Skip(pp, pcntdn, itemSize)) + return enErrorIncomplete; + } // switch (itemParseState) + itemParseState = 0; + return enErrorSuccess; +} + +const char *usagePageTitles0[] PROGMEM = +{ + pstrUsagePageGenericDesktopControls , + pstrUsagePageSimulationControls , + pstrUsagePageVRControls , + pstrUsagePageSportControls , + pstrUsagePageGameControls , + pstrUsagePageGenericDeviceControls , + pstrUsagePageKeyboardKeypad , + pstrUsagePageLEDs , + pstrUsagePageButton , + pstrUsagePageOrdinal , + pstrUsagePageTelephone , + pstrUsagePageConsumer , + pstrUsagePageDigitizer , + pstrUsagePagePID , + pstrUsagePageUnicode +}; +const char *usagePageTitles1[] PROGMEM = +{ + pstrUsagePageBarCodeScanner , + pstrUsagePageScale , + pstrUsagePageMSRDevices , + pstrUsagePagePointOfSale , + pstrUsagePageCameraControl , + pstrUsagePageArcade +}; + +void ReportDescParser::PrintUsagePage(uint16_t page) +{ + Notify(pstrSpace); + + if (page > 0x00 && page < 0x11) + Notify((char*)pgm_read_word(&usagePageTitles0[page - 1])); + else if (page > 0x7f && page < 0x84) + Notify(pstrUsagePageMonitor); + else if (page > 0x83 && page < 0x8c) + Notify(pstrUsagePagePower); + else if (page > 0x8b && page < 0x92) + Notify((char*)pgm_read_word(&usagePageTitles1[page - 0x8c])); + else if (page > 0xfeff && page <= 0xffff) + Notify(pstrUsagePageVendorDefined); + else + switch (page) + { + case 0x14: + Notify(pstrUsagePageAlphaNumericDisplay); + break; + case 0x40: + Notify(pstrUsagePageMedicalInstruments); + break; + default: + Notify(pstrUsagePageUndefined); + } +} + +const char *genDesktopTitles0[] PROGMEM = +{ + pstrUsagePointer , + pstrUsageMouse , + pstrUsageJoystick , + pstrUsageGamePad , + pstrUsageKeyboard , + pstrUsageKeypad , + pstrUsageMultiAxisController , + pstrUsageTabletPCSystemControls + +}; +const char *genDesktopTitles1[] PROGMEM = +{ + pstrUsageX , + pstrUsageY , + pstrUsageZ , + pstrUsageRx , + pstrUsageRy , + pstrUsageRz , + pstrUsageSlider , + pstrUsageDial , + pstrUsageWheel , + pstrUsageHatSwitch , + pstrUsageCountedBuffer , + pstrUsageByteCount , + pstrUsageMotionWakeup , + pstrUsageStart , + pstrUsageSelect , + pstrUsagePageReserved , + pstrUsageVx , + pstrUsageVy , + pstrUsageVz , + pstrUsageVbrx , + pstrUsageVbry , + pstrUsageVbrz , + pstrUsageVno , + pstrUsageFeatureNotification , + pstrUsageResolutionMultiplier +}; +const char *genDesktopTitles2[] PROGMEM = +{ + pstrUsageSystemControl , + pstrUsageSystemPowerDown , + pstrUsageSystemSleep , + pstrUsageSystemWakeup , + pstrUsageSystemContextMenu , + pstrUsageSystemMainMenu , + pstrUsageSystemAppMenu , + pstrUsageSystemMenuHelp , + pstrUsageSystemMenuExit , + pstrUsageSystemMenuSelect , + pstrUsageSystemMenuRight , + pstrUsageSystemMenuLeft , + pstrUsageSystemMenuUp , + pstrUsageSystemMenuDown , + pstrUsageSystemColdRestart , + pstrUsageSystemWarmRestart , + pstrUsageDPadUp , + pstrUsageDPadDown , + pstrUsageDPadRight , + pstrUsageDPadLeft +}; +const char *genDesktopTitles3[] PROGMEM = +{ + pstrUsageSystemDock , + pstrUsageSystemUndock , + pstrUsageSystemSetup , + pstrUsageSystemBreak , + pstrUsageSystemDebuggerBreak , + pstrUsageApplicationBreak , + pstrUsageApplicationDebuggerBreak, + pstrUsageSystemSpeakerMute , + pstrUsageSystemHibernate +}; +const char *genDesktopTitles4[] PROGMEM = +{ + pstrUsageSystemDisplayInvert , + pstrUsageSystemDisplayInternal , + pstrUsageSystemDisplayExternal , + pstrUsageSystemDisplayBoth , + pstrUsageSystemDisplayDual , + pstrUsageSystemDisplayToggleIntExt , + pstrUsageSystemDisplaySwapPriSec , + pstrUsageSystemDisplayLCDAutoscale +}; + +void ReportDescParser::PrintGenericDesktopPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x0a) + Notify((char*)pgm_read_word(&genDesktopTitles0[usage - 1])); + else if (usage > 0x2f && usage < 0x49) + Notify((char*)pgm_read_word(&genDesktopTitles1[usage - 0x30])); + else if (usage > 0x7f && usage < 0x94) + Notify((char*)pgm_read_word(&genDesktopTitles2[usage - 0x80])); + else if (usage > 0x9f && usage < 0xa9) + Notify((char*)pgm_read_word(&genDesktopTitles3[usage - 0xa0])); + else if (usage > 0xaf && usage < 0xb8) + Notify((char*)pgm_read_word(&genDesktopTitles4[usage - 0xb0])); + else + Notify(pstrUsagePageUndefined); +} + +const char *simuTitles0[] PROGMEM = +{ + pstrUsageFlightSimulationDevice , + pstrUsageAutomobileSimulationDevice , + pstrUsageTankSimulationDevice , + pstrUsageSpaceshipSimulationDevice , + pstrUsageSubmarineSimulationDevice , + pstrUsageSailingSimulationDevice , + pstrUsageMotocicleSimulationDevice , + pstrUsageSportsSimulationDevice , + pstrUsageAirplaneSimulationDevice , + pstrUsageHelicopterSimulationDevice , + pstrUsageMagicCarpetSimulationDevice, + pstrUsageBicycleSimulationDevice +}; +const char *simuTitles1[] PROGMEM = +{ + pstrUsageFlightControlStick , + pstrUsageFlightStick , + pstrUsageCyclicControl , + pstrUsageCyclicTrim , + pstrUsageFlightYoke , + pstrUsageTrackControl +}; +const char *simuTitles2[] PROGMEM = +{ + pstrUsageAileron , + pstrUsageAileronTrim , + pstrUsageAntiTorqueControl , + pstrUsageAutopilotEnable , + pstrUsageChaffRelease , + pstrUsageCollectiveControl , + pstrUsageDiveBrake , + pstrUsageElectronicCountermeasures , + pstrUsageElevator , + pstrUsageElevatorTrim , + pstrUsageRudder , + pstrUsageThrottle , + pstrUsageFlightCommunications , + pstrUsageFlareRelease , + pstrUsageLandingGear , + pstrUsageToeBrake , + pstrUsageTrigger , + pstrUsageWeaponsArm , + pstrUsageWeaponsSelect , + pstrUsageWingFlaps , + pstrUsageAccelerator , + pstrUsageBrake , + pstrUsageClutch , + pstrUsageShifter , + pstrUsageSteering , + pstrUsageTurretDirection , + pstrUsageBarrelElevation , + pstrUsageDivePlane , + pstrUsageBallast , + pstrUsageBicycleCrank , + pstrUsageHandleBars , + pstrUsageFrontBrake , + pstrUsageRearBrake +}; + +void ReportDescParser::PrintSimulationControlsPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x0d) + Notify((char*)pgm_read_word(&simuTitles0[usage - 1])); + else if (usage > 0x1f && usage < 0x26) + Notify((char*)pgm_read_word(&simuTitles1[usage - 0x20])); + else if (usage > 0xaf && usage < 0xd1) + Notify((char*)pgm_read_word(&simuTitles2[usage - 0xb0])); + else + Notify(pstrUsagePageUndefined); +} + +const char *vrTitles0[] PROGMEM = +{ + pstrUsageBelt , + pstrUsageBodySuit , + pstrUsageFlexor , + pstrUsageGlove , + pstrUsageHeadTracker , + pstrUsageHeadMountedDisplay , + pstrUsageHandTracker , + pstrUsageOculometer , + pstrUsageVest , + pstrUsageAnimatronicDevice +}; +const char *vrTitles1[] PROGMEM = +{ + pstrUsageStereoEnable , + pstrUsageDisplayEnable +}; + +void ReportDescParser::PrintVRControlsPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x0b) + Notify((char*)pgm_read_word(&vrTitles0[usage - 1])); + else if (usage > 0x1f && usage < 0x22) + Notify((char*)pgm_read_word(&vrTitles1[usage - 0x20])); + else + Notify(pstrUsagePageUndefined); +} + +const char *sportsCtrlTitles0[] PROGMEM = +{ + pstrUsageBaseballBat , + pstrUsageGolfClub , + pstrUsageRowingMachine , + pstrUsageTreadmill +}; +const char *sportsCtrlTitles1[] PROGMEM = +{ + pstrUsageOar , + pstrUsageSlope , + pstrUsageRate , + pstrUsageStickSpeed , + pstrUsageStickFaceAngle , + pstrUsageStickHeelToe , + pstrUsageStickFollowThough , + pstrUsageStickTempo , + pstrUsageStickType , + pstrUsageStickHeight +}; +const char *sportsCtrlTitles2[] PROGMEM = +{ + pstrUsagePutter , + pstrUsage1Iron , + pstrUsage2Iron , + pstrUsage3Iron , + pstrUsage4Iron , + pstrUsage5Iron , + pstrUsage6Iron , + pstrUsage7Iron , + pstrUsage8Iron , + pstrUsage9Iron , + pstrUsage10Iron , + pstrUsage11Iron , + pstrUsageSandWedge , + pstrUsageLoftWedge , + pstrUsagePowerWedge , + pstrUsage1Wood , + pstrUsage3Wood , + pstrUsage5Wood , + pstrUsage7Wood , + pstrUsage9Wood +}; + +void ReportDescParser::PrintSportsControlsPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x05) + Notify((char*)pgm_read_word(&sportsCtrlTitles0[usage - 1])); + else if (usage > 0x2f && usage < 0x3a) + Notify((char*)pgm_read_word(&sportsCtrlTitles1[usage - 0x30])); + else if (usage > 0x4f && usage < 0x64) + Notify((char*)pgm_read_word(&sportsCtrlTitles2[usage - 0x50])); + else + Notify(pstrUsagePageUndefined); +} + + + + +const char *gameTitles0[] PROGMEM = +{ + pstrUsage3DGameController , + pstrUsagePinballDevice , + pstrUsageGunDevice +}; +const char *gameTitles1[] PROGMEM = +{ + pstrUsagePointOfView , + pstrUsageTurnRightLeft , + pstrUsagePitchForwardBackward , + pstrUsageRollRightLeft , + pstrUsageMoveRightLeft , + pstrUsageMoveForwardBackward , + pstrUsageMoveUpDown , + pstrUsageLeanRightLeft , + pstrUsageLeanForwardBackward , + pstrUsageHeightOfPOV , + pstrUsageFlipper , + pstrUsageSecondaryFlipper , + pstrUsageBump , + pstrUsageNewGame , + pstrUsageShootBall , + pstrUsagePlayer , + pstrUsageGunBolt , + pstrUsageGunClip , + pstrUsageGunSelector , + pstrUsageGunSingleShot , + pstrUsageGunBurst , + pstrUsageGunAutomatic , + pstrUsageGunSafety , + pstrUsageGamepadFireJump , + pstrUsageGamepadTrigger +}; + +void ReportDescParser::PrintGameControlsPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x04) + Notify((char*)pgm_read_word(&gameTitles0[usage - 1])); + else if (usage > 0x1f && usage < 0x3a) + Notify((char*)pgm_read_word(&gameTitles1[usage - 0x20])); + else + Notify(pstrUsagePageUndefined); +} + +const char *genDevCtrlTitles[] PROGMEM = +{ + pstrUsageBatteryStrength, + pstrUsageWirelessChannel, + pstrUsageWirelessID, + pstrUsageDiscoverWirelessControl, + pstrUsageSecurityCodeCharEntered, + pstrUsageSecurityCodeCharErased, + pstrUsageSecurityCodeCleared +}; + +void ReportDescParser::PrintGenericDeviceControlsPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x1f && usage < 0x27) + Notify((char*)pgm_read_word(&genDevCtrlTitles[usage - 0x20])); + else + Notify(pstrUsagePageUndefined); +} + +const char *ledTitles[] PROGMEM = +{ + pstrUsageNumLock , + pstrUsageCapsLock , + pstrUsageScrollLock , + pstrUsageCompose , + pstrUsageKana , + pstrUsagePower , + pstrUsageShift , + pstrUsageDoNotDisturb , + pstrUsageMute , + pstrUsageToneEnable , + pstrUsageHighCutFilter , + pstrUsageLowCutFilter , + pstrUsageEqualizerEnable , + pstrUsageSoundFieldOn , + pstrUsageSurroundOn , + pstrUsageRepeat , + pstrUsageStereo , + pstrUsageSamplingRateDetect , + pstrUsageSpinning , + pstrUsageCAV , + pstrUsageCLV , + pstrUsageRecordingFormatDetect , + pstrUsageOffHook , + pstrUsageRing , + pstrUsageMessageWaiting , + pstrUsageDataMode , + pstrUsageBatteryOperation , + pstrUsageBatteryOK , + pstrUsageBatteryLow , + pstrUsageSpeaker , + pstrUsageHeadSet , + pstrUsageHold , + pstrUsageMicrophone , + pstrUsageCoverage , + pstrUsageNightMode , + pstrUsageSendCalls , + pstrUsageCallPickup , + pstrUsageConference , + pstrUsageStandBy , + pstrUsageCameraOn , + pstrUsageCameraOff , + pstrUsageOnLine , + pstrUsageOffLine , + pstrUsageBusy , + pstrUsageReady , + pstrUsagePaperOut , + pstrUsagePaperJam , + pstrUsageRemote , + pstrUsageForward , + pstrUsageReverse , + pstrUsageStop , + pstrUsageRewind , + pstrUsageFastForward , + pstrUsagePlay , + pstrUsagePause , + pstrUsageRecord , + pstrUsageError , + pstrUsageSelectedIndicator , + pstrUsageInUseIndicator , + pstrUsageMultiModeIndicator , + pstrUsageIndicatorOn , + pstrUsageIndicatorFlash , + pstrUsageIndicatorSlowBlink , + pstrUsageIndicatorFastBlink , + pstrUsageIndicatorOff , + pstrUsageFlashOnTime , + pstrUsageSlowBlinkOnTime , + pstrUsageSlowBlinkOffTime , + pstrUsageFastBlinkOnTime , + pstrUsageFastBlinkOffTime , + pstrUsageIndicatorColor , + pstrUsageIndicatorRed , + pstrUsageIndicatorGreen , + pstrUsageIndicatorAmber , + pstrUsageGenericIndicator , + pstrUsageSystemSuspend , + pstrUsageExternalPowerConnected +}; + +void ReportDescParser::PrintLEDPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x4e) + Notify((char*)pgm_read_word(&ledTitles[usage - 1])); + else + Notify(pstrUsagePageUndefined); +} + +const char *telTitles0 [] PROGMEM = +{ + pstrUsagePhone , + pstrUsageAnsweringMachine , + pstrUsageMessageControls , + pstrUsageHandset , + pstrUsageHeadset , + pstrUsageTelephonyKeyPad , + pstrUsageProgrammableButton +}; +const char *telTitles1 [] PROGMEM = +{ + pstrUsageHookSwitch , + pstrUsageFlash , + pstrUsageFeature , + pstrUsageHold , + pstrUsageRedial , + pstrUsageTransfer , + pstrUsageDrop , + pstrUsagePark , + pstrUsageForwardCalls , + pstrUsageAlternateFunction , + pstrUsageLine , + pstrUsageSpeakerPhone , + pstrUsageConference , + pstrUsageRingEnable , + pstrUsageRingSelect , + pstrUsagePhoneMute , + pstrUsageCallerID , + pstrUsageSend +}; +const char *telTitles2 [] PROGMEM = +{ + pstrUsageSpeedDial , + pstrUsageStoreNumber , + pstrUsageRecallNumber , + pstrUsagePhoneDirectory +}; +const char *telTitles3 [] PROGMEM = +{ + pstrUsageVoiceMail , + pstrUsageScreenCalls , + pstrUsageDoNotDisturb , + pstrUsageMessage , + pstrUsageAnswerOnOff +}; +const char *telTitles4 [] PROGMEM = +{ + pstrUsageInsideDialTone , + pstrUsageOutsideDialTone , + pstrUsageInsideRingTone , + pstrUsageOutsideRingTone , + pstrUsagePriorityRingTone , + pstrUsageInsideRingback , + pstrUsagePriorityRingback , + pstrUsageLineBusyTone , + pstrUsageReorderTone , + pstrUsageCallWaitingTone , + pstrUsageConfirmationTone1 , + pstrUsageConfirmationTone2 , + pstrUsageTonesOff , + pstrUsageOutsideRingback , + pstrUsageRinger +}; +const char *telTitles5 [] PROGMEM = +{ + pstrUsagePhoneKey0 , + pstrUsagePhoneKey1 , + pstrUsagePhoneKey2 , + pstrUsagePhoneKey3 , + pstrUsagePhoneKey4 , + pstrUsagePhoneKey5 , + pstrUsagePhoneKey6 , + pstrUsagePhoneKey7 , + pstrUsagePhoneKey8 , + pstrUsagePhoneKey9 , + pstrUsagePhoneKeyStar , + pstrUsagePhoneKeyPound , + pstrUsagePhoneKeyA , + pstrUsagePhoneKeyB , + pstrUsagePhoneKeyC , + pstrUsagePhoneKeyD +}; + +void ReportDescParser::PrintTelephonyPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x08) + Notify((char*)pgm_read_word(&telTitles0[usage - 1])); + else if (usage > 0x1f && usage < 0x32) + Notify((char*)pgm_read_word(&telTitles1[usage - 0x1f])); + else if (usage > 0x4f && usage < 0x54) + Notify((char*)pgm_read_word(&telTitles2[usage - 0x4f])); + else if (usage > 0x6f && usage < 0x75) + Notify((char*)pgm_read_word(&telTitles3[usage - 0x6f])); + else if (usage > 0x8f && usage < 0x9f) + Notify((char*)pgm_read_word(&telTitles4[usage - 0x8f])); + else if (usage > 0xaf && usage < 0xc0) + Notify((char*)pgm_read_word(&telTitles5[usage - 0xaf])); + else + Notify(pstrUsagePageUndefined); +} + +const char *consTitles0[] PROGMEM = +{ + pstrUsageConsumerControl, + pstrUsageNumericKeyPad, + pstrUsageProgrammableButton, + pstrUsageMicrophone, + pstrUsageHeadphone, + pstrUsageGraphicEqualizer +}; +const char *consTitles1[] PROGMEM = +{ + pstrUsagePlus10 , + pstrUsagePlus100, + pstrUsageAMPM +}; +const char *consTitles2[] PROGMEM = +{ + pstrUsagePower , + pstrUsageReset , + pstrUsageSleep , + pstrUsageSleepAfter , + pstrUsageSleepMode , + pstrUsageIllumination , + pstrUsageFunctionButtons + +}; +const char *consTitles3[] PROGMEM = +{ + pstrUsageMenu , + pstrUsageMenuPick , + pstrUsageMenuUp , + pstrUsageMenuDown , + pstrUsageMenuLeft , + pstrUsageMenuRight , + pstrUsageMenuEscape , + pstrUsageMenuValueIncrease, + pstrUsageMenuValueDecrease +}; +const char *consTitles4[] PROGMEM = +{ + pstrUsageDataOnScreen , + pstrUsageClosedCaption , + pstrUsageClosedCaptionSelect, + pstrUsageVCRTV , + pstrUsageBroadcastMode , + pstrUsageSnapshot , + pstrUsageStill +}; +const char *consTitles5[] PROGMEM = +{ + pstrUsageSelection , + pstrUsageAssignSelection , + pstrUsageModeStep , + pstrUsageRecallLast , + pstrUsageEnterChannel , + pstrUsageOrderMovie , + pstrUsageChannel , + pstrUsageMediaSelection , + pstrUsageMediaSelectComputer , + pstrUsageMediaSelectTV , + pstrUsageMediaSelectWWW , + pstrUsageMediaSelectDVD , + pstrUsageMediaSelectTelephone , + pstrUsageMediaSelectProgramGuide , + pstrUsageMediaSelectVideoPhone , + pstrUsageMediaSelectGames , + pstrUsageMediaSelectMessages , + pstrUsageMediaSelectCD , + pstrUsageMediaSelectVCR , + pstrUsageMediaSelectTuner , + pstrUsageQuit , + pstrUsageHelp , + pstrUsageMediaSelectTape , + pstrUsageMediaSelectCable , + pstrUsageMediaSelectSatellite , + pstrUsageMediaSelectSecurity , + pstrUsageMediaSelectHome , + pstrUsageMediaSelectCall , + pstrUsageChannelIncrement , + pstrUsageChannelDecrement , + pstrUsageMediaSelectSAP , + pstrUsagePageReserved , + pstrUsageVCRPlus , + pstrUsageOnce , + pstrUsageDaily , + pstrUsageWeekly , + pstrUsageMonthly +}; +const char *consTitles6[] PROGMEM = +{ + pstrUsagePlay , + pstrUsagePause , + pstrUsageRecord , + pstrUsageFastForward , + pstrUsageRewind , + pstrUsageScanNextTrack , + pstrUsageScanPreviousTrack , + pstrUsageStop , + pstrUsageEject , + pstrUsageRandomPlay , + pstrUsageSelectDisk , + pstrUsageEnterDisk , + pstrUsageRepeat , + pstrUsageTracking , + pstrUsageTrackNormal , + pstrUsageSlowTracking , + pstrUsageFrameForward , + pstrUsageFrameBackwards , + pstrUsageMark , + pstrUsageClearMark , + pstrUsageRepeatFromMark , + pstrUsageReturnToMark , + pstrUsageSearchMarkForward , + pstrUsageSearchMarkBackwards , + pstrUsageCounterReset , + pstrUsageShowCounter , + pstrUsageTrackingIncrement , + pstrUsageTrackingDecrement , + pstrUsageStopEject , + pstrUsagePlayPause , + pstrUsagePlaySkip +}; +const char *consTitles7[] PROGMEM = +{ + pstrUsageVolume , + pstrUsageBalance , + pstrUsageMute , + pstrUsageBass , + pstrUsageTreble , + pstrUsageBassBoost , + pstrUsageSurroundMode , + pstrUsageLoudness , + pstrUsageMPX , + pstrUsageVolumeIncrement , + pstrUsageVolumeDecrement +}; +const char *consTitles8[] PROGMEM = +{ + pstrUsageSpeedSelect , + pstrUsagePlaybackSpeed , + pstrUsageStandardPlay , + pstrUsageLongPlay , + pstrUsageExtendedPlay , + pstrUsageSlow +}; +const char *consTitles9[] PROGMEM = +{ + pstrUsageFanEnable , + pstrUsageFanSpeed , + pstrUsageLightEnable , + pstrUsageLightIlluminationLevel , + pstrUsageClimateControlEnable , + pstrUsageRoomTemperature , + pstrUsageSecurityEnable , + pstrUsageFireAlarm , + pstrUsagePoliceAlarm , + pstrUsageProximity , + pstrUsageMotion , + pstrUsageDuresAlarm , + pstrUsageHoldupAlarm , + pstrUsageMedicalAlarm +}; +const char *consTitlesA[] PROGMEM = +{ + pstrUsageBalanceRight , + pstrUsageBalanceLeft , + pstrUsageBassIncrement , + pstrUsageBassDecrement , + pstrUsageTrebleIncrement , + pstrUsageTrebleDecrement +}; +const char *consTitlesB[] PROGMEM = +{ + pstrUsageSpeakerSystem , + pstrUsageChannelLeft , + pstrUsageChannelRight , + pstrUsageChannelCenter , + pstrUsageChannelFront , + pstrUsageChannelCenterFront , + pstrUsageChannelSide , + pstrUsageChannelSurround , + pstrUsageChannelLowFreqEnhancement , + pstrUsageChannelTop , + pstrUsageChannelUnknown +}; +const char *consTitlesC[] PROGMEM = +{ + pstrUsageSubChannel , + pstrUsageSubChannelIncrement , + pstrUsageSubChannelDecrement , + pstrUsageAlternateAudioIncrement , + pstrUsageAlternateAudioDecrement +}; +const char *consTitlesD[] PROGMEM = +{ + pstrUsageApplicationLaunchButtons , + pstrUsageALLaunchButtonConfigTool , + pstrUsageALProgrammableButton , + pstrUsageALConsumerControlConfig , + pstrUsageALWordProcessor , + pstrUsageALTextEditor , + pstrUsageALSpreadsheet , + pstrUsageALGraphicsEditor , + pstrUsageALPresentationApp , + pstrUsageALDatabaseApp , + pstrUsageALEmailReader , + pstrUsageALNewsreader , + pstrUsageALVoicemail , + pstrUsageALContactsAddressBook , + pstrUsageALCalendarSchedule , + pstrUsageALTaskProjectManager , + pstrUsageALLogJournalTimecard , + pstrUsageALCheckbookFinance , + pstrUsageALCalculator , + pstrUsageALAVCapturePlayback , + pstrUsageALLocalMachineBrowser , + pstrUsageALLANWANBrow , + pstrUsageALInternetBrowser , + pstrUsageALRemoteNetISPConnect , + pstrUsageALNetworkConference , + pstrUsageALNetworkChat , + pstrUsageALTelephonyDialer , + pstrUsageALLogon , + pstrUsageALLogoff , + pstrUsageALLogonLogoff , + pstrUsageALTermLockScrSav , + pstrUsageALControlPannel , + pstrUsageALCommandLineProcessorRun , + pstrUsageALProcessTaskManager , + pstrUsageALSelectTaskApplication , + pstrUsageALNextTaskApplication , + pstrUsageALPreviousTaskApplication , + pstrUsageALPreemptiveHaltTaskApp , + pstrUsageALIntegratedHelpCenter , + pstrUsageALDocuments , + pstrUsageALThesaurus , + pstrUsageALDictionary , + pstrUsageALDesktop , + pstrUsageALSpellCheck , + pstrUsageALGrammarCheck , + pstrUsageALWirelessStatus , + pstrUsageALKeyboardLayout , + pstrUsageALVirusProtection , + pstrUsageALEncryption , + pstrUsageALScreenSaver , + pstrUsageALAlarms , + pstrUsageALClock , + pstrUsageALFileBrowser , + pstrUsageALPowerStatus , + pstrUsageALImageBrowser , + pstrUsageALAudioBrowser , + pstrUsageALMovieBrowser , + pstrUsageALDigitalRightsManager , + pstrUsageALDigitalWallet , + pstrUsagePageReserved , + pstrUsageALInstantMessaging , + pstrUsageALOEMFeaturesBrowser , + pstrUsageALOEMHelp , + pstrUsageALOnlineCommunity , + pstrUsageALEntertainmentContentBrow , + pstrUsageALOnlineShoppingBrowser , + pstrUsageALSmartCardInfoHelp , + pstrUsageALMarketMonitorFinBrowser , + pstrUsageALCustomCorpNewsBrowser , + pstrUsageALOnlineActivityBrowser , + pstrUsageALResearchSearchBrowser , + pstrUsageALAudioPlayer +}; +const char *consTitlesE[] PROGMEM = +{ + pstrUsageGenericGUIAppControls , + pstrUsageACNew , + pstrUsageACOpen , + pstrUsageACClose , + pstrUsageACExit , + pstrUsageACMaximize , + pstrUsageACMinimize , + pstrUsageACSave , + pstrUsageACPrint , + pstrUsageACProperties , + pstrUsageACUndo , + pstrUsageACCopy , + pstrUsageACCut , + pstrUsageACPaste , + pstrUsageACSelectAll , + pstrUsageACFind , + pstrUsageACFindAndReplace , + pstrUsageACSearch , + pstrUsageACGoto , + pstrUsageACHome , + pstrUsageACBack , + pstrUsageACForward , + pstrUsageACStop , + pstrUsageACRefresh , + pstrUsageACPreviousLink , + pstrUsageACNextLink , + pstrUsageACBookmarks , + pstrUsageACHistory , + pstrUsageACSubscriptions , + pstrUsageACZoomIn , + pstrUsageACZoomOut , + pstrUsageACZoom , + pstrUsageACFullScreenView , + pstrUsageACNormalView , + pstrUsageACViewToggle , + pstrUsageACScrollUp , + pstrUsageACScrollDown , + pstrUsageACScroll , + pstrUsageACPanLeft , + pstrUsageACPanRight , + pstrUsageACPan , + pstrUsageACNewWindow , + pstrUsageACTileHoriz , + pstrUsageACTileVert , + pstrUsageACFormat , + pstrUsageACEdit , + pstrUsageACBold , + pstrUsageACItalics , + pstrUsageACUnderline , + pstrUsageACStrikethrough , + pstrUsageACSubscript , + pstrUsageACSuperscript , + pstrUsageACAllCaps , + pstrUsageACRotate , + pstrUsageACResize , + pstrUsageACFlipHorizontal , + pstrUsageACFlipVertical , + pstrUsageACMirrorHorizontal , + pstrUsageACMirrorVertical , + pstrUsageACFontSelect , + pstrUsageACFontColor , + pstrUsageACFontSize , + pstrUsageACJustifyLeft , + pstrUsageACJustifyCenterH , + pstrUsageACJustifyRight , + pstrUsageACJustifyBlockH , + pstrUsageACJustifyTop , + pstrUsageACJustifyCenterV , + pstrUsageACJustifyBottom , + pstrUsageACJustifyBlockV , + pstrUsageACIndentDecrease , + pstrUsageACIndentIncrease , + pstrUsageACNumberedList , + pstrUsageACRestartNumbering , + pstrUsageACBulletedList , + pstrUsageACPromote , + pstrUsageACDemote , + pstrUsageACYes , + pstrUsageACNo , + pstrUsageACCancel , + pstrUsageACCatalog , + pstrUsageACBuyChkout , + pstrUsageACAddToCart , + pstrUsageACExpand , + pstrUsageACExpandAll , + pstrUsageACCollapse , + pstrUsageACCollapseAll , + pstrUsageACPrintPreview , + pstrUsageACPasteSpecial , + pstrUsageACInsertMode , + pstrUsageACDelete , + pstrUsageACLock , + pstrUsageACUnlock , + pstrUsageACProtect , + pstrUsageACUnprotect , + pstrUsageACAttachComment , + pstrUsageACDeleteComment , + pstrUsageACViewComment , + pstrUsageACSelectWord , + pstrUsageACSelectSentence , + pstrUsageACSelectParagraph , + pstrUsageACSelectColumn , + pstrUsageACSelectRow , + pstrUsageACSelectTable , + pstrUsageACSelectObject , + pstrUsageACRedoRepeat , + pstrUsageACSort , + pstrUsageACSortAscending , + pstrUsageACSortDescending , + pstrUsageACFilter , + pstrUsageACSetClock , + pstrUsageACViewClock , + pstrUsageACSelectTimeZone , + pstrUsageACEditTimeZone , + pstrUsageACSetAlarm , + pstrUsageACClearAlarm , + pstrUsageACSnoozeAlarm , + pstrUsageACResetAlarm , + pstrUsageACSyncronize , + pstrUsageACSendReceive , + pstrUsageACSendTo , + pstrUsageACReply , + pstrUsageACReplyAll , + pstrUsageACForwardMessage , + pstrUsageACSend , + pstrUsageACAttachFile , + pstrUsageACUpload , + pstrUsageACDownload , + pstrUsageACSetBorders , + pstrUsageACInsertRow , + pstrUsageACInsertColumn , + pstrUsageACInsertFile , + pstrUsageACInsertPicture , + pstrUsageACInsertObject , + pstrUsageACInsertSymbol , + pstrUsageACSaveAndClose , + pstrUsageACRename , + pstrUsageACMerge , + pstrUsageACSplit , + pstrUsageACDistributeHorizontaly , + pstrUsageACDistributeVerticaly +}; + +void ReportDescParser::PrintConsumerPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x07) + Notify((char*)pgm_read_word(&consTitles0[usage - 1])); + else if (usage > 0x1f && usage < 0x23) + Notify((char*)pgm_read_word(&consTitles1[usage - 0x1f])); + else if (usage > 0x2f && usage < 0x37) + Notify((char*)pgm_read_word(&consTitles2[usage - 0x2f])); + else if (usage > 0x3f && usage < 0x49) + Notify((char*)pgm_read_word(&consTitles3[usage - 0x3f])); + else if (usage > 0x5f && usage < 0x67) + Notify((char*)pgm_read_word(&consTitles4[usage - 0x5f])); + else if (usage > 0x7f && usage < 0xa5) + Notify((char*)pgm_read_word(&consTitles5[usage - 0x7f])); + else if (usage > 0xaf && usage < 0xcf) + Notify((char*)pgm_read_word(&consTitles6[usage - 0xaf])); + else if (usage > 0xdf && usage < 0xeb) + Notify((char*)pgm_read_word(&consTitles7[usage - 0xdf])); + else if (usage > 0xef && usage < 0xf6) + Notify((char*)pgm_read_word(&consTitles8[usage - 0xef])); + else if (usage > 0xff && usage < 0x10e) + Notify((char*)pgm_read_word(&consTitles9[usage - 0xff])); + else if (usage > 0x14f && usage < 0x156) + Notify((char*)pgm_read_word(&consTitlesA[usage - 0x14f])); + else if (usage > 0x15f && usage < 0x16b) + Notify((char*)pgm_read_word(&consTitlesB[usage - 0x15f])); + else if (usage > 0x16f && usage < 0x175) + Notify((char*)pgm_read_word(&consTitlesC[usage - 0x16f])); + else if (usage > 0x17f && usage < 0x1c8) + Notify((char*)pgm_read_word(&consTitlesD[usage - 0x17f])); + else if (usage > 0x1ff && usage < 0x29d) + Notify((char*)pgm_read_word(&consTitlesE[usage - 0x1ff])); + else + Notify(pstrUsagePageUndefined); +} + +const char *digitTitles0[] PROGMEM = +{ + pstrUsageDigitizer , + pstrUsagePen , + pstrUsageLightPen , + pstrUsageTouchScreen , + pstrUsageTouchPad , + pstrUsageWhiteBoard , + pstrUsageCoordinateMeasuringMachine , + pstrUsage3DDigitizer , + pstrUsageStereoPlotter , + pstrUsageArticulatedArm , + pstrUsageArmature , + pstrUsageMultiplePointDigitizer , + pstrUsageFreeSpaceWand +}; +const char *digitTitles1[] PROGMEM = +{ + pstrUsageStylus , + pstrUsagePuck , + pstrUsageFinger + +}; +const char *digitTitles2[] PROGMEM = +{ + pstrUsageTipPressure , + pstrUsageBarrelPressure , + pstrUsageInRange , + pstrUsageTouch , + pstrUsageUntouch , + pstrUsageTap , + pstrUsageQuality , + pstrUsageDataValid , + pstrUsageTransducerIndex , + pstrUsageTabletFunctionKeys , + pstrUsageProgramChangeKeys , + pstrUsageBatteryStrength , + pstrUsageInvert , + pstrUsageXTilt , + pstrUsageYTilt , + pstrUsageAzimuth , + pstrUsageAltitude , + pstrUsageTwist , + pstrUsageTipSwitch , + pstrUsageSecondaryTipSwitch , + pstrUsageBarrelSwitch , + pstrUsageEraser , + pstrUsageTabletPick +}; + +void ReportDescParser::PrintDigitizerPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x0e) + Notify((char*)pgm_read_word(&digitTitles0[usage - 1])); + else if (usage > 0x1f && usage < 0x23) + Notify((char*)pgm_read_word(&digitTitles1[usage - 0x1f])); + else if (usage > 0x2f && usage < 0x47) + Notify((char*)pgm_read_word(&digitTitles2[usage - 0x2f])); + else + Notify(pstrUsagePageUndefined); +} + +const char *aplphanumTitles0[] PROGMEM = +{ + pstrUsageAlphanumericDisplay, + pstrUsageBitmappedDisplay +}; +const char *aplphanumTitles1[] PROGMEM = +{ + pstrUsageDisplayAttributesReport , + pstrUsageASCIICharacterSet , + pstrUsageDataReadBack , + pstrUsageFontReadBack , + pstrUsageDisplayControlReport , + pstrUsageClearDisplay , + pstrUsageDisplayEnable , + pstrUsageScreenSaverDelay , + pstrUsageScreenSaverEnable , + pstrUsageVerticalScroll , + pstrUsageHorizontalScroll , + pstrUsageCharacterReport , + pstrUsageDisplayData , + pstrUsageDisplayStatus , + pstrUsageStatusNotReady , + pstrUsageStatusReady , + pstrUsageErrorNotALoadableCharacter , + pstrUsageErrorFotDataCanNotBeRead , + pstrUsageCursorPositionReport , + pstrUsageRow , + pstrUsageColumn , + pstrUsageRows , + pstrUsageColumns , + pstrUsageCursorPixelPosition , + pstrUsageCursorMode , + pstrUsageCursorEnable , + pstrUsageCursorBlink , + pstrUsageFontReport , + pstrUsageFontData , + pstrUsageCharacterWidth , + pstrUsageCharacterHeight , + pstrUsageCharacterSpacingHorizontal , + pstrUsageCharacterSpacingVertical , + pstrUsageUnicodeCharset , + pstrUsageFont7Segment , + pstrUsage7SegmentDirectMap , + pstrUsageFont14Segment , + pstrUsage14SegmentDirectMap , + pstrUsageDisplayBrightness , + pstrUsageDisplayContrast , + pstrUsageCharacterAttribute , + pstrUsageAttributeReadback , + pstrUsageAttributeData , + pstrUsageCharAttributeEnhance , + pstrUsageCharAttributeUnderline , + pstrUsageCharAttributeBlink +}; +const char *aplphanumTitles2[] PROGMEM = +{ + pstrUsageBitmapSizeX , + pstrUsageBitmapSizeY , + pstrUsagePageReserved , + pstrUsageBitDepthFormat , + pstrUsageDisplayOrientation , + pstrUsagePaletteReport , + pstrUsagePaletteDataSize , + pstrUsagePaletteDataOffset , + pstrUsagePaletteData , + pstrUsageBlitReport , + pstrUsageBlitRectangleX1 , + pstrUsageBlitRectangleY1 , + pstrUsageBlitRectangleX2 , + pstrUsageBlitRectangleY2 , + pstrUsageBlitData , + pstrUsageSoftButton , + pstrUsageSoftButtonID , + pstrUsageSoftButtonSide , + pstrUsageSoftButtonOffset1 , + pstrUsageSoftButtonOffset2 , + pstrUsageSoftButtonReport +}; + +void ReportDescParser::PrintAlphanumDisplayPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage > 0x00 && usage < 0x03) + Notify((char*)pgm_read_word(&aplphanumTitles0[usage - 1])); + else if (usage > 0x1f && usage < 0x4e) + Notify((char*)pgm_read_word(&aplphanumTitles1[usage - 0x1f])); + else if (usage > 0x7f && usage < 0x96) + Notify((char*)pgm_read_word(&digitTitles2[usage - 0x80])); + else + Notify(pstrUsagePageUndefined); +} + +const char *medInstrTitles0[] PROGMEM = +{ + pstrUsageVCRAcquisition , + pstrUsageFreezeThaw , + pstrUsageClipStore , + pstrUsageUpdate , + pstrUsageNext , + pstrUsageSave , + pstrUsagePrint , + pstrUsageMicrophoneEnable +}; +const char *medInstrTitles1[] PROGMEM = +{ + pstrUsageCine , + pstrUsageTransmitPower , + pstrUsageVolume , + pstrUsageFocus , + pstrUsageDepth +}; +const char *medInstrTitles2[] PROGMEM = +{ + pstrUsageSoftStepPrimary , + pstrUsageSoftStepSecondary +}; +const char *medInstrTitles3[] PROGMEM = +{ + pstrUsageZoomSelect , + pstrUsageZoomAdjust , + pstrUsageSpectralDopplerModeSelect , + pstrUsageSpectralDopplerModeAdjust , + pstrUsageColorDopplerModeSelect , + pstrUsageColorDopplerModeAdjust , + pstrUsageMotionModeSelect , + pstrUsageMotionModeAdjust , + pstrUsage2DModeSelect , + pstrUsage2DModeAdjust +}; +const char *medInstrTitles4[] PROGMEM = +{ + pstrUsageSoftControlSelect , + pstrUsageSoftControlAdjust +}; + +void ReportDescParser::PrintMedicalInstrumentPageUsage(uint16_t usage) +{ + Notify(pstrSpace); + + if (usage == 1) + Notify(pstrUsageMedicalUltrasound); + else if (usage > 0x1f && usage < 0x28) + Notify((char*)pgm_read_word(&medInstrTitles0[usage - 0x1f])); + else if (usage > 0x3f && usage < 0x45) + Notify((char*)pgm_read_word(&medInstrTitles1[usage - 0x40])); + else if (usage > 0x5f && usage < 0x62) + Notify((char*)pgm_read_word(&medInstrTitles2[usage - 0x60])); + else if (usage == 0x70) + Notify(pstrUsageDepthGainCompensation); + else if (usage > 0x7f && usage < 0x8a) + Notify((char*)pgm_read_word(&medInstrTitles3[usage - 0x80])); + else if (usage > 0x9f && usage < 0xa2) + Notify((char*)pgm_read_word(&medInstrTitles4[usage - 0xa0])); + else + Notify(pstrUsagePageUndefined); +} + +void HID::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) +{ + Notify(PSTR("Endpoint descriptor:")); + Notify(PSTR("\r\nLength:\t\t")); + PrintHex(ep_ptr->bLength); + Notify(PSTR("\r\nType:\t\t")); + PrintHex(ep_ptr->bDescriptorType); + Notify(PSTR("\r\nAddress:\t")); + PrintHex(ep_ptr->bEndpointAddress); + Notify(PSTR("\r\nAttributes:\t")); + PrintHex(ep_ptr->bmAttributes); + Notify(PSTR("\r\nMaxPktSize:\t")); + PrintHex(ep_ptr->wMaxPacketSize); + Notify(PSTR("\r\nPoll Intrv:\t")); + PrintHex(ep_ptr->bInterval); +} + +void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) +{ + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n")); + Notify(PSTR("bDescLength:\t\t")); + PrintHex(pDesc->bLength); + + Notify(PSTR("\r\nbDescriptorType:\t")); + PrintHex(pDesc->bDescriptorType); + + Notify(PSTR("\r\nbcdHID:\t\t\t")); + PrintHex(pDesc->bcdHID); + + Notify(PSTR("\r\nbCountryCode:\t\t")); + PrintHex(pDesc->bCountryCode); + + Notify(PSTR("\r\nbNumDescriptors:\t")); + PrintHex(pDesc->bNumDescriptors); + + Notify(PSTR("\r\nbDescrType:\t\t")); + PrintHex(pDesc->bDescrType); + + Notify(PSTR("\r\nwDescriptorLength:\t")); + PrintHex(pDesc->wDescriptorLength); +} diff --git a/hid.h b/hid.h new file mode 100644 index 00000000..66dc3eea --- /dev/null +++ b/hid.h @@ -0,0 +1,1180 @@ +#if !defined(__HID_H__) +#define __HID_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" + +#define DATA_SIZE_MASK 0x03 +#define TYPE_MASK 0x0C +#define TAG_MASK 0xF0 + +#define DATA_SIZE_0 0x00 +#define DATA_SIZE_1 0x01 +#define DATA_SIZE_2 0x02 +#define DATA_SIZE_4 0x03 + +#define TYPE_MAIN 0x00 +#define TYPE_GLOBAL 0x04 +#define TYPE_LOCAL 0x08 + +#define TAG_MAIN_INPUT 0x80 +#define TAG_MAIN_OUTPUT 0x90 +#define TAG_MAIN_COLLECTION 0xA0 +#define TAG_MAIN_FEATURE 0xB0 +#define TAG_MAIN_ENDCOLLECTION 0xC0 + +#define TAG_GLOBAL_USAGEPAGE 0x00 +#define TAG_GLOBAL_LOGICALMIN 0x10 +#define TAG_GLOBAL_LOGICALMAX 0x20 +#define TAG_GLOBAL_PHYSMIN 0x30 +#define TAG_GLOBAL_PHYSMAX 0x40 +#define TAG_GLOBAL_UNITEXP 0x50 +#define TAG_GLOBAL_UNIT 0x60 +#define TAG_GLOBAL_REPORTSIZE 0x70 +#define TAG_GLOBAL_REPORTID 0x80 +#define TAG_GLOBAL_REPORTCOUNT 0x90 +#define TAG_GLOBAL_PUSH 0xA0 +#define TAG_GLOBAL_POP 0xB0 + +#define TAG_LOCAL_USAGE 0x00 +#define TAG_LOCAL_USAGEMIN 0x10 +#define TAG_LOCAL_USAGEMAX 0x20 + +/* HID requests */ +#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE + +/* HID constants. Not part of chapter 9 */ +/* Class-Specific Requests */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B + +/* Class Descriptor Types */ +#define HID_DESCRIPTOR_HID 0x21 +#define HID_DESCRIPTOR_REPORT 0x22 +#define HID_DESRIPTOR_PHY 0x23 + +/* Protocol Selection */ +#define BOOT_PROTOCOL 0x00 +#define RPT_PROTOCOL 0x01 + +/* HID Interface Class Code */ +#define HID_INTF 0x03 + +/* HID Interface Class SubClass Codes */ +#define HID_BOOT_INTF_SUBCLASS 0x01 + +/* HID Interface Class Protocol Codes */ +#define HID_PROTOCOL_NONE 0x00 +#define HID_PROTOCOL_KEYBOARD 0x01 +#define HID_PROTOCOL_MOUSE 0x02 + +///* HID descriptor */ +//typedef struct +//{ +// uint8_t bLength; +// uint8_t bDescriptorType; +// uint16_t bcdHID; // HID class specification release +// uint8_t bCountryCode; +// uint8_t bNumDescriptors; // Number of additional class specific descriptors +// uint8_t bDescrType; // Type of class descriptor +// uint16_t wDescriptorLength; // Total size of the Report descriptor +//} USB_HID_DESCRIPTOR; +// +//typedef struct +//{ +// uint8_t bDescrType; // Type of class descriptor +// uint16_t wDescriptorLength; // Total size of the Report descriptor +//} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; + +struct HidItemPrefix +{ + uint8_t bSize : 2; + uint8_t bType : 2; + uint8_t bTag : 4; +}; + +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value + +#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask + +#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value +#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value +#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value +#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value +#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value + +#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0 +#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1 +#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2 +#define HID_MAIN_ITEM_COLLECTION_REPORT 3 +#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4 +#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5 +#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6 + +struct MainItemIOFeature +{ + uint8_t bmIsConstantOrData : 1; + uint8_t bmIsArrayOrVariable : 1; + uint8_t bmIsRelativeOrAbsolute : 1; + uint8_t bmIsWrapOrNoWrap : 1; + uint8_t bmIsNonLonearOrLinear : 1; + uint8_t bmIsNoPreferedOrPrefered : 1; + uint8_t bmIsNullOrNoNull : 1; + uint8_t bmIsVolatileOrNonVolatile : 1; +}; + +class ReportDescParser : public USBReadParser +{ +public: + typedef void (*UsagePageFunc)(uint16_t usage); + +private: + //static UsagePageFunc usagePageFunctions[]; + + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; + + uint8_t itemParseState; // Item parser state variable + uint8_t itemSize; // Item size + uint8_t itemPrefix; // Item prefix (first byte) + + uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn); + + UsagePageFunc pfUsage; + + static void PrintUsagePage(uint16_t page); + static void PrintGenericDesktopPageUsage(uint16_t usage); + static void PrintSimulationControlsPageUsage(uint16_t usage); + static void PrintVRControlsPageUsage(uint16_t usage); + static void PrintSportsControlsPageUsage(uint16_t usage); + static void PrintGameControlsPageUsage(uint16_t usage); + static void PrintGenericDeviceControlsPageUsage(uint16_t usage); + static void PrintLEDPageUsage(uint16_t usage); + static void PrintTelephonyPageUsage(uint16_t usage); + static void PrintConsumerPageUsage(uint16_t usage); + static void PrintDigitizerPageUsage(uint16_t usage); + static void PrintAlphanumDisplayPageUsage(uint16_t usage); + static void PrintMedicalInstrumentPageUsage(uint16_t usage); + +public: + ReportDescParser() : + itemParseState(0), + itemSize(0), + itemPrefix(0), + pfUsage(NULL) + {}; + + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); + + enum + { + enErrorSuccess = 0 + , enErrorIncomplete // value or record is partialy read in buffer + , enErrorBufferTooSmall + }; +}; + + +#define maxHidInterfaces 3 +#define maxEpPerInterface 2 +#define totalEndpoints (maxHidInterfaces * maxEpPerInterface + 1) + +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +class HID : public USBDeviceConfig, public UsbConfigXtracter +{ + // HID class specific descriptor type and length info obtained from HID descriptor + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS]; + + // Returns HID class specific descriptor length by its type and order number + uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num); + + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + static const uint8_t epInterruptOutIndex; // InterruptOUT endpoint index + + EpInfo epInfo[totalEndpoints]; + + struct HIDInterface + { + struct + { + uint8_t bmInterface : 3; + uint8_t bmAltSet : 3; + uint8_t bmProtocol : 2; + }; + uint8_t epIndex[maxEpPerInterface]; + }; + + HIDInterface hidInterfaces[maxHidInterfaces]; + + USB *pUsb; // USB class instance pointer + uint8_t bAddress; // address + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + void Initialize(); + HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto); + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + +public: + HID(USB *p); + + uint8_t setProto( uint8_t ep, uint8_t iface, uint8_t protocol ); + uint8_t getProto( uint8_t ep, uint8_t iface, uint8_t* dataptr ); + + uint8_t getReportDescr( uint8_t ep, USBReadParser *parser = NULL); + + uint8_t getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr ); + //uint8_t getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t iface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ); + uint8_t setReport( uint8_t ep, uint16_t nbytes, uint8_t iface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ); + uint8_t getReport( uint8_t ep, uint16_t nbytes, uint8_t iface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ); + uint8_t getIdle( uint8_t ep, uint8_t iface, uint8_t reportID, uint8_t* dataptr ); + uint8_t setIdle( uint8_t ep, uint8_t iface, uint8_t reportID, uint8_t duration ); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) {}; + //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) {}; + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +const char pstrSpace [] PROGMEM = " "; +const char pstrCRLF [] PROGMEM = "\r\n"; +const char pstrSingleTab [] PROGMEM = "\t"; +const char pstrDoubleTab [] PROGMEM = "\t\t"; +const char pstrTripleTab [] PROGMEM = "\t\t\t"; + +// Usage Page String Titles +const char pstrUsagePageUndefined [] PROGMEM = "Undef"; +const char pstrUsagePageGenericDesktopControls [] PROGMEM = "Gen Desktop Ctrls"; +const char pstrUsagePageSimulationControls [] PROGMEM = "Simu Ctrls"; +const char pstrUsagePageVRControls [] PROGMEM = "VR Ctrls"; +const char pstrUsagePageSportControls [] PROGMEM = "Sport Ctrls"; +const char pstrUsagePageGameControls [] PROGMEM = "Game Ctrls"; +const char pstrUsagePageGenericDeviceControls [] PROGMEM = "Gen Dev Ctrls"; +const char pstrUsagePageKeyboardKeypad [] PROGMEM = "Kbrd/Keypad"; +const char pstrUsagePageLEDs [] PROGMEM = "LEDs"; +const char pstrUsagePageButton [] PROGMEM = "Button"; +const char pstrUsagePageOrdinal [] PROGMEM = "Ordinal"; +const char pstrUsagePageTelephone [] PROGMEM = "Tel"; +const char pstrUsagePageConsumer [] PROGMEM = "Consumer"; +const char pstrUsagePageDigitizer [] PROGMEM = "Digitizer"; +const char pstrUsagePagePID [] PROGMEM = "PID"; +const char pstrUsagePageUnicode [] PROGMEM = "Unicode"; +const char pstrUsagePageAlphaNumericDisplay [] PROGMEM = "Alpha Num Disp"; +const char pstrUsagePageMedicalInstruments [] PROGMEM = "Medical Instr"; +const char pstrUsagePageMonitor [] PROGMEM = "Monitor"; +const char pstrUsagePagePower [] PROGMEM = "Power"; +const char pstrUsagePageBarCodeScanner [] PROGMEM = "Bar Code Scan"; +const char pstrUsagePageScale [] PROGMEM = "Scale"; +const char pstrUsagePageMSRDevices [] PROGMEM = "Magn Stripe Read Dev"; +const char pstrUsagePagePointOfSale [] PROGMEM = "POS"; +const char pstrUsagePageCameraControl [] PROGMEM = "Cam Ctrl"; +const char pstrUsagePageArcade [] PROGMEM = "Arcade"; +const char pstrUsagePageReserved [] PROGMEM = "Reserved"; +const char pstrUsagePageVendorDefined [] PROGMEM = "Vendor Def"; + +// Generic Desktop Controls Page +const char pstrUsagePointer [] PROGMEM = "Pointer"; +const char pstrUsageMouse [] PROGMEM = "Mouse"; +const char pstrUsageJoystick [] PROGMEM = "Joystick"; +const char pstrUsageGamePad [] PROGMEM = "Game Pad"; +const char pstrUsageKeyboard [] PROGMEM = "Kbrd"; +const char pstrUsageKeypad [] PROGMEM = "Keypad"; +const char pstrUsageMultiAxisController [] PROGMEM = "Multi-axis Ctrl"; +const char pstrUsageTabletPCSystemControls [] PROGMEM = "Tablet PC Sys Ctrls"; +const char pstrUsageX [] PROGMEM = "X"; +const char pstrUsageY [] PROGMEM = "Y"; +const char pstrUsageZ [] PROGMEM = "Z"; +const char pstrUsageRx [] PROGMEM = "Rx"; +const char pstrUsageRy [] PROGMEM = "Ry"; +const char pstrUsageRz [] PROGMEM = "Rz"; +const char pstrUsageSlider [] PROGMEM = "Slider"; +const char pstrUsageDial [] PROGMEM = "Dial"; +const char pstrUsageWheel [] PROGMEM = "Wheel"; +const char pstrUsageHatSwitch [] PROGMEM = "Hat Switch"; +const char pstrUsageCountedBuffer [] PROGMEM = "Counted Buf"; +const char pstrUsageByteCount [] PROGMEM = "Byte Count"; +const char pstrUsageMotionWakeup [] PROGMEM = "Motion Wakeup"; +const char pstrUsageStart [] PROGMEM = "Start"; +const char pstrUsageSelect [] PROGMEM = "Sel"; +const char pstrUsageVx [] PROGMEM = "Vx"; +const char pstrUsageVy [] PROGMEM = "Vy"; +const char pstrUsageVz [] PROGMEM = "Vz"; +const char pstrUsageVbrx [] PROGMEM = "Vbrx"; +const char pstrUsageVbry [] PROGMEM = "Vbry"; +const char pstrUsageVbrz [] PROGMEM = "Vbrz"; +const char pstrUsageVno [] PROGMEM = "Vno"; +const char pstrUsageFeatureNotification [] PROGMEM = "Feature Notif"; +const char pstrUsageResolutionMultiplier [] PROGMEM = "Res Mult"; +const char pstrUsageSystemControl [] PROGMEM = "Sys Ctrl"; +const char pstrUsageSystemPowerDown [] PROGMEM = "Sys Pwr Down"; +const char pstrUsageSystemSleep [] PROGMEM = "Sys Sleep"; +const char pstrUsageSystemWakeup [] PROGMEM = "Sys Wakeup"; +const char pstrUsageSystemContextMenu [] PROGMEM = "Sys Context Menu"; +const char pstrUsageSystemMainMenu [] PROGMEM = "Sys Main Menu"; +const char pstrUsageSystemAppMenu [] PROGMEM = "Sys App Menu"; +const char pstrUsageSystemMenuHelp [] PROGMEM = "Sys Menu Help"; +const char pstrUsageSystemMenuExit [] PROGMEM = "Sys Menu Exit"; +const char pstrUsageSystemMenuSelect [] PROGMEM = "Sys Menu Select"; +const char pstrUsageSystemMenuRight [] PROGMEM = "Sys Menu Right"; +const char pstrUsageSystemMenuLeft [] PROGMEM = "Sys Menu Left"; +const char pstrUsageSystemMenuUp [] PROGMEM = "Sys Menu Up"; +const char pstrUsageSystemMenuDown [] PROGMEM = "Sys Menu Down"; +const char pstrUsageSystemColdRestart [] PROGMEM = "Sys Cold Restart"; +const char pstrUsageSystemWarmRestart [] PROGMEM = "Sys Warm Restart"; +const char pstrUsageDPadUp [] PROGMEM = "D-pad Up"; +const char pstrUsageDPadDown [] PROGMEM = "D-pad Down"; +const char pstrUsageDPadRight [] PROGMEM = "D-pad Right"; +const char pstrUsageDPadLeft [] PROGMEM = "D-pad Left"; +const char pstrUsageSystemDock [] PROGMEM = "Sys Dock"; +const char pstrUsageSystemUndock [] PROGMEM = "Sys Undock"; +const char pstrUsageSystemSetup [] PROGMEM = "Sys Setup"; +const char pstrUsageSystemBreak [] PROGMEM = "Sys Break"; +const char pstrUsageSystemDebuggerBreak [] PROGMEM = "Sys Dbg Brk"; +const char pstrUsageApplicationBreak [] PROGMEM = "App Break"; +const char pstrUsageApplicationDebuggerBreak [] PROGMEM = "App Dbg Brk"; +const char pstrUsageSystemSpeakerMute [] PROGMEM = "Sys Spk Mute"; +const char pstrUsageSystemHibernate [] PROGMEM = "Sys Hiber"; +const char pstrUsageSystemDisplayInvert [] PROGMEM = "Sys Disp Inv"; +const char pstrUsageSystemDisplayInternal [] PROGMEM = "Sys Disp Int"; +const char pstrUsageSystemDisplayExternal [] PROGMEM = "Sys Disp Ext"; +const char pstrUsageSystemDisplayBoth [] PROGMEM = "Sys Disp Both"; +const char pstrUsageSystemDisplayDual [] PROGMEM = "Sys Disp Dual"; +const char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = "Sys Disp Tgl Int/Ext"; +const char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = "Sys Disp Swap Pri/Sec"; +const char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = "Sys Disp LCD Autoscale"; + +// Simulation Controls Page +const char pstrUsageFlightSimulationDevice [] PROGMEM = "Flight Simu Dev"; +const char pstrUsageAutomobileSimulationDevice [] PROGMEM = "Auto Simu Dev"; +const char pstrUsageTankSimulationDevice [] PROGMEM = "Tank Simu Dev"; +const char pstrUsageSpaceshipSimulationDevice [] PROGMEM = "Space Simu Dev"; +const char pstrUsageSubmarineSimulationDevice [] PROGMEM = "Subm Simu Dev"; +const char pstrUsageSailingSimulationDevice [] PROGMEM = "Sail Simu Dev"; +const char pstrUsageMotocicleSimulationDevice [] PROGMEM = "Moto Simu Dev"; +const char pstrUsageSportsSimulationDevice [] PROGMEM = "Sport Simu Dev"; +const char pstrUsageAirplaneSimulationDevice [] PROGMEM = "Airp Simu Dev"; +const char pstrUsageHelicopterSimulationDevice [] PROGMEM = "Heli Simu Dev"; +const char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = "Magic Carpet Simu Dev"; +const char pstrUsageBicycleSimulationDevice [] PROGMEM = "Bike Simu Dev"; +const char pstrUsageFlightControlStick [] PROGMEM = "Flight Ctrl Stick"; +const char pstrUsageFlightStick [] PROGMEM = "Flight Stick"; +const char pstrUsageCyclicControl [] PROGMEM = "Cyclic Ctrl"; +const char pstrUsageCyclicTrim [] PROGMEM = "Cyclic Trim"; +const char pstrUsageFlightYoke [] PROGMEM = "Flight Yoke"; +const char pstrUsageTrackControl [] PROGMEM = "Track Ctrl"; +const char pstrUsageAileron [] PROGMEM = "Aileron"; +const char pstrUsageAileronTrim [] PROGMEM = "Aileron Trim"; +const char pstrUsageAntiTorqueControl [] PROGMEM = "Anti-Torque Ctrl"; +const char pstrUsageAutopilotEnable [] PROGMEM = "Autopilot Enable"; +const char pstrUsageChaffRelease [] PROGMEM = "Chaff Release"; +const char pstrUsageCollectiveControl [] PROGMEM = "Collective Ctrl"; +const char pstrUsageDiveBrake [] PROGMEM = "Dive Brake"; +const char pstrUsageElectronicCountermeasures [] PROGMEM = "El Countermeasures"; +const char pstrUsageElevator [] PROGMEM = "Elevator"; +const char pstrUsageElevatorTrim [] PROGMEM = "Elevator Trim"; +const char pstrUsageRudder [] PROGMEM = "Rudder"; +const char pstrUsageThrottle [] PROGMEM = "Throttle"; +const char pstrUsageFlightCommunications [] PROGMEM = "Flight Comm"; +const char pstrUsageFlareRelease [] PROGMEM = "Flare Release"; +const char pstrUsageLandingGear [] PROGMEM = "Landing Gear"; +const char pstrUsageToeBrake [] PROGMEM = "Toe Brake"; +const char pstrUsageTrigger [] PROGMEM = "Trigger"; +const char pstrUsageWeaponsArm [] PROGMEM = "Weapons Arm"; +const char pstrUsageWeaponsSelect [] PROGMEM = "Weapons Sel"; +const char pstrUsageWingFlaps [] PROGMEM = "Wing Flaps"; +const char pstrUsageAccelerator [] PROGMEM = "Accel"; +const char pstrUsageBrake [] PROGMEM = "Brake"; +const char pstrUsageClutch [] PROGMEM = "Clutch"; +const char pstrUsageShifter [] PROGMEM = "Shifter"; +const char pstrUsageSteering [] PROGMEM = "Steering"; +const char pstrUsageTurretDirection [] PROGMEM = "Turret Dir"; +const char pstrUsageBarrelElevation [] PROGMEM = "Barrel Ele"; +const char pstrUsageDivePlane [] PROGMEM = "Dive Plane"; +const char pstrUsageBallast [] PROGMEM = "Ballast"; +const char pstrUsageBicycleCrank [] PROGMEM = "Bicycle Crank"; +const char pstrUsageHandleBars [] PROGMEM = "Handle Bars"; +const char pstrUsageFrontBrake [] PROGMEM = "Front Brake"; +const char pstrUsageRearBrake [] PROGMEM = "Rear Brake"; + +// VR Controls Page +const char pstrUsageBelt [] PROGMEM = "Belt"; +const char pstrUsageBodySuit [] PROGMEM = "Body Suit"; +const char pstrUsageFlexor [] PROGMEM = "Flexor"; +const char pstrUsageGlove [] PROGMEM = "Glove"; +const char pstrUsageHeadTracker [] PROGMEM = "Head Track"; +const char pstrUsageHeadMountedDisplay [] PROGMEM = "Head Disp"; +const char pstrUsageHandTracker [] PROGMEM = "Hand Track"; +const char pstrUsageOculometer [] PROGMEM = "Oculometer"; +const char pstrUsageVest [] PROGMEM = "Vest"; +const char pstrUsageAnimatronicDevice [] PROGMEM = "Animat Dev"; +const char pstrUsageStereoEnable [] PROGMEM = "Stereo Enbl"; +const char pstrUsageDisplayEnable [] PROGMEM = "Display Enbl"; + +// Sport Controls Page +const char pstrUsageBaseballBat [] PROGMEM = "Baseball Bat"; +const char pstrUsageGolfClub [] PROGMEM = "Golf Club"; +const char pstrUsageRowingMachine [] PROGMEM = "Rowing Mach"; +const char pstrUsageTreadmill [] PROGMEM = "Treadmill"; +const char pstrUsageOar [] PROGMEM = "Oar"; +const char pstrUsageSlope [] PROGMEM = "Slope"; +const char pstrUsageRate [] PROGMEM = "Rate"; +const char pstrUsageStickSpeed [] PROGMEM = "Stick Speed"; +const char pstrUsageStickFaceAngle [] PROGMEM = "Stick Face Ang"; +const char pstrUsageStickHeelToe [] PROGMEM = "Stick Heel/Toe"; +const char pstrUsageStickFollowThough [] PROGMEM = "Stick Flw Thru"; +const char pstrUsageStickTempo [] PROGMEM = "Stick Tempo"; +const char pstrUsageStickType [] PROGMEM = "Stick Type"; +const char pstrUsageStickHeight [] PROGMEM = "Stick Hght"; +const char pstrUsagePutter [] PROGMEM = "Putter"; +const char pstrUsage1Iron [] PROGMEM = "1 Iron"; +const char pstrUsage2Iron [] PROGMEM = "2 Iron"; +const char pstrUsage3Iron [] PROGMEM = "3 Iron"; +const char pstrUsage4Iron [] PROGMEM = "4 Iron"; +const char pstrUsage5Iron [] PROGMEM = "5 Iron"; +const char pstrUsage6Iron [] PROGMEM = "6 Iron"; +const char pstrUsage7Iron [] PROGMEM = "7 Iron"; +const char pstrUsage8Iron [] PROGMEM = "8 Iron"; +const char pstrUsage9Iron [] PROGMEM = "9 Iron"; +const char pstrUsage10Iron [] PROGMEM = "10 Iron"; +const char pstrUsage11Iron [] PROGMEM = "11 Iron"; +const char pstrUsageSandWedge [] PROGMEM = "Sand Wedge"; +const char pstrUsageLoftWedge [] PROGMEM = "Loft Wedge"; +const char pstrUsagePowerWedge [] PROGMEM = "Pwr Wedge"; +const char pstrUsage1Wood [] PROGMEM = "1 Wood"; +const char pstrUsage3Wood [] PROGMEM = "3 Wood"; +const char pstrUsage5Wood [] PROGMEM = "5 Wood"; +const char pstrUsage7Wood [] PROGMEM = "7 Wood"; +const char pstrUsage9Wood [] PROGMEM = "9 Wood"; + +// Game Controls Page +const char pstrUsage3DGameController [] PROGMEM = "3D Game Ctrl"; +const char pstrUsagePinballDevice [] PROGMEM = "Pinball Dev"; +const char pstrUsageGunDevice [] PROGMEM = "Gun Dev"; +const char pstrUsagePointOfView [] PROGMEM = "POV"; +const char pstrUsageTurnRightLeft [] PROGMEM = "Turn Right Left"; +const char pstrUsagePitchForwardBackward [] PROGMEM = "Pitch Fwd/Back"; +const char pstrUsageRollRightLeft [] PROGMEM = "Roll Right/Left"; +const char pstrUsageMoveRightLeft [] PROGMEM = "Move Right/Left"; +const char pstrUsageMoveForwardBackward [] PROGMEM = "Move Fwd/Back"; +const char pstrUsageMoveUpDown [] PROGMEM = "Move Up/Down"; +const char pstrUsageLeanRightLeft [] PROGMEM = "Lean Right/Left"; +const char pstrUsageLeanForwardBackward [] PROGMEM = "Lean Fwd/Back"; +const char pstrUsageHeightOfPOV [] PROGMEM = "Height of POV"; +const char pstrUsageFlipper [] PROGMEM = "Flipper"; +const char pstrUsageSecondaryFlipper [] PROGMEM = "Second Flipper"; +const char pstrUsageBump [] PROGMEM = "Bump"; +const char pstrUsageNewGame [] PROGMEM = "New Game"; +const char pstrUsageShootBall [] PROGMEM = "Shoot Ball"; +const char pstrUsagePlayer [] PROGMEM = "Player"; +const char pstrUsageGunBolt [] PROGMEM = "Gun Bolt"; +const char pstrUsageGunClip [] PROGMEM = "Gun Clip"; +const char pstrUsageGunSelector [] PROGMEM = "Gun Sel"; +const char pstrUsageGunSingleShot [] PROGMEM = "Gun Sngl Shot"; +const char pstrUsageGunBurst [] PROGMEM = "Gun Burst"; +const char pstrUsageGunAutomatic [] PROGMEM = "Gun Auto"; +const char pstrUsageGunSafety [] PROGMEM = "Gun Safety"; +const char pstrUsageGamepadFireJump [] PROGMEM = "Gamepad Fire/Jump"; +const char pstrUsageGamepadTrigger [] PROGMEM = "Gamepad Trig"; + +// Generic Device Controls Page +const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; +const char pstrUsageWirelessChannel [] PROGMEM = "Wireless Ch"; +const char pstrUsageWirelessID [] PROGMEM = "Wireless ID"; +const char pstrUsageDiscoverWirelessControl [] PROGMEM = "Discover Wireless Ctrl"; +const char pstrUsageSecurityCodeCharEntered [] PROGMEM = "Sec Code Char Entrd"; +const char pstrUsageSecurityCodeCharErased [] PROGMEM = "Sec Code Char Erased"; +const char pstrUsageSecurityCodeCleared [] PROGMEM = "Sec Code Cleared"; + +// LED Page +const char pstrUsageNumLock [] PROGMEM = "Num Lock"; +const char pstrUsageCapsLock [] PROGMEM = "Caps Lock"; +const char pstrUsageScrollLock [] PROGMEM = "Scroll Lock"; +const char pstrUsageCompose [] PROGMEM = "Compose"; +const char pstrUsageKana [] PROGMEM = "Kana"; +const char pstrUsagePower [] PROGMEM = "Pwr"; +const char pstrUsageShift [] PROGMEM = "Shift"; +const char pstrUsageDoNotDisturb [] PROGMEM = "DND"; +const char pstrUsageMute [] PROGMEM = "Mute"; +const char pstrUsageToneEnable [] PROGMEM = "Tone Enbl"; +const char pstrUsageHighCutFilter [] PROGMEM = "High Cut Fltr"; +const char pstrUsageLowCutFilter [] PROGMEM = "Low Cut Fltr"; +const char pstrUsageEqualizerEnable [] PROGMEM = "Eq Enbl"; +const char pstrUsageSoundFieldOn [] PROGMEM = "Sound Field On"; +const char pstrUsageSurroundOn [] PROGMEM = "Surround On"; +const char pstrUsageRepeat [] PROGMEM = "Repeat"; +const char pstrUsageStereo [] PROGMEM = "Stereo"; +const char pstrUsageSamplingRateDetect [] PROGMEM = "Smpl Rate Detect"; +const char pstrUsageSpinning [] PROGMEM = "Spinning"; +const char pstrUsageCAV [] PROGMEM = "CAV"; +const char pstrUsageCLV [] PROGMEM = "CLV"; +const char pstrUsageRecordingFormatDetect [] PROGMEM = "Rec Format Detect"; +const char pstrUsageOffHook [] PROGMEM = "Off Hook"; +const char pstrUsageRing [] PROGMEM = "Ring"; +const char pstrUsageMessageWaiting [] PROGMEM = "Msg Wait"; +const char pstrUsageDataMode [] PROGMEM = "Data Mode"; +const char pstrUsageBatteryOperation [] PROGMEM = "Bat Op"; +const char pstrUsageBatteryOK [] PROGMEM = "Bat OK"; +const char pstrUsageBatteryLow [] PROGMEM = "Bat Low"; +const char pstrUsageSpeaker [] PROGMEM = "Speaker"; +const char pstrUsageHeadSet [] PROGMEM = "Head Set"; +const char pstrUsageHold [] PROGMEM = "Hold"; +const char pstrUsageMicrophone [] PROGMEM = "Mic"; +const char pstrUsageCoverage [] PROGMEM = "Coverage"; +const char pstrUsageNightMode [] PROGMEM = "Night Mode"; +const char pstrUsageSendCalls [] PROGMEM = "Send Calls"; +const char pstrUsageCallPickup [] PROGMEM = "Call Pickup"; +const char pstrUsageConference [] PROGMEM = "Conf"; +const char pstrUsageStandBy [] PROGMEM = "Stand-by"; +const char pstrUsageCameraOn [] PROGMEM = "Cam On"; +const char pstrUsageCameraOff [] PROGMEM = "Cam Off"; +const char pstrUsageOnLine [] PROGMEM = "On-Line"; +const char pstrUsageOffLine [] PROGMEM = "Off-Line"; +const char pstrUsageBusy [] PROGMEM = "Busy"; +const char pstrUsageReady [] PROGMEM = "Ready"; +const char pstrUsagePaperOut [] PROGMEM = "Paper Out"; +const char pstrUsagePaperJam [] PROGMEM = "Paper Jam"; +const char pstrUsageRemote [] PROGMEM = "Remote"; +const char pstrUsageForward [] PROGMEM = "Fwd"; +const char pstrUsageReverse [] PROGMEM = "Rev"; +const char pstrUsageStop [] PROGMEM = "Stop"; +const char pstrUsageRewind [] PROGMEM = "Rewind"; +const char pstrUsageFastForward [] PROGMEM = "Fast Fwd"; +const char pstrUsagePlay [] PROGMEM = "Play"; +const char pstrUsagePause [] PROGMEM = "Pause"; +const char pstrUsageRecord [] PROGMEM = "Rec"; +const char pstrUsageError [] PROGMEM = "Error"; +const char pstrUsageSelectedIndicator [] PROGMEM = "Usage Sel Ind"; +const char pstrUsageInUseIndicator [] PROGMEM = "Usage In Use Ind"; +const char pstrUsageMultiModeIndicator [] PROGMEM = "Usage Multi Mode Ind"; +const char pstrUsageIndicatorOn [] PROGMEM = "Ind On"; +const char pstrUsageIndicatorFlash [] PROGMEM = "Ind Flash"; +const char pstrUsageIndicatorSlowBlink [] PROGMEM = "Ind Slow Blk"; +const char pstrUsageIndicatorFastBlink [] PROGMEM = "Ind Fast Blk"; +const char pstrUsageIndicatorOff [] PROGMEM = "Ind Off"; +const char pstrUsageFlashOnTime [] PROGMEM = "Flash On Time"; +const char pstrUsageSlowBlinkOnTime [] PROGMEM = "Slow Blk On Time"; +const char pstrUsageSlowBlinkOffTime [] PROGMEM = "Slow Blk Off Time"; +const char pstrUsageFastBlinkOnTime [] PROGMEM = "Fast Blk On Time"; +const char pstrUsageFastBlinkOffTime [] PROGMEM = "Fast Blk Off Time"; +const char pstrUsageIndicatorColor [] PROGMEM = "Usage Ind Color"; +const char pstrUsageIndicatorRed [] PROGMEM = "Ind Red"; +const char pstrUsageIndicatorGreen [] PROGMEM = "Ind Green"; +const char pstrUsageIndicatorAmber [] PROGMEM = "Ind Amber"; +const char pstrUsageGenericIndicator [] PROGMEM = "Gen Ind"; +const char pstrUsageSystemSuspend [] PROGMEM = "Sys Suspend"; +const char pstrUsageExternalPowerConnected [] PROGMEM = "Ext Pwr Conn"; + +// Telephony Usage Page +const char pstrUsagePhone [] PROGMEM = "Phone"; +const char pstrUsageAnsweringMachine [] PROGMEM = "Answ Mach"; +const char pstrUsageMessageControls [] PROGMEM = "Msg Ctrls"; +const char pstrUsageHandset [] PROGMEM = "Handset"; +const char pstrUsageHeadset [] PROGMEM = "Headset"; +const char pstrUsageTelephonyKeyPad [] PROGMEM = "Tel Key Pad"; +const char pstrUsageProgrammableButton [] PROGMEM = "Prog Button"; +const char pstrUsageHookSwitch [] PROGMEM = "Hook Sw"; +const char pstrUsageFlash [] PROGMEM = "Flash"; +const char pstrUsageFeature [] PROGMEM = "Feature"; +//const char pstrUsageHold [] PROGMEM = "Hold"; +const char pstrUsageRedial [] PROGMEM = "Redial"; +const char pstrUsageTransfer [] PROGMEM = "Transfer"; +const char pstrUsageDrop [] PROGMEM = "Drop"; +const char pstrUsagePark [] PROGMEM = "Park"; +const char pstrUsageForwardCalls [] PROGMEM = "Fwd Calls"; +const char pstrUsageAlternateFunction [] PROGMEM = "Alt Func"; +const char pstrUsageLine [] PROGMEM = "Line"; +const char pstrUsageSpeakerPhone [] PROGMEM = "Spk Phone"; +//const char pstrUsageConference [] PROGMEM = "Conference"; +const char pstrUsageRingEnable [] PROGMEM = "Ring Enbl"; +const char pstrUsageRingSelect [] PROGMEM = "Ring Sel"; +const char pstrUsagePhoneMute [] PROGMEM = "Phone Mute"; +const char pstrUsageCallerID [] PROGMEM = "Caller ID"; +const char pstrUsageSend [] PROGMEM = "Send"; +const char pstrUsageSpeedDial [] PROGMEM = "Speed Dial"; +const char pstrUsageStoreNumber [] PROGMEM = "Store Num"; +const char pstrUsageRecallNumber [] PROGMEM = "Recall Num"; +const char pstrUsagePhoneDirectory [] PROGMEM = "Phone Dir"; +const char pstrUsageVoiceMail [] PROGMEM = "Voice Mail"; +const char pstrUsageScreenCalls [] PROGMEM = "Screen Calls"; +//const char pstrUsageDoNotDisturb [] PROGMEM = "Do Not Disturb"; +const char pstrUsageMessage [] PROGMEM = "Msg"; +const char pstrUsageAnswerOnOff [] PROGMEM = "Answer On/Off"; +const char pstrUsageInsideDialTone [] PROGMEM = "Inside Dial Tone"; +const char pstrUsageOutsideDialTone [] PROGMEM = "Outside Dial Tone"; +const char pstrUsageInsideRingTone [] PROGMEM = "Inside Ring Tone"; +const char pstrUsageOutsideRingTone [] PROGMEM = "Outside Ring Tone"; +const char pstrUsagePriorityRingTone [] PROGMEM = "Prior Ring Tone"; +const char pstrUsageInsideRingback [] PROGMEM = "Inside Ringback"; +const char pstrUsagePriorityRingback [] PROGMEM = "Priority Ringback"; +const char pstrUsageLineBusyTone [] PROGMEM = "Ln Busy Tone"; +const char pstrUsageReorderTone [] PROGMEM = "Reorder Tone"; +const char pstrUsageCallWaitingTone [] PROGMEM = "Call Wait Tone"; +const char pstrUsageConfirmationTone1 [] PROGMEM = "Cnfrm Tone1"; +const char pstrUsageConfirmationTone2 [] PROGMEM = "Cnfrm Tone2"; +const char pstrUsageTonesOff [] PROGMEM = "Tones Off"; +const char pstrUsageOutsideRingback [] PROGMEM = "Outside Ringback"; +const char pstrUsageRinger [] PROGMEM = "Ringer"; +const char pstrUsagePhoneKey0 [] PROGMEM = "0"; +const char pstrUsagePhoneKey1 [] PROGMEM = "1"; +const char pstrUsagePhoneKey2 [] PROGMEM = "2"; +const char pstrUsagePhoneKey3 [] PROGMEM = "3"; +const char pstrUsagePhoneKey4 [] PROGMEM = "4"; +const char pstrUsagePhoneKey5 [] PROGMEM = "5"; +const char pstrUsagePhoneKey6 [] PROGMEM = "6"; +const char pstrUsagePhoneKey7 [] PROGMEM = "7"; +const char pstrUsagePhoneKey8 [] PROGMEM = "8"; +const char pstrUsagePhoneKey9 [] PROGMEM = "9"; +const char pstrUsagePhoneKeyStar [] PROGMEM = "*"; +const char pstrUsagePhoneKeyPound [] PROGMEM = "#"; +const char pstrUsagePhoneKeyA [] PROGMEM = "A"; +const char pstrUsagePhoneKeyB [] PROGMEM = "B"; +const char pstrUsagePhoneKeyC [] PROGMEM = "C"; +const char pstrUsagePhoneKeyD [] PROGMEM = "D"; + +// Consumer Usage Page +const char pstrUsageConsumerControl [] PROGMEM = "Consumer Ctrl"; +const char pstrUsageNumericKeyPad [] PROGMEM = "Num Key Pad"; +//const char pstrUsageProgrammableButton [] PROGMEM = "Prog Btn"; +//const char pstrUsageMicrophone [] PROGMEM = "Mic"; +const char pstrUsageHeadphone [] PROGMEM = "Headphone"; +const char pstrUsageGraphicEqualizer [] PROGMEM = "Graph Eq"; +const char pstrUsagePlus10 [] PROGMEM = "+10"; +const char pstrUsagePlus100 [] PROGMEM = "+100"; +const char pstrUsageAMPM [] PROGMEM = "AM/PM"; +//const char pstrUsagePower [] PROGMEM = "Pwr"; +const char pstrUsageReset [] PROGMEM = "Reset"; +const char pstrUsageSleep [] PROGMEM = "Sleep"; +const char pstrUsageSleepAfter [] PROGMEM = "Sleep After"; +const char pstrUsageSleepMode [] PROGMEM = "Sleep Mode"; +const char pstrUsageIllumination [] PROGMEM = "Illumin"; +const char pstrUsageFunctionButtons [] PROGMEM = "Func Btns"; +const char pstrUsageMenu [] PROGMEM = "Menu"; +const char pstrUsageMenuPick [] PROGMEM = "Menu Pick"; +const char pstrUsageMenuUp [] PROGMEM = "Menu Up"; +const char pstrUsageMenuDown [] PROGMEM = "Menu Down"; +const char pstrUsageMenuLeft [] PROGMEM = "Menu Left"; +const char pstrUsageMenuRight [] PROGMEM = "Menu Right"; +const char pstrUsageMenuEscape [] PROGMEM = "Menu Esc"; +const char pstrUsageMenuValueIncrease [] PROGMEM = "Menu Val Inc"; +const char pstrUsageMenuValueDecrease [] PROGMEM = "Menu Val Dec"; +const char pstrUsageDataOnScreen [] PROGMEM = "Data On Scr"; +const char pstrUsageClosedCaption [] PROGMEM = "Closed Cptn"; +const char pstrUsageClosedCaptionSelect [] PROGMEM = "Closed Cptn Sel"; +const char pstrUsageVCRTV [] PROGMEM = "VCR/TV"; +const char pstrUsageBroadcastMode [] PROGMEM = "Brdcast Mode"; +const char pstrUsageSnapshot [] PROGMEM = "Snapshot"; +const char pstrUsageStill [] PROGMEM = "Still"; +const char pstrUsageSelection [] PROGMEM = "Sel"; +const char pstrUsageAssignSelection [] PROGMEM = "Assign Sel"; +const char pstrUsageModeStep [] PROGMEM = "Mode Step"; +const char pstrUsageRecallLast [] PROGMEM = "Recall Last"; +const char pstrUsageEnterChannel [] PROGMEM = "Entr Channel"; +const char pstrUsageOrderMovie [] PROGMEM = "Ord Movie"; +const char pstrUsageChannel [] PROGMEM = "Channel"; +const char pstrUsageMediaSelection [] PROGMEM = "Med Sel"; +const char pstrUsageMediaSelectComputer [] PROGMEM = "Med Sel Comp"; +const char pstrUsageMediaSelectTV [] PROGMEM = "Med Sel TV"; +const char pstrUsageMediaSelectWWW [] PROGMEM = "Med Sel WWW"; +const char pstrUsageMediaSelectDVD [] PROGMEM = "Med Sel DVD"; +const char pstrUsageMediaSelectTelephone [] PROGMEM = "Med Sel Tel"; +const char pstrUsageMediaSelectProgramGuide [] PROGMEM = "Med Sel PG"; +const char pstrUsageMediaSelectVideoPhone [] PROGMEM = "Med Sel Vid"; +const char pstrUsageMediaSelectGames [] PROGMEM = "Med Sel Games"; +const char pstrUsageMediaSelectMessages [] PROGMEM = "Med Sel Msg"; +const char pstrUsageMediaSelectCD [] PROGMEM = "Med Sel CD"; +const char pstrUsageMediaSelectVCR [] PROGMEM = "Med Sel VCR"; +const char pstrUsageMediaSelectTuner [] PROGMEM = "Med Sel Tuner"; +const char pstrUsageQuit [] PROGMEM = "Quit"; +const char pstrUsageHelp [] PROGMEM = "Help"; +const char pstrUsageMediaSelectTape [] PROGMEM = "Med Sel Tape"; +const char pstrUsageMediaSelectCable [] PROGMEM = "Med Sel Cbl"; +const char pstrUsageMediaSelectSatellite [] PROGMEM = "Med Sel Sat"; +const char pstrUsageMediaSelectSecurity [] PROGMEM = "Med Sel Secur"; +const char pstrUsageMediaSelectHome [] PROGMEM = "Med Sel Home"; +const char pstrUsageMediaSelectCall [] PROGMEM = "Med Sel Call"; +const char pstrUsageChannelIncrement [] PROGMEM = "Ch Inc"; +const char pstrUsageChannelDecrement [] PROGMEM = "Ch Dec"; +const char pstrUsageMediaSelectSAP [] PROGMEM = "Med Sel SAP"; +const char pstrUsageVCRPlus [] PROGMEM = "VCR+"; +const char pstrUsageOnce [] PROGMEM = "Once"; +const char pstrUsageDaily [] PROGMEM = "Daily"; +const char pstrUsageWeekly [] PROGMEM = "Weekly"; +const char pstrUsageMonthly [] PROGMEM = "Monthly"; +//const char pstrUsagePlay [] PROGMEM = "Play"; +//const char pstrUsagePause [] PROGMEM = "Pause"; +//const char pstrUsageRecord [] PROGMEM = "Rec"; +//const char pstrUsageFastForward [] PROGMEM = "FF"; +//const char pstrUsageRewind [] PROGMEM = "Rewind"; +const char pstrUsageScanNextTrack [] PROGMEM = "Next Track"; +const char pstrUsageScanPreviousTrack [] PROGMEM = "Prev Track"; +//const char pstrUsageStop [] PROGMEM = "Stop"; +const char pstrUsageEject [] PROGMEM = "Eject"; +const char pstrUsageRandomPlay [] PROGMEM = "Random"; +const char pstrUsageSelectDisk [] PROGMEM = "Sel Disk"; +const char pstrUsageEnterDisk [] PROGMEM = "Ent Disk"; +//const char pstrUsageRepeat [] PROGMEM = "Repeat"; +const char pstrUsageTracking [] PROGMEM = "Tracking"; +const char pstrUsageTrackNormal [] PROGMEM = "Trk Norm"; +const char pstrUsageSlowTracking [] PROGMEM = "Slow Trk"; +const char pstrUsageFrameForward [] PROGMEM = "Frm Fwd"; +const char pstrUsageFrameBackwards [] PROGMEM = "Frm Back"; +const char pstrUsageMark [] PROGMEM = "Mark"; +const char pstrUsageClearMark [] PROGMEM = "Clr Mark"; +const char pstrUsageRepeatFromMark [] PROGMEM = "Rpt Mark"; +const char pstrUsageReturnToMark [] PROGMEM = "Ret to Mark"; +const char pstrUsageSearchMarkForward [] PROGMEM = "Search Mark Fwd"; +const char pstrUsageSearchMarkBackwards [] PROGMEM = "Search Mark Back"; +const char pstrUsageCounterReset [] PROGMEM = "Counter Reset"; +const char pstrUsageShowCounter [] PROGMEM = "Show Counter"; +const char pstrUsageTrackingIncrement [] PROGMEM = "Track Inc"; +const char pstrUsageTrackingDecrement [] PROGMEM = "Track Dec"; +const char pstrUsageStopEject [] PROGMEM = "Stop/Eject"; +const char pstrUsagePlayPause [] PROGMEM = "Play/Pause"; +const char pstrUsagePlaySkip [] PROGMEM = "Play/Skip"; +const char pstrUsageVolume [] PROGMEM = "Vol"; +const char pstrUsageBalance [] PROGMEM = "Balance"; +//const char pstrUsageMute [] PROGMEM = "Mute"; +const char pstrUsageBass [] PROGMEM = "Bass"; +const char pstrUsageTreble [] PROGMEM = "Treble"; +const char pstrUsageBassBoost [] PROGMEM = "Bass Boost"; +const char pstrUsageSurroundMode [] PROGMEM = "Surround"; +const char pstrUsageLoudness [] PROGMEM = "Loud"; +const char pstrUsageMPX [] PROGMEM = "MPX"; +const char pstrUsageVolumeIncrement [] PROGMEM = "Vol Inc"; +const char pstrUsageVolumeDecrement [] PROGMEM = "Vol Dec"; +const char pstrUsageSpeedSelect [] PROGMEM = "Speed"; +const char pstrUsagePlaybackSpeed [] PROGMEM = "Play Speed"; +const char pstrUsageStandardPlay [] PROGMEM = "Std Play"; +const char pstrUsageLongPlay [] PROGMEM = "Long Play"; +const char pstrUsageExtendedPlay [] PROGMEM = "Ext Play"; +const char pstrUsageSlow [] PROGMEM = "Slow"; +const char pstrUsageFanEnable [] PROGMEM = "Fan Enbl"; +const char pstrUsageFanSpeed [] PROGMEM = "Fan Speed"; +const char pstrUsageLightEnable [] PROGMEM = "Light Enbl"; +const char pstrUsageLightIlluminationLevel [] PROGMEM = "Light Illum Lev"; +const char pstrUsageClimateControlEnable [] PROGMEM = "Climate Enbl"; +const char pstrUsageRoomTemperature [] PROGMEM = "Room Temp"; +const char pstrUsageSecurityEnable [] PROGMEM = "Secur Enbl"; +const char pstrUsageFireAlarm [] PROGMEM = "Fire Alm"; +const char pstrUsagePoliceAlarm [] PROGMEM = "Police Alm"; +const char pstrUsageProximity [] PROGMEM = "Prox"; +const char pstrUsageMotion [] PROGMEM = "Motion"; +const char pstrUsageDuresAlarm [] PROGMEM = "Dures Alm"; +const char pstrUsageHoldupAlarm [] PROGMEM = "Holdup Alm"; +const char pstrUsageMedicalAlarm [] PROGMEM = "Med Alm"; +const char pstrUsageBalanceRight [] PROGMEM = "Balance Right"; +const char pstrUsageBalanceLeft [] PROGMEM = "Balance Left"; +const char pstrUsageBassIncrement [] PROGMEM = "Bass Inc"; +const char pstrUsageBassDecrement [] PROGMEM = "Bass Dec"; +const char pstrUsageTrebleIncrement [] PROGMEM = "Treble Inc"; +const char pstrUsageTrebleDecrement [] PROGMEM = "Treble Dec"; +const char pstrUsageSpeakerSystem [] PROGMEM = "Spk Sys"; +const char pstrUsageChannelLeft [] PROGMEM = "Ch Left"; +const char pstrUsageChannelRight [] PROGMEM = "Ch Right"; +const char pstrUsageChannelCenter [] PROGMEM = "Ch Center"; +const char pstrUsageChannelFront [] PROGMEM = "Ch Front"; +const char pstrUsageChannelCenterFront [] PROGMEM = "Ch Cntr Front"; +const char pstrUsageChannelSide [] PROGMEM = "Ch Side"; +const char pstrUsageChannelSurround [] PROGMEM = "Ch Surround"; +const char pstrUsageChannelLowFreqEnhancement [] PROGMEM = "Ch Low Freq Enh"; +const char pstrUsageChannelTop [] PROGMEM = "Ch Top"; +const char pstrUsageChannelUnknown [] PROGMEM = "Ch Unk"; +const char pstrUsageSubChannel [] PROGMEM = "Sub-ch"; +const char pstrUsageSubChannelIncrement [] PROGMEM = "Sub-ch Inc"; +const char pstrUsageSubChannelDecrement [] PROGMEM = "Sub-ch Dec"; +const char pstrUsageAlternateAudioIncrement [] PROGMEM = "Alt Aud Inc"; +const char pstrUsageAlternateAudioDecrement [] PROGMEM = "Alt Aud Dec"; +const char pstrUsageApplicationLaunchButtons [] PROGMEM = "App Launch Btns"; +const char pstrUsageALLaunchButtonConfigTool [] PROGMEM = "AL Launch Conf Tl"; +const char pstrUsageALProgrammableButton [] PROGMEM = "AL Pgm Btn"; +const char pstrUsageALConsumerControlConfig [] PROGMEM = "AL Cons Ctrl Cfg"; +const char pstrUsageALWordProcessor [] PROGMEM = "AL Word Proc"; +const char pstrUsageALTextEditor [] PROGMEM = "AL Txt Edtr"; +const char pstrUsageALSpreadsheet [] PROGMEM = "AL Sprdsheet"; +const char pstrUsageALGraphicsEditor [] PROGMEM = "AL Graph Edtr"; +const char pstrUsageALPresentationApp [] PROGMEM = "AL Present App"; +const char pstrUsageALDatabaseApp [] PROGMEM = "AL DB App"; +const char pstrUsageALEmailReader [] PROGMEM = "AL E-mail Rdr"; +const char pstrUsageALNewsreader [] PROGMEM = "AL Newsrdr"; +const char pstrUsageALVoicemail [] PROGMEM = "AL Voicemail"; +const char pstrUsageALContactsAddressBook [] PROGMEM = "AL Addr Book"; +const char pstrUsageALCalendarSchedule [] PROGMEM = "AL Clndr/Schdlr"; +const char pstrUsageALTaskProjectManager [] PROGMEM = "AL Task/Prj Mgr"; +const char pstrUsageALLogJournalTimecard [] PROGMEM = "AL Log/Jrnl/Tmcrd"; +const char pstrUsageALCheckbookFinance [] PROGMEM = "AL Chckbook/Fin"; +const char pstrUsageALCalculator [] PROGMEM = "AL Calc"; +const char pstrUsageALAVCapturePlayback [] PROGMEM = "AL A/V Capt/Play"; +const char pstrUsageALLocalMachineBrowser [] PROGMEM = "AL Loc Mach Brow"; +const char pstrUsageALLANWANBrow [] PROGMEM = "AL LAN/WAN Brow"; +const char pstrUsageALInternetBrowser [] PROGMEM = "AL I-net Brow"; +const char pstrUsageALRemoteNetISPConnect [] PROGMEM = "AL Rem Net Con"; +const char pstrUsageALNetworkConference [] PROGMEM = "AL Net Conf"; +const char pstrUsageALNetworkChat [] PROGMEM = "AL Net Chat"; +const char pstrUsageALTelephonyDialer [] PROGMEM = "AL Tel/Dial"; +const char pstrUsageALLogon [] PROGMEM = "AL Logon"; +const char pstrUsageALLogoff [] PROGMEM = "AL Logoff"; +const char pstrUsageALLogonLogoff [] PROGMEM = "AL Logon/Logoff"; +const char pstrUsageALTermLockScrSav [] PROGMEM = "AL Term Lock/Scr Sav"; +const char pstrUsageALControlPannel [] PROGMEM = "AL Ctrl Pan"; +const char pstrUsageALCommandLineProcessorRun [] PROGMEM = "AL Cmd/Run"; +const char pstrUsageALProcessTaskManager [] PROGMEM = "AL Task Mgr"; +const char pstrUsageALSelectTaskApplication [] PROGMEM = "AL Sel App"; +const char pstrUsageALNextTaskApplication [] PROGMEM = "AL Next App"; +const char pstrUsageALPreviousTaskApplication [] PROGMEM = "AL Prev App"; +const char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = "AL Prmpt Halt App"; +const char pstrUsageALIntegratedHelpCenter [] PROGMEM = "AL Hlp Cntr"; +const char pstrUsageALDocuments [] PROGMEM = "AL Docs"; +const char pstrUsageALThesaurus [] PROGMEM = "AL Thsrs"; +const char pstrUsageALDictionary [] PROGMEM = "AL Dict"; +const char pstrUsageALDesktop [] PROGMEM = "AL Desktop"; +const char pstrUsageALSpellCheck [] PROGMEM = "AL Spell Chk"; +const char pstrUsageALGrammarCheck [] PROGMEM = "AL Gram Chk"; +const char pstrUsageALWirelessStatus [] PROGMEM = "AL Wireless Sts"; +const char pstrUsageALKeyboardLayout [] PROGMEM = "AL Kbd Layout"; +const char pstrUsageALVirusProtection [] PROGMEM = "AL Vir Protect"; +const char pstrUsageALEncryption [] PROGMEM = "AL Encrypt"; +const char pstrUsageALScreenSaver [] PROGMEM = "AL Scr Sav"; +const char pstrUsageALAlarms [] PROGMEM = "AL Alarms"; +const char pstrUsageALClock [] PROGMEM = "AL Clock"; +const char pstrUsageALFileBrowser [] PROGMEM = "AL File Brow"; +const char pstrUsageALPowerStatus [] PROGMEM = "AL Pwr Sts"; +const char pstrUsageALImageBrowser [] PROGMEM = "AL Img Brow"; +const char pstrUsageALAudioBrowser [] PROGMEM = "AL Aud Brow"; +const char pstrUsageALMovieBrowser [] PROGMEM = "AL Mov Brow"; +const char pstrUsageALDigitalRightsManager [] PROGMEM = "AL Dig Rights Mgr"; +const char pstrUsageALDigitalWallet [] PROGMEM = "AL Dig Wallet"; +const char pstrUsageALInstantMessaging [] PROGMEM = "AL Inst Msg"; +const char pstrUsageALOEMFeaturesBrowser [] PROGMEM = "AL OEM Tips Brow"; +const char pstrUsageALOEMHelp [] PROGMEM = "AL OEM Hlp"; +const char pstrUsageALOnlineCommunity [] PROGMEM = "AL Online Com"; +const char pstrUsageALEntertainmentContentBrow [] PROGMEM = "AL Ent Cont Brow"; +const char pstrUsageALOnlineShoppingBrowser [] PROGMEM = "AL Online Shop Brow"; +const char pstrUsageALSmartCardInfoHelp [] PROGMEM = "AL SmartCard Inf"; +const char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = "AL Market Brow"; +const char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = "AL Cust Corp News Brow"; +const char pstrUsageALOnlineActivityBrowser [] PROGMEM = "AL Online Act Brow"; +const char pstrUsageALResearchSearchBrowser [] PROGMEM = "AL Search Brow"; +const char pstrUsageALAudioPlayer [] PROGMEM = "AL Aud Player"; +const char pstrUsageGenericGUIAppControls [] PROGMEM = "Gen GUI App Ctrl"; +const char pstrUsageACNew [] PROGMEM = "AC New"; +const char pstrUsageACOpen [] PROGMEM = "AC Open"; +const char pstrUsageACClose [] PROGMEM = "AC Close"; +const char pstrUsageACExit [] PROGMEM = "AC Exit"; +const char pstrUsageACMaximize [] PROGMEM = "AC Max"; +const char pstrUsageACMinimize [] PROGMEM = "AC Min"; +const char pstrUsageACSave [] PROGMEM = "AC Save"; +const char pstrUsageACPrint [] PROGMEM = "AC Print"; +const char pstrUsageACProperties [] PROGMEM = "AC Prop"; +const char pstrUsageACUndo [] PROGMEM = "AC Undo"; +const char pstrUsageACCopy [] PROGMEM = "AC Copy"; +const char pstrUsageACCut [] PROGMEM = "AC Cut"; +const char pstrUsageACPaste [] PROGMEM = "AC Paste"; +const char pstrUsageACSelectAll [] PROGMEM = "AC Sel All"; +const char pstrUsageACFind [] PROGMEM = "AC Find"; +const char pstrUsageACFindAndReplace [] PROGMEM = "AC Find/Replace"; +const char pstrUsageACSearch [] PROGMEM = "AC Search"; +const char pstrUsageACGoto [] PROGMEM = "AC Goto"; +const char pstrUsageACHome [] PROGMEM = "AC Home"; +const char pstrUsageACBack [] PROGMEM = "AC Back"; +const char pstrUsageACForward [] PROGMEM = "AC Fwd"; +const char pstrUsageACStop [] PROGMEM = "AC Stop"; +const char pstrUsageACRefresh [] PROGMEM = "AC Refresh"; +const char pstrUsageACPreviousLink [] PROGMEM = "AC Prev Link"; +const char pstrUsageACNextLink [] PROGMEM = "AC Next Link"; +const char pstrUsageACBookmarks [] PROGMEM = "AC Bkmarks"; +const char pstrUsageACHistory [] PROGMEM = "AC Hist"; +const char pstrUsageACSubscriptions [] PROGMEM = "AC Subscr"; +const char pstrUsageACZoomIn [] PROGMEM = "AC Zoom In"; +const char pstrUsageACZoomOut [] PROGMEM = "AC Zoom Out"; +const char pstrUsageACZoom [] PROGMEM = "AC Zoom"; +const char pstrUsageACFullScreenView [] PROGMEM = "AC Full Scr"; +const char pstrUsageACNormalView [] PROGMEM = "AC Norm View"; +const char pstrUsageACViewToggle [] PROGMEM = "AC View Tgl"; +const char pstrUsageACScrollUp [] PROGMEM = "AC Scroll Up"; +const char pstrUsageACScrollDown [] PROGMEM = "AC Scroll Down"; +const char pstrUsageACScroll [] PROGMEM = "AC Scroll"; +const char pstrUsageACPanLeft [] PROGMEM = "AC Pan Left"; +const char pstrUsageACPanRight [] PROGMEM = "AC Pan Right"; +const char pstrUsageACPan [] PROGMEM = "AC Pan"; +const char pstrUsageACNewWindow [] PROGMEM = "AC New Wnd"; +const char pstrUsageACTileHoriz [] PROGMEM = "AC Tile Horiz"; +const char pstrUsageACTileVert [] PROGMEM = "AC Tile Vert"; +const char pstrUsageACFormat [] PROGMEM = "AC Frmt"; +const char pstrUsageACEdit [] PROGMEM = "AC Edit"; +const char pstrUsageACBold [] PROGMEM = "AC Bold"; +const char pstrUsageACItalics [] PROGMEM = "AC Ital"; +const char pstrUsageACUnderline [] PROGMEM = "AC Under"; +const char pstrUsageACStrikethrough [] PROGMEM = "AC Strike"; +const char pstrUsageACSubscript [] PROGMEM = "AC Sub"; +const char pstrUsageACSuperscript [] PROGMEM = "AC Super"; +const char pstrUsageACAllCaps [] PROGMEM = "AC All Caps"; +const char pstrUsageACRotate [] PROGMEM = "AC Rotate"; +const char pstrUsageACResize [] PROGMEM = "AC Resize"; +const char pstrUsageACFlipHorizontal [] PROGMEM = "AC Flp H"; +const char pstrUsageACFlipVertical [] PROGMEM = "AC Flp V"; +const char pstrUsageACMirrorHorizontal [] PROGMEM = "AC Mir H"; +const char pstrUsageACMirrorVertical [] PROGMEM = "AC Mir V"; +const char pstrUsageACFontSelect [] PROGMEM = "AC Fnt Sel"; +const char pstrUsageACFontColor [] PROGMEM = "AC Fnt Clr"; +const char pstrUsageACFontSize [] PROGMEM = "AC Fnt Size"; +const char pstrUsageACJustifyLeft [] PROGMEM = "AC Just Left"; +const char pstrUsageACJustifyCenterH [] PROGMEM = "AC Just Cent H"; +const char pstrUsageACJustifyRight [] PROGMEM = "AC Just Right"; +const char pstrUsageACJustifyBlockH [] PROGMEM = "AC Just Block H"; +const char pstrUsageACJustifyTop [] PROGMEM = "AC Just Top"; +const char pstrUsageACJustifyCenterV [] PROGMEM = "AC Just Cent V"; +const char pstrUsageACJustifyBottom [] PROGMEM = "AC Just Bot"; +const char pstrUsageACJustifyBlockV [] PROGMEM = "AC Just Block V"; +const char pstrUsageACIndentDecrease [] PROGMEM = "AC Indent Dec"; +const char pstrUsageACIndentIncrease [] PROGMEM = "AC Indent Inc"; +const char pstrUsageACNumberedList [] PROGMEM = "AC Num List"; +const char pstrUsageACRestartNumbering [] PROGMEM = "AC Res Num"; +const char pstrUsageACBulletedList [] PROGMEM = "AC Blt List"; +const char pstrUsageACPromote [] PROGMEM = "AC Promote"; +const char pstrUsageACDemote [] PROGMEM = "AC Demote"; +const char pstrUsageACYes [] PROGMEM = "AC Yes"; +const char pstrUsageACNo [] PROGMEM = "AC No"; +const char pstrUsageACCancel [] PROGMEM = "AC Cancel"; +const char pstrUsageACCatalog [] PROGMEM = "AC Ctlg"; +const char pstrUsageACBuyChkout [] PROGMEM = "AC Buy"; +const char pstrUsageACAddToCart [] PROGMEM = "AC Add2Cart"; +const char pstrUsageACExpand [] PROGMEM = "AC Xpnd"; +const char pstrUsageACExpandAll [] PROGMEM = "AC Xpand All"; +const char pstrUsageACCollapse [] PROGMEM = "AC Collapse"; +const char pstrUsageACCollapseAll [] PROGMEM = "AC Collapse All"; +const char pstrUsageACPrintPreview [] PROGMEM = "AC Prn Prevw"; +const char pstrUsageACPasteSpecial [] PROGMEM = "AC Paste Spec"; +const char pstrUsageACInsertMode [] PROGMEM = "AC Ins Mode"; +const char pstrUsageACDelete [] PROGMEM = "AC Del"; +const char pstrUsageACLock [] PROGMEM = "AC Lock"; +const char pstrUsageACUnlock [] PROGMEM = "AC Unlock"; +const char pstrUsageACProtect [] PROGMEM = "AC Prot"; +const char pstrUsageACUnprotect [] PROGMEM = "AC Unprot"; +const char pstrUsageACAttachComment [] PROGMEM = "AC Attach Cmnt"; +const char pstrUsageACDeleteComment [] PROGMEM = "AC Del Cmnt"; +const char pstrUsageACViewComment [] PROGMEM = "AC View Cmnt"; +const char pstrUsageACSelectWord [] PROGMEM = "AC Sel Word"; +const char pstrUsageACSelectSentence [] PROGMEM = "AC Sel Sntc"; +const char pstrUsageACSelectParagraph [] PROGMEM = "AC Sel Para"; +const char pstrUsageACSelectColumn [] PROGMEM = "AC Sel Col"; +const char pstrUsageACSelectRow [] PROGMEM = "AC Sel Row"; +const char pstrUsageACSelectTable [] PROGMEM = "AC Sel Tbl"; +const char pstrUsageACSelectObject [] PROGMEM = "AC Sel Obj"; +const char pstrUsageACRedoRepeat [] PROGMEM = "AC Redo"; +const char pstrUsageACSort [] PROGMEM = "AC Sort"; +const char pstrUsageACSortAscending [] PROGMEM = "AC Sort Asc"; +const char pstrUsageACSortDescending [] PROGMEM = "AC Sort Desc"; +const char pstrUsageACFilter [] PROGMEM = "AC Filt"; +const char pstrUsageACSetClock [] PROGMEM = "AC Set Clk"; +const char pstrUsageACViewClock [] PROGMEM = "AC View Clk"; +const char pstrUsageACSelectTimeZone [] PROGMEM = "AC Sel Time Z"; +const char pstrUsageACEditTimeZone [] PROGMEM = "AC Edt Time Z"; +const char pstrUsageACSetAlarm [] PROGMEM = "AC Set Alm"; +const char pstrUsageACClearAlarm [] PROGMEM = "AC Clr Alm"; +const char pstrUsageACSnoozeAlarm [] PROGMEM = "AC Snz Alm"; +const char pstrUsageACResetAlarm [] PROGMEM = "AC Rst Alm"; +const char pstrUsageACSyncronize [] PROGMEM = "AC Sync"; +const char pstrUsageACSendReceive [] PROGMEM = "AC Snd/Rcv"; +const char pstrUsageACSendTo [] PROGMEM = "AC Snd To"; +const char pstrUsageACReply [] PROGMEM = "AC Reply"; +const char pstrUsageACReplyAll [] PROGMEM = "AC Reply All"; +const char pstrUsageACForwardMessage [] PROGMEM = "AC Fwd Msg"; +const char pstrUsageACSend [] PROGMEM = "AC Snd"; +const char pstrUsageACAttachFile [] PROGMEM = "AC Att File"; +const char pstrUsageACUpload [] PROGMEM = "AC Upld"; +const char pstrUsageACDownload [] PROGMEM = "AC Dnld"; +const char pstrUsageACSetBorders [] PROGMEM = "AC Set Brd"; +const char pstrUsageACInsertRow [] PROGMEM = "AC Ins Row"; +const char pstrUsageACInsertColumn [] PROGMEM = "AC Ins Col"; +const char pstrUsageACInsertFile [] PROGMEM = "AC Ins File"; +const char pstrUsageACInsertPicture [] PROGMEM = "AC Ins Pic"; +const char pstrUsageACInsertObject [] PROGMEM = "AC Ins Obj"; +const char pstrUsageACInsertSymbol [] PROGMEM = "AC Ins Sym"; +const char pstrUsageACSaveAndClose [] PROGMEM = "AC Sav&Cls"; +const char pstrUsageACRename [] PROGMEM = "AC Rename"; +const char pstrUsageACMerge [] PROGMEM = "AC Merge"; +const char pstrUsageACSplit [] PROGMEM = "AC Split"; +const char pstrUsageACDistributeHorizontaly [] PROGMEM = "AC Dist Hor"; +const char pstrUsageACDistributeVerticaly [] PROGMEM = "AC Dist Ver"; + +// Digitaizers +const char pstrUsageDigitizer [] PROGMEM = "Digitizer"; +const char pstrUsagePen [] PROGMEM = "Pen"; +const char pstrUsageLightPen [] PROGMEM = "Light Pen"; +const char pstrUsageTouchScreen [] PROGMEM = "Touch Scr"; +const char pstrUsageTouchPad [] PROGMEM = "Touch Pad"; +const char pstrUsageWhiteBoard [] PROGMEM = "White Brd"; +const char pstrUsageCoordinateMeasuringMachine [] PROGMEM = "Coord Meas Mach"; +const char pstrUsage3DDigitizer [] PROGMEM = "3D Dgtz"; +const char pstrUsageStereoPlotter [] PROGMEM = "Stereo Plot"; +const char pstrUsageArticulatedArm [] PROGMEM = "Art Arm"; +const char pstrUsageArmature [] PROGMEM = "Armature"; +const char pstrUsageMultiplePointDigitizer [] PROGMEM = "Multi Point Dgtz"; +const char pstrUsageFreeSpaceWand [] PROGMEM = "Free Space Wand"; +const char pstrUsageStylus [] PROGMEM = "Stylus"; +const char pstrUsagePuck [] PROGMEM = "Puck"; +const char pstrUsageFinger [] PROGMEM = "Finger"; +const char pstrUsageTipPressure [] PROGMEM = "Tip Press"; +const char pstrUsageBarrelPressure [] PROGMEM = "Brl Press"; +const char pstrUsageInRange [] PROGMEM = "In Range"; +const char pstrUsageTouch [] PROGMEM = "Touch"; +const char pstrUsageUntouch [] PROGMEM = "Untouch"; +const char pstrUsageTap [] PROGMEM = "Tap"; +const char pstrUsageQuality [] PROGMEM = "Qlty"; +const char pstrUsageDataValid [] PROGMEM = "Data Valid"; +const char pstrUsageTransducerIndex [] PROGMEM = "Transducer Ind"; +const char pstrUsageTabletFunctionKeys [] PROGMEM = "Tabl Func Keys"; +const char pstrUsageProgramChangeKeys [] PROGMEM = "Pgm Chng Keys"; +//const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength"; +const char pstrUsageInvert [] PROGMEM = "Invert"; +const char pstrUsageXTilt [] PROGMEM = "X Tilt"; +const char pstrUsageYTilt [] PROGMEM = "Y Tilt"; +const char pstrUsageAzimuth [] PROGMEM = "Azimuth"; +const char pstrUsageAltitude [] PROGMEM = "Altitude"; +const char pstrUsageTwist [] PROGMEM = "Twist"; +const char pstrUsageTipSwitch [] PROGMEM = "Tip Sw"; +const char pstrUsageSecondaryTipSwitch [] PROGMEM = "Scnd Tip Sw"; +const char pstrUsageBarrelSwitch [] PROGMEM = "Brl Sw"; +const char pstrUsageEraser [] PROGMEM = "Eraser"; +const char pstrUsageTabletPick [] PROGMEM = "Tbl Pick"; + +// Alphanumeric Display Page +const char pstrUsageAlphanumericDisplay [] PROGMEM = "Alphanum Disp"; +const char pstrUsageBitmappedDisplay [] PROGMEM = "Bmp Disp"; +const char pstrUsageDisplayAttributesReport [] PROGMEM = "Disp Attr Rpt"; +const char pstrUsageASCIICharacterSet [] PROGMEM = "ASCII chset"; +const char pstrUsageDataReadBack [] PROGMEM = "Data Rd Back"; +const char pstrUsageFontReadBack [] PROGMEM = "Fnt Rd Back"; +const char pstrUsageDisplayControlReport [] PROGMEM = "Disp Ctrl Rpt"; +const char pstrUsageClearDisplay [] PROGMEM = "Clr Disp"; +//const char pstrUsageDisplayEnable [] PROGMEM = "Disp Enbl"; +const char pstrUsageScreenSaverDelay [] PROGMEM = "Scr Sav Delay"; +const char pstrUsageScreenSaverEnable [] PROGMEM = "Scr Sav Enbl"; +const char pstrUsageVerticalScroll [] PROGMEM = "V Scroll"; +const char pstrUsageHorizontalScroll [] PROGMEM = "H Scroll"; +const char pstrUsageCharacterReport [] PROGMEM = "Char Rpt"; +const char pstrUsageDisplayData [] PROGMEM = "Disp Data"; +const char pstrUsageDisplayStatus [] PROGMEM = "Disp Stat"; +const char pstrUsageStatusNotReady [] PROGMEM = "Stat !Ready"; +const char pstrUsageStatusReady [] PROGMEM = "Stat Ready"; +const char pstrUsageErrorNotALoadableCharacter [] PROGMEM = "Err Not Ld Char"; +const char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = "Fnt Data Rd Err"; +const char pstrUsageCursorPositionReport [] PROGMEM = "Cur Pos Rpt"; +const char pstrUsageRow [] PROGMEM = "Row"; +const char pstrUsageColumn [] PROGMEM = "Col"; +const char pstrUsageRows [] PROGMEM = "Rows"; +const char pstrUsageColumns [] PROGMEM = "Cols"; +const char pstrUsageCursorPixelPosition [] PROGMEM = "Cur Pix Pos"; +const char pstrUsageCursorMode [] PROGMEM = "Cur Mode"; +const char pstrUsageCursorEnable [] PROGMEM = "Cur Enbl"; +const char pstrUsageCursorBlink [] PROGMEM = "Cur Blnk"; +const char pstrUsageFontReport [] PROGMEM = "Fnt Rpt"; +const char pstrUsageFontData [] PROGMEM = "Fnt Data"; +const char pstrUsageCharacterWidth [] PROGMEM = "Char Wdth"; +const char pstrUsageCharacterHeight [] PROGMEM = "Char Hght"; +const char pstrUsageCharacterSpacingHorizontal [] PROGMEM = "Char Space H"; +const char pstrUsageCharacterSpacingVertical [] PROGMEM = "Char Space V"; +const char pstrUsageUnicodeCharset [] PROGMEM = "Unicode Char"; +const char pstrUsageFont7Segment [] PROGMEM = "Fnt 7-seg"; +const char pstrUsage7SegmentDirectMap [] PROGMEM = "7-seg map"; +const char pstrUsageFont14Segment [] PROGMEM = "Fnt 14-seg"; +const char pstrUsage14SegmentDirectMap [] PROGMEM = "14-seg map"; +const char pstrUsageDisplayBrightness [] PROGMEM = "Disp Bright"; +const char pstrUsageDisplayContrast [] PROGMEM = "Disp Cntrst"; +const char pstrUsageCharacterAttribute [] PROGMEM = "Char Attr"; +const char pstrUsageAttributeReadback [] PROGMEM = "Attr Readbk"; +const char pstrUsageAttributeData [] PROGMEM = "Attr Data"; +const char pstrUsageCharAttributeEnhance [] PROGMEM = "Char Attr Enh"; +const char pstrUsageCharAttributeUnderline [] PROGMEM = "Char Attr Undl"; +const char pstrUsageCharAttributeBlink [] PROGMEM = "Char Attr Blnk"; +const char pstrUsageBitmapSizeX [] PROGMEM = "Bmp Size X"; +const char pstrUsageBitmapSizeY [] PROGMEM = "Bmp Size Y"; +const char pstrUsageBitDepthFormat [] PROGMEM = "Bit Dpth Fmt"; +const char pstrUsageDisplayOrientation [] PROGMEM = "Disp Ornt"; +const char pstrUsagePaletteReport [] PROGMEM = "Pal Rpt"; +const char pstrUsagePaletteDataSize [] PROGMEM = "Pal Data Size"; +const char pstrUsagePaletteDataOffset [] PROGMEM = "Pal Data Off"; +const char pstrUsagePaletteData [] PROGMEM = "Pal Data"; +const char pstrUsageBlitReport [] PROGMEM = "Blit Rpt"; +const char pstrUsageBlitRectangleX1 [] PROGMEM = "Blit Rect X1"; +const char pstrUsageBlitRectangleY1 [] PROGMEM = "Blit Rect Y1"; +const char pstrUsageBlitRectangleX2 [] PROGMEM = "Blit Rect X2"; +const char pstrUsageBlitRectangleY2 [] PROGMEM = "Blit Rect Y2"; +const char pstrUsageBlitData [] PROGMEM = "Blit Data"; +const char pstrUsageSoftButton [] PROGMEM = "Soft Btn"; +const char pstrUsageSoftButtonID [] PROGMEM = "Soft Btn ID"; +const char pstrUsageSoftButtonSide [] PROGMEM = "Soft Btn Side"; +const char pstrUsageSoftButtonOffset1 [] PROGMEM = "Soft Btn Off1"; +const char pstrUsageSoftButtonOffset2 [] PROGMEM = "Soft Btn Off2"; +const char pstrUsageSoftButtonReport [] PROGMEM = "Soft Btn Rpt"; + +// Medical Instrument Page +const char pstrUsageMedicalUltrasound [] PROGMEM = "Med Ultrasnd"; +const char pstrUsageVCRAcquisition [] PROGMEM = "VCR/Acq"; +const char pstrUsageFreezeThaw [] PROGMEM = "Freeze"; +const char pstrUsageClipStore [] PROGMEM = "Clip Store"; +const char pstrUsageUpdate [] PROGMEM = "Update"; +const char pstrUsageNext [] PROGMEM = "Next"; +const char pstrUsageSave [] PROGMEM = "Save"; +const char pstrUsagePrint [] PROGMEM = "Print"; +const char pstrUsageMicrophoneEnable [] PROGMEM = "Mic Enbl"; +const char pstrUsageCine [] PROGMEM = "Cine"; +const char pstrUsageTransmitPower [] PROGMEM = "Trans Pwr"; +//const char pstrUsageVolume [] PROGMEM = "Vol"; +const char pstrUsageFocus [] PROGMEM = "Focus"; +const char pstrUsageDepth [] PROGMEM = "Depth"; +const char pstrUsageSoftStepPrimary [] PROGMEM = "Soft Stp-Pri"; +const char pstrUsageSoftStepSecondary [] PROGMEM = "Soft Stp-Sec"; +const char pstrUsageDepthGainCompensation [] PROGMEM = "Dpth Gain Comp"; +const char pstrUsageZoomSelect [] PROGMEM = "Zoom Sel"; +const char pstrUsageZoomAdjust [] PROGMEM = "Zoom Adj"; +const char pstrUsageSpectralDopplerModeSelect [] PROGMEM = "Spec Dop Mode Sel"; +const char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = "Spec Dop Mode Adj"; +const char pstrUsageColorDopplerModeSelect [] PROGMEM = "Color Dop Mode Sel"; +const char pstrUsageColorDopplerModeAdjust [] PROGMEM = "Color Dop Mode Adj"; +const char pstrUsageMotionModeSelect [] PROGMEM = "Motion Mode Sel"; +const char pstrUsageMotionModeAdjust [] PROGMEM = "Motion Mode Adj"; +const char pstrUsage2DModeSelect [] PROGMEM = "2D Mode Sel"; +const char pstrUsage2DModeAdjust [] PROGMEM = "2D Mode Adj"; +const char pstrUsageSoftControlSelect [] PROGMEM = "Soft Ctrl Sel"; +const char pstrUsageSoftControlAdjust [] PROGMEM = "Soft Ctrl Adj"; + + +#endif // __HID_H__ \ No newline at end of file diff --git a/masstorage.h b/masstorage.h new file mode 100644 index 00000000..b3c42ae2 --- /dev/null +++ b/masstorage.h @@ -0,0 +1,97 @@ +#if !defined(__MASSTORAGE_H__) +#define __MASSTORAGE_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" + +//#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +//#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +// Mass Storage Subclass Constants +#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use +#define MASS_SUBCLASS_RBC 0x01 +#define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI) +#define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157 +#define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB +#define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i +#define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set +#define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI +#define MASS_SUBCLASS_IEEE1667 0x08 + +// Mass Storage Class Protocols +#define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt) +#define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt) +#define MASS_PROTO_OBSOLETE 0x02 +#define MASS_PROTO_BBB 0x50 // Bulk Only Transport +#define MASS_PROTO_UAS 0x62 + +// Request Codes +#define MASS_REQ_ADSC 0x00 +#define MASS_REQ_GET 0xFC +#define MASS_REQ_PUT 0xFD +#define MASS_REQ_GET_MAX_LUN 0xFE +#define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset + +#define MASS_CBW_SIGNATURE 0x43425355 +#define MASS_CBS_SIGNATURE 0x53425355 + +struct CommandBlockWrapper +{ + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + + struct + { + uint8_t bCBWLUN : 4; + uint8_r bReserved1 : 4; + }; + struct + { + uint8_t bCBWCBLength : 4; + uint8_t bReserved2 : 4; + }; + + uint8_t CBWCB[16]; +}; + +struct CommandStatusWrapper +{ + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +}; + +class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter +{ +public: + uint8_t Reset(); + uint8_t GetMaxLun(uint8_t *max_lun); + + uint8_t ResetRecovery(); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __MASSTORAGE_H__ \ No newline at end of file diff --git a/usb_ch9.h b/usb_ch9.h index 150a077b..b1b2fb43 100644 --- a/usb_ch9.h +++ b/usb_ch9.h @@ -52,6 +52,10 @@ #define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. #define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. +#define HID_DESCRIPTOR_HID 0x21 + + + /* OTG SET FEATURE Constants */ #define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP #define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP @@ -128,4 +132,23 @@ typedef struct uint8_t bInterval; // Polling interval in frames. } USB_ENDPOINT_DESCRIPTOR; + +/* HID descriptor */ +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; // HID class specification release + uint8_t bCountryCode; + uint8_t bNumDescriptors; // Number of additional class specific descriptors + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} USB_HID_DESCRIPTOR; + +typedef struct +{ + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; + #endif // _ch9_h_ From bc40559679411adbddec9be533b6728c8b5cc839 Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Mon, 6 Jun 2011 07:18:31 -0600 Subject: [PATCH 4/6] CtrlReq callback bugfix --- Usb.cpp | 12 ++++++++---- hid.cpp | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Usb.cpp b/Usb.cpp index 6cc60fe3..60e2af9e 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -153,7 +153,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ rcode = InTransfer( pep, nak_limit, &read, dataptr ); - if (rcode /*&& rcode != hrSTALL*/) + if (rcode) return rcode; // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified @@ -161,6 +161,9 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ ((USBReadParser*)p)->Parse( read, dataptr, total - left ); left -= read; + + if (read < nbytes) + break; } } else //OUT transfer @@ -222,15 +225,16 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui if (mem_left < 0) mem_left = 0; - data = bytesRd( rRCVFIFO, (pktsize > mem_left) ? mem_left : pktsize, data ); + data = bytesRd( rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data ); regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer *nbytesptr += pktsize; // add this packet's byte count to total transfer length + /* The transfer is complete under two conditions: */ /* 1. The device sent a short packet (L.T. maxPacketSize) */ /* 2. 'nbytes' have been transferred. */ - if (( pktsize < maxpktsize ) || (*nbytesptr >= nbytes )) // have we transferred 'nbytes' bytes? - { + if (/*pktsize == 6 ||*/ ( pktsize < maxpktsize ) || (*nbytesptr >= nbytes )) // have we transferred 'nbytes' bytes? + { // Save toggle value pep->bmRcvToggle = ( regRd( rHRSL ) & bmRCVTOGRD ) ? 1 : 0; diff --git a/hid.cpp b/hid.cpp index 5b756453..4ebfd182 100644 --- a/hid.cpp +++ b/hid.cpp @@ -2,8 +2,8 @@ //const uint16_t HID::maxHidInterfaces = 3; //const uint16_t HID::maxEpPerInterface = 2; -const uint8_t HID::epInterruptInIndex = 0; -const uint8_t HID::epInterruptOutIndex = 1; +const uint8_t HID::epInterruptInIndex = 1; +const uint8_t HID::epInterruptOutIndex = 2; HID::HID(USB *p) : pUsb(p), @@ -278,6 +278,7 @@ uint8_t HID::Release() { pUsb->GetAddressPool().FreeAddress(bAddress); + bNumEP = 1; bAddress = 0; qNextPollTime = 0; bPollEnable = false; From f1802bbc7a20d5f8f2912b999514e481830bc06b Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Tue, 14 Jun 2011 23:05:10 -0600 Subject: [PATCH 5/6] hid --- hid.cpp | 174 ++++++++++++++++++++++++++++++++++------------------- hid.h | 34 ++++++----- max3421e.h | 4 +- 3 files changed, 135 insertions(+), 77 deletions(-) diff --git a/hid.cpp b/hid.cpp index 4ebfd182..628c0bea 100644 --- a/hid.cpp +++ b/hid.cpp @@ -256,9 +256,15 @@ void HID::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto uint8_t index; if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + { + USBTRACE("I8\r\n"); index = epInterruptInIndex; + } else + { + USBTRACE("I0\r\n"); index = epInterruptOutIndex; + } // Fill in the endpoint info structure epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); @@ -289,15 +295,29 @@ uint8_t HID::Poll() { uint8_t rcode = 0; - //if (!bPollEnable) - // return 0; + if (!bPollEnable) + return 0; - //if (qNextPollTime <= millis()) - //{ - // Serial.println(bAddress, HEX); + if (qNextPollTime <= millis()) + { + qNextPollTime = millis() + 100; - // qNextPollTime = millis() + 100; - //} + const uint8_t const_buff_len = 16; + uint8_t buf[const_buff_len]; + + HexDumper Hex; + uint16_t read = (uint16_t)const_buff_len; + + uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); + + if (rcode && rcode != hrNAK) + { + USBTRACE2("Poll:", rcode); + return rcode; + } + for (uint8_t i=0; i(buf[i]); + } return rcode; } @@ -313,7 +333,7 @@ uint8_t HID::getReportDescr( uint8_t ep, USBReadParser *parser ) // HID_DESCRIPTOR_REPORT, 0x0000, constBufLen, constBufLen, buf, NULL )); uint8_t rcode = pUsb->ctrlReq( bAddress, ep, /*bmREQ_HIDREPORT*/0x81, USB_REQUEST_GET_DESCRIPTOR, 0x00, - HID_DESCRIPTOR_REPORT, 0x0000, constBufLen, constBufLen, buf, (USBReadParser*)parser ); + HID_DESCRIPTOR_REPORT, 0x0000, 0x142, constBufLen, buf, (USBReadParser*)parser ); //return ((rcode != hrSTALL) ? rcode : 0); return rcode; @@ -347,42 +367,24 @@ uint8_t HID::getProto( uint8_t ep, uint8_t iface, uint8_t* dataptr ) return( pUsb->ctrlReq( bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL )); } -//ReportDescParser::UsagePageFunc usagePageFunctions[] /*PROGMEM*/ = -//{ -// ReportDescParser::PrintGenericDesktopPageUsage, -// ReportDescParser::PrintSimulationControlsPageUsage, -// ReportDescParser::PrintVRControlsPageUsage, -// ReportDescParser::PrintSportsControlsPageUsage, -// ReportDescParser::PrintGameControlsPageUsage, -// ReportDescParser::PrintGenericDeviceControlsPageUsage, -// ReportDescParser::PrintLEDPageUsage, -// ReportDescParser::PrintTelephonyPageUsage, -// ReportDescParser::PrintConsumerPageUsage, -// ReportDescParser::PrintDigitizerPageUsage, -// ReportDescParser::PrintAlphanumDisplayPageUsage, -// ReportDescParser::PrintMedicalInstrumentPageUsage -//}; - void ReportDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { uint16_t cntdn = (uint16_t)len; uint8_t *p = (uint8_t*)pbuf; - Serial.print("\r\nL:"); - Serial.println(len, HEX); - while(cntdn) { - //Serial.print("CDN:"); - //Serial.println(cntdn, HEX); + ParseItem(&p, &cntdn); - if (ParseItem(&p, &cntdn)) - return; + //if (ParseItem(&p, &cntdn)) + // return; } } uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) { + uint8_t ret = enErrorSuccess; + switch (itemParseState) { case 0: @@ -404,7 +406,7 @@ uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) //USBTRACE2("Sz1:", size); //Serial.print("\r\nSz:"); - //Serial.print(itemSize,DEC); + //Serial.println(itemSize,DEC); switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { @@ -474,19 +476,32 @@ uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) (*pcntdn) --; itemSize --; itemParseState = 1; - case 1: + if (!itemSize) break; if (!pcntdn) + return enErrorIncomplete; + case 1: + theBuffer.valueSize = itemSize; + valParser.Initialize(&theBuffer); + itemParseState = 2; + case 2: + if (!valParser.Parse(pp, pcntdn)) + return enErrorIncomplete; + itemParseState = 3; + case 3: { - if (itemSize) - return enErrorIncomplete; + uint8_t data = *((uint8_t*)varBuffer); - break; - } switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { + case (TYPE_LOCAL | TAG_LOCAL_USAGE): + if (pfUsage) + if (theBuffer.valueSize > 1) + pfUsage(*((uint16_t*)varBuffer)); + else + pfUsage(data); case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN): case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX): case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN): @@ -498,33 +513,26 @@ uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX): case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP): case (TYPE_GLOBAL | TAG_GLOBAL_UNIT): - case (TYPE_LOCAL | TAG_LOCAL_USAGE): - //PrintGenericDesktopPageUsage((**pp)); - //PrintSimulationControlsPageUsage((**pp)); - //PrintVRControlsPageUsage((**pp)); - //PrintSportsControlsPageUsage((**pp)); - //PrintGameControlsPageUsage((**pp)); - //PrintGenericDeviceControlsPageUsage((**pp)); - //PrintLEDPageUsage((**pp)); - //PrintTelephonyPageUsage((**pp)); - //PrintConsumerPageUsage((**pp)); - //PrintDigitizerPageUsage((**pp)); - //PrintAlphanumDisplayPageUsage((**pp)); - //PrintMedicalInstrumentPageUsage((**pp)); Notify(PSTR("(")); - PrintHex((**pp)); + for (uint8_t i=0; i(data); Notify(PSTR(")")); break; - break; case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): case (TYPE_GLOBAL | TAG_GLOBAL_POP): break; case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): - PrintUsagePage((**pp)); + SetUsagePage(data); + PrintUsagePage(data); + + Notify(PSTR("(")); + for (uint8_t i=0; i(data); + Notify(PSTR(")")); break; case (TYPE_MAIN | TAG_MAIN_COLLECTION): case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION): - switch ((**pp)) + switch (data) { case 0x00: Notify(PSTR(" Physical")); @@ -549,7 +557,7 @@ uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) break; default: Notify(PSTR(" Vendor Defined(")); - PrintHex((**pp)); + PrintHex(data); Notify(PSTR(")")); } break; @@ -557,15 +565,13 @@ uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) case (TYPE_MAIN | TAG_MAIN_OUTPUT): case (TYPE_MAIN | TAG_MAIN_FEATURE): Notify(PSTR("(")); - PrintBin((**pp)); + PrintBin(data); Notify(PSTR(")")); break; } // switch (**pp & (TYPE_MASK | TAG_MASK)) - (*pp) ++; - (*pcntdn) --; - itemSize --; - itemParseState = 2; - case 2: + } + itemParseState = 4; + case 4: if (itemSize > 1 && !theSkipper.Skip(pp, pcntdn, itemSize)) return enErrorIncomplete; } // switch (itemParseState) @@ -601,6 +607,52 @@ const char *usagePageTitles1[] PROGMEM = pstrUsagePageArcade }; +ReportDescParser::UsagePageFunc ReportDescParser::usagePageFunctions[] /*PROGMEM*/ = +{ + &ReportDescParser::PrintGenericDesktopPageUsage, + &ReportDescParser::PrintSimulationControlsPageUsage, + &ReportDescParser::PrintVRControlsPageUsage, + &ReportDescParser::PrintSportsControlsPageUsage, + &ReportDescParser::PrintGameControlsPageUsage, + &ReportDescParser::PrintGenericDeviceControlsPageUsage, + NULL, // Keyboard/Keypad + &ReportDescParser::PrintLEDPageUsage, + NULL, // Button + NULL, // Ordinal + &ReportDescParser::PrintTelephonyPageUsage, + &ReportDescParser::PrintConsumerPageUsage, + &ReportDescParser::PrintDigitizerPageUsage, + NULL, // Reserved + NULL, // PID + NULL // Unicode +}; + +void ReportDescParser::SetUsagePage(uint16_t page) +{ + pfUsage = NULL; + + if (page > 0x00 && page < 0x11) + pfUsage = /*(UsagePageFunc)pgm_read_word*/(usagePageFunctions[page - 1]); + //else if (page > 0x7f && page < 0x84) + // Notify(pstrUsagePageMonitor); + //else if (page > 0x83 && page < 0x8c) + // Notify(pstrUsagePagePower); + //else if (page > 0x8b && page < 0x92) + // Notify((char*)pgm_read_word(&usagePageTitles1[page - 0x8c])); + //else if (page > 0xfeff && page <= 0xffff) + // Notify(pstrUsagePageVendorDefined); + else + switch (page) + { + case 0x14: + pfUsage = &ReportDescParser::PrintAlphanumDisplayPageUsage; + break; + case 0x40: + pfUsage = &ReportDescParser::PrintMedicalInstrumentPageUsage; + break; + } +} + void ReportDescParser::PrintUsagePage(uint16_t page) { Notify(pstrSpace); diff --git a/hid.h b/hid.h index 66dc3eea..c98fe001 100644 --- a/hid.h +++ b/hid.h @@ -151,8 +151,21 @@ class ReportDescParser : public USBReadParser public: typedef void (*UsagePageFunc)(uint16_t usage); + static void PrintGenericDesktopPageUsage(uint16_t usage); + static void PrintSimulationControlsPageUsage(uint16_t usage); + static void PrintVRControlsPageUsage(uint16_t usage); + static void PrintSportsControlsPageUsage(uint16_t usage); + static void PrintGameControlsPageUsage(uint16_t usage); + static void PrintGenericDeviceControlsPageUsage(uint16_t usage); + static void PrintLEDPageUsage(uint16_t usage); + static void PrintTelephonyPageUsage(uint16_t usage); + static void PrintConsumerPageUsage(uint16_t usage); + static void PrintDigitizerPageUsage(uint16_t usage); + static void PrintAlphanumDisplayPageUsage(uint16_t usage); + static void PrintMedicalInstrumentPageUsage(uint16_t usage); + private: - //static UsagePageFunc usagePageFunctions[]; + static UsagePageFunc usagePageFunctions[]; MultiValueBuffer theBuffer; MultiByteValueParser valParser; @@ -168,18 +181,7 @@ private: UsagePageFunc pfUsage; static void PrintUsagePage(uint16_t page); - static void PrintGenericDesktopPageUsage(uint16_t usage); - static void PrintSimulationControlsPageUsage(uint16_t usage); - static void PrintVRControlsPageUsage(uint16_t usage); - static void PrintSportsControlsPageUsage(uint16_t usage); - static void PrintGameControlsPageUsage(uint16_t usage); - static void PrintGenericDeviceControlsPageUsage(uint16_t usage); - static void PrintLEDPageUsage(uint16_t usage); - static void PrintTelephonyPageUsage(uint16_t usage); - static void PrintConsumerPageUsage(uint16_t usage); - static void PrintDigitizerPageUsage(uint16_t usage); - static void PrintAlphanumDisplayPageUsage(uint16_t usage); - static void PrintMedicalInstrumentPageUsage(uint16_t usage); + void SetUsagePage(uint16_t page); public: ReportDescParser() : @@ -187,7 +189,11 @@ public: itemSize(0), itemPrefix(0), pfUsage(NULL) - {}; + { + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); + }; virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); diff --git a/max3421e.h b/max3421e.h index e39a61f2..b4320886 100644 --- a/max3421e.h +++ b/max3421e.h @@ -9,8 +9,8 @@ /* pin numbers to port numbers */ //#define MAX_SS 10 -#define MAX_INT 3 // Black Widdow -//#define MAX_INT 9 // Duemielanove +//#define MAX_INT 3 // Black Widdow +#define MAX_INT 9 // Duemielanove #define MAX_GPX 8 //#define MAX_RESET 7 From 05726f3ed10a81921c01d8b7200d53a19470c330 Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Wed, 22 Jun 2011 11:41:22 -0600 Subject: [PATCH 6/6] first release --- README | 6 +- Usb.cpp | 23 +- Usb.h | 30 +- address.h | 16 + avrpins.h | 20 +- cdcacm.cpp | 16 + cdcacm.h | 22 +- cdcftdi.cpp | 16 + cdcftdi.h | 22 +- cdcprolific.cpp | 16 + cdcprolific.h | 22 +- confdescparser.h | 24 +- examples/acm/acm_terminal/acm_terminal.pde | 103 +++++++ examples/acm/acm_terminal/pgmstrings.h | 52 ++++ examples/hub_demo/hub_demo.pde | 343 +++++++++++++++++++++ examples/hub_demo/pgmstrings.h | 52 ++++ gpl2.txt | 340 ++++++++++++++++++++ hexdump.h | 58 ++++ hid.cpp | 16 + hid.h | 22 +- masstorage.h | 22 +- max3421e.h | 32 +- max_LCD.cpp | 34 +- max_LCD.h | 20 +- message.cpp | 27 ++ message.h | 37 +++ parsetools.cpp | 72 +++++ parsetools.h | 147 +++++++++ printhex.h | 62 ++++ usb_ch9.h | 16 + usbhost.h | 20 +- usbhub.cpp | 16 + usbhub.h | 16 + 33 files changed, 1665 insertions(+), 75 deletions(-) create mode 100644 examples/acm/acm_terminal/acm_terminal.pde create mode 100644 examples/acm/acm_terminal/pgmstrings.h create mode 100644 examples/hub_demo/hub_demo.pde create mode 100644 examples/hub_demo/pgmstrings.h create mode 100644 gpl2.txt create mode 100644 hexdump.h create mode 100644 message.cpp create mode 100644 message.h create mode 100644 parsetools.cpp create mode 100644 parsetools.h create mode 100644 printhex.h diff --git a/README b/README index 7328e500..f5226960 100644 --- a/README +++ b/README @@ -1,5 +1 @@ -This is Rev.2.0 of MAX3421E-based USB Host Library for Arduino. At the moment, this repo contains current development copy -of the code facilitating developer's exchange. For those not involved in the project, the code in its' current state doesn't bear any value. -In other words, nothing works yet. - -The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects \ No newline at end of file +This is Rev.2.0 of MAX3421E-based USB Host Shield Library. Project web site is http://www.circuitsathome.com \ No newline at end of file diff --git a/Usb.cpp b/Usb.cpp index 60e2af9e..992f57e1 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -1,3 +1,19 @@ +/* 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 +*/ /* USB functions */ #include "avrpins.h" @@ -218,8 +234,8 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) return ( 0xf0 ); //receive error - pktsize = regRd( rRCVBC ); //number of received bytes - + pktsize = regRd( rRCVBC ); //number of received bytes */ + int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); if (mem_left < 0) @@ -243,10 +259,9 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui } //while( 1 ) } -/* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ +/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */ /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ -/* major part of this function borrowed from code shared by Richard Ibbotson */ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data ) { EpInfo *pep = NULL; diff --git a/Usb.h b/Usb.h index a584f1ba..d331a09b 100644 --- a/Usb.h +++ b/Usb.h @@ -1,3 +1,19 @@ +/* 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 +*/ /* USB functions */ #ifndef _usb_h_ #define _usb_h_ @@ -12,9 +28,14 @@ #include "address.h" #include -#include "..\DebugTools\printhex.h" -#include "..\DebugTools\hexdump.h" -#include "..\DebugTools\message.h" +#include "printhex.h" +#include "hexdump.h" +#include "message.h" + + +/* shield pins. First parameter - SS pin, second parameter - INT pin */ +//typedef MAX3421e MAX3421E; // Black Widow +typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560 #define USBTRACE(s) (Serial.print((s))) #define USBTRACE2(s,r) (Serial.print((s)), Serial.println((r),HEX)) @@ -134,9 +155,6 @@ public: }; -//typedef MAX3421e MAX3421E; // Black Widdow -typedef MAX3421e MAX3421E; // Duemielanove - class USB : public MAX3421E { AddressPoolImpl addrPool; diff --git a/address.h b/address.h index f3da24f8..24ae0935 100644 --- a/address.h +++ b/address.h @@ -1,3 +1,19 @@ +/* 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(__ADDRESS_H__) #define __ADDRESS_H__ diff --git a/avrpins.h b/avrpins.h index 35d05fe0..f2909024 100644 --- a/avrpins.h +++ b/avrpins.h @@ -1,9 +1,25 @@ -/* copied from Konstantin Chizhov's AVR port templates */ +/* 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 +*/ + +/* derived from Konstantin Chizhov's AVR port templates */ #ifndef _avrpins_h_ #define _avrpins_h_ -//#include "WProgram.h" #include #ifdef PORTA diff --git a/cdcacm.cpp b/cdcacm.cpp index 8bef335d..17706388 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -1,3 +1,19 @@ +/* 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 "cdcacm.h" const uint8_t ACM::epDataInIndex = 1; diff --git a/cdcacm.h b/cdcacm.h index fc63b587..25d82e53 100644 --- a/cdcacm.h +++ b/cdcacm.h @@ -1,3 +1,19 @@ +/* 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(__CDCACM_H__) #define __CDCACM_H__ @@ -10,9 +26,9 @@ #include "Usb.h" #include -#include "..\DebugTools\printhex.h" -#include "..\DebugTools\hexdump.h" -#include "..\DebugTools\message.h" +#include "printhex.h" +#include "hexdump.h" +#include "message.h" #include "confdescparser.h" diff --git a/cdcftdi.cpp b/cdcftdi.cpp index 10386262..c5b9b0c8 100644 --- a/cdcftdi.cpp +++ b/cdcftdi.cpp @@ -1,3 +1,19 @@ +/* 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 "cdcftdi.h" const uint8_t FTDI::epDataInIndex = 1; diff --git a/cdcftdi.h b/cdcftdi.h index 7ebea5f7..270492a1 100644 --- a/cdcftdi.h +++ b/cdcftdi.h @@ -1,3 +1,19 @@ +/* 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(__CDCFTDI_H__) #define __CDCFTDI_H__ @@ -10,9 +26,9 @@ #include "Usb.h" #include -#include "..\DebugTools\printhex.h" -#include "..\DebugTools\hexdump.h" -#include "..\DebugTools\message.h" +#include "printhex.h" +#include "hexdump.h" +#include "message.h" #include "confdescparser.h" diff --git a/cdcprolific.cpp b/cdcprolific.cpp index 3d0fd4c7..f1a97376 100644 --- a/cdcprolific.cpp +++ b/cdcprolific.cpp @@ -1,3 +1,19 @@ +/* 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 "cdcprolific.h" PL::PL(USB *p, CDCAsyncOper *pasync) : diff --git a/cdcprolific.h b/cdcprolific.h index c2a7bfd0..e3702bc5 100644 --- a/cdcprolific.h +++ b/cdcprolific.h @@ -1,3 +1,19 @@ +/* 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(__CDCPROLIFIC_H__) #define __CDCPROLIFIC_H__ @@ -10,9 +26,9 @@ #include "Usb.h" #include -#include "..\DebugTools\printhex.h" -#include "..\DebugTools\hexdump.h" -#include "..\DebugTools\message.h" +#include "printhex.h" +#include "hexdump.h" +#include "message.h" #include "confdescparser.h" #include "cdcacm.h" diff --git a/confdescparser.h b/confdescparser.h index a17a6dac..27ea57e5 100644 --- a/confdescparser.h +++ b/confdescparser.h @@ -1,13 +1,29 @@ +/* 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(__CONFDESCPARSER_H__) #define __CONFDESCPARSER_H__ #include -#include "..\ParseTools\parsetools.h" #include -#include "..\DebugTools\printhex.h" -#include "..\DebugTools\hexdump.h" -#include "..\DebugTools\message.h" +#include "printhex.h" +#include "hexdump.h" +#include "message.h" +#include "parsetools.h" //#include "hid.h" diff --git a/examples/acm/acm_terminal/acm_terminal.pde b/examples/acm/acm_terminal/acm_terminal.pde new file mode 100644 index 00000000..cf6f4169 --- /dev/null +++ b/examples/acm/acm_terminal/acm_terminal.pde @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "pgmstrings.h" + +class ACMAsyncOper : public CDCAsyncOper +{ +public: + virtual uint8_t OnInit(ACM *pacm); +}; + +uint8_t ACMAsyncOper::OnInit(ACM *pacm) +{ + uint8_t rcode; + // Set DTR = 1 RTS=1 + rcode = pacm->SetControlLineState(3); + + if (rcode) + { + ErrorMessage(PSTR("SetControlLineState"), rcode); + return rcode; + } + + LINE_CODING lc; + lc.dwDTERate = 115200; + lc.bCharFormat = 0; + lc.bParityType = 0; + lc.bDataBits = 8; + + rcode = pacm->SetLineCoding(&lc); + + if (rcode) + ErrorMessage(PSTR("SetLineCoding"), rcode); + + return rcode; +} + +USB Usb; +//USBHub Hub(&Usb); +ACMAsyncOper AsyncOper; +ACM Acm(&Usb, &AsyncOper); + +void setup() +{ + Serial.begin( 115200 ); + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSCOKIRQ failed to assert"); + + delay( 200 ); +} + +void loop() +{ + Usb.Task(); + + if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + uint8_t rcode; + + /* reading the keyboard */ + if(Serial.available()) { + uint8_t data= Serial.read(); + /* sending to the phone */ + rcode = Acm.SndData(1, &data); + if (rcode) + ErrorMessage(PSTR("SndData"), rcode); + }//if(Serial.available()... + + delay(50); + + /* reading the phone */ + /* buffer size must be larger than max.packet size */ + uint8_t buf[32]; + uint16_t rcvd = 32; + rcode = Acm.RcvData(&rcvd, buf); + if (rcode && rcode != hrNAK) + ErrorMessage(PSTR("Ret"), rcode); + + if( rcvd ) { //more than zero bytes received + for(uint16_t i=0; i < rcvd; i++ ) { + Serial.print(buf[i]); //printing on the screen + } + } + delay(10); + }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING.. +} + + diff --git a/examples/acm/acm_terminal/pgmstrings.h b/examples/acm/acm_terminal/pgmstrings.h new file mode 100644 index 00000000..bdb0077e --- /dev/null +++ b/examples/acm/acm_terminal/pgmstrings.h @@ -0,0 +1,52 @@ +#if !defined(__PGMSTRINGS_H__) +#define __PGMSTRINGS_H__ + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 //buffer size + + +/* Print strings in Program Memory */ +const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; +const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; +const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; +const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; +const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; +const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; +const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; +const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; +const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; +const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; +const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; +const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; +const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; +const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; +const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; +const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; +const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; +const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; +const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; +const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; +const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; +const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; +const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; + +#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/examples/hub_demo/hub_demo.pde b/examples/hub_demo/hub_demo.pde new file mode 100644 index 00000000..a0b801e4 --- /dev/null +++ b/examples/hub_demo/hub_demo.pde @@ -0,0 +1,343 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "pgmstrings.h" + +USB Usb; +USBHub Hub1(&Usb); +USBHub Hub2(&Usb); +USBHub Hub3(&Usb); +USBHub Hub4(&Usb); + +uint32_t next_time; + +void PrintAllAddresses(UsbDevice *pdev) +{ + UsbDeviceAddress adr; + adr.devAddress = pdev->address; + Serial.print("\r\nAddr:"); + Serial.print(adr.devAddress, HEX); + Serial.print("("); + Serial.print(adr.bmHub, HEX); + Serial.print("."); + Serial.print(adr.bmParent, HEX); + Serial.print("."); + Serial.print(adr.bmAddress, HEX); + Serial.println(")"); +} + +void PrintAddress(uint8_t addr) +{ + UsbDeviceAddress adr; + adr.devAddress = addr; + Serial.print("\r\nADDR:\t"); + Serial.println(adr.devAddress,HEX); + Serial.print("DEV:\t"); + Serial.println(adr.bmAddress,HEX); + Serial.print("PRNT:\t"); + Serial.println(adr.bmParent,HEX); + Serial.print("HUB:\t"); + Serial.println(adr.bmHub,HEX); +} + +void setup() +{ + Serial.begin( 115200 ); + Serial.println("Start"); + + if (Usb.Init() == -1) + Serial.println("OSC did not start."); + + delay( 200 ); + + next_time = millis() + 10000; +} + +byte getdevdescr( byte addr, byte &num_conf ); + +void PrintDescriptors(uint8_t addr) +{ + uint8_t rcode = 0; + byte num_conf = 0; + + rcode = getdevdescr( (byte)addr, num_conf ); + if( rcode ) + { + printProgStr(Gen_Error_str); + print_hex( rcode, 8 ); + } + Serial.print("\r\n"); + + for (int i=0; iaddress, 8); + Serial.println("\r\n--"); + PrintDescriptors( pdev->address ); +} + +void loop() +{ + Usb.Task(); + + if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + if (millis() >= next_time) + { + Usb.ForEachUsbDevice(&PrintAllDescriptors); + Usb.ForEachUsbDevice(&PrintAllAddresses); + + while( 1 ); //stop + } + } +} + +byte getdevdescr( byte addr, byte &num_conf ) +{ + USB_DEVICE_DESCRIPTOR buf; + byte rcode; + rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf ); + if( rcode ) { + return( rcode ); + } + printProgStr(Dev_Header_str); + printProgStr(Dev_Length_str); + print_hex( buf.bLength, 8 ); + printProgStr(Dev_Type_str); + print_hex( buf.bDescriptorType, 8 ); + printProgStr(Dev_Version_str); + print_hex( buf.bcdUSB, 16 ); + printProgStr(Dev_Class_str); + print_hex( buf.bDeviceClass, 8 ); + printProgStr(Dev_Subclass_str); + print_hex( buf.bDeviceSubClass, 8 ); + printProgStr(Dev_Protocol_str); + print_hex( buf.bDeviceProtocol, 8 ); + printProgStr(Dev_Pktsize_str); + print_hex( buf.bMaxPacketSize0, 8 ); + printProgStr(Dev_Vendor_str); + print_hex( buf.idVendor, 16 ); + printProgStr(Dev_Product_str); + print_hex( buf.idProduct, 16 ); + printProgStr(Dev_Revision_str); + print_hex( buf.bcdDevice, 16 ); + printProgStr(Dev_Mfg_str); + print_hex( buf.iManufacturer, 8 ); + printProgStr(Dev_Prod_str); + print_hex( buf.iProduct, 8 ); + printProgStr(Dev_Serial_str); + print_hex( buf.iSerialNumber, 8 ); + printProgStr(Dev_Nconf_str); + print_hex( buf.bNumConfigurations, 8 ); + num_conf = buf.bNumConfigurations; + return( 0 ); +} + +void printhubdescr(uint8_t *descrptr, uint8_t addr) +{ + HubDescriptor *pHub = (HubDescriptor*) descrptr; + uint8_t len = *((uint8_t*)descrptr); + + printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n")); + printProgStr(PSTR("bDescLength:\t\t")); + Serial.println(pHub->bDescLength, HEX); + + printProgStr(PSTR("bDescriptorType:\t")); + Serial.println(pHub->bDescriptorType, HEX); + + printProgStr(PSTR("bNbrPorts:\t\t")); + Serial.println(pHub->bNbrPorts, HEX); + + printProgStr(PSTR("LogPwrSwitchMode:\t")); + Serial.println(pHub->LogPwrSwitchMode, BIN); + + printProgStr(PSTR("CompoundDevice:\t\t")); + Serial.println(pHub->CompoundDevice, BIN); + + printProgStr(PSTR("OverCurrentProtectMode:\t")); + Serial.println(pHub->OverCurrentProtectMode, BIN); + + printProgStr(PSTR("TTThinkTime:\t\t")); + Serial.println(pHub->TTThinkTime, BIN); + + printProgStr(PSTR("PortIndicatorsSupported:")); + Serial.println(pHub->PortIndicatorsSupported, BIN); + + printProgStr(PSTR("Reserved:\t\t")); + Serial.println(pHub->Reserved, HEX); + + printProgStr(PSTR("bPwrOn2PwrGood:\t\t")); + Serial.println(pHub->bPwrOn2PwrGood, HEX); + + printProgStr(PSTR("bHubContrCurrent:\t")); + Serial.println(pHub->bHubContrCurrent, HEX); + + for (uint8_t i=7; ibNbrPorts; i++) + // PrintHubPortStatus(&Usb, addr, i, 1); +} + +byte getconfdescr( byte addr, byte conf ) +{ + uint8_t buf[ BUFSIZE ]; + uint8_t* buf_ptr = buf; + byte rcode; + byte descr_length; + byte descr_type; + unsigned int total_length; + rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length + LOBYTE( total_length ) = buf[ 2 ]; + HIBYTE( total_length ) = buf[ 3 ]; + if( total_length > 256 ) { //check if total length is larger than buffer + printProgStr(Conf_Trunc_str); + total_length = 256; + } + rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor + while( buf_ptr < buf + total_length ) { //parsing descriptors + descr_length = *( buf_ptr ); + descr_type = *( buf_ptr + 1 ); + switch( descr_type ) { + case( USB_DESCRIPTOR_CONFIGURATION ): + printconfdescr( buf_ptr ); + break; + case( USB_DESCRIPTOR_INTERFACE ): + printintfdescr( buf_ptr ); + break; + case( USB_DESCRIPTOR_ENDPOINT ): + printepdescr( buf_ptr ); + break; + case 0x29: + printhubdescr( buf_ptr, addr ); + break; + default: + printunkdescr( buf_ptr ); + break; + }//switch( descr_type + buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer + }//while( buf_ptr <=... + return( 0 ); +} +/* prints hex numbers with leading zeroes */ +// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 +// source: http://www.phanderson.com/arduino/arduino_display.html +void print_hex(int v, int num_places) +{ + int mask=0, n, num_nibbles, digit; + + for (n=1; n<=num_places; n++) { + mask = (mask << 1) | 0x0001; + } + v = v & mask; // truncate v to specified number of places + + num_nibbles = num_places / 4; + if ((num_places % 4) != 0) { + ++num_nibbles; + } + do { + digit = ((v >> (num_nibbles-1) * 4)) & 0x0f; + Serial.print(digit, HEX); + } + while(--num_nibbles); +} +/* function to print configuration descriptor */ +void printconfdescr( uint8_t* descr_ptr ) +{ + USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; + printProgStr(Conf_Header_str); + printProgStr(Conf_Totlen_str); + print_hex( conf_ptr->wTotalLength, 16 ); + printProgStr(Conf_Nint_str); + print_hex( conf_ptr->bNumInterfaces, 8 ); + printProgStr(Conf_Value_str); + print_hex( conf_ptr->bConfigurationValue, 8 ); + printProgStr(Conf_String_str); + print_hex( conf_ptr->iConfiguration, 8 ); + printProgStr(Conf_Attr_str); + print_hex( conf_ptr->bmAttributes, 8 ); + printProgStr(Conf_Pwr_str); + print_hex( conf_ptr->bMaxPower, 8 ); + return; +} +/* function to print interface descriptor */ +void printintfdescr( uint8_t* descr_ptr ) +{ + USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; + printProgStr(Int_Header_str); + printProgStr(Int_Number_str); + print_hex( intf_ptr->bInterfaceNumber, 8 ); + printProgStr(Int_Alt_str); + print_hex( intf_ptr->bAlternateSetting, 8 ); + printProgStr(Int_Endpoints_str); + print_hex( intf_ptr->bNumEndpoints, 8 ); + printProgStr(Int_Class_str); + print_hex( intf_ptr->bInterfaceClass, 8 ); + printProgStr(Int_Subclass_str); + print_hex( intf_ptr->bInterfaceSubClass, 8 ); + printProgStr(Int_Protocol_str); + print_hex( intf_ptr->bInterfaceProtocol, 8 ); + printProgStr(Int_String_str); + print_hex( intf_ptr->iInterface, 8 ); + return; +} +/* function to print endpoint descriptor */ +void printepdescr( uint8_t* descr_ptr ) +{ + USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; + printProgStr(End_Header_str); + printProgStr(End_Address_str); + print_hex( ep_ptr->bEndpointAddress, 8 ); + printProgStr(End_Attr_str); + print_hex( ep_ptr->bmAttributes, 8 ); + printProgStr(End_Pktsize_str); + print_hex( ep_ptr->wMaxPacketSize, 16 ); + printProgStr(End_Interval_str); + print_hex( ep_ptr->bInterval, 8 ); + + return; +} +/*function to print unknown descriptor */ +void printunkdescr( uint8_t* descr_ptr ) +{ + byte length = *descr_ptr; + byte i; + printProgStr(Unk_Header_str); + printProgStr(Unk_Length_str); + print_hex( *descr_ptr, 8 ); + printProgStr(Unk_Type_str); + print_hex( *(descr_ptr + 1 ), 8 ); + printProgStr(Unk_Contents_str); + descr_ptr += 2; + for( i = 0; i < length; i++ ) { + print_hex( *descr_ptr, 8 ); + descr_ptr++; + } +} + + +/* Print a string from Program Memory directly to save RAM */ +void printProgStr(const prog_char str[]) +{ + char c; + if(!str) return; + while((c = pgm_read_byte(str++))) + Serial.print(c,BYTE); +} diff --git a/examples/hub_demo/pgmstrings.h b/examples/hub_demo/pgmstrings.h new file mode 100644 index 00000000..bdb0077e --- /dev/null +++ b/examples/hub_demo/pgmstrings.h @@ -0,0 +1,52 @@ +#if !defined(__PGMSTRINGS_H__) +#define __PGMSTRINGS_H__ + +#define LOBYTE(x) ((char*)(&(x)))[0] +#define HIBYTE(x) ((char*)(&(x)))[1] +#define BUFSIZE 256 //buffer size + + +/* Print strings in Program Memory */ +const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: "; +const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t"; +const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t"; +const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t"; +const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t"; +const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t"; +const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t"; +const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t"; +const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes"; +const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t"; +const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t"; +const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t"; +const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t"; +const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t"; +const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t"; +const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t"; +const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t"; +const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t"; +const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t"; +const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:"; +const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t"; +const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t"; +const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t"; + +#endif // __PGMSTRINGS_H__ \ No newline at end of file diff --git a/gpl2.txt b/gpl2.txt new file mode 100644 index 00000000..5b6e7c66 --- /dev/null +++ b/gpl2.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/hexdump.h b/hexdump.h new file mode 100644 index 00000000..e63376af --- /dev/null +++ b/hexdump.h @@ -0,0 +1,58 @@ +/* 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(__HEXDUMP_H__) +#define __HEXDUMP_H__ + +#include +#include +#include "printhex.h" + +template +class HexDumper : public BASE_CLASS +{ + uint8_t byteCount; + OFFSET_TYPE byteTotal; + +public: + HexDumper() : byteCount(0), byteTotal(0) {}; + void Initialize() { byteCount = 0; byteTotal = 0; }; + + virtual void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset); +}; + +template +void HexDumper::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) +{ + for (LEN_TYPE j=0; j(byteTotal); + Serial.print(": "); + } + PrintHex(pbuf[j]); + Serial.print(" "); + + if (byteCount == 15) + { + Serial.println(""); + byteCount = 0xFF; + } + } +} + +#endif // __HEXDUMP_H__ \ No newline at end of file diff --git a/hid.cpp b/hid.cpp index 628c0bea..3c53bbc9 100644 --- a/hid.cpp +++ b/hid.cpp @@ -1,3 +1,19 @@ +/* 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 "hid.h" //const uint16_t HID::maxHidInterfaces = 3; diff --git a/hid.h b/hid.h index c98fe001..0f41e7e5 100644 --- a/hid.h +++ b/hid.h @@ -1,3 +1,19 @@ +/* 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(__HID_H__) #define __HID_H__ @@ -10,9 +26,9 @@ #include "Usb.h" #include -#include "..\DebugTools\printhex.h" -#include "..\DebugTools\hexdump.h" -#include "..\DebugTools\message.h" +#include "printhex.h" +#include "hexdump.h" +#include "message.h" #include "confdescparser.h" diff --git a/masstorage.h b/masstorage.h index b3c42ae2..2d667ad9 100644 --- a/masstorage.h +++ b/masstorage.h @@ -1,3 +1,19 @@ +/* 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(__MASSTORAGE_H__) #define __MASSTORAGE_H__ @@ -10,9 +26,9 @@ #include "Usb.h" #include -#include "..\DebugTools\printhex.h" -#include "..\DebugTools\hexdump.h" -#include "..\DebugTools\message.h" +#include "printhex.h" +#include "hexdump.h" +#include "message.h" #include "confdescparser.h" diff --git a/max3421e.h b/max3421e.h index b4320886..cab2359c 100644 --- a/max3421e.h +++ b/max3421e.h @@ -1,27 +1,31 @@ +/* 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 +*/ /* MAX3421E register/bit names and bitmasks */ #ifndef _max3421e_h_ #define _max3421e_h_ /* Arduino pin definitions */ - - /* pin numbers to port numbers */ -//#define MAX_SS 10 -//#define MAX_INT 3 // Black Widdow -#define MAX_INT 9 // Duemielanove -#define MAX_GPX 8 -//#define MAX_RESET 7 -// -//#define BPNT_0 3 -//#define BPNT_1 2 -// -//#define Select_MAX3421E digitalWrite( MAX_SS,LOW ) -//#define Deselect_MAX3421E digitalWrite( MAX_SS,HIGH ) +//#define MAX_INT 9 // Duemielanove -/* */ +//#define MAX_GPX 8 #define ON true #define OFF false diff --git a/max_LCD.cpp b/max_LCD.cpp index 2b84db0c..5ee7302f 100644 --- a/max_LCD.cpp +++ b/max_LCD.cpp @@ -1,3 +1,19 @@ +/* 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 "Max_LCD.h" #include "Max3421e.h" @@ -6,24 +22,6 @@ #include #include "WProgram.h" -// When the display powers up, it is configured as follows: -// -// 1. Display clear -// 2. Function set: -// DL = 1; 8-bit interface data -// N = 0; 1-line display -// F = 0; 5x8 dot character font -// 3. Display on/off control: -// D = 0; Display off -// C = 0; Cursor off -// B = 0; Blinking off -// 4. Entry mode set: -// I/D = 1; Increment by 1 -// S = 0; No shift -// -// Note, however, that resetting the Arduino doesn't reset the LCD, so we -// can't assume that its in that state when a sketch starts - // pin definition and set/clear #define RS 0x04 // RS pin diff --git a/max_LCD.h b/max_LCD.h index 718162c3..c42d78e3 100644 --- a/max_LCD.h +++ b/max_LCD.h @@ -1,9 +1,23 @@ +/* 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 +*/ //HD44780 compatible LCD display via MAX3421E GPOUT support header //pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3] // -//this code is heavily borrowed from official Arduino source v.0017 -// link to original http://code.google.com/p/arduino/source/browse/trunk/hardware/libraries/LiquidCrystal/LiquidCrystal.h -// + #ifndef _Max_LCD_h_ #define _Max_LCD_h_ diff --git a/message.cpp b/message.cpp new file mode 100644 index 00000000..82ee97de --- /dev/null +++ b/message.cpp @@ -0,0 +1,27 @@ +/* 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 "message.h" + +void Notify(char const * msg) +//void Notify(const char* msg) +{ + if(!msg) return; + char c; + + while((c = pgm_read_byte(msg++))) + Serial.print(c,BYTE); +} diff --git a/message.h b/message.h new file mode 100644 index 00000000..e276a275 --- /dev/null +++ b/message.h @@ -0,0 +1,37 @@ +/* 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(__MESSAGE_H__) +#define __MESSAGE_H__ + +#include +#include +#include "printhex.h" + +void Notify(char const * msg); +//void Notify(const char* msg); + +template +void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) +{ + Notify(msg); + Notify(PSTR(": ")); + PrintHex(rcode); + Notify(PSTR("\r\n")); +} + + +#endif // __MESSAGE_H__ diff --git a/parsetools.cpp b/parsetools.cpp new file mode 100644 index 00000000..bbcca772 --- /dev/null +++ b/parsetools.cpp @@ -0,0 +1,72 @@ +/* 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 "parsetools.h" + +bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) +{ + if (!pBuf) + { + Notify(PSTR("Buffer pointer is NULL!\r\n")); + 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; +} diff --git a/parsetools.h b/parsetools.h new file mode 100644 index 00000000..ba42038d --- /dev/null +++ b/parsetools.h @@ -0,0 +1,147 @@ +/* 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(__PARSETOOLS_H__) +#define __PARSETOOLS_H__ + +#include +#include +#include "printhex.h" +#include "hexdump.h" +#include "message.h" +#include + + +struct MultiValueBuffer +{ + uint8_t valueSize; + void *pValue; +}; + +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() : + pBuf(NULL), + nStage(0), + enStage(0), + arLenCntdn(0), + arLen(0), + lenSize(0), + valSize(0), + 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__ \ No newline at end of file diff --git a/printhex.h b/printhex.h new file mode 100644 index 00000000..9f09adda --- /dev/null +++ b/printhex.h @@ -0,0 +1,62 @@ +/* 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(__PRINTHEX_H__) +#define __PRINTHEX_H__ + +#include + +template +void PrintHex(T val) +{ + T mask = (((T)1) << (((sizeof(T) << 1) - 1) << 2)); + + while (mask > 1) + { + if (val < mask) + Serial.print("0"); + + mask >>= 4; + } + Serial.print((T)val, HEX); +} + +template +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 +void PrintBin(T val) +{ + for (T mask = (((T)1) << (sizeof(T) << 3)-1); mask; mask>>=1) + if (val & mask) + Serial.print("1"); + else + Serial.print("0"); +} + +#endif // __PRINTHEX_H__ \ No newline at end of file diff --git a/usb_ch9.h b/usb_ch9.h index b1b2fb43..12501aff 100644 --- a/usb_ch9.h +++ b/usb_ch9.h @@ -1,3 +1,19 @@ +/* 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 +*/ /* USB chapter 9 structures */ #ifndef _ch9_h_ #define _ch9_h_ diff --git a/usbhost.h b/usbhost.h index 46212f31..253e5160 100644 --- a/usbhost.h +++ b/usbhost.h @@ -1,3 +1,19 @@ +/* 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 +*/ /* MAX3421E-based USB Host Library header file */ #ifndef _USBHOST_H_ #define _USBHOST_H_ @@ -66,10 +82,6 @@ MAX3421e< SS, INTR >::MAX3421e() /* pin and peripheral setup */ SS::SetDirWrite(); SS::Set(); - /* For shield rev.1.xx uncomment following two lines */ - P7::SetDirWrite(); - P7::Set(); - spi::init(); INTR::SetDirRead(); diff --git a/usbhub.cpp b/usbhub.cpp index 405d2ffb..2ec1f754 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -1,3 +1,19 @@ +/* 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; diff --git a/usbhub.h b/usbhub.h index 7a113883..8e878821 100644 --- a/usbhub.h +++ b/usbhub.h @@ -1,3 +1,19 @@ +/* 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__