mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
inTransfer with pointer to nbytes
This commit is contained in:
parent
672758c45c
commit
2e52a1dfa6
13 changed files with 1560 additions and 209 deletions
160
Usb.cpp
160
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 = (left<nbytes) ? left : nbytes;
|
||||
|
||||
rcode = InTransfer( pep, nak_limit, &read, dataptr );
|
||||
|
||||
if (rcode)
|
||||
return rcode;
|
||||
|
||||
// Invoke callback function if inTransfer completed successfuly and callback function pointer is specified
|
||||
if (!rcode && p)
|
||||
p->Parse( 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;
|
||||
|
||||
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)
|
||||
|
||||
|
|
80
Usb.h
80
Usb.h
|
@ -12,23 +12,23 @@
|
|||
#include "address.h"
|
||||
#include <WProgram.h>
|
||||
|
||||
#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<P6, P3> MAX3421E; // Black Widdow
|
||||
typedef MAX3421e<P10, P9> MAX3421E; // Duemielanove
|
||||
typedef MAX3421e<P6, P3> MAX3421E; // Black Widdow
|
||||
//typedef MAX3421e<P10, P9> 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_
|
330
cdcacm.cpp
Normal file
330
cdcacm.cpp
Normal file
|
@ -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; i<ACM_MAX_ENDPOINTS; i++)
|
||||
{
|
||||
epInfo[i].epAddr = 0;
|
||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||
epInfo[i].epAttribs = 0;
|
||||
|
||||
if (!i)
|
||||
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
||||
}
|
||||
if (pUsb)
|
||||
pUsb->RegisterDeviceClass(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<num_of_conf; i++)
|
||||
{
|
||||
ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
|
||||
CDC_SUBCLASS_ACM,
|
||||
CDC_PROTOCOL_ITU_T_V_250,
|
||||
CP_MASK_COMPARE_CLASS |
|
||||
CP_MASK_COMPARE_SUBCLASS |
|
||||
CP_MASK_COMPARE_PROTOCOL> CdcControlParser(this);
|
||||
|
||||
ConfigDescParser<USB_CLASS_CDC_DATA, 0, 0,
|
||||
CP_MASK_COMPARE_CLASS> 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<uint8_t>(PSTR("Conf.Val"), conf);
|
||||
ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
|
||||
ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
|
||||
|
||||
bConfNum = conf;
|
||||
|
||||
uint8_t index;
|
||||
|
||||
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
|
||||
index = epInterruptInIndex;
|
||||
else
|
||||
if ((pep->bmAttributes & 0x02) == 2)
|
||||
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
|
||||
else
|
||||
return;
|
||||
|
||||
// Fill in the endpoint info structure
|
||||
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
|
||||
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
|
||||
epInfo[index].epAttribs = 0;
|
||||
|
||||
bNumEP ++;
|
||||
|
||||
PrintEndpointDescriptor(pep);
|
||||
}
|
||||
|
||||
uint8_t ACM::Release()
|
||||
{
|
||||
pUsb->GetAddressPool().FreeAddress(bAddress);
|
||||
|
||||
bControlIface = 0;
|
||||
bDataIface = 0;
|
||||
bNumEP = 1;
|
||||
|
||||
bAddress = 0;
|
||||
qNextPollTime = 0;
|
||||
bPollEnable = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ACM::Poll()
|
||||
{
|
||||
uint8_t rcode = 0;
|
||||
|
||||
if (!bPollEnable)
|
||||
return 0;
|
||||
|
||||
uint32_t time_now = millis();
|
||||
|
||||
if (qNextPollTime <= time_now)
|
||||
{
|
||||
qNextPollTime = time_now + 100;
|
||||
|
||||
uint8_t rcode;
|
||||
const uint8_t constBufSize = 16;
|
||||
uint8_t buf[constBufSize];
|
||||
|
||||
for (uint8_t i=0; i<constBufSize; i++)
|
||||
buf[i] = 0;
|
||||
|
||||
uint16_t read = constBufSize;
|
||||
rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
|
||||
|
||||
if (rcode)
|
||||
return rcode;
|
||||
|
||||
for (uint8_t i=0; i<read; i++)
|
||||
{
|
||||
PrintHex<uint8_t>(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<uint8_t>(ep_ptr->bLength);
|
||||
Notify(PSTR("\r\nType:\t\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bDescriptorType);
|
||||
Notify(PSTR("\r\nAddress:\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
|
||||
Notify(PSTR("\r\nAttributes:\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bmAttributes);
|
||||
Notify(PSTR("\r\nMaxPktSize:\t"));
|
||||
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
|
||||
Notify(PSTR("\r\nPoll Intrv:\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bInterval);
|
||||
Notify(PSTR("\r\n"));
|
||||
}
|
166
cdcacm.h
Normal file
166
cdcacm.h
Normal file
|
@ -0,0 +1,166 @@
|
|||
#if !defined(__CDCACM_H__)
|
||||
#define __CDCACM_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
|
||||
|
||||
// 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__
|
330
cdcftdi.cpp
Normal file
330
cdcftdi.cpp
Normal file
|
@ -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; i<FTDI_MAX_ENDPOINTS; i++)
|
||||
{
|
||||
epInfo[i].epAddr = 0;
|
||||
epInfo[i].maxPktSize = (i) ? 0 : 8;
|
||||
epInfo[i].epAttribs = 0;
|
||||
|
||||
if (!i)
|
||||
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
|
||||
}
|
||||
if (pUsb)
|
||||
pUsb->RegisterDeviceClass(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<num_of_conf; i++)
|
||||
{
|
||||
HexDumper<USBReadParser, uint16_t, uint16_t> 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<uint8_t>(PSTR("Conf.Val"), conf);
|
||||
ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
|
||||
ErrorMessage<uint8_t>(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<uint8_t>(ep_ptr->bLength);
|
||||
Notify(PSTR("\r\nType:\t\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bDescriptorType);
|
||||
Notify(PSTR("\r\nAddress:\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
|
||||
Notify(PSTR("\r\nAttributes:\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bmAttributes);
|
||||
Notify(PSTR("\r\nMaxPktSize:\t"));
|
||||
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
|
||||
Notify(PSTR("\r\nPoll Intrv:\t"));
|
||||
PrintHex<uint8_t>(ep_ptr->bInterval);
|
||||
Notify(PSTR("\r\n"));
|
||||
}
|
119
cdcftdi.h
Normal file
119
cdcftdi.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
#if !defined(__CDCFTDI_H__)
|
||||
#define __CDCFTDI_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_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__
|
189
cdcprolific.cpp
Normal file
189
cdcprolific.cpp
Normal file
|
@ -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<num_of_conf; i++)
|
||||
{
|
||||
HexDumper<USBReadParser, uint16_t, uint16_t> 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;
|
||||
//}
|
||||
|
||||
|
134
cdcprolific.h
Normal file
134
cdcprolific.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
#if !defined(__CDCPROLIFIC_H__)
|
||||
#define __CDCPROLIFIC_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"
|
||||
#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<<SPECIAL_SHIFT) - 1)
|
||||
#define STATE_ALL ( PD_RS232_S_MASK | PD_S_MASK )
|
||||
#define FLOW_RX_AUTO ( PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO )
|
||||
#define FLOW_TX_AUTO ( PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD )
|
||||
#define CAN_BE_AUTO ( FLOW_RX_AUTO | FLOW_TX_AUTO )
|
||||
#define CAN_NOTIFY ( PD_RS232_N_MASK )
|
||||
#define EXTERNAL_MASK ( PD_S_MASK | (PD_RS232_S_MASK & ~PD_RS232_S_LOOP) )
|
||||
#define INTERNAL_DELAY ( PD_RS232_S_LOOP )
|
||||
#define DEFAULT_AUTO ( PD_RS232_A_DTR | PD_RS232_A_RFR | PD_RS232_A_CTS | PD_RS232_A_DSR )
|
||||
#define DEFAULT_NOTIFY 0x00
|
||||
#define DEFAULT_STATE ( PD_S_TX_ENABLE | PD_S_RX_ENABLE | PD_RS232_A_TXO | PD_RS232_A_RXO )
|
||||
|
||||
#define CONTINUE_SEND 1
|
||||
#define PAUSE_SEND 2
|
||||
|
||||
#define kRxAutoFlow ((UInt32)( PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO ))
|
||||
#define kTxAutoFlow ((UInt32)( PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD ))
|
||||
#define kControl_StateMask ((UInt32)( PD_RS232_S_CTS | PD_RS232_S_DSR | PD_RS232_S_CAR | PD_RS232_S_RI ))
|
||||
#define kRxQueueState ((UInt32)( PD_S_RXQ_EMPTY | PD_S_RXQ_LOW_WATER | PD_S_RXQ_HIGH_WATER | PD_S_RXQ_FULL ))
|
||||
#define kTxQueueState ((UInt32)( PD_S_TXQ_EMPTY | PD_S_TXQ_LOW_WATER | PD_S_TXQ_HIGH_WATER | PD_S_TXQ_FULL ))
|
||||
|
||||
#define kCONTROL_DTR 0x01
|
||||
#define kCONTROL_RTS 0x02
|
||||
|
||||
|
||||
enum tXO_State
|
||||
{
|
||||
kXOnSent = -2,
|
||||
kXOffSent = -1,
|
||||
kXO_Idle = 0,
|
||||
kXOffNeeded = 1,
|
||||
kXOnNeeded = 2
|
||||
} ;
|
||||
|
||||
#define kStateTransientMask 0x74
|
||||
#define kBreakError 0x04
|
||||
#define kFrameError 0x10
|
||||
#define kParityError 0x20
|
||||
#define kOverrunError 0x40
|
||||
|
||||
#define kCTS 0x80
|
||||
#define kDSR 0x02
|
||||
#define kRI 0x08
|
||||
#define kDCD 0x01
|
||||
#define kHandshakeInMask ((UInt32)( PD_RS232_S_CTS | PD_RS232_S_DSR | PD_RS232_S_CAR | PD_RS232_S_RI ))
|
||||
|
||||
#define VENDOR_WRITE_REQUEST_TYPE 0x40
|
||||
#define VENDOR_WRITE_REQUEST 0x01
|
||||
|
||||
#define VENDOR_READ_REQUEST_TYPE 0xc0
|
||||
#define VENDOR_READ_REQUEST 0x01
|
||||
|
||||
// Device Configuration Registers (DCR0, DCR1, DCR2)
|
||||
#define SET_DCR0 0x00
|
||||
#define GET_DCR0 0x80
|
||||
#define DCR0_INIT 0x01
|
||||
#define DCR0_INIT_H 0x41
|
||||
#define DCR0_INIT_X 0x61
|
||||
|
||||
#define SET_DCR1 0x01
|
||||
#define GET_DCR1 0x81
|
||||
#define DCR1_INIT_H 0x80
|
||||
#define DCR1_INIT_X 0x00
|
||||
|
||||
#define SET_DCR2 0x02
|
||||
#define GET_DCR2 0x82
|
||||
#define DCR2_INIT_H 0x24
|
||||
#define DCR2_INIT_X 0x44
|
||||
|
||||
// On-chip Data Buffers:
|
||||
#define RESET_DOWNSTREAM_DATA_PIPE 0x08
|
||||
#define RESET_UPSTREAM_DATA_PIPE 0x09
|
||||
|
||||
enum pl2303_type
|
||||
{
|
||||
unknown,
|
||||
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 */
|
||||
rev_H
|
||||
};
|
||||
|
||||
|
||||
#define PL_MAX_ENDPOINTS 4
|
||||
|
||||
class PL : public ACM
|
||||
{
|
||||
uint16_t wPLType; // Type of chip
|
||||
|
||||
public:
|
||||
PL(USB *pusb, CDCAsyncOper *pasync);
|
||||
|
||||
// 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 // __CDCPROLIFIC_H__
|
148
confdescparser.h
Normal file
148
confdescparser.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
#if !defined(__CONFDESCPARSER_H__)
|
||||
#define __CONFDESCPARSER_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#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 <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||
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 <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||
ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
|
||||
stateParseDescr(0),
|
||||
dscrLen(0),
|
||||
dscrType(0),
|
||||
theXtractor(xtractor)
|
||||
{
|
||||
theBuffer.pValue = varBuffer;
|
||||
valParser.Initialize(&theBuffer);
|
||||
theSkipper.Initialize(&theBuffer);
|
||||
};
|
||||
|
||||
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>::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 <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
|
||||
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::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__
|
|
@ -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
|
38
usb_ch9.h
38
usb_ch9.h
|
@ -70,33 +70,6 @@
|
|||
#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 */
|
||||
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
|
|
19
usbhub.h
19
usbhub.h
|
@ -10,6 +10,8 @@
|
|||
#include "Usb.h"
|
||||
#include <WProgram.h>
|
||||
|
||||
#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
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue