acm bug fix

This commit is contained in:
Oleg Mazurov 2012-02-29 12:37:16 -07:00
parent 389c6115e3
commit 702897bd5b
15 changed files with 105 additions and 79 deletions

View file

@ -109,6 +109,7 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_l
nak_limit = (0x0001UL << ( ( (*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower) ); nak_limit = (0x0001UL << ( ( (*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower) );
nak_limit--; nak_limit--;
/* /*
USBTRACE2("\r\nAddress: ", addr); USBTRACE2("\r\nAddress: ", addr);
USBTRACE2(" EP: ", ep); USBTRACE2(" EP: ", ep);

8
Usb.h
View file

@ -47,16 +47,8 @@ e-mail : support@circuitsathome.com
/* shield pins. First parameter - SS pin, second parameter - INT pin */ /* 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 #ifdef BOARD_BLACK_WIDDOW
typedef MAX3421e<P6, P3> MAX3421E; // Black Widow typedef MAX3421e<P6, P3> MAX3421E; // Black Widow
#elif defined(BOARD_TEENSY_PLUS_PLUS)
typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 2.0 & 1.0
#elif defined(BOARD_MEGA_ADK)
typedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK
#else #else
typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560 typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560
#endif #endif

31
adk.cpp
View file

@ -48,11 +48,12 @@ ADK::ADK(USB *p, const char* manufacturer,
for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++) { for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = ( 0xfc & ( USB_NAK_MAX_POWER<<2 ));
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
//epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
}//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++... }//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...
//set bulk-IN EP naklimit to 1
epInfo[epDataInIndex].epAttribs = ( 0xfc & ( USB_NAK_NOWAIT<<2 ));
// register in USB subsystem // register in USB subsystem
if (pUsb) { if (pUsb) {
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(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<num_of_conf; i++) { for (uint8_t i=0; i<num_of_conf; i++) {
ConfigDescParser<0, 0, 0, 0> confDescrParser(this); ConfigDescParser<0, 0, 0, 0> confDescrParser(this);
delay(1);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); 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 ) { if( rcode ) {
goto FailGetConfDescr; goto FailGetConfDescr;
} }
@ -182,6 +174,8 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
} }
} }
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if( rcode ){ if( rcode ){
@ -207,22 +201,11 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed)
return 0; //successful configuration return 0; //successful configuration
}//if( buf->idVendor == ADK_VID... }//if( buf->idVendor == ADK_VID...
//delay(20); //testing compatibility w/Motorola Xoom
//probe device - get accessory protocol revision //probe device - get accessory protocol revision
{ {
uint16_t adkproto = -1; uint16_t adkproto = -1;
delay(1);
rcode = getProto((uint8_t*)&adkproto ); rcode = getProto((uint8_t*)&adkproto );
#if defined(XOOM) if( rcode ){
//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 ){
goto FailGetProto; //init fails goto FailGetProto; //init fails
} }
USBTRACE2("\r\nADK protocol rev. ", adkproto ); USBTRACE2("\r\nADK protocol rev. ", adkproto );

6
adk.h
View file

@ -44,10 +44,6 @@ e-mail : support@circuitsathome.com
#define ADK_PID 0x2D00 #define ADK_PID 0x2D00
#define ADB_PID 0x2D01 #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 */ /* requests */
#define ADK_GETPROTO 51 //check USB accessory protocol version #define ADK_GETPROTO 51 //check USB accessory protocol version
@ -109,7 +105,7 @@ public:
const char* uri, const char* uri,
const char* serial); 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 RcvData(uint16_t *nbytesptr, uint8_t *dataptr);
uint8_t SndData(uint16_t nbytes, uint8_t *dataptr); uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);

View file

@ -20,9 +20,6 @@ e-mail : support@circuitsathome.com
#ifndef _avrpins_h_ #ifndef _avrpins_h_
#define _avrpins_h_ #define _avrpins_h_
/* Uncomment the following if you have Arduino Mega ADK board with MAX3421e built-in */
//#define BOARD_MEGA_ADK
#include <avr/io.h> #include <avr/io.h>
#ifdef PORTA #ifdef PORTA
@ -468,7 +465,6 @@ template<typename Tp_pin, typename Tc_bit>
#define P51 Pb2 #define P51 Pb2
#define P52 Pb1 #define P52 Pb1
#define P53 Pb0 #define P53 Pb0
#define P54 Pj2
#endif //"Mega" pin numbers #endif //"Mega" pin numbers

View file

@ -28,18 +28,20 @@ ACM::ACM(USB *p, CDCAsyncOper *pasync) :
bPollEnable(false), bPollEnable(false),
bControlIface(0), bControlIface(0),
bDataIface(0), bDataIface(0),
bNumEP(1) bNumEP(1),
ready(false)
{ {
for(uint8_t i=0; i<ACM_MAX_ENDPOINTS; i++) for(uint8_t i=0; i<ACM_MAX_ENDPOINTS; i++)
{ {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
//epInfo[i].bmNakPower = USB_NAK_NOWAIT; epInfo[i].bmNakPower = USB_NAK_NOWAIT;
epInfo[i].bmNakPower = USB_NAK_MAX_POWER; //epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
//if (!i) if (!i)
epInfo[i].bmNakPower = USB_NAK_MAX_POWER; epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
} }
if (pUsb) if (pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
@ -172,6 +174,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed)
goto FailOnInit; goto FailOnInit;
USBTRACE("ACM configured\r\n"); USBTRACE("ACM configured\r\n");
ready = true;
//bPollEnable = 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 // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0; //epInfo[index].epAttribs = 0;
bNumEP ++; bNumEP ++;
@ -244,6 +247,7 @@ uint8_t ACM::Release()
bAddress = 0; bAddress = 0;
qNextPollTime = 0; qNextPollTime = 0;
bPollEnable = false; bPollEnable = false;
ready = false;
return 0; return 0;
} }
@ -254,7 +258,7 @@ uint8_t ACM::Poll()
if (!bPollEnable) if (!bPollEnable)
return 0; return 0;
uint32_t time_now = millis(); //uint32_t time_now = millis();
//if (qNextPollTime <= time_now) //if (qNextPollTime <= time_now)
//{ //{

View file

@ -154,6 +154,7 @@ protected:
uint8_t bNumEP; // total number of EP in the configuration uint8_t bNumEP; // total number of EP in the configuration
uint32_t qNextPollTime; // next poll time uint32_t qNextPollTime; // next poll time
bool bPollEnable; // poll enable flag bool bPollEnable; // poll enable flag
bool ready; //device ready indicator
EpInfo epInfo[ACM_MAX_ENDPOINTS]; EpInfo epInfo[ACM_MAX_ENDPOINTS];
@ -179,6 +180,7 @@ public:
virtual uint8_t Release(); virtual uint8_t Release();
virtual uint8_t Poll(); virtual uint8_t Poll();
virtual uint8_t GetAddress() { return bAddress; }; virtual uint8_t GetAddress() { return bAddress; };
virtual bool isReady() { return ready; };
// UsbConfigXtracter implementation // UsbConfigXtracter implementation
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);

View file

@ -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 // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0; //epInfo[index].epAttribs = 0;
bNumEP ++; bNumEP ++;

View file

@ -17,8 +17,8 @@ e-mail : support@circuitsathome.com
#include "cdcprolific.h" #include "cdcprolific.h"
PL2303::PL2303(USB *p, CDCAsyncOper *pasync) : PL2303::PL2303(USB *p, CDCAsyncOper *pasync) :
ACM(p, pasync), ACM(p, pasync)
wPLType(0) //wPLType(0)
{ {
} }
@ -31,6 +31,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
UsbDevice *p = NULL; UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL; EpInfo *oldep_ptr = NULL;
uint8_t num_of_conf; // number of configurations uint8_t num_of_conf; // number of configurations
enum pl2303_type pltype = unknown;
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
@ -68,11 +69,24 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
if( rcode ) if( rcode )
goto FailGetDevDescr; 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; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
}
// Save type of PL chip /* determine chip variant */
wPLType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice;
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 // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); 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); USBTRACE2("NC:", num_of_conf);
for (uint8_t i=0; i<num_of_conf; i++) for( uint8_t i=0; i<num_of_conf; i++ )
{ {
HexDumper<USBReadParser, uint16_t, uint16_t> HexDump; HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
ConfigDescParser<0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this); 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; break;
} // for } // for
if (bNumEP < 2) if ( bNumEP < 2 )
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); rcode = pUsb->setEpInfoEntry( bAddress, bNumEP, epInfo );
USBTRACE2("Conf:", bConfNum); USBTRACE2("Conf:", bConfNum);
@ -142,6 +156,29 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
if (rcode) if (rcode)
goto FailSetConfDescr; 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); rcode = pAsync->OnInit(this);
if (rcode) if (rcode)
@ -149,7 +186,8 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed)
USBTRACE("PL configured\r\n"); USBTRACE("PL configured\r\n");
bPollEnable = true; //bPollEnable = true;
ready = true;
return 0; return 0;
FailGetDevDescr: FailGetDevDescr:

View file

@ -38,11 +38,11 @@ e-mail : support@circuitsathome.com
#include "confdescparser.h" #include "confdescparser.h"
#include "cdcacm.h" #include "cdcacm.h"
//#define PL2303_COMPAT //uncomment it if you have compatibility problems
#define PL_VID 0x067B #define PL_VID 0x067B
#define PL_PID ( 0x2303 || 0x0609 ) #define PL_PID ( 0x2303 || 0x0609 )
//#define PL_PID 0x0609
#define PROLIFIC_REV_H 0x0202 #define PROLIFIC_REV_H 0x0202
#define PROLIFIC_REV_X 0x0300 #define PROLIFIC_REV_X 0x0300
#define PROLIFIC_REV_HX_CHIP_D 0x0400 #define PROLIFIC_REV_HX_CHIP_D 0x0400
@ -128,6 +128,7 @@ enum tXO_State
enum pl2303_type enum pl2303_type
{ {
unknown, unknown,
type_0,
type_1, /* don't know the difference between type 0 and */ type_1, /* don't know the difference between type 0 and */
rev_X, /* type 1, until someone from prolific tells us... */ rev_X, /* type 1, until someone from prolific tells us... */
rev_HX, /* HX version of the pl2303 chip */ rev_HX, /* HX version of the pl2303 chip */
@ -137,9 +138,13 @@ enum pl2303_type
#define PL_MAX_ENDPOINTS 4 #define PL_MAX_ENDPOINTS 4
//class PL2303;
class PL2303 : public ACM class PL2303 : public ACM
{ {
uint16_t wPLType; // Type of chip
//uint16_t wPLType; // Type of chip
public: public:
PL2303(USB *pusb, CDCAsyncOper *pasync); PL2303(USB *pusb, CDCAsyncOper *pasync);
@ -152,6 +157,23 @@ public:
//// UsbConfigXtracter implementation //// UsbConfigXtracter implementation
//virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); //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__ #endif // __CDCPROLIFIC_H__

View file

@ -110,7 +110,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
dscrType = *((uint8_t*)theBuffer.pValue + 1); dscrType = *((uint8_t*)theBuffer.pValue + 1);
stateParseDescr = 2; stateParseDescr = 2;
case 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 // 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. // to be read right after the size and the type fields.
// This should be used carefuly. varBuffer should be used directly to handle data // This should be used carefuly. varBuffer should be used directly to handle data

View file

@ -68,8 +68,7 @@ void loop()
{ {
Usb.Task(); Usb.Task();
if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) if( Acm.isReady()) {
{
uint8_t rcode; uint8_t rcode;
/* reading the keyboard */ /* reading the keyboard */

View file

@ -77,8 +77,7 @@ uint16_t rcvd = 64;
Usb.Task(); Usb.Task();
if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) if( Pl.isReady()) {
{
/* reading the GPS */ /* reading the GPS */
if( read_delay < millis() ){ if( read_delay < millis() ){
read_delay += READ_DELAY; read_delay += READ_DELAY;

View file

@ -95,7 +95,7 @@ void loop()
{ {
Usb.Task(); Usb.Task();
if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { if( Pl.isReady()) {
bool newdata = false; bool newdata = false;
unsigned long start = millis(); unsigned long start = millis();
@ -210,7 +210,7 @@ bool feedgps()
rcode = false; rcode = false;
if( rcvd ) { //more than zero bytes received if( rcvd ) { //more than zero bytes received
for( uint16_t i=0; i < rcvd; i++ ) { 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; rcode = true;
}//if( gps.encode(buf[i]... }//if( gps.encode(buf[i]...
}//for( uint16_t i=0; i < rcvd; i++... }//for( uint16_t i=0; i < rcvd; i++...

View file

@ -87,12 +87,6 @@ MAX3421e< SS, INTR >::MAX3421e()
spi::init(); spi::init();
INTR::SetDirRead(); 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 */ /* MAX3421E - full-duplex SPI, level interrupt */
regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL )); regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL ));
}; };