From 702897bd5bc33dd06dfc05a8cef3b7d44cca2f9e Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Wed, 29 Feb 2012 12:37:16 -0700 Subject: [PATCH] acm bug fix --- Usb.cpp | 3 +- Usb.h | 10 +--- adk.cpp | 33 +++-------- adk.h | 6 +- avrpins.h | 4 -- cdcacm.cpp | 18 +++--- cdcacm.h | 2 + cdcftdi.cpp | 2 +- cdcprolific.cpp | 58 +++++++++++++++---- cdcprolific.h | 28 ++++++++- confdescparser.h | 2 +- examples/acm/acm_terminal/acm_terminal.pde | 3 +- examples/pl2303/pl2303_gps/pl2303_gps.pde | 5 +- .../pl2303/pl2303_tinygps/pl2303_tinygps.pde | 4 +- usbhost.h | 6 -- 15 files changed, 105 insertions(+), 79 deletions(-) diff --git a/Usb.cpp b/Usb.cpp index a94ff8bb..a8096cad 100644 --- a/Usb.cpp +++ b/Usb.cpp @@ -108,7 +108,8 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_l return USB_ERROR_EP_NOT_FOUND_IN_TBL; nak_limit = (0x0001UL << ( ( (*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower) ); - nak_limit--; + nak_limit--; + /* USBTRACE2("\r\nAddress: ", addr); USBTRACE2(" EP: ", ep); diff --git a/Usb.h b/Usb.h index c0953f3b..341c1368 100644 --- a/Usb.h +++ b/Usb.h @@ -47,16 +47,8 @@ e-mail : support@circuitsathome.com /* shield pins. First parameter - SS pin, second parameter - INT pin */ -#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -#define BOARD_TEENSY_PLUS_PLUS -#endif - #ifdef BOARD_BLACK_WIDDOW typedef MAX3421e MAX3421E; // Black Widow -#elif defined(BOARD_TEENSY_PLUS_PLUS) -typedef MAX3421e MAX3421E; // Teensy++ 2.0 & 1.0 -#elif defined(BOARD_MEGA_ADK) -typedef MAX3421e MAX3421E; // Arduino Mega ADK #else typedef MAX3421e MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560 #endif @@ -280,4 +272,4 @@ inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ) #endif // defined(USB_METHODS_INLINE) -#endif //_usb_h_ +#endif //_usb_h_ \ No newline at end of file diff --git a/adk.cpp b/adk.cpp index 1304992a..e846d611 100644 --- a/adk.cpp +++ b/adk.cpp @@ -48,11 +48,12 @@ ADK::ADK(USB *p, const char* manufacturer, for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry @@ -156,16 +157,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) for (uint8_t i=0; i confDescrParser(this); - delay(1); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); -#if defined(XOOM) - //added by Jaylen Scott Vanorden - if( rcode ) { - USBTRACE2("\r\nGot 1st bad code for config: ", rcode); - // Try once more - rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); - } -#endif if( rcode ) { goto FailGetConfDescr; } @@ -181,7 +173,9 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) goto FailSetDevTblEntry; } } - + + + // Set Configuration Value rcode = pUsb->setConf(bAddress, 0, bConfNum); if( rcode ){ @@ -207,22 +201,11 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) return 0; //successful configuration }//if( buf->idVendor == ADK_VID... - //delay(20); //testing compatibility w/Motorola Xoom - //probe device - get accessory protocol revision { uint16_t adkproto = -1; - delay(1); rcode = getProto((uint8_t*)&adkproto ); -#if defined(XOOM) - //added by Jaylen Scott Vanorden - if( rcode ) { - USBTRACE2("\r\nGot 1st bad code for proto: ", rcode); - // Try once more - rcode = getProto((uint8_t*)&adkproto ); - } -#endif - if( rcode ){ + if( rcode ){ goto FailGetProto; //init fails } USBTRACE2("\r\nADK protocol rev. ", adkproto ); diff --git a/adk.h b/adk.h index 8084decb..024b013b 100644 --- a/adk.h +++ b/adk.h @@ -44,10 +44,6 @@ e-mail : support@circuitsathome.com #define ADK_PID 0x2D00 #define ADB_PID 0x2D01 -#define XOOM //enables repeating getProto() and getConf() attempts - //necessary for slow devices such as Motorola XOOM - //defined by default, can be commented out to save memory - /* requests */ #define ADK_GETPROTO 51 //check USB accessory protocol version @@ -109,7 +105,7 @@ public: const char* uri, const char* serial); - // Methods for receiving and sending data + // Methods for recieving and sending data uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr); uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); diff --git a/avrpins.h b/avrpins.h index eb999a98..99e10776 100644 --- a/avrpins.h +++ b/avrpins.h @@ -20,9 +20,6 @@ e-mail : support@circuitsathome.com #ifndef _avrpins_h_ #define _avrpins_h_ -/* Uncomment the following if you have Arduino Mega ADK board with MAX3421e built-in */ -//#define BOARD_MEGA_ADK - #include #ifdef PORTA @@ -468,7 +465,6 @@ template #define P51 Pb2 #define P52 Pb1 #define P53 Pb0 -#define P54 Pj2 #endif //"Mega" pin numbers diff --git a/cdcacm.cpp b/cdcacm.cpp index df013fbc..9f9f6193 100644 --- a/cdcacm.cpp +++ b/cdcacm.cpp @@ -28,18 +28,20 @@ ACM::ACM(USB *p, CDCAsyncOper *pasync) : bPollEnable(false), bControlIface(0), bDataIface(0), - bNumEP(1) + bNumEP(1), + ready(false) { for(uint8_t i=0; iRegisterDeviceClass(this); @@ -172,6 +174,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) goto FailOnInit; USBTRACE("ACM configured\r\n"); + ready = true; //bPollEnable = true; @@ -226,7 +229,7 @@ void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto // Fill in the endpoint info structure epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; + //epInfo[index].epAttribs = 0; bNumEP ++; @@ -244,6 +247,7 @@ uint8_t ACM::Release() bAddress = 0; qNextPollTime = 0; bPollEnable = false; + ready = false; return 0; } @@ -254,7 +258,7 @@ uint8_t ACM::Poll() if (!bPollEnable) return 0; - uint32_t time_now = millis(); + //uint32_t time_now = millis(); //if (qNextPollTime <= time_now) //{ diff --git a/cdcacm.h b/cdcacm.h index b315787d..062ad696 100644 --- a/cdcacm.h +++ b/cdcacm.h @@ -154,6 +154,7 @@ protected: uint8_t bNumEP; // total number of EP in the configuration uint32_t qNextPollTime; // next poll time bool bPollEnable; // poll enable flag + bool ready; //device ready indicator EpInfo epInfo[ACM_MAX_ENDPOINTS]; @@ -179,6 +180,7 @@ public: virtual uint8_t Release(); virtual uint8_t Poll(); virtual uint8_t GetAddress() { return bAddress; }; + virtual bool isReady() { return ready; }; // UsbConfigXtracter implementation virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); diff --git a/cdcftdi.cpp b/cdcftdi.cpp index 04fdca9a..4dbbc267 100644 --- a/cdcftdi.cpp +++ b/cdcftdi.cpp @@ -232,7 +232,7 @@ void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t prot // Fill in the endpoint info structure epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; - epInfo[index].epAttribs = 0; + //epInfo[index].epAttribs = 0; bNumEP ++; diff --git a/cdcprolific.cpp b/cdcprolific.cpp index 30694d43..23189d6e 100644 --- a/cdcprolific.cpp +++ b/cdcprolific.cpp @@ -17,8 +17,8 @@ e-mail : support@circuitsathome.com #include "cdcprolific.h" PL2303::PL2303(USB *p, CDCAsyncOper *pasync) : - ACM(p, pasync), - wPLType(0) + ACM(p, pasync) + //wPLType(0) { } @@ -31,6 +31,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) UsbDevice *p = NULL; EpInfo *oldep_ptr = NULL; uint8_t num_of_conf; // number of configurations + enum pl2303_type pltype = unknown; AddressPool &addrPool = pUsb->GetAddressPool(); @@ -68,11 +69,24 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) if( rcode ) goto FailGetDevDescr; - if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID ) + 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; + } + + /* determine chip variant */ + + if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x02 ) { + pltype = type_0; + } + else if (((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0 == 0x40 ) { + pltype = rev_HX; + } + else if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x00) { + pltype = type_1; + } + else if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0xff) { + pltype = type_1; + } // Allocate new address according to device class bAddress = addrPool.AllocAddress(parent, false, port); @@ -116,7 +130,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) USBTRACE2("NC:", num_of_conf); - for (uint8_t i=0; i HexDump; ConfigDescParser<0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); @@ -128,11 +142,11 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) break; } // for - if (bNumEP < 2) + if ( bNumEP < 2 ) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Assign epInfo to epinfo pointer - rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + rcode = pUsb->setEpInfoEntry( bAddress, bNumEP, epInfo ); USBTRACE2("Conf:", bConfNum); @@ -142,6 +156,29 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) if (rcode) goto FailSetConfDescr; +#if defined(PL2303_COMPAT) + /* shamanic dance - sending Prolific init data as-is */ + vendorRead( 0x84, 0x84, 0, buf ); + vendorWrite( 0x04, 0x04, 0 ); + vendorRead( 0x84, 0x84, 0, buf ); + vendorRead( 0x83, 0x83, 0, buf ); + vendorRead( 0x84, 0x84, 0, buf ); + vendorWrite( 0x04, 0x04, 1 ); + vendorRead( 0x84, 0x84, 0, buf); + vendorRead( 0x83, 0x83, 0, buf); + vendorWrite( 0, 0, 1 ); + vendorWrite( 1, 0, 0 ); + if ( pltype == rev_HX ) { + vendorWrite( 2, 0, 0x44 ); + vendorWrite( 0x06, 0x06, 0 ); //from W7 init + } + else { + vendorWrite( 2, 0, 0x24 ); + } + /* shamanic dance end */ +#endif + + /* calling post-init callback */ rcode = pAsync->OnInit(this); if (rcode) @@ -149,7 +186,8 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) USBTRACE("PL configured\r\n"); - bPollEnable = true; + //bPollEnable = true; + ready = true; return 0; FailGetDevDescr: diff --git a/cdcprolific.h b/cdcprolific.h index b008ddd0..38e7d032 100644 --- a/cdcprolific.h +++ b/cdcprolific.h @@ -38,11 +38,11 @@ e-mail : support@circuitsathome.com #include "confdescparser.h" #include "cdcacm.h" +//#define PL2303_COMPAT //uncomment it if you have compatibility problems + #define PL_VID 0x067B #define PL_PID ( 0x2303 || 0x0609 ) -//#define PL_PID 0x0609 - #define PROLIFIC_REV_H 0x0202 #define PROLIFIC_REV_X 0x0300 #define PROLIFIC_REV_HX_CHIP_D 0x0400 @@ -128,6 +128,7 @@ enum tXO_State enum pl2303_type { unknown, + type_0, type_1, /* don't know the difference between type 0 and */ rev_X, /* type 1, until someone from prolific tells us... */ rev_HX, /* HX version of the pl2303 chip */ @@ -137,9 +138,13 @@ enum pl2303_type #define PL_MAX_ENDPOINTS 4 +//class PL2303; + class PL2303 : public ACM { - uint16_t wPLType; // Type of chip + + //uint16_t wPLType; // Type of chip + public: PL2303(USB *pusb, CDCAsyncOper *pasync); @@ -152,6 +157,23 @@ public: //// UsbConfigXtracter implementation //virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); + +private: + /* Prolific proprietary requests */ + uint8_t vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf ); + uint8_t vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index ); }; +/* vendor read request */ +inline uint8_t PL2303::vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf ) +{ + return( pUsb->ctrlReq(bAddress, 0, VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, val_lo, val_hi, index, 1, 1, buf, NULL )); +} + +/* vendor write request */ +inline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index ) +{ + return( pUsb->ctrlReq(bAddress, 0, VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, val_lo, val_hi, index, 0, 0, NULL, NULL )); +} + #endif // __CDCPROLIFIC_H__ \ No newline at end of file diff --git a/confdescparser.h b/confdescparser.h index 3d82f349..0c215227 100644 --- a/confdescparser.h +++ b/confdescparser.h @@ -110,7 +110,7 @@ bool ConfigDescParser::ParseDescriptor dscrType = *((uint8_t*)theBuffer.pValue + 1); stateParseDescr = 2; case 2: - // This is a sort of hack. Assuming that two bytes are already in the buffer + // 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 diff --git a/examples/acm/acm_terminal/acm_terminal.pde b/examples/acm/acm_terminal/acm_terminal.pde index ae2756d0..a60115c6 100644 --- a/examples/acm/acm_terminal/acm_terminal.pde +++ b/examples/acm/acm_terminal/acm_terminal.pde @@ -68,8 +68,7 @@ void loop() { Usb.Task(); - if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) - { + if( Acm.isReady()) { uint8_t rcode; /* reading the keyboard */ diff --git a/examples/pl2303/pl2303_gps/pl2303_gps.pde b/examples/pl2303/pl2303_gps/pl2303_gps.pde index 24585e0a..8cf26fd5 100644 --- a/examples/pl2303/pl2303_gps/pl2303_gps.pde +++ b/examples/pl2303/pl2303_gps/pl2303_gps.pde @@ -76,9 +76,8 @@ uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint uint16_t rcvd = 64; Usb.Task(); - - if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) - { + + if( Pl.isReady()) { /* reading the GPS */ if( read_delay < millis() ){ read_delay += READ_DELAY; diff --git a/examples/pl2303/pl2303_tinygps/pl2303_tinygps.pde b/examples/pl2303/pl2303_tinygps/pl2303_tinygps.pde index 985f9d3d..85798192 100644 --- a/examples/pl2303/pl2303_tinygps/pl2303_tinygps.pde +++ b/examples/pl2303/pl2303_tinygps/pl2303_tinygps.pde @@ -95,7 +95,7 @@ void loop() { Usb.Task(); - if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { + if( Pl.isReady()) { bool newdata = false; unsigned long start = millis(); @@ -210,7 +210,7 @@ bool feedgps() rcode = false; if( rcvd ) { //more than zero bytes received for( uint16_t i=0; i < rcvd; i++ ) { - if( gps.encode(buf[i])) { //feed a character to gps object + if( gps.encode((char)buf[i])) { //feed a character to gps object rcode = true; }//if( gps.encode(buf[i]... }//for( uint16_t i=0; i < rcvd; i++... diff --git a/usbhost.h b/usbhost.h index a94b42e1..264b317a 100644 --- a/usbhost.h +++ b/usbhost.h @@ -87,12 +87,6 @@ MAX3421e< SS, INTR >::MAX3421e() spi::init(); INTR::SetDirRead(); -#ifdef BOARD_MEGA_ADK - /* For Mega ADK, which has Max3421e on-board, set MAX_RESET to Output mode, and pull Reset to HIGH */ - DDRJ |= 0x04; - PORTJ |= 0x04; -#endif - /* MAX3421E - full-duplex SPI, level interrupt */ regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL )); };