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 653a4334..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" @@ -106,78 +122,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,19 +159,27 @@ 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; + + if (read < nbytes) + break; } } else //OUT transfer @@ -245,7 +198,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 +208,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 rcode = 0; 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 @@ -277,18 +231,26 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, 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 - data = bytesRd( rRCVFIFO, pktsize, data ); + + pktsize = regRd( rRCVBC ); //number of received bytes */ + + 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 == 6 ||*/ ( pktsize < maxpktsize ) || (*nbytesptr >= nbytes )) // have we transferred 'nbytes' bytes? + { // Save toggle value pep->bmRcvToggle = ( regRd( rHRSL ) & bmRCVTOGRD ) ? 1 : 0; @@ -297,11 +259,10 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, 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, 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 +275,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 +579,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..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,23 +28,28 @@ #include "address.h" #include +#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)) + + /* 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 @@ -67,9 +88,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 @@ -114,29 +135,26 @@ 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 - class USB : public MAX3421E { AddressPoolImpl addrPool; @@ -176,22 +194,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 +218,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 +254,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/address.h b/address.h index ee7a8d2f..234a433e 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 new file mode 100644 index 00000000..17706388 --- /dev/null +++ b/cdcacm.cpp @@ -0,0 +1,347 @@ +/* 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; +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; i epInfo[epInterruptInIndex].maxPktSize) + // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize; + // rcode = pUsb->inTransfer(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..25d82e53 --- /dev/null +++ b/cdcacm.h @@ -0,0 +1,182 @@ +/* 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__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "printhex.h" +#include "hexdump.h" +#include "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..c5b9b0c8 --- /dev/null +++ b/cdcftdi.cpp @@ -0,0 +1,348 @@ +/* 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; +const uint8_t FTDI::epDataOutIndex = 2; +const uint8_t FTDI::epInterruptInIndex = 3; + +FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) : + pAsync(pasync), + pUsb(p), + bAddress(0), + bNumEP(1), + 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; + + USBTRACE2("NumEP:", bNumEP); + + // 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("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; + +FailOnInit: + USBTRACE("OnInit:"); + 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; + bNumEP = 1; + 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..270492a1 --- /dev/null +++ b/cdcftdi.h @@ -0,0 +1,145 @@ +/* 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__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "printhex.h" +#include "hexdump.h" +#include "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 + +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 + +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 + + 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]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + FTDI(USB *pusb, FTDIAsyncOper *pasync); + + 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..f1a97376 --- /dev/null +++ b/cdcprolific.cpp @@ -0,0 +1,205 @@ +/* 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) : + 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..e3702bc5 --- /dev/null +++ b/cdcprolific.h @@ -0,0 +1,150 @@ +/* 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__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "printhex.h" +#include "hexdump.h" +#include "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 +#include "printhex.h" +#include "hexdump.h" +#include "message.h" +#include "parsetools.h" + +//#include "hid.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[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; + + uint8_t stateParseDescr; // ParseDescriptor state + + uint8_t dscrLen; // Descriptor length + uint8_t dscrType; // Descriptor type + + bool isGoodInterface; // Apropriate interface flag + uint8_t confValue; // Configuration value + uint8_t protoValue; // Protocol value + uint8_t ifaceNumber; // Interface number + uint8_t ifaceAltSet; // Interface alternate settings + + bool 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); +}; + +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; + case HID_DESCRIPTOR_HID: + theBuffer.valueSize = dscrLen - 2; + break; + } + valParser.Initialize(&theBuffer); + stateParseDescr = 4; + case 4: + switch (dscrType) + { + case USB_DESCRIPTOR_CONFIGURATION: + if (!valParser.Parse(pp, pcntdn)) + return false; + confValue = ((USB_CONFIGURATION_DESCRIPTOR*)varBuffer)->bConfigurationValue; + break; + case USB_DESCRIPTOR_INTERFACE: + if (!valParser.Parse(pp, pcntdn)) + return false; + if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceClass != CLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceSubClass != SUBCLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol != PROTOCOL_ID) + break; + + isGoodInterface = true; + ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceNumber; + ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bAlternateSetting; + protoValue = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol; + break; + case USB_DESCRIPTOR_ENDPOINT: + if (!valParser.Parse(pp, pcntdn)) + return false; + if (isGoodInterface) + if (theXtractor) + theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); + break; + case HID_DESCRIPTOR_HID: + if (!valParser.Parse(pp, pcntdn)) + return false; + PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); + break; + default: + if (!theSkipper.Skip(pp, pcntdn, dscrLen-2)) + return false; + } + theBuffer.pValue = varBuffer; + stateParseDescr = 0; + } + return true; +} + +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/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 new file mode 100644 index 00000000..3c53bbc9 --- /dev/null +++ b/hid.cpp @@ -0,0 +1,1948 @@ +/* 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; +//const uint16_t HID::maxEpPerInterface = 2; +const uint8_t HID::epInterruptInIndex = 1; +const uint8_t HID::epInterruptOutIndex = 2; + +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) + { + 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); + 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); + + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t HID::Poll() +{ + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + if (qNextPollTime <= millis()) + { + 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; +} + +//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, 0x142, 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 )); +} + +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; + + while(cntdn) + { + ParseItem(&p, &cntdn); + + //if (ParseItem(&p, &cntdn)) + // return; + } +} + +uint8_t ReportDescParser::ParseItem(uint8_t **pp, uint16_t *pcntdn) +{ + uint8_t ret = enErrorSuccess; + + 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.println(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; + + 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: + { + uint8_t data = *((uint8_t*)varBuffer); + + 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): + 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): + Notify(PSTR("(")); + for (uint8_t i=0; i(data); + Notify(PSTR(")")); + break; + case (TYPE_GLOBAL | TAG_GLOBAL_PUSH): + case (TYPE_GLOBAL | TAG_GLOBAL_POP): + break; + case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE): + 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 (data) + { + 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(data); + Notify(PSTR(")")); + } + break; + case (TYPE_MAIN | TAG_MAIN_INPUT): + case (TYPE_MAIN | TAG_MAIN_OUTPUT): + case (TYPE_MAIN | TAG_MAIN_FEATURE): + Notify(PSTR("(")); + PrintBin(data); + Notify(PSTR(")")); + break; + } // switch (**pp & (TYPE_MASK | TAG_MASK)) + } + itemParseState = 4; + case 4: + 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 +}; + +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); + + 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..0f41e7e5 --- /dev/null +++ b/hid.h @@ -0,0 +1,1202 @@ +/* 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__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "printhex.h" +#include "hexdump.h" +#include "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); + + 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[]; + + 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); + void SetUsagePage(uint16_t page); + +public: + ReportDescParser() : + itemParseState(0), + 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); + + 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..2d667ad9 --- /dev/null +++ b/masstorage.h @@ -0,0 +1,113 @@ +/* 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__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "printhex.h" +#include "hexdump.h" +#include "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/max3421e.h b/max3421e.h index e39a61f2..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_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 e746b6d3..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_ @@ -49,7 +63,7 @@ #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 -class Max_LCD : public Print +class Max_LCD //: public Print { USB *pUsb; @@ -85,7 +99,4 @@ private: uint8_t _numlines,_currline; }; - - - #endif \ No newline at end of file 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 33bc2f61..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_ @@ -52,6 +68,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 @@ -70,51 +90,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 +148,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; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bDescrType; - uint16_t wDescriptorLength; +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_ diff --git a/usbhost.h b/usbhost.h index 4c7da560..515eed02 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 64efaafc..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; @@ -55,7 +71,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 +241,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..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__ @@ -10,6 +26,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 +108,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 +171,6 @@ struct HubEvent }; }; - class USBHub : USBDeviceConfig { static bool bResetInitiated; // True when reset is triggered @@ -194,42 +211,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);