FTDI fixed

This commit is contained in:
Oleg Mazurov 2011-06-05 21:22:39 -06:00
parent b30f62d931
commit cf1611cb48
11 changed files with 3298 additions and 51 deletions

2
README
View file

@ -1,5 +1,5 @@
This is Rev.2.0 of MAX3421E-based USB Host Library for Arduino. At the moment, this repo contains current development copy This is Rev.2.0 of MAX3421E-based USB Host Library for Arduino. At the moment, this repo contains current development copy
of the code facilitating developer's exchange. For those not involved in the project, the code in its current state doesn't bear any value. of the code facilitating developer's exchange. For those not involved in the project, the code in its' current state doesn't bear any value.
In other words, nothing works yet. In other words, nothing works yet.
The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects

View file

@ -153,7 +153,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ
rcode = InTransfer( pep, nak_limit, &read, dataptr ); rcode = InTransfer( pep, nak_limit, &read, dataptr );
if (rcode) if (rcode /*&& rcode != hrSTALL*/)
return rcode; return rcode;
// Invoke callback function if inTransfer completed successfuly and callback function pointer is specified // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified
@ -194,7 +194,7 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t*
uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data)
{ {
uint8_t rcode; uint8_t rcode = 0;
uint8_t pktsize; uint8_t pktsize;
uint16_t nbytes = *nbytesptr; uint16_t nbytes = *nbytesptr;
@ -212,9 +212,9 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
/* check for RCVDAVIRQ and generate error if not present */ /* check for RCVDAVIRQ and generate error if not present */
/* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) { if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 )
return ( 0xf0 ); //receive error return ( 0xf0 ); //receive error
}
pktsize = regRd( rRCVBC ); //number of received bytes pktsize = regRd( rRCVBC ); //number of received bytes
int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);

View file

@ -238,31 +238,31 @@ uint8_t ACM::Poll()
uint32_t time_now = millis(); uint32_t time_now = millis();
if (qNextPollTime <= time_now) //if (qNextPollTime <= time_now)
{ //{
qNextPollTime = time_now + 100; // qNextPollTime = time_now + 100;
uint8_t rcode; // uint8_t rcode;
const uint8_t constBufSize = 16; // const uint8_t constBufSize = 16;
uint8_t buf[constBufSize]; // uint8_t buf[constBufSize];
for (uint8_t i=0; i<constBufSize; i++) // for (uint8_t i=0; i<constBufSize; i++)
buf[i] = 0; // buf[i] = 0;
uint16_t read = (constBufSize > epInfo[epInterruptInIndex].maxPktSize) // uint16_t read = (constBufSize > epInfo[epInterruptInIndex].maxPktSize)
? epInfo[epInterruptInIndex].maxPktSize : constBufSize; // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize;
rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); // rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
if (rcode) // if (rcode)
return rcode; // return rcode;
for (uint8_t i=0; i<read; i++) // for (uint8_t i=0; i<read; i++)
{ // {
PrintHex<uint8_t>(buf[i]); // PrintHex<uint8_t>(buf[i]);
Serial.print(" "); // Serial.print(" ");
} // }
USBTRACE("\r\n"); // USBTRACE("\r\n");
} //}
return rcode; return rcode;
} }

View file

@ -4,9 +4,11 @@ const uint8_t FTDI::epDataInIndex = 1;
const uint8_t FTDI::epDataOutIndex = 2; const uint8_t FTDI::epDataOutIndex = 2;
const uint8_t FTDI::epInterruptInIndex = 3; const uint8_t FTDI::epInterruptInIndex = 3;
FTDI::FTDI(USB *p) : FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) :
pAsync(pasync),
pUsb(p), pUsb(p),
bAddress(0), bAddress(0),
bNumEP(1),
wFTDIType(0) wFTDIType(0)
{ {
for(uint8_t i=0; i<FTDI_MAX_ENDPOINTS; i++) for(uint8_t i=0; i<FTDI_MAX_ENDPOINTS; i++)
@ -135,6 +137,8 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
if (bNumEP < 2) if (bNumEP < 2)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
USBTRACE2("NumEP:", bNumEP);
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
@ -146,17 +150,10 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
if (rcode) if (rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
rcode = SetBaudRate(115200); rcode = pAsync->OnInit(this);
if (rcode) if (rcode)
goto FailSetBaudRate; goto FailOnInit;
rcode = SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL);
//rcode = SetFlowControl(FTDI_SIO_SET_DTR_HIGH);
if (rcode)
goto FailSetFlowControl;
USBTRACE("FTDI configured\r\n"); USBTRACE("FTDI configured\r\n");
@ -187,6 +184,10 @@ FailSetFlowControl:
USBTRACE("SetFlowControl:"); USBTRACE("SetFlowControl:");
goto Fail; goto Fail;
FailOnInit:
USBTRACE("OnInit:");
goto Fail;
Fail: Fail:
Serial.println(rcode, HEX); Serial.println(rcode, HEX);
Release(); Release();
@ -227,6 +228,7 @@ uint8_t FTDI::Release()
pUsb->GetAddressPool().FreeAddress(bAddress); pUsb->GetAddressPool().FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
bNumEP = 1;
qNextPollTime = 0; qNextPollTime = 0;
bPollEnable = false; bPollEnable = false;
return 0; return 0;

View file

@ -71,6 +71,15 @@
#define FTDI_SIO_RI_MASK 0x40 #define FTDI_SIO_RI_MASK 0x40
#define FTDI_SIO_RLSD_MASK 0x80 #define FTDI_SIO_RLSD_MASK 0x80
class FTDI;
class FTDIAsyncOper
{
public:
virtual uint8_t OnInit(FTDI *pftdi) = 0;
};
// Only single port chips are currently supported by the library, // Only single port chips are currently supported by the library,
// so only three endpoints are allocated. // so only three endpoints are allocated.
#define FTDI_MAX_ENDPOINTS 3 #define FTDI_MAX_ENDPOINTS 3
@ -81,6 +90,7 @@ class FTDI : public USBDeviceConfig, public UsbConfigXtracter
static const uint8_t epDataOutIndex; // DataOUT endpoint index static const uint8_t epDataOutIndex; // DataOUT endpoint index
static const uint8_t epInterruptInIndex; // InterruptIN endpoint index static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
FTDIAsyncOper *pAsync;
USB *pUsb; USB *pUsb;
uint8_t bAddress; uint8_t bAddress;
uint8_t bConfNum; // configuration number uint8_t bConfNum; // configuration number
@ -95,7 +105,7 @@ class FTDI : public USBDeviceConfig, public UsbConfigXtracter
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
public: public:
FTDI(USB *pusb); FTDI(USB *pusb, FTDIAsyncOper *pasync);
uint8_t SetBaudRate(uint32_t baud); uint8_t SetBaudRate(uint32_t baud);
uint8_t SetModemControl(uint16_t control); uint8_t SetModemControl(uint16_t control);

View file

@ -4,6 +4,13 @@
#include <inttypes.h> #include <inttypes.h>
#include "..\ParseTools\parsetools.h" #include "..\ParseTools\parsetools.h"
#include <avr/pgmspace.h>
#include "..\DebugTools\printhex.h"
#include "..\DebugTools\hexdump.h"
#include "..\DebugTools\message.h"
//#include "hid.h"
class UsbConfigXtracter class UsbConfigXtracter
{ {
public: public:
@ -25,7 +32,7 @@ class ConfigDescParser : public USBReadParser
MultiValueBuffer theBuffer; MultiValueBuffer theBuffer;
MultiByteValueParser valParser; MultiByteValueParser valParser;
ByteSkipper theSkipper; ByteSkipper theSkipper;
uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
uint8_t stateParseDescr; // ParseDescriptor state uint8_t stateParseDescr; // ParseDescriptor state
@ -40,6 +47,8 @@ class ConfigDescParser : public USBReadParser
bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
public: public:
ConfigDescParser(UsbConfigXtracter *xtractor); ConfigDescParser(UsbConfigXtracter *xtractor);
virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
@ -102,6 +111,9 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
case USB_DESCRIPTOR_ENDPOINT: case USB_DESCRIPTOR_ENDPOINT:
theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2; theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2;
break; break;
case HID_DESCRIPTOR_HID:
theBuffer.valueSize = dscrLen - 2;
break;
} }
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
stateParseDescr = 4; stateParseDescr = 4;
@ -135,6 +147,11 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
if (theXtractor) if (theXtractor)
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
break; break;
case HID_DESCRIPTOR_HID:
if (!valParser.Parse(pp, pcntdn))
return false;
PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
break;
default: default:
if (!theSkipper.Skip(pp, pcntdn, dscrLen-2)) if (!theSkipper.Skip(pp, pcntdn, dscrLen-2))
return false; return false;
@ -145,4 +162,43 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
return true; return true;
} }
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)
{
Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"));
Notify(PSTR("bDescLength:\t\t"));
PrintHex<uint8_t>(pDesc->bLength);
Notify(PSTR("\r\nbDescriptorType:\t"));
PrintHex<uint8_t>(pDesc->bDescriptorType);
Notify(PSTR("\r\nbcdHID:\t\t\t"));
PrintHex<uint16_t>(pDesc->bcdHID);
Notify(PSTR("\r\nbCountryCode:\t\t"));
PrintHex<uint8_t>(pDesc->bCountryCode);
Notify(PSTR("\r\nbNumDescriptors:\t"));
PrintHex<uint8_t>(pDesc->bNumDescriptors);
//Notify(PSTR("\r\nbDescrType:\t\t"));
//PrintHex<uint8_t>(pDesc->bDescrType);
//
//Notify(PSTR("\r\nwDescriptorLength:\t"));
//PrintHex<uint16_t>(pDesc->wDescriptorLength);
for (uint8_t i=0; i<pDesc->bNumDescriptors; i++)
{
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
Notify(PSTR("\r\nbDescrType:\t\t"));
PrintHex<uint8_t>(pLT[i].bDescrType);
Notify(PSTR("\r\nwDescriptorLength:\t"));
PrintHex<uint16_t>(pLT[i].wDescriptorLength);
}
Notify(PSTR("\r\n"));
}
#endif // __CONFDESCPARSER_H__ #endif // __CONFDESCPARSER_H__

1879
hid.cpp Normal file

File diff suppressed because it is too large Load diff

1180
hid.h Normal file

File diff suppressed because it is too large Load diff

97
masstorage.h Normal file
View file

@ -0,0 +1,97 @@
#if !defined(__MASSTORAGE_H__)
#define __MASSTORAGE_H__
#include <inttypes.h>
#include <avr/pgmspace.h>
#include "avrpins.h"
#include "max3421e.h"
#include "usbhost.h"
#include "usb_ch9.h"
#include "Usb.h"
#include <WProgram.h>
#include "..\DebugTools\printhex.h"
#include "..\DebugTools\hexdump.h"
#include "..\DebugTools\message.h"
#include "confdescparser.h"
//#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
//#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
// Mass Storage Subclass Constants
#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use
#define MASS_SUBCLASS_RBC 0x01
#define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI)
#define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157
#define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB
#define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i
#define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set
#define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI
#define MASS_SUBCLASS_IEEE1667 0x08
// Mass Storage Class Protocols
#define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt)
#define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt)
#define MASS_PROTO_OBSOLETE 0x02
#define MASS_PROTO_BBB 0x50 // Bulk Only Transport
#define MASS_PROTO_UAS 0x62
// Request Codes
#define MASS_REQ_ADSC 0x00
#define MASS_REQ_GET 0xFC
#define MASS_REQ_PUT 0xFD
#define MASS_REQ_GET_MAX_LUN 0xFE
#define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset
#define MASS_CBW_SIGNATURE 0x43425355
#define MASS_CBS_SIGNATURE 0x53425355
struct CommandBlockWrapper
{
uint32_t dCBWSignature;
uint32_t dCBWTag;
uint32_t dCBWDataTransferLength;
uint8_t bmCBWFlags;
struct
{
uint8_t bCBWLUN : 4;
uint8_r bReserved1 : 4;
};
struct
{
uint8_t bCBWCBLength : 4;
uint8_t bReserved2 : 4;
};
uint8_t CBWCB[16];
};
struct CommandStatusWrapper
{
uint32_t dCSWSignature;
uint32_t dCSWTag;
uint32_t dCSWDataResidue;
uint8_t bCSWStatus;
};
class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter
{
public:
uint8_t Reset();
uint8_t GetMaxLun(uint8_t *max_lun);
uint8_t ResetRecovery();
// USBDeviceConfig implementation
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
virtual uint8_t Release();
virtual uint8_t Poll();
virtual uint8_t GetAddress() { return bAddress; };
// UsbConfigXtracter implementation
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
};
#endif // __MASSTORAGE_H__

View file

@ -52,6 +52,10 @@
#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. #define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. #define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor.
#define HID_DESCRIPTOR_HID 0x21
/* OTG SET FEATURE Constants */ /* OTG SET FEATURE Constants */
#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP #define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP #define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
@ -128,4 +132,23 @@ typedef struct
uint8_t bInterval; // Polling interval in frames. uint8_t bInterval; // Polling interval in frames.
} USB_ENDPOINT_DESCRIPTOR; } USB_ENDPOINT_DESCRIPTOR;
/* HID descriptor */
typedef struct
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID; // HID class specification release
uint8_t bCountryCode;
uint8_t bNumDescriptors; // Number of additional class specific descriptors
uint8_t bDescrType; // Type of class descriptor
uint16_t wDescriptorLength; // Total size of the Report descriptor
} USB_HID_DESCRIPTOR;
typedef struct
{
uint8_t bDescrType; // Type of class descriptor
uint16_t wDescriptorLength; // Total size of the Report descriptor
} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
#endif // _ch9_h_ #endif // _ch9_h_