diff --git a/Usb.cpp b/Usb.cpp index 653a4334..6da62e4b 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -106,78 +106,7 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_l /* 00 = success */ /* 01-0f = non-zero HRSLT */ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - unsigned int wInd, unsigned int nbytes, uint8_t* dataptr ) -{ - return ctrlReq(addr, ep, bmReqType, bRequest, wValLo, wValHi, wInd, nbytes, nbytes, dataptr, NULL); -} - -//uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, -// uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBREADCALLBACK pf) -//{ -// boolean direction = false; //request direction, IN or OUT -// uint8_t rcode; -// SETUP_PKT setup_pkt; -// -// EpInfo *pep = NULL; -// uint16_t nak_limit; -// -// rcode = SetAddress(addr, ep, &pep, nak_limit); -// -// if (rcode) -// return rcode; -// -// direction = (( bmReqType & 0x80 ) > 0); -// -// /* fill in setup packet */ -// setup_pkt.ReqType_u.bmRequestType = bmReqType; -// setup_pkt.bRequest = bRequest; -// setup_pkt.wVal_u.wValueLo = wValLo; -// setup_pkt.wVal_u.wValueHi = wValHi; -// setup_pkt.wIndex = wInd; -// setup_pkt.wLength = total; -// -// bytesWr( rSUDFIFO, 8, (uint8_t*)&setup_pkt ); //transfer to setup packet FIFO -// -// rcode = dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet -// -// if( rcode ) //return HRSLT if not zero -// return( rcode ); -// -// if( dataptr != NULL ) //data stage, if present -// { -// if( direction ) //IN transfer -// { -// uint16_t left = total; -// -// while (left) -// { -// pep->bmRcvToggle = 1; //bmRCVTOG1; -// rcode = InTransfer( pep, nak_limit, nbytes, dataptr ); -// -// // Bytes read into buffer -// uint16_t read = (left < nbytes) ? left : nbytes; -// -// // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified -// if (!rcode && pf) -// pf( read, dataptr, total - left ); -// -// left -= read; -// } -// } -// else //OUT transfer -// { -// pep->bmSndToggle = 1; //bmSNDTOG1; -// rcode = OutTransfer( pep, nak_limit, nbytes, dataptr ); -// } -// if( rcode ) //return error -// return( rcode ); -// } -// // Status stage -// return dispatchPkt( (direction) ? tokOUTHS : tokINHS, ep, nak_limit ); //GET if direction -//} - -uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, UsbReadParser *p) + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) { boolean direction = false; //request direction, IN or OUT uint8_t rcode; @@ -214,17 +143,22 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ { uint16_t left = total; + pep->bmRcvToggle = 1; //bmRCVTOG1; + while (left) { - pep->bmRcvToggle = 1; //bmRCVTOG1; - rcode = InTransfer( pep, nak_limit, nbytes, dataptr ); - // Bytes read into buffer - uint16_t read = (left < nbytes) ? left : nbytes; + uint16_t read = nbytes; + //uint16_t read = (leftParse( read, dataptr, total - left ); + ((USBReadParser*)p)->Parse( read, dataptr, total - left ); left -= read; } @@ -245,7 +179,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ /* Keep sending INs and writes data to memory area pointed by 'data' */ /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error, fe USB xfer timeout */ -uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ) +uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) { EpInfo *pep = NULL; uint16_t nak_limit = 0; @@ -255,17 +189,18 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* if (rcode) return rcode; - return InTransfer(pep, nak_limit, nbytes, data); + return InTransfer(pep, nak_limit, nbytesptr, data); } -uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t* data ) +uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) { uint8_t rcode; uint8_t pktsize; - uint8_t maxpktsize = pep->maxPktSize; + uint16_t nbytes = *nbytesptr; + uint8_t maxpktsize = pep->maxPktSize; - unsigned int xfrlen = 0; + *nbytesptr = 0; regWr( rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0 ); //set toggle value while( 1 ) // use a 'return' to exit this loop @@ -281,13 +216,20 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, ui return ( 0xf0 ); //receive error } pktsize = regRd( rRCVBC ); //number of received bytes - data = bytesRd( rRCVFIFO, pktsize, data ); + + int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); + + if (mem_left < 0) + mem_left = 0; + + data = bytesRd( rRCVFIFO, (pktsize > mem_left) ? mem_left : pktsize, data ); + regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer - xfrlen += pktsize; // add this packet's byte count to total transfer length + *nbytesptr += pktsize; // add this packet's byte count to total transfer length /* The transfer is complete under two conditions: */ /* 1. The device sent a short packet (L.T. maxPacketSize) */ /* 2. 'nbytes' have been transferred. */ - if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) // have we transferred 'nbytes' bytes? + if (( pktsize < maxpktsize ) || (*nbytesptr >= nbytes )) // have we transferred 'nbytes' bytes? { // Save toggle value pep->bmRcvToggle = ( regRd( rHRSL ) & bmRCVTOGRD ) ? 1 : 0; @@ -301,7 +243,7 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, ui /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */ /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */ /* major part of this function borrowed from code shared by Richard Ibbotson */ -uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ) +uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data ) { EpInfo *pep = NULL; uint16_t nak_limit; @@ -314,7 +256,7 @@ uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t return OutTransfer(pep, nak_limit, nbytes, data); } -uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t *data) +uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) { uint8_t rcode, retry_count; uint8_t *data_p = data; //local copy of the data pointer @@ -618,4 +560,50 @@ uint8_t USB::ReleaseDevice(uint8_t addr) return devConfig[i]->Release(); } +#if 1 //!defined(USB_METHODS_INLINE) +//get device descriptor +uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) +{ + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL )); +} +//get configuration descriptor +uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr ) +{ + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL )); +} + +uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p ) +{ + const uint8_t bufSize = 64; + uint8_t buf[bufSize]; + + uint8_t ret = getConfDescr( addr, ep, 8, conf, buf ); + + if (ret) + return ret; + + uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength; + + USBTRACE2("total:", total); + + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p )); +} + +//get string descriptor +uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr ) +{ + return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL )); +} +//set address +uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr ) +{ + return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL )); +} +//set configuration +uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ) +{ + return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL )); +} + +#endif // defined(USB_METHODS_INLINE) diff --git a/Usb.h b/Usb.h index 2c762179..0f054621 100644 --- a/Usb.h +++ b/Usb.h @@ -12,23 +12,23 @@ #include "address.h" #include +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#define USBTRACE(s) (Serial.print((s))) +#define USBTRACE2(s,r) (Serial.print((s)), Serial.println((r),HEX)) + + /* Common setup data constant combinations */ #define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type #define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type -/* HID requests */ -#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE - - - // D7 data transfer direction (0 - host-to-device, 1 - device-to-host) // D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved) // D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved) - // USB Device Classes #define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors #define USB_CLASS_AUDIO 0x01 // Audio @@ -114,28 +114,28 @@ typedef struct { }ReqType_u; uint8_t bRequest; // 1 Request union { - unsigned int wValue; // 2 Depends on bRequest + uint16_t wValue; // 2 Depends on bRequest struct { uint8_t wValueLo; uint8_t wValueHi; }; }wVal_u; - unsigned int wIndex; // 4 Depends on bRequest - unsigned int wLength; // 6 Depends on bRequest + uint16_t wIndex; // 4 Depends on bRequest + uint16_t wLength; // 6 Depends on bRequest } SETUP_PKT, *PSETUP_PKT; // Base class for incomming data parser -class UsbReadParser +class USBReadParser { public: - virtual void Parse(const uint8_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; }; -//typedef MAX3421e MAX3421E; // Black Widdow -typedef MAX3421e MAX3421E; // Duemielanove +typedef MAX3421e MAX3421E; // Black Widdow +//typedef MAX3421e MAX3421E; // Duemielanove class USB : public MAX3421E { @@ -176,22 +176,22 @@ class USB : public MAX3421E EpInfo* getEpInfoEntry( uint8_t addr, uint8_t ep ); uint8_t setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr ); - uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, unsigned int wInd, unsigned int nbytes, uint8_t* dataptr); + //uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t nbytes, uint8_t* dataptr); /* Control requests */ - uint8_t getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ); - uint8_t getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr ); - uint8_t getStrDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t index, unsigned int langid, uint8_t* dataptr ); + uint8_t getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ); + uint8_t getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr ); + + uint8_t getConfDescr( uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p ); + + uint8_t getStrDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr ); uint8_t setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr ); uint8_t setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ); /**/ - uint8_t setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol ); - uint8_t getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr ); - /**/ - uint8_t ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction ); + uint8_t ctrlData( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, boolean direction ); uint8_t ctrlStatus( uint8_t ep, boolean direction, uint16_t nak_limit ); - uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ); - uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data ); + uint8_t inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data ); + uint8_t outTransfer( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data ); uint8_t dispatchPkt( uint8_t token, uint8_t ep, uint16_t nak_limit ); void Task( void ); @@ -200,34 +200,29 @@ class USB : public MAX3421E uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed); uint8_t ReleaseDevice(uint8_t addr); - //typedef void (*USBREADCALLBACK)(uint16_t nbytes, uint8_t *data, uint16_t offset); - - //uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - // uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBREADCALLBACK pf); - uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, - uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, UsbReadParser *p); + uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p); private: void init(); uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit); - uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t *data); - uint8_t InTransfer (EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t* data); + uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); + uint8_t InTransfer (EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data); }; -//#if defined(USB_METHODS_INLINE) +#if 0 //defined(USB_METHODS_INLINE) //get device descriptor -inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ) +inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr ) { return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr )); } //get configuration descriptor -inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr ) +inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr ) { return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr )); } //get string descriptor -inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t index, unsigned int langid, uint8_t* dataptr ) +inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr ) { return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr )); } @@ -241,16 +236,7 @@ inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ) { return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL )); } -//class requests -inline uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol ) -{ - return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL )); -} -inline uint8_t USB::getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr ) -{ - return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr )); -} -//#endif // defined(USB_METHODS_INLINE) +#endif // defined(USB_METHODS_INLINE) #endif //_usb_h_ \ No newline at end of file diff --git a/cdcacm.cpp b/cdcacm.cpp new file mode 100644 index 00000000..b911dda2 --- /dev/null +++ b/cdcacm.cpp @@ -0,0 +1,330 @@ +#include "cdcacm.h" + +const uint8_t ACM::epDataInIndex = 1; +const uint8_t ACM::epDataOutIndex = 2; +const uint8_t ACM::epInterruptInIndex = 3; + +ACM::ACM(USB *p, CDCAsyncOper *pasync) : + pUsb(p), + pAsync(pasync), + bAddress(0), + qNextPollTime(0), + bPollEnable(false), + bControlIface(0), + bDataIface(0), + bNumEP(1) +{ + for(uint8_t i=0; iRegisterDeviceClass(this); +} + +uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) +{ + const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("ACM Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) + { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr( 0, 0, constBufSize, (uint8_t*)buf ); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if( rcode ) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i CdcControlParser(this); + + ConfigDescParser CdcDataParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser); + rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 4) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConf; + + rcode = pAsync->OnInit(this); + + if (rcode) + goto FailOnInit; + + USBTRACE("ACM configured\r\n"); + + //bPollEnable = true; + + //USBTRACE("Poll enabled\r\n"); + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConf: + USBTRACE("setConf:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + + +void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) +{ + ErrorMessage(PSTR("Conf.Val"), conf); + ErrorMessage(PSTR("Iface Num"),iface); + ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP ++; + + PrintEndpointDescriptor(pep); +} + +uint8_t ACM::Release() +{ + pUsb->GetAddressPool().FreeAddress(bAddress); + + bControlIface = 0; + bDataIface = 0; + bNumEP = 1; + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t ACM::Poll() +{ + uint8_t rcode = 0; + + if (!bPollEnable) + return 0; + + uint32_t time_now = millis(); + + if (qNextPollTime <= time_now) + { + qNextPollTime = time_now + 100; + + uint8_t rcode; + const uint8_t constBufSize = 16; + uint8_t buf[constBufSize]; + + for (uint8_t i=0; iinTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); + + if (rcode) + return rcode; + + for (uint8_t i=0; i(buf[i]); + Serial.print(" "); + } + USBTRACE("\r\n"); + } + return rcode; +} + +uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) +{ + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) +{ + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL )); +} + +uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL )); +} + +uint8_t ACM::ClearCommFeature(uint16_t fid) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL )); +} + +uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof(LINE_CODING), sizeof(LINE_CODING), (uint8_t*)dataptr, NULL )); +} + +uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof(LINE_CODING), sizeof(LINE_CODING), (uint8_t*)dataptr, NULL )); +} + +uint8_t ACM::SetControlLineState(uint8_t state) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL )); +} + +uint8_t ACM::SendBreak(uint16_t duration) +{ + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL )); +} + + +void ACM::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) +{ + Notify(PSTR("Endpoint descriptor:")); + Notify(PSTR("\r\nLength:\t\t")); + PrintHex(ep_ptr->bLength); + Notify(PSTR("\r\nType:\t\t")); + PrintHex(ep_ptr->bDescriptorType); + Notify(PSTR("\r\nAddress:\t")); + PrintHex(ep_ptr->bEndpointAddress); + Notify(PSTR("\r\nAttributes:\t")); + PrintHex(ep_ptr->bmAttributes); + Notify(PSTR("\r\nMaxPktSize:\t")); + PrintHex(ep_ptr->wMaxPacketSize); + Notify(PSTR("\r\nPoll Intrv:\t")); + PrintHex(ep_ptr->bInterval); + Notify(PSTR("\r\n")); +} diff --git a/cdcacm.h b/cdcacm.h new file mode 100644 index 00000000..fc63b587 --- /dev/null +++ b/cdcacm.h @@ -0,0 +1,166 @@ +#if !defined(__CDCACM_H__) +#define __CDCACM_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" + +#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +// CDC Subclass Constants +#define CDC_SUBCLASS_DLCM 0x01 // Direct Line Control Model +#define CDC_SUBCLASS_ACM 0x02 // Abstract Control Model +#define CDC_SUBCLASS_TCM 0x03 // Telephone Control Model +#define CDC_SUBCLASS_MCCM 0x04 // Multi Channel Control Model +#define CDC_SUBCLASS_CAPI 0x05 // CAPI Control Model +#define CDC_SUBCLASS_ETHERNET 0x06 // Ethernet Network Control Model +#define CDC_SUBCLASS_ATM 0x07 // ATM Network Control Model +#define CDC_SUBCLASS_WIRELESS_HANDSET 0x08 // Wireless Handset Control Model +#define CDC_SUBCLASS_DEVICE_MANAGEMENT 0x09 // Device Management +#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A // Mobile Direct Line Model +#define CDC_SUBCLASS_OBEX 0x0B // OBEX +#define CDC_SUBCLASS_ETHERNET_EMU 0x0C // Ethernet Emulation Model + +// Communication Interface Class Control Protocol Codes +#define CDC_PROTOCOL_ITU_T_V_250 0x01 // AT Commands defined by ITU-T V.250 +#define CDC_PROTOCOL_PCCA_101 0x02 // AT Commands defined by PCCA-101 +#define CDC_PROTOCOL_PCCA_101_O 0x03 // AT Commands defined by PCCA-101 & Annex O +#define CDC_PROTOCOL_GSM_7_07 0x04 // AT Commands defined by GSM 7.07 +#define CDC_PROTOCOL_3GPP_27_07 0x05 // AT Commands defined by 3GPP 27.007 +#define CDC_PROTOCOL_C_S0017_0 0x06 // AT Commands defined by TIA for CDMA +#define CDC_PROTOCOL_USB_EEM 0x07 // Ethernet Emulation Model + +// CDC Commands defined by CDC 1.2 +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 + +// CDC Commands defined by PSTN 1.2 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_AUX_LINE_STATE 0x10 +#define CDC_SET_HOOK_STATE 0x11 +#define CDC_PULSE_SETUP 0x12 +#define CDC_SEND_PULSE 0x13 +#define CDC_SET_PULSE_TIME 0x14 +#define CDC_RING_AUX_JACK 0x15 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 +#define CDC_SET_RINGER_PARMS 0x30 +#define CDC_GET_RINGER_PARMS 0x31 +#define CDC_SET_OPERATION_PARMS 0x32 +#define CDC_GET_OPERATION_PARMS 0x33 +#define CDC_SET_LINE_PARMS 0x34 +#define CDC_GET_LINE_PARMS 0x35 +#define CDC_DIAL_DIGITS 0x36 + +// CDC Functional Descriptor Structures +typedef struct +{ + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} CALL_MGMNT_FUNC_DESCR; + +typedef struct +{ + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR, + TEL_CALL_STATE_REP_CPBL_FUNC_DESCR; + +typedef struct +{ + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bRingerVolSteps; + uint8_t bNumRingerPatterns; +} TEL_RINGER_FUNC_DESCR; + +typedef struct +{ + uint32_t dwDTERate; // Data Terminal Rate in bits per second + uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits + uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space + uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16) +} LINE_CODING; + +class ACM; + +class CDCAsyncOper +{ +public: + virtual uint8_t OnInit(ACM *pacm) = 0; + //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0; + //virtual void OnDisconnected(ACM *pacm) = 0; +}; + + +#define ACM_MAX_ENDPOINTS 4 + +class ACM : public USBDeviceConfig, public UsbConfigXtracter +{ +protected: + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + CDCAsyncOper *pAsync; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bControlIface; // Control interface value + uint8_t bDataIface; // Data interface value + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + EpInfo epInfo[ACM_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + ACM(USB *pusb, CDCAsyncOper *pasync); + + uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr); + uint8_t ClearCommFeature(uint16_t fid); + uint8_t SetLineCoding(const LINE_CODING *dataptr); + uint8_t GetLineCoding(LINE_CODING *dataptr); + uint8_t SetControlLineState(uint8_t state); + uint8_t SendBreak(uint16_t duration); + + // Methods for recieving and sending data + uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __CDCACM_H__ \ No newline at end of file diff --git a/cdcftdi.cpp b/cdcftdi.cpp new file mode 100644 index 00000000..76076f89 --- /dev/null +++ b/cdcftdi.cpp @@ -0,0 +1,330 @@ +#include "cdcftdi.h" + +const uint8_t FTDI::epDataInIndex = 1; +const uint8_t FTDI::epDataOutIndex = 2; +const uint8_t FTDI::epInterruptInIndex = 3; + +FTDI::FTDI(USB *p) : + pUsb(p), + bAddress(0), + wFTDIType(0) +{ + for(uint8_t i=0; iRegisterDeviceClass(this); +} + +uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) +{ + const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t len = 0; + uint16_t cd_len = 0; + + uint8_t num_of_conf; // number of configurations + uint8_t num_of_intf; // number of interfaces + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("FTDI Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) + { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf ); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if( rcode ) + goto FailGetDevDescr; + + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != FTDI_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of FTDI chip + wFTDIType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i HexDump; + ConfigDescParser<0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + rcode = SetBaudRate(115200); + + if (rcode) + goto FailSetBaudRate; + + rcode = SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL); + //rcode = SetFlowControl(FTDI_SIO_SET_DTR_HIGH); + + if (rcode) + goto FailSetFlowControl; + + + USBTRACE("FTDI configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailSetBaudRate: + USBTRACE("SetBaudRate:"); + goto Fail; + +FailSetFlowControl: + USBTRACE("SetFlowControl:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + + +void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) +{ + ErrorMessage(PSTR("Conf.Val"), conf); + ErrorMessage(PSTR("Iface Num"),iface); + ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + + uint8_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + index = epInterruptInIndex; + else + if ((pep->bmAttributes & 0x02) == 2) + index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; + else + return; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP ++; + + PrintEndpointDescriptor(pep); +} + +uint8_t FTDI::Release() +{ + pUsb->GetAddressPool().FreeAddress(bAddress); + + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +uint8_t FTDI::Poll() +{ + uint8_t rcode = 0; + + //if (!bPollEnable) + // return 0; + + //if (qNextPollTime <= millis()) + //{ + // Serial.println(bAddress, HEX); + + // qNextPollTime = millis() + 100; + //} + return rcode; +} + +uint8_t FTDI::SetBaudRate(uint32_t baud) +{ + uint16_t baud_value, baud_index = 0; + uint32_t divisor3; + + divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left + + if (wFTDIType == FT232AM) + { + if ((divisor3 & 0x7) == 7) + divisor3 ++; // round x.7/8 up to x+1 + + baud_value = divisor3 >> 3; + divisor3 &= 0x7; + + if (divisor3 == 1) baud_value |= 0xc000; else // 0.125 + if (divisor3 >= 4) baud_value |= 0x4000; else // 0.5 + if (divisor3 != 0) baud_value |= 0x8000; // 0.25 + if (baud_value == 1) baud_value = 0; /* special case for maximum baud rate */ + } + else + { + static const unsigned char divfrac [8] = { 0, 3, 2, 0, 1, 1, 2, 3 }; + static const unsigned char divindex[8] = { 0, 0, 0, 1, 0, 1, 1, 1 }; + + baud_value = divisor3 >> 3; + baud_value |= divfrac [divisor3 & 0x7] << 14; + baud_index = divindex[divisor3 & 0x7]; + + /* Deal with special cases for highest baud rates. */ + if (baud_value == 1) baud_value = 0; else // 1.0 + if (baud_value == 0x4001) baud_value = 1; // 1.5 + } + USBTRACE2("baud_value:", baud_value); + USBTRACE2("baud_index:", baud_index); + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL ); +} + +uint8_t FTDI::SetModemControl(uint16_t signal) +{ + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL); +} + +uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) +{ + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL); +} + +uint8_t FTDI::SetData(uint16_t databm) +{ + return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL); +} + +uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) +{ + return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); +} + +uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) +{ + return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); +} + +void FTDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) +{ + Notify(PSTR("Endpoint descriptor:")); + Notify(PSTR("\r\nLength:\t\t")); + PrintHex(ep_ptr->bLength); + Notify(PSTR("\r\nType:\t\t")); + PrintHex(ep_ptr->bDescriptorType); + Notify(PSTR("\r\nAddress:\t")); + PrintHex(ep_ptr->bEndpointAddress); + Notify(PSTR("\r\nAttributes:\t")); + PrintHex(ep_ptr->bmAttributes); + Notify(PSTR("\r\nMaxPktSize:\t")); + PrintHex(ep_ptr->wMaxPacketSize); + Notify(PSTR("\r\nPoll Intrv:\t")); + PrintHex(ep_ptr->bInterval); + Notify(PSTR("\r\n")); +} diff --git a/cdcftdi.h b/cdcftdi.h new file mode 100644 index 00000000..0bb81792 --- /dev/null +++ b/cdcftdi.h @@ -0,0 +1,119 @@ +#if !defined(__CDCFTDI_H__) +#define __CDCFTDI_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" + +#define bmREQ_FTDI_OUT 0x40 +#define bmREQ_FTDI_IN 0xc0 + +//#define bmREQ_FTDI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +//#define bmREQ_FTDI_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE + +#define FTDI_VID 0x0403 // FTDI VID +#define FTDI_PID 0x6001 // FTDI PID + +#define FT232AM 0x0200 +#define FT232BM 0x0400 +#define FT2232 0x0500 +#define FT232R 0x0600 + +// Commands +#define FTDI_SIO_RESET 0 /* Reset the port */ +#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ +#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ +#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ +#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ +#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ +#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ +#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ + +#define FTDI_SIO_RESET_SIO 0 +#define FTDI_SIO_RESET_PURGE_RX 1 +#define FTDI_SIO_RESET_PURGE_TX 2 + +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 ) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 ) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) + +#define FTDI_SIO_SET_DTR_MASK 0x1 +#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_RTS_MASK 0x2 +#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) +#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) + +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) +#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) +#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) + +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 + +// Only single port chips are currently supported by the library, +// so only three endpoints are allocated. +#define FTDI_MAX_ENDPOINTS 3 + +class FTDI : public USBDeviceConfig, public UsbConfigXtracter +{ + static const uint8_t epDataInIndex; // DataIn endpoint index + static const uint8_t epDataOutIndex; // DataOUT endpoint index + static const uint8_t epInterruptInIndex; // InterruptIN endpoint index + + USB *pUsb; + uint8_t bAddress; + uint8_t bConfNum; // configuration number + uint8_t bNumIface; // number of interfaces in the configuration + uint8_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + uint16_t wFTDIType; // Type of FTDI chip + + EpInfo epInfo[FTDI_MAX_ENDPOINTS]; + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + +public: + FTDI(USB *pusb); + + uint8_t SetBaudRate(uint32_t baud); + uint8_t SetModemControl(uint16_t control); + uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13); + uint8_t SetData(uint16_t databm); + + // Methods for recieving and sending data + uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr); + uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +#endif // __CDCFTDI_H__ \ No newline at end of file diff --git a/cdcprolific.cpp b/cdcprolific.cpp new file mode 100644 index 00000000..3d0fd4c7 --- /dev/null +++ b/cdcprolific.cpp @@ -0,0 +1,189 @@ +#include "cdcprolific.h" + +PL::PL(USB *p, CDCAsyncOper *pasync) : + ACM(p, pasync), + wPLType(0) +{ +} + +uint8_t PL::Init(uint8_t parent, uint8_t port, bool lowspeed) +{ + const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint8_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + USBTRACE("PL Init\r\n"); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) + { + USBTRACE("epinfo\r\n"); + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr( 0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf ); + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if( rcode ) + goto FailGetDevDescr; + + if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Save type of PL chip + wPLType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + USBTRACE2("setAddr:",rcode); + return rcode; + } + + USBTRACE2("Addr:", bAddress); + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + USBTRACE2("NC:", num_of_conf); + + for (uint8_t i=0; i HexDump; + ConfigDescParser<0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); + + rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } // for + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + USBTRACE2("Conf:", bConfNum); + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + rcode = pAsync->OnInit(this); + + if (rcode) + goto FailOnInit; + + USBTRACE("PL configured\r\n"); + + bPollEnable = true; + return 0; + +FailGetDevDescr: + USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + USBTRACE("setDevTblEn:"); + goto Fail; + +FailGetConfDescr: + USBTRACE("getConf:"); + goto Fail; + +FailSetConfDescr: + USBTRACE("setConf:"); + goto Fail; + +FailSetControlLineState: + USBTRACE("SetControlLineState:"); + goto Fail; + +FailSetLineCoding: + USBTRACE("SetLineCoding:"); + goto Fail; + +FailOnInit: + USBTRACE("OnInit:"); + goto Fail; + +Fail: + Serial.println(rcode, HEX); + Release(); + return rcode; +} + +//uint8_t PL::Poll() +//{ +// uint8_t rcode = 0; +// +// //if (!bPollEnable) +// // return 0; +// +// //if (qNextPollTime <= millis()) +// //{ +// // Serial.println(bAddress, HEX); +// +// // qNextPollTime = millis() + 100; +// //} +// return rcode; +//} + + diff --git a/cdcprolific.h b/cdcprolific.h new file mode 100644 index 00000000..c2a7bfd0 --- /dev/null +++ b/cdcprolific.h @@ -0,0 +1,134 @@ +#if !defined(__CDCPROLIFIC_H__) +#define __CDCPROLIFIC_H__ + +#include +#include +#include "avrpins.h" +#include "max3421e.h" +#include "usbhost.h" +#include "usb_ch9.h" +#include "Usb.h" +#include + +#include "..\DebugTools\printhex.h" +#include "..\DebugTools\hexdump.h" +#include "..\DebugTools\message.h" + +#include "confdescparser.h" +#include "cdcacm.h" + +#define PL_VID 0x067B +#define PL_PID 0x2303 + +#define PROLIFIC_REV_H 0x0202 +#define PROLIFIC_REV_X 0x0300 +#define PROLIFIC_REV_HX_CHIP_D 0x0400 +#define PROLIFIC_REV_1 0x0001 + +#define kXOnChar '\x11' +#define kXOffChar '\x13' + +#define SPECIAL_SHIFT (5) +#define SPECIAL_MASK ((1< +#include "..\ParseTools\parsetools.h" + +class UsbConfigXtracter +{ +public: + //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0; + //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0; + virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0; +}; + +#define CP_MASK_COMPARE_CLASS 1 +#define CP_MASK_COMPARE_SUBCLASS 2 +#define CP_MASK_COMPARE_PROTOCOL 4 +#define CP_MASK_COMPARE_ALL 7 + +// Configuration Descriptor Parser Class Template +template +class ConfigDescParser : public USBReadParser +{ + UsbConfigXtracter *theXtractor; + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; + + uint8_t stateParseDescr; // ParseDescriptor state + + uint8_t dscrLen; // Descriptor length + uint8_t dscrType; // Descriptor type + + bool isGoodInterface; // Apropriate interface flag + uint8_t confValue; // Configuration value + uint8_t protoValue; // Protocol value + uint8_t ifaceNumber; // Interface number + uint8_t ifaceAltSet; // Interface alternate settings + + bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); + +public: + ConfigDescParser(UsbConfigXtracter *xtractor); + virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); +}; + +template +ConfigDescParser::ConfigDescParser(UsbConfigXtracter *xtractor) : + stateParseDescr(0), + dscrLen(0), + dscrType(0), + theXtractor(xtractor) +{ + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); +}; + +template +void ConfigDescParser::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) +{ + uint16_t cntdn = (uint16_t)len; + uint8_t *p = (uint8_t*)pbuf; + + while(cntdn) + if (!ParseDescriptor(&p, &cntdn)) + return; +} + +template +bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) +{ + switch (stateParseDescr) + { + case 0: + theBuffer.valueSize = 2; + valParser.Initialize(&theBuffer); + stateParseDescr = 1; + case 1: + if (!valParser.Parse(pp, pcntdn)) + return false; + dscrLen = *((uint8_t*)theBuffer.pValue); + dscrType = *((uint8_t*)theBuffer.pValue + 1); + stateParseDescr = 2; + case 2: + // This is a sort of hack. Assuming that two bytes are allready in the buffer + // the pointer is positioned two bytes ahead in order for the rest of descriptor + // to be read right after the size and the type fields. + // This should be used carefuly. varBuffer should be used directly to handle data + // in the buffer. + theBuffer.pValue = varBuffer + 2; + stateParseDescr = 3; + case 3: + switch (dscrType) + { + case USB_DESCRIPTOR_INTERFACE: + isGoodInterface = false; + case USB_DESCRIPTOR_CONFIGURATION: + theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR)-2; + break; + case USB_DESCRIPTOR_ENDPOINT: + theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR)-2; + break; + } + valParser.Initialize(&theBuffer); + stateParseDescr = 4; + case 4: + switch (dscrType) + { + case USB_DESCRIPTOR_CONFIGURATION: + if (!valParser.Parse(pp, pcntdn)) + return false; + confValue = ((USB_CONFIGURATION_DESCRIPTOR*)varBuffer)->bConfigurationValue; + break; + case USB_DESCRIPTOR_INTERFACE: + if (!valParser.Parse(pp, pcntdn)) + return false; + if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceClass != CLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceSubClass != SUBCLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol != PROTOCOL_ID) + break; + + isGoodInterface = true; + ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceNumber; + ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bAlternateSetting; + protoValue = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol; + break; + case USB_DESCRIPTOR_ENDPOINT: + if (!valParser.Parse(pp, pcntdn)) + return false; + if (isGoodInterface) + if (theXtractor) + theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); + break; + default: + if (!theSkipper.Skip(pp, pcntdn, dscrLen-2)) + return false; + } + theBuffer.pValue = varBuffer; + stateParseDescr = 0; + } + return true; +} + +#endif // __CONFDESCPARSER_H__ \ No newline at end of file diff --git a/max_LCD.h b/max_LCD.h index e746b6d3..718162c3 100644 --- a/max_LCD.h +++ b/max_LCD.h @@ -49,7 +49,7 @@ #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 -class Max_LCD : public Print +class Max_LCD //: public Print { USB *pUsb; @@ -85,7 +85,4 @@ private: uint8_t _numlines,_currline; }; - - - #endif \ No newline at end of file diff --git a/usb_ch9.h b/usb_ch9.h index 33bc2f61..150a077b 100644 --- a/usb_ch9.h +++ b/usb_ch9.h @@ -70,51 +70,24 @@ #define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient #define USB_FEATURE_TEST_MODE 2 // Device recipient -/* HID constants. Not part of chapter 9 */ -/* Class-Specific Requests */ -#define HID_REQUEST_GET_REPORT 0x01 -#define HID_REQUEST_GET_IDLE 0x02 -#define HID_REQUEST_GET_PROTOCOL 0x03 -#define HID_REQUEST_SET_REPORT 0x09 -#define HID_REQUEST_SET_IDLE 0x0A -#define HID_REQUEST_SET_PROTOCOL 0x0B - -/* Class Descriptor Types */ -#define HID_DESCRIPTOR_HID 0x21 -#define HID_DESCRIPTOR_REPORT 0x22 -#define HID_DESRIPTOR_PHY 0x23 - -/* Protocol Selection */ -#define BOOT_PROTOCOL 0x00 -#define RPT_PROTOCOL 0x01 -/* HID Interface Class Code */ -#define HID_INTF 0x03 -/* HID Interface Class SubClass Codes */ -#define BOOT_INTF_SUBCLASS 0x01 -/* HID Interface Class Protocol Codes */ -#define HID_PROTOCOL_NONE 0x00 -#define HID_PROTOCOL_KEYBOARD 0x01 -#define HID_PROTOCOL_MOUSE 0x02 - - /* descriptor data structures */ /* Device descriptor structure */ typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). - uint16_t bcdUSB; // USB Spec Release Number (BCD). - uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). - uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. - uint16_t idVendor; // Vendor ID (assigned by the USB-IF). - uint16_t idProduct; // Product ID (assigned by the manufacturer). - uint16_t bcdDevice; // Device release number (BCD). - uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. - uint8_t iProduct; // Index of String Descriptor describing the product. - uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. - uint8_t bNumConfigurations; // Number of possible configurations. + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + uint8_t iProduct; // Index of String Descriptor describing the product. + uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. + uint8_t bNumConfigurations; // Number of possible configurations. } USB_DEVICE_DESCRIPTOR; /* Configuration descriptor structure */ @@ -155,15 +128,4 @@ typedef struct uint8_t bInterval; // Polling interval in frames. } USB_ENDPOINT_DESCRIPTOR; -/* HID descriptor */ -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bDescrType; - uint16_t wDescriptorLength; -} USB_HID_DESCRIPTOR; - #endif // _ch9_h_ diff --git a/usbhub.cpp b/usbhub.cpp index 64efaafc..405d2ffb 100644 --- a/usbhub.cpp +++ b/usbhub.cpp @@ -55,7 +55,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence p->epinfo = epInfo; - p->lowspeed = lowspeed; + p->lowspeed = lowspeed; // Get device descriptor rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); @@ -225,8 +225,9 @@ uint8_t USBHub::CheckHubStatus() { uint8_t rcode; uint8_t buf[8]; + uint16_t read = 1; - rcode = pUsb->inTransfer(bAddress, 1, 1, buf); + rcode = pUsb->inTransfer(bAddress, 1, &read, buf); if (rcode) return rcode; diff --git a/usbhub.h b/usbhub.h index cb03f228..7a113883 100644 --- a/usbhub.h +++ b/usbhub.h @@ -10,6 +10,8 @@ #include "Usb.h" #include +#define USB_DESCRIPTOR_HUB 0x09 // Hub descriptor type + // Hub Requests #define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE #define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER @@ -90,16 +92,16 @@ // Hub Port Configuring Substates -#define USB_STATE_HUB_PORT_CONFIGURING 0xb0 -#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1 -#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2 -#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3 -#define USB_STATE_HUB_PORT_DISABLED 0xb4 -#define USB_STATE_HUB_PORT_RESETTING 0xb5 -#define USB_STATE_HUB_PORT_ENABLED 0xb6 +#define USB_STATE_HUB_PORT_CONFIGURING 0xb0 +#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1 +#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2 +#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3 +#define USB_STATE_HUB_PORT_DISABLED 0xb4 +#define USB_STATE_HUB_PORT_RESETTING 0xb5 +#define USB_STATE_HUB_PORT_ENABLED 0xb6 // Additional Error Codes -#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1 +#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1 // The bit mask to check for all necessary state bits #define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND) @@ -153,7 +155,6 @@ struct HubEvent }; }; - class USBHub : USBDeviceConfig { static bool bResetInitiated; // True when reset is triggered @@ -194,42 +195,42 @@ public: // Clear Hub Feature inline uint8_t USBHub::ClearHubFeature( uint8_t fid ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL )); } // Clear Port Feature inline uint8_t USBHub::ClearPortFeature( uint8_t fid, uint8_t port, uint8_t sel ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, 0, NULL, NULL )); } // Get Hub Descriptor inline uint8_t USBHub::GetHubDescriptor( uint8_t index, uint16_t nbytes, uint8_t *dataptr ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, dataptr )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL )); } // Get Hub Status inline uint8_t USBHub::GetHubStatus( uint16_t nbytes, uint8_t* dataptr ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, dataptr )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL )); } // Get Port Status inline uint8_t USBHub::GetPortStatus( uint8_t port, uint16_t nbytes, uint8_t* dataptr ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL )); } // Set Hub Descriptor inline uint8_t USBHub::SetHubDescriptor( uint8_t port, uint16_t nbytes, uint8_t* dataptr ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, dataptr )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL )); } // Set Hub Feature inline uint8_t USBHub::SetHubFeature( uint8_t fid ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, NULL )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL )); } // Set Port Feature inline uint8_t USBHub::SetPortFeature( uint8_t fid, uint8_t port, uint8_t sel ) { - return( pUsb->ctrlReq( bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL )); + return( pUsb->ctrlReq( bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, 0, NULL, NULL )); } void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false);