mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
avrpins with mega1280/2560 support
This commit is contained in:
parent
e238472454
commit
600e5c3a07
10 changed files with 2013 additions and 368 deletions
681
Usb.cpp
681
Usb.cpp
|
@ -5,11 +5,12 @@
|
||||||
#include "usbhost.h"
|
#include "usbhost.h"
|
||||||
#include "Usb.h"
|
#include "Usb.h"
|
||||||
#include "WProgram.h"
|
#include "WProgram.h"
|
||||||
|
//#include <ptpdebug.h>
|
||||||
|
|
||||||
static uint8_t usb_error = 0;
|
static uint8_t usb_error = 0;
|
||||||
static uint8_t usb_task_state;
|
static uint8_t usb_task_state;
|
||||||
DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
|
//DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
|
||||||
EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
//EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
||||||
|
|
||||||
|
|
||||||
/* constructor */
|
/* constructor */
|
||||||
|
@ -19,19 +20,23 @@ USB::USB ()
|
||||||
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
|
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Initialize data structures */
|
/* Initialize data structures */
|
||||||
void USB::init()
|
void USB::init()
|
||||||
{
|
{
|
||||||
uint8_t i;
|
devConfigIndex = 0;
|
||||||
for( i = 0; i < ( USB_NUMDEVICES + 1 ); i++ ) {
|
|
||||||
devtable[ i ].epinfo = NULL; //clear device table
|
//UsbDevice *p = addrPool.GetUsbDevicePtr(0);
|
||||||
devtable[ i ].devclass = 0;
|
|
||||||
}
|
//if (p)
|
||||||
devtable[ 0 ].epinfo = &dev0ep; //set single ep for uninitialized device
|
//{
|
||||||
// not necessary dev0ep.MaxPktSize = 8; //minimum possible
|
// p->epinfo = &dev0ep;
|
||||||
dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
// dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||||
dev0ep.rcvToggle = bmRCVTOG0;
|
// dev0ep.rcvToggle = bmRCVTOG0;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t USB::getUsbTaskState( void )
|
uint8_t USB::getUsbTaskState( void )
|
||||||
{
|
{
|
||||||
return( usb_task_state );
|
return( usb_task_state );
|
||||||
|
@ -42,17 +47,30 @@ void USB::setUsbTaskState( uint8_t state )
|
||||||
}
|
}
|
||||||
EP_RECORD* USB::getDevTableEntry( uint8_t addr, uint8_t ep )
|
EP_RECORD* USB::getDevTableEntry( uint8_t addr, uint8_t ep )
|
||||||
{
|
{
|
||||||
EP_RECORD* ptr;
|
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||||
ptr = devtable[ addr ].epinfo;
|
|
||||||
ptr += ep;
|
if (p)
|
||||||
return( ptr );
|
return (p->epinfo + ep);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
/* set device table entry */
|
/* set device table entry */
|
||||||
/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
|
/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
|
||||||
void USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr )
|
uint8_t USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr )
|
||||||
{
|
{
|
||||||
devtable[ addr ].epinfo = eprecord_ptr;
|
if (!eprecord_ptr)
|
||||||
//return();
|
return USB_ERROR_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
|
p->address = addr;
|
||||||
|
p->devclass = 0;
|
||||||
|
p->epinfo = eprecord_ptr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
|
/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
|
||||||
/* depending on request. Actual requests are defined as inlines */
|
/* depending on request. Actual requests are defined as inlines */
|
||||||
|
@ -61,14 +79,15 @@ void USB::setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr )
|
||||||
/* 01-0f = non-zero HRSLT */
|
/* 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, unsigned int nak_limit )
|
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, unsigned int nak_limit )
|
||||||
{
|
{
|
||||||
boolean direction = false; //request direction, IN or OUT
|
boolean direction = false; //request direction, IN or OUT
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
SETUP_PKT setup_pkt;
|
SETUP_PKT setup_pkt;
|
||||||
|
|
||||||
|
regWr( rPERADDR, addr ); //set peripheral address
|
||||||
|
|
||||||
|
if( bmReqType & 0x80 )
|
||||||
|
direction = true; //determine request direction
|
||||||
|
|
||||||
regWr( rPERADDR, addr ); //set peripheral address
|
|
||||||
if( bmReqType & 0x80 ) {
|
|
||||||
direction = true; //determine request direction
|
|
||||||
}
|
|
||||||
/* fill in setup packet */
|
/* fill in setup packet */
|
||||||
setup_pkt.ReqType_u.bmRequestType = bmReqType;
|
setup_pkt.ReqType_u.bmRequestType = bmReqType;
|
||||||
setup_pkt.bRequest = bRequest;
|
setup_pkt.bRequest = bRequest;
|
||||||
|
@ -100,7 +119,7 @@ uint8_t USB::ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequ
|
||||||
/* Assumed peripheral address is already set */
|
/* Assumed peripheral address is already set */
|
||||||
uint8_t USB::ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit )
|
uint8_t USB::ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit )
|
||||||
{
|
{
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
if( direction ) { //GET
|
if( direction ) { //GET
|
||||||
rcode = dispatchPkt( tokOUTHS, ep, nak_limit );
|
rcode = dispatchPkt( tokOUTHS, ep, nak_limit );
|
||||||
}
|
}
|
||||||
|
@ -112,17 +131,34 @@ uint8_t USB::ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit )
|
||||||
/* Control transfer with data stage. Stages 2 and 3 of control transfer. Assumes preipheral address is set and setup packet has been sent */
|
/* Control transfer with data stage. Stages 2 and 3 of control transfer. Assumes preipheral address is set and setup packet has been sent */
|
||||||
uint8_t USB::ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction, unsigned int nak_limit )
|
uint8_t USB::ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction, unsigned int nak_limit )
|
||||||
{
|
{
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
if( direction ) { //IN transfer
|
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
|
|
||||||
rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
//Serial.print("cD");
|
||||||
return( rcode );
|
//Serial.print("\tA:");
|
||||||
}
|
//Serial.print(addr, HEX);
|
||||||
else { //OUT transfer
|
//Serial.print("\tE:");
|
||||||
devtable[ addr ].epinfo[ ep ].sndToggle = bmSNDTOG1;
|
//Serial.println(ep, HEX);
|
||||||
rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
|
||||||
return( rcode );
|
if (!p)
|
||||||
}
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
|
if (!p->epinfo)
|
||||||
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
|
|
||||||
|
EP_RECORD *pep = &p->epinfo[ep];
|
||||||
|
|
||||||
|
if( direction ) //IN transfer
|
||||||
|
{
|
||||||
|
pep->rcvToggle = bmRCVTOG1;
|
||||||
|
rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
||||||
|
}
|
||||||
|
else //OUT transfer
|
||||||
|
{
|
||||||
|
pep->sndToggle = bmSNDTOG1;
|
||||||
|
rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit );
|
||||||
|
}
|
||||||
|
return( rcode );
|
||||||
}
|
}
|
||||||
/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
||||||
/* Keep sending INs and writes data to memory area pointed by 'data' */
|
/* Keep sending INs and writes data to memory area pointed by 'data' */
|
||||||
|
@ -130,16 +166,33 @@ uint8_t USB::ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* d
|
||||||
fe USB xfer timeout */
|
fe USB xfer timeout */
|
||||||
uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit )
|
uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit )
|
||||||
{
|
{
|
||||||
uint8_t rcode;
|
uint8_t rcode;
|
||||||
uint8_t pktsize;
|
uint8_t pktsize;
|
||||||
uint8_t maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
|
|
||||||
unsigned int xfrlen = 0;
|
//Serial.println("iT");
|
||||||
regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle ); //set toggle value
|
|
||||||
while( 1 ) { // use a 'return' to exit this loop
|
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
|
if (!p->epinfo)
|
||||||
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
|
|
||||||
|
EP_RECORD *pep = &p->epinfo[ep];
|
||||||
|
|
||||||
|
uint8_t maxpktsize = pep->MaxPktSize;
|
||||||
|
|
||||||
|
unsigned int xfrlen = 0;
|
||||||
|
regWr( rHCTL, pep->rcvToggle ); //set toggle value
|
||||||
|
|
||||||
|
while( 1 ) // use a 'return' to exit this loop
|
||||||
|
{
|
||||||
rcode = dispatchPkt( tokIN, ep, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS.
|
rcode = dispatchPkt( tokIN, ep, nak_limit ); //IN packet to EP-'endpoint'. Function takes care of NAKS.
|
||||||
if( rcode ) {
|
|
||||||
|
if( rcode )
|
||||||
return( rcode ); //should be 0, indicating ACK. Else return error code.
|
return( rcode ); //should be 0, indicating ACK. Else return error code.
|
||||||
}
|
|
||||||
/* 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 ) {
|
||||||
|
@ -152,16 +205,16 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t*
|
||||||
/* The transfer is complete under two conditions: */
|
/* The transfer is complete under two conditions: */
|
||||||
/* 1. The device sent a short packet (L.T. maxPacketSize) */
|
/* 1. The device sent a short packet (L.T. maxPacketSize) */
|
||||||
/* 2. 'nbytes' have been transferred. */
|
/* 2. 'nbytes' have been transferred. */
|
||||||
if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes?
|
if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) // have we transferred 'nbytes' bytes?
|
||||||
if( regRd( rHRSL ) & bmRCVTOGRD ) { //save toggle value
|
{
|
||||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;
|
if( regRd( rHRSL ) & bmRCVTOGRD ) //save toggle value
|
||||||
}
|
pep->rcvToggle = bmRCVTOG1;
|
||||||
else {
|
else
|
||||||
devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;
|
pep->rcvToggle = bmRCVTOG0;
|
||||||
}
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
} // if
|
||||||
}//while( 1 )
|
} //while( 1 )
|
||||||
}
|
}
|
||||||
/* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
/* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
|
||||||
/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
|
/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
|
||||||
|
@ -169,59 +222,77 @@ uint8_t USB::inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t*
|
||||||
/* major part of this function borrowed from code shared by Richard Ibbotson */
|
/* 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, unsigned int nak_limit )
|
uint8_t USB::outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit )
|
||||||
{
|
{
|
||||||
uint8_t rcode, retry_count;
|
uint8_t rcode, retry_count;
|
||||||
uint8_t* data_p = data; //local copy of the data pointer
|
uint8_t* data_p = data; //local copy of the data pointer
|
||||||
unsigned int bytes_tosend, nak_count;
|
unsigned int bytes_tosend, nak_count;
|
||||||
unsigned int bytes_left = nbytes;
|
unsigned int bytes_left = nbytes;
|
||||||
uint8_t maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
|
|
||||||
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
|
|
||||||
|
|
||||||
if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64
|
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
|
||||||
return 0xFE;
|
|
||||||
}
|
|
||||||
|
|
||||||
regWr( rHCTL, devtable[ addr ].epinfo[ ep ].sndToggle ); //set toggle value
|
if (!p)
|
||||||
while( bytes_left ) {
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
retry_count = 0;
|
|
||||||
nak_count = 0;
|
EP_RECORD *pep = p->epinfo + ep;
|
||||||
bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;
|
|
||||||
bytesWr( rSNDFIFO, bytes_tosend, data_p ); //filling output FIFO
|
if (!p->epinfo)
|
||||||
regWr( rSNDBC, bytes_tosend ); //set number of bytes
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
|
||||||
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
uint8_t maxpktsize = pep->MaxPktSize;
|
||||||
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
|
||||||
rcode = ( regRd( rHRSL ) & 0x0f );
|
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
|
||||||
while( rcode && ( timeout > millis())) {
|
|
||||||
switch( rcode ) {
|
if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64
|
||||||
case hrNAK:
|
return 0xFE;
|
||||||
nak_count++;
|
}
|
||||||
if( nak_limit && ( nak_count == USB_NAK_LIMIT )) {
|
|
||||||
return( rcode); //return NAK
|
regWr( rHCTL, pep->sndToggle ); //set toggle value
|
||||||
}
|
|
||||||
break;
|
while( bytes_left )
|
||||||
case hrTIMEOUT:
|
{
|
||||||
retry_count++;
|
retry_count = 0;
|
||||||
if( retry_count == USB_RETRY_LIMIT ) {
|
nak_count = 0;
|
||||||
return( rcode ); //return TIMEOUT
|
bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;
|
||||||
}
|
bytesWr( rSNDFIFO, bytes_tosend, data_p ); //filling output FIFO
|
||||||
break;
|
regWr( rSNDBC, bytes_tosend ); //set number of bytes
|
||||||
default:
|
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
||||||
return( rcode );
|
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
||||||
}//switch( rcode...
|
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
||||||
/* process NAK according to Host out NAK bug */
|
rcode = ( regRd( rHRSL ) & 0x0f );
|
||||||
regWr( rSNDBC, 0 );
|
|
||||||
regWr( rSNDFIFO, *data_p );
|
while( rcode && ( timeout > millis()))
|
||||||
regWr( rSNDBC, bytes_tosend );
|
{
|
||||||
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
switch( rcode )
|
||||||
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
{
|
||||||
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
case hrNAK:
|
||||||
rcode = ( regRd( rHRSL ) & 0x0f );
|
nak_count++;
|
||||||
}//while( rcode && ....
|
if( nak_limit && ( nak_count == USB_NAK_LIMIT ))
|
||||||
bytes_left -= bytes_tosend;
|
{
|
||||||
data_p += bytes_tosend;
|
return( rcode); //return NAK
|
||||||
}//while( bytes_left...
|
}
|
||||||
devtable[ addr ].epinfo[ ep ].sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0; //update toggle
|
break;
|
||||||
return( rcode ); //should be 0 in all cases
|
case hrTIMEOUT:
|
||||||
|
retry_count++;
|
||||||
|
if( retry_count == USB_RETRY_LIMIT ) {
|
||||||
|
return( rcode ); //return TIMEOUT
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return( rcode );
|
||||||
|
} //switch( rcode...
|
||||||
|
/* process NAK according to Host out NAK bug */
|
||||||
|
regWr( rSNDBC, 0 );
|
||||||
|
regWr( rSNDFIFO, *data_p );
|
||||||
|
regWr( rSNDBC, bytes_tosend );
|
||||||
|
regWr( rHXFR, ( tokOUT | ep )); //dispatch packet
|
||||||
|
while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ
|
||||||
|
regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ
|
||||||
|
rcode = ( regRd( rHRSL ) & 0x0f );
|
||||||
|
}//while( rcode && ....
|
||||||
|
bytes_left -= bytes_tosend;
|
||||||
|
data_p += bytes_tosend;
|
||||||
|
}//while( bytes_left...
|
||||||
|
pep->sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0; //update toggle
|
||||||
|
return( rcode ); //should be 0 in all cases
|
||||||
}
|
}
|
||||||
/* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
|
/* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
|
||||||
/* If NAK, tries to re-send up to nak_limit times */
|
/* If NAK, tries to re-send up to nak_limit times */
|
||||||
|
@ -285,7 +356,8 @@ void USB::Task( void ) //USB state machine
|
||||||
tmpdata = getVbusState();
|
tmpdata = getVbusState();
|
||||||
/* modify USB task state if Vbus changed */
|
/* modify USB task state if Vbus changed */
|
||||||
|
|
||||||
switch( tmpdata ) {
|
switch( tmpdata )
|
||||||
|
{
|
||||||
case SE1: //illegal state
|
case SE1: //illegal state
|
||||||
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
|
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
|
||||||
break;
|
break;
|
||||||
|
@ -296,90 +368,399 @@ void USB::Task( void ) //USB state machine
|
||||||
break;
|
break;
|
||||||
case FSHOST: //attached
|
case FSHOST: //attached
|
||||||
case LSHOST:
|
case LSHOST:
|
||||||
|
//Serial.println("FSHOST");
|
||||||
if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
|
if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {
|
||||||
delay = millis() + USB_SETTLE_DELAY;
|
delay = millis() + USB_SETTLE_DELAY;
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
|
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}// switch( tmpdata
|
}// switch( tmpdata
|
||||||
//Serial.print("USB task state: ");
|
|
||||||
//Serial.println( usb_task_state, HEX );
|
for (uint8_t i=0; i<USB_NUMDEVICES; i++)
|
||||||
|
{
|
||||||
|
if (devConfig[i])
|
||||||
|
{
|
||||||
|
rcode = devConfig[i]->Poll();
|
||||||
|
}
|
||||||
|
} //for
|
||||||
|
|
||||||
switch( usb_task_state ) {
|
switch( usb_task_state ) {
|
||||||
case USB_DETACHED_SUBSTATE_INITIALIZE:
|
case USB_DETACHED_SUBSTATE_INITIALIZE:
|
||||||
|
Serial.println("INIT");
|
||||||
init();
|
init();
|
||||||
usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
|
usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
|
||||||
break;
|
break;
|
||||||
case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
|
case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
|
||||||
|
Serial.println("WFD");
|
||||||
break;
|
break;
|
||||||
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
|
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
|
||||||
|
Serial.println("ILL");
|
||||||
break;
|
break;
|
||||||
case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device
|
case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device
|
||||||
|
Serial.println("STL");
|
||||||
if( delay < millis() ) {
|
if( delay < millis() ) {
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
|
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
|
case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
|
||||||
regWr( rHCTL, bmBUSRST ); //issue bus reset
|
Serial.println("RES");
|
||||||
|
regWr( rHCTL, bmBUSRST ); //issue bus reset
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
|
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
|
||||||
break;
|
break;
|
||||||
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
|
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
|
||||||
if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) {
|
Serial.println("RCOMP");
|
||||||
|
if(( regRd( rHCTL ) & bmBUSRST ) == 0 )
|
||||||
|
{
|
||||||
tmpdata = regRd( rMODE ) | bmSOFKAENAB; //start SOF generation
|
tmpdata = regRd( rMODE ) | bmSOFKAENAB; //start SOF generation
|
||||||
regWr( rMODE, tmpdata );
|
regWr( rMODE, tmpdata );
|
||||||
// regWr( rMODE, bmSOFKAENAB );
|
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
|
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
|
||||||
delay = millis() + 20; //20ms wait after reset per USB spec
|
delay = millis() + 20; //20ms wait after reset per USB spec
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
|
case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
|
||||||
|
Serial.println("WSOF");
|
||||||
if( regRd( rHIRQ ) & bmFRAMEIRQ ) { //when first SOF received we can continue
|
if( regRd( rHIRQ ) & bmFRAMEIRQ ) { //when first SOF received we can continue
|
||||||
if( delay < millis() ) { //20ms passed
|
if( delay < millis() ) { //20ms passed
|
||||||
usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
usb_task_state = USB_STATE_ADDRESSING;
|
||||||
|
//usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE:
|
|
||||||
// toggle( BPNT_0 );
|
|
||||||
devtable[ 0 ].epinfo->MaxPktSize = 8; //set max.packet size to min.allowed
|
|
||||||
rcode = getDevDescr( 0, 0, 8, (uint8_t*)&buf );
|
|
||||||
if( rcode == 0 ) {
|
|
||||||
devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0;
|
|
||||||
usb_task_state = USB_STATE_ADDRESSING;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
|
||||||
usb_task_state = USB_STATE_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case USB_STATE_ADDRESSING:
|
case USB_STATE_ADDRESSING:
|
||||||
for( i = 1; i < USB_NUMDEVICES; i++ ) {
|
Serial.println("ADR");
|
||||||
if( devtable[ i ].epinfo == NULL ) {
|
|
||||||
devtable[ i ].epinfo = devtable[ 0 ].epinfo; //set correct MaxPktSize
|
|
||||||
//temporary record
|
|
||||||
//until plugged with real device endpoint structure
|
|
||||||
rcode = setAddr( 0, 0, i );
|
|
||||||
if( rcode == 0 ) {
|
|
||||||
tmpaddr = i;
|
|
||||||
usb_task_state = USB_STATE_CONFIGURING;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
usb_error = USB_STATE_ADDRESSING; //set address error
|
|
||||||
usb_task_state = USB_STATE_ERROR;
|
|
||||||
}
|
|
||||||
break; //break if address assigned or error occured during address assignment attempt
|
|
||||||
}
|
|
||||||
} //for( i = 1; i < USB_NUMDEVICES; i++)
|
|
||||||
|
|
||||||
if( usb_task_state == USB_STATE_ADDRESSING ) { //no vacant place in devtable
|
rcode = Addressing(&tmpaddr);
|
||||||
usb_error = 0xfe;
|
|
||||||
usb_task_state = USB_STATE_ERROR;
|
if (rcode == hrSUCCESS)
|
||||||
}
|
usb_task_state = USB_STATE_CONFIGURING;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usb_error = rcode;
|
||||||
|
usb_task_state = USB_STATE_ERROR;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case USB_STATE_CONFIGURING:
|
case USB_STATE_CONFIGURING:
|
||||||
|
Serial.print("CNF");
|
||||||
|
|
||||||
|
rcode = Configuring(tmpaddr);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
|
||||||
|
{
|
||||||
|
usb_error = rcode;
|
||||||
|
usb_task_state = USB_STATE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usb_task_state = USB_STATE_RUNNING;
|
||||||
break;
|
break;
|
||||||
case USB_STATE_RUNNING:
|
case USB_STATE_RUNNING:
|
||||||
|
Serial.println("RUN");
|
||||||
break;
|
break;
|
||||||
case USB_STATE_ERROR:
|
case USB_STATE_ERROR:
|
||||||
break;
|
break;
|
||||||
}// switch( usb_task_state
|
} // switch( usb_task_state )
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USB::Addressing(uint8_t *address)
|
||||||
|
{
|
||||||
|
uint8_t rcode = hrSUCCESS, buf[8];
|
||||||
|
|
||||||
|
Serial.println("Adrsng");
|
||||||
|
|
||||||
|
UsbDevice *p = addrPool.GetUsbDevicePtr(0);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
|
||||||
|
|
||||||
|
if (!p->epinfo)
|
||||||
|
{
|
||||||
|
Serial.println("epinfo");
|
||||||
|
return USB_ERROR_EPINFO_IS_NULL;
|
||||||
|
}
|
||||||
|
Serial.print("addr:");
|
||||||
|
Serial.println(p->address, HEX);
|
||||||
|
Serial.print("ep:");
|
||||||
|
Serial.println(p->epinfo->epAddr, HEX);
|
||||||
|
|
||||||
|
//p->epinfo->MaxPktSize = 8;
|
||||||
|
|
||||||
|
Serial.print("Max:");
|
||||||
|
Serial.println(p->epinfo->MaxPktSize, HEX);
|
||||||
|
|
||||||
|
rcode = getDevDescr( 0, 0, 8, (uint8_t*)buf );
|
||||||
|
|
||||||
|
if( rcode == 0 )
|
||||||
|
{
|
||||||
|
Serial.println("OK!");
|
||||||
|
p->epinfo->MaxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
|
||||||
|
p->devclass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.println("getDevDesc:");
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t addr = addrPool.AllocAddress(0, (p->devclass == 0x09) ? true : false);
|
||||||
|
|
||||||
|
if (!addr)
|
||||||
|
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
|
||||||
|
|
||||||
|
Serial.print("Addr:");
|
||||||
|
Serial.println(addr,HEX);
|
||||||
|
|
||||||
|
rcode = setAddr( 0, 0, addr );
|
||||||
|
|
||||||
|
if (!rcode)
|
||||||
|
{
|
||||||
|
*address = addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.print("setAddr:");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USB::Configuring(uint8_t addr)
|
||||||
|
{
|
||||||
|
static uint8_t dev_index = 0;
|
||||||
|
uint8_t rcode = 0, buf[8];
|
||||||
|
|
||||||
|
for (; devConfigIndex<USB_NUMDEVICES; devConfigIndex++)
|
||||||
|
{
|
||||||
|
rcode = devConfig[devConfigIndex]->Init(addr);
|
||||||
|
|
||||||
|
Serial.println(".");
|
||||||
|
|
||||||
|
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
|
||||||
|
{
|
||||||
|
// in case of an error dev_index should be reset to 0
|
||||||
|
// in order to start from the very beginning the
|
||||||
|
// next time the program gets here
|
||||||
|
if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
|
||||||
|
devConfigIndex = 0;
|
||||||
|
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if we get here that means that the device class is not supported by any of registered classes
|
||||||
|
devConfigIndex = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//class UsbHub
|
||||||
|
//{
|
||||||
|
// uint8_t bNbrPorts; // Number of ports
|
||||||
|
// uint8_t portStates[HUB_MAX_PORTS]; // State of each port a hub has
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//struct HubPort
|
||||||
|
//{
|
||||||
|
// UsbDevAddress *hubAddr;
|
||||||
|
// uint8_t numPort;
|
||||||
|
// uint8_t portState;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//static uint8_t USB::PortTask(HubPort *phub_port, uint8_t sig)
|
||||||
|
////static uint8_t USB::PortTask(uint8_t hub_addr, uint8_t port, uint8_t &state, uint8_t sig)
|
||||||
|
//{
|
||||||
|
// switch(state)
|
||||||
|
// {
|
||||||
|
// case USB_STATE_HUB_PORT_POWERED_OFF:
|
||||||
|
// Serial.println("POWERED_OFF");
|
||||||
|
//
|
||||||
|
// for (uint8_t j=1; j<=hubs[0].bNbrPorts; j++)
|
||||||
|
// HubPortPowerOn(hubs[0].bAddress, j);
|
||||||
|
//
|
||||||
|
// delay = millis() + USB_SETTLE_DELAY;
|
||||||
|
// usb_task_state = USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD;
|
||||||
|
// break;
|
||||||
|
// case USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD:
|
||||||
|
// Serial.println("WAIT_FOR_POWER_GOOD");
|
||||||
|
// if (millis() >= delay)
|
||||||
|
// usb_task_state = USB_STATE_HUB_PORT_DISCONNECTED;
|
||||||
|
//// usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||||
|
// break;
|
||||||
|
// case USB_STATE_HUB_PORT_DISCONNECTED:
|
||||||
|
// Serial.println("PORT_DISCONNECTED");
|
||||||
|
//
|
||||||
|
// for (uint8_t j=1; j<=hubs[0].bNbrPorts; j++)
|
||||||
|
// HubClearPortFeatures(hubs[0].bAddress, j, HUB_FEATURE_PORT_ENABLE | HUB_FEATURE_C_PORT_CONNECTION);
|
||||||
|
//
|
||||||
|
// usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||||
|
// break;
|
||||||
|
// case USB_STATE_HUB_PORT_DISABLED:
|
||||||
|
// Serial.println("PORT_DISABLED");
|
||||||
|
//
|
||||||
|
// for (uint8_t j=1; j<=hubs[0].bNbrPorts; j++)
|
||||||
|
// HubPortReset(hubs[0].bAddress, j);
|
||||||
|
//
|
||||||
|
// delay = millis() + HUB_PORT_RESET_DELAY;
|
||||||
|
// usb_task_state = USB_STATE_HUB_PORT_RESETTING;
|
||||||
|
// break;
|
||||||
|
// case USB_STATE_HUB_PORT_RESETTING:
|
||||||
|
// Serial.println("PORT_RESETTING");
|
||||||
|
// if (millis() >= delay)
|
||||||
|
// usb_task_state = USB_STATE_HUB_PORT_ENABLED;
|
||||||
|
// break;
|
||||||
|
// case USB_STATE_HUB_PORT_ENABLED:
|
||||||
|
// Serial.println("PORT_ENABLED");
|
||||||
|
// usb_task_state = USB_STATE_RUNNING;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t USB::HubPortPowerOn(uint8_t addr, uint8_t port)
|
||||||
|
{
|
||||||
|
uint8_t rcode = SetPortFeature(addr, 0, HUB_FEATURE_PORT_POWER, port, 0);
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("PORT #");
|
||||||
|
Serial.print(port, DEC);
|
||||||
|
Serial.print(" pwr err:");
|
||||||
|
Serial.println(rcode,HEX);
|
||||||
|
}
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USB::HubPortReset(uint8_t addr, uint8_t port)
|
||||||
|
{
|
||||||
|
uint8_t rcode = SetPortFeature(addr, 0, HUB_FEATURE_PORT_RESET, port, 0);
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("PORT #");
|
||||||
|
Serial.print(port, DEC);
|
||||||
|
Serial.print(" rst err:");
|
||||||
|
Serial.println(rcode,HEX);
|
||||||
|
}
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USB::HubClearPortFeatures(uint8_t addr, uint8_t port, uint8_t bm_features)
|
||||||
|
{
|
||||||
|
uint8_t rcode = ClearPortFeature(addr, 0, bm_features, port, 0);
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("PORT #");
|
||||||
|
Serial.print(port, DEC);
|
||||||
|
Serial.print(" f.clr err:");
|
||||||
|
Serial.println(rcode,HEX);
|
||||||
|
}
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Hub Polling
|
||||||
|
uint8_t USB::PollHub()
|
||||||
|
{
|
||||||
|
uint8_t rcode;
|
||||||
|
uint8_t buf[8];
|
||||||
|
|
||||||
|
// uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
//Serial.println(devtable[1].epinfo->epAddr, HEX);
|
||||||
|
|
||||||
|
rcode = inTransfer(1, 0x1 /*devtable[1].epinfo->epAddr*/, 1, buf, 1);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("inTransfer:");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
Serial.print("Int:");
|
||||||
|
Serial.println(buf[0],HEX);
|
||||||
|
|
||||||
|
//return 0;
|
||||||
|
|
||||||
|
if (buf[0] & 0x01) // Hub Status Change
|
||||||
|
{
|
||||||
|
PrintHubStatus(1);
|
||||||
|
//rcode = GetHubStatus(1, 0, 1, 4, buf);
|
||||||
|
//if (rcode)
|
||||||
|
//{
|
||||||
|
// Serial.print("GetHubStatus Error");
|
||||||
|
// Serial.println(rcode, HEX);
|
||||||
|
// return rcode;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
if (buf[0] & 0x02) // Port 1
|
||||||
|
{
|
||||||
|
rcode = GetPortStatus(1, 0, 1, 4, buf);
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("GetPortStatus Error");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
if (buf[2] & bmHUB_PORT_STATUS_C_PORT_RESET)
|
||||||
|
{
|
||||||
|
Serial.println("PORT_RESET");
|
||||||
|
|
||||||
|
rcode = ClearPortFeature(1, 0, 1, HUB_FEATURE_C_PORT_RESET);
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("ClearPortFeature Error");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
//usb_task_state = USB_STATE_HUB_PORT_ENABLED; //USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (buf[2] & bmHUB_PORT_STATUS_C_PORT_CONNECTION)
|
||||||
|
{
|
||||||
|
Serial.println("PORT_CONNECTION");
|
||||||
|
|
||||||
|
rcode = ClearPortFeature(1, 0, 1, HUB_FEATURE_C_PORT_CONNECTION);
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("ClearPortFeature Error");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
// //if (buf & bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||||
|
// // usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||||
|
// //else
|
||||||
|
// // usb_task_state = USB_STATE_RUNNING;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // if (buf[0] & 0x02) // Port 1
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void USB::PrintHubStatus(/*USB *usbptr,*/ uint8_t addr)
|
||||||
|
{
|
||||||
|
uint8_t rcode = 0;
|
||||||
|
uint8_t buf[4];
|
||||||
|
|
||||||
|
rcode = /*usbptr->*/GetHubStatus(addr, 0, 4, (uint8_t*)&buf);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("ERROR:");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Serial.println("\r\nHub");
|
||||||
|
Serial.println("\r\nStatus");
|
||||||
|
|
||||||
|
Serial.print("Local Pwr Src:\t");
|
||||||
|
Serial.println((buf[0] & bmHUB_STATUS_LOCAL_POWER_SOURCE) > 0, DEC);
|
||||||
|
Serial.print("Over-current:\t");
|
||||||
|
Serial.println((buf[0] & bmHUB_STATUS_OVER_CURRENT) > 0, DEC);
|
||||||
|
|
||||||
|
Serial.println("\r\nChanges");
|
||||||
|
Serial.print("Local Pwr Src:\t");
|
||||||
|
Serial.println((buf[2] & bmHUB_STATUS_C_LOCAL_POWER_SOURCE) > 0, DEC);
|
||||||
|
Serial.print("Over-current:\t");
|
||||||
|
Serial.println((buf[2] & bmHUB_STATUS_C_OVER_CURRENT) > 0, DEC);
|
||||||
|
Serial.println("");
|
||||||
}
|
}
|
||||||
|
|
309
Usb.h
309
Usb.h
|
@ -7,27 +7,155 @@
|
||||||
#include "max3421e.h"
|
#include "max3421e.h"
|
||||||
#include "usbhost.h"
|
#include "usbhost.h"
|
||||||
#include "usb_ch9.h"
|
#include "usb_ch9.h"
|
||||||
|
#include "address.h"
|
||||||
#include <WProgram.h>
|
#include <WProgram.h>
|
||||||
|
|
||||||
/* Common setup data constant combinations */
|
/* 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_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_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
|
#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type
|
||||||
|
|
||||||
/* HID requests */
|
/* HID requests */
|
||||||
#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
#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_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
|
#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
|
||||||
|
|
||||||
#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
|
|
||||||
#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted
|
|
||||||
#define USB_RETRY_LIMIT 3 //retry limit for a transfer
|
|
||||||
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds
|
|
||||||
#define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code
|
|
||||||
|
|
||||||
#define USB_NUMDEVICES 2 //number of USB devices
|
|
||||||
|
// 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
|
||||||
|
#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control
|
||||||
|
#define USB_CLASS_HID 0x03 // HID
|
||||||
|
#define USB_CLASS_PHYSICAL 0x05 // Physical
|
||||||
|
#define USB_CLASS_IMAGE 0x06 // Image
|
||||||
|
#define USB_CLASS_PRINTER 0x07 // Printer
|
||||||
|
#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage
|
||||||
|
#define USB_CLASS_HUB 0x09 // Hub
|
||||||
|
#define USB_CLASS_CDC_DATA 0x0a // CDC-Data
|
||||||
|
#define USB_CLASS_SMART_CARD 0x0b // Smart-Card
|
||||||
|
#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security
|
||||||
|
#define USB_CLASS_VIDEO 0x0e // Video
|
||||||
|
#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare
|
||||||
|
#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device
|
||||||
|
#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller
|
||||||
|
#define USB_CLASS_MISC 0xef // Miscellaneous
|
||||||
|
#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific
|
||||||
|
#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
||||||
|
#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||||
|
#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||||
|
#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||||
|
#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||||
|
#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||||
|
#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||||
|
#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
|
||||||
|
#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||||
|
#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||||
|
#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
|
||||||
|
|
||||||
|
// Hub Class Requests
|
||||||
|
#define HUB_REQUEST_CLEAR_TT_BUFFER 8
|
||||||
|
#define HUB_REQUEST_RESET_TT 9
|
||||||
|
#define HUB_REQUEST_GET_TT_STATE 10
|
||||||
|
#define HUB_REQUEST_STOP_TT 11
|
||||||
|
|
||||||
|
// Hub Features
|
||||||
|
#define HUB_FEATURE_C_HUB_LOCAL_POWER 0
|
||||||
|
#define HUB_FEATURE_C_HUB_OVER_CURRENT 1
|
||||||
|
#define HUB_FEATURE_PORT_CONNECTION 0
|
||||||
|
#define HUB_FEATURE_PORT_ENABLE 1
|
||||||
|
#define HUB_FEATURE_PORT_SUSPEND 2
|
||||||
|
#define HUB_FEATURE_PORT_OVER_CURRENT 3
|
||||||
|
#define HUB_FEATURE_PORT_RESET 4
|
||||||
|
#define HUB_FEATURE_PORT_POWER 8
|
||||||
|
#define HUB_FEATURE_PORT_LOW_SPEED 9
|
||||||
|
#define HUB_FEATURE_C_PORT_CONNECTION 16
|
||||||
|
#define HUB_FEATURE_C_PORT_ENABLE 17
|
||||||
|
#define HUB_FEATURE_C_PORT_SUSPEND 18
|
||||||
|
#define HUB_FEATURE_C_PORT_OVER_CURRENT 19
|
||||||
|
#define HUB_FEATURE_C_PORT_RESET 20
|
||||||
|
#define HUB_FEATURE_PORT_TEST 21
|
||||||
|
#define HUB_FEATURE_PORT_INDICATOR 22
|
||||||
|
|
||||||
|
// Hub Port Test Modes
|
||||||
|
#define HUB_PORT_TEST_MODE_J 1
|
||||||
|
#define HUB_PORT_TEST_MODE_K 2
|
||||||
|
#define HUB_PORT_TEST_MODE_SE0_NAK 3
|
||||||
|
#define HUB_PORT_TEST_MODE_PACKET 4
|
||||||
|
#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5
|
||||||
|
|
||||||
|
// Hub Port Indicator Color
|
||||||
|
#define HUB_PORT_INDICATOR_AUTO 0
|
||||||
|
#define HUB_PORT_INDICATOR_AMBER 1
|
||||||
|
#define HUB_PORT_INDICATOR_GREEN 2
|
||||||
|
#define HUB_PORT_INDICATOR_OFF 3
|
||||||
|
|
||||||
|
// Hub Port Status Bitmasks
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_CONNECTION 0x0001
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_ENABLE 0x0002
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_SUSPEND 0x0004
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_RESET 0x0010
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_POWER 0x0100
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_TEST 0x0800
|
||||||
|
#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000
|
||||||
|
|
||||||
|
// Hub Port Status Change Bitmasks (used one byte instead of two)
|
||||||
|
#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001
|
||||||
|
#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002
|
||||||
|
#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004
|
||||||
|
#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008
|
||||||
|
#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010
|
||||||
|
|
||||||
|
// Hub Status Bitmasks (used one byte instead of two)
|
||||||
|
#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01
|
||||||
|
#define bmHUB_STATUS_OVER_CURRENT 0x12
|
||||||
|
|
||||||
|
// Hub Status Change Bitmasks (used one byte instead of two)
|
||||||
|
#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01
|
||||||
|
#define bmHUB_STATUS_C_OVER_CURRENT 0x12
|
||||||
|
|
||||||
|
// Additional Error Codes
|
||||||
|
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1
|
||||||
|
#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2
|
||||||
|
#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3
|
||||||
|
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4
|
||||||
|
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD5
|
||||||
|
#define USB_ERROR_EPINFO_IS_NULL 0xD6
|
||||||
|
#define USB_ERROR_INVALID_ARGUMENT 0xD7
|
||||||
|
|
||||||
|
class USBDeviceConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual uint8_t Init(uint8_t addr) = 0;
|
||||||
|
virtual uint8_t Release(uint8_t addr) = 0;
|
||||||
|
virtual uint8_t Poll() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
|
||||||
|
#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted
|
||||||
|
#define USB_RETRY_LIMIT 3 //retry limit for a transfer
|
||||||
|
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds
|
||||||
|
#define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code
|
||||||
|
|
||||||
|
#define USB_NUMDEVICES 6 //number of USB devices
|
||||||
|
#define HUB_MAX_HUBS 5 // maximum number of hubs that can be attached to the host controller
|
||||||
|
#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms
|
||||||
|
|
||||||
/* USB state machine states */
|
/* USB state machine states */
|
||||||
|
|
||||||
#define USB_STATE_MASK 0xf0
|
#define USB_STATE_MASK 0xf0
|
||||||
|
|
||||||
#define USB_STATE_DETACHED 0x10
|
#define USB_STATE_DETACHED 0x10
|
||||||
|
@ -44,6 +172,7 @@
|
||||||
#define USB_STATE_RUNNING 0x90
|
#define USB_STATE_RUNNING 0x90
|
||||||
#define USB_STATE_ERROR 0xa0
|
#define USB_STATE_ERROR 0xa0
|
||||||
|
|
||||||
|
|
||||||
// byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE
|
// byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE
|
||||||
|
|
||||||
/* USB Setup Packet Structure */
|
/* USB Setup Packet Structure */
|
||||||
|
@ -56,7 +185,7 @@ typedef struct {
|
||||||
uint8_t direction: 1; // Direction of data X-fer
|
uint8_t direction: 1; // Direction of data X-fer
|
||||||
};
|
};
|
||||||
}ReqType_u;
|
}ReqType_u;
|
||||||
uint8_t bRequest; // 1 Request
|
uint8_t bRequest; // 1 Request
|
||||||
union {
|
union {
|
||||||
unsigned int wValue; // 2 Depends on bRequest
|
unsigned int wValue; // 2 Depends on bRequest
|
||||||
struct {
|
struct {
|
||||||
|
@ -68,26 +197,38 @@ typedef struct {
|
||||||
unsigned int wLength; // 6 Depends on bRequest
|
unsigned int wLength; // 6 Depends on bRequest
|
||||||
} SETUP_PKT, *PSETUP_PKT;
|
} SETUP_PKT, *PSETUP_PKT;
|
||||||
|
|
||||||
/* Endpoint information structure */
|
|
||||||
/* bToggle of endpoint 0 initialized to 0xff */
|
|
||||||
/* during enumeration bToggle is set to 00 */
|
|
||||||
typedef struct {
|
|
||||||
uint8_t epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )
|
|
||||||
uint8_t Attr; // Endpoint transfer type.
|
|
||||||
unsigned int MaxPktSize; // Maximum packet size.
|
|
||||||
uint8_t Interval; // Polling interval in frames.
|
|
||||||
uint8_t sndToggle; //last toggle value, bitmask for HCTL toggle bits
|
|
||||||
uint8_t rcvToggle; //last toggle value, bitmask for HCTL toggle bits
|
|
||||||
/* not sure if both are necessary */
|
|
||||||
} EP_RECORD;
|
|
||||||
/* device record structure */
|
/* device record structure */
|
||||||
typedef struct {
|
typedef struct
|
||||||
EP_RECORD* epinfo; //device endpoint information
|
{
|
||||||
uint8_t devclass; //device class
|
EP_RECORD *epinfo; //device endpoint information
|
||||||
|
uint8_t devclass; //device class
|
||||||
} DEV_RECORD;
|
} DEV_RECORD;
|
||||||
|
|
||||||
|
|
||||||
typedef MAX3421e<P10, P9> MAX3421E;
|
struct HubDescriptor
|
||||||
|
{
|
||||||
|
uint8_t bDescLength; // descriptor length
|
||||||
|
uint8_t bDescriptorType; // descriptor type
|
||||||
|
uint8_t bNbrPorts; // number of ports a hub equiped with
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t LogPwrSwitchMode : 2;
|
||||||
|
uint16_t CompoundDevice : 1;
|
||||||
|
uint16_t OverCurrentProtectMode : 2;
|
||||||
|
uint16_t TTThinkTime : 2;
|
||||||
|
uint16_t PortIndicatorsSupported : 1;
|
||||||
|
uint16_t Reserved : 8;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t bPwrOn2PwrGood;
|
||||||
|
uint8_t bHubContrCurrent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//typedef MAX3421e<P6, P3> MAX3421E; // Black Widdow
|
||||||
|
typedef MAX3421e<P10, P9> MAX3421E; // Duemielanove
|
||||||
|
|
||||||
class USB : public MAX3421E
|
class USB : public MAX3421E
|
||||||
{
|
{
|
||||||
|
@ -101,14 +242,39 @@ class USB : public MAX3421E
|
||||||
|
|
||||||
//byte usb_task_state;
|
//byte usb_task_state;
|
||||||
|
|
||||||
|
|
||||||
|
AddressPoolImpl<USB_NUMDEVICES> addrPool;
|
||||||
|
USBDeviceConfig* devConfig[USB_NUMDEVICES];
|
||||||
|
uint8_t devConfigIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
USB( void );
|
USB( void );
|
||||||
uint8_t getUsbTaskState( void );
|
|
||||||
|
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
|
||||||
|
{
|
||||||
|
for (uint8_t i=0; i<USB_NUMDEVICES; i++)
|
||||||
|
{
|
||||||
|
if (!devConfig[i])
|
||||||
|
{
|
||||||
|
devConfig[i] = pdev;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
|
||||||
|
};
|
||||||
|
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
|
||||||
|
{
|
||||||
|
addrPool.ForEachUsbDevice(pfunc);
|
||||||
|
};
|
||||||
|
uint8_t getUsbTaskState( void );
|
||||||
void setUsbTaskState( uint8_t state );
|
void setUsbTaskState( uint8_t state );
|
||||||
|
|
||||||
EP_RECORD* getDevTableEntry( uint8_t addr, uint8_t ep );
|
EP_RECORD* getDevTableEntry( uint8_t addr, uint8_t ep );
|
||||||
void setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr );
|
uint8_t setDevTableEntry( uint8_t addr, EP_RECORD* 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, unsigned int nak_limit = USB_NAK_LIMIT );
|
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, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
/* Control requests */
|
|
||||||
|
/* Control requests */
|
||||||
uint8_t getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t getStrDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t index, unsigned int langid, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t getStrDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t index, unsigned int langid, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
@ -119,7 +285,7 @@ class USB : public MAX3421E
|
||||||
uint8_t getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t setReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t setReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t getReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t getReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
/**/
|
/**/
|
||||||
|
@ -128,19 +294,46 @@ class USB : public MAX3421E
|
||||||
uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
uint8_t dispatchPkt( uint8_t token, uint8_t ep, unsigned int nak_limit = USB_NAK_LIMIT );
|
uint8_t dispatchPkt( uint8_t token, uint8_t ep, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
|
||||||
|
// Hub Methods
|
||||||
|
uint8_t ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
uint8_t ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
uint8_t GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
uint8_t GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
uint8_t GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
uint8_t SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
uint8_t SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
uint8_t SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
|
||||||
|
uint8_t HubPortPowerOn(uint8_t addr, uint8_t port);
|
||||||
|
uint8_t HubPortReset(uint8_t addr, uint8_t port);
|
||||||
|
uint8_t HubClearPortFeatures(uint8_t addr, uint8_t port, uint8_t bm_features);
|
||||||
|
|
||||||
|
uint8_t GetNumDevices();
|
||||||
|
uint8_t GetNumHubs();
|
||||||
|
|
||||||
|
uint8_t PollHubs();
|
||||||
|
uint8_t PollHub();
|
||||||
|
|
||||||
|
void PrintHubStatus(/*USB *usbptr,*/ uint8_t addr);
|
||||||
|
|
||||||
void Task( void );
|
void Task( void );
|
||||||
//uint8_t nit() {};
|
|
||||||
|
uint8_t Addressing(uint8_t *address);
|
||||||
|
uint8_t Configuring(uint8_t addr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//get device descriptor
|
//get device descriptor
|
||||||
inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit ) {
|
inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit ) {
|
||||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit ));
|
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit ));
|
||||||
}
|
}
|
||||||
//get configuration descriptor
|
//get configuration descriptor
|
||||||
inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit ) {
|
inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit ) {
|
||||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nuint8_ts, dataptr, nak_limit ));
|
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit ));
|
||||||
}
|
}
|
||||||
//get string descriptor
|
//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, unsigned int nak_limit ) {
|
inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t index, unsigned int langid, uint8_t* dataptr, unsigned int nak_limit ) {
|
||||||
|
@ -178,4 +371,58 @@ inline uint8_t USB::getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_
|
||||||
inline uint8_t USB::setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, unsigned int nak_limit ) {
|
inline uint8_t USB::setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, unsigned int nak_limit ) {
|
||||||
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit ));
|
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
//unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
|
||||||
|
// Clear Hub Feature
|
||||||
|
inline uint8_t USB::ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL, nak_limit ));
|
||||||
|
}
|
||||||
|
// Clear Port Feature
|
||||||
|
inline uint8_t USB::ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL, nak_limit ));
|
||||||
|
}
|
||||||
|
// Get Hub Descriptor
|
||||||
|
inline uint8_t USB::GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, dataptr, nak_limit ));
|
||||||
|
}
|
||||||
|
// Get Hub Status
|
||||||
|
inline uint8_t USB::GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, dataptr, nak_limit ));
|
||||||
|
}
|
||||||
|
// Get Port Status
|
||||||
|
inline uint8_t USB::GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
//Serial.println(bmREQ_GET_PORT_STATUS, BIN);
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr, nak_limit ));
|
||||||
|
}
|
||||||
|
// Set Hub Descriptor
|
||||||
|
inline uint8_t USB::SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, dataptr, nak_limit ));
|
||||||
|
}
|
||||||
|
// Set Hub Feature
|
||||||
|
inline uint8_t USB::SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, NULL, nak_limit ));
|
||||||
|
}
|
||||||
|
// Set Port Feature
|
||||||
|
inline uint8_t USB::SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel, unsigned int nak_limit )
|
||||||
|
{
|
||||||
|
return( ctrlReq( addr, ep, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL, nak_limit ));
|
||||||
|
}
|
||||||
#endif //_usb_h_
|
#endif //_usb_h_
|
237
address.h
Normal file
237
address.h
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
#if !defined(__ADDRESS_H__)
|
||||||
|
#define __ADDRESS_H__
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "max3421e.h"
|
||||||
|
|
||||||
|
/* Endpoint information structure */
|
||||||
|
/* bToggle of endpoint 0 initialized to 0xff */
|
||||||
|
/* during enumeration bToggle is set to 00 */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )
|
||||||
|
uint8_t Attr; // Endpoint transfer type.
|
||||||
|
unsigned int MaxPktSize; // Maximum packet size.
|
||||||
|
uint8_t Interval; // Polling interval in frames.
|
||||||
|
uint8_t sndToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||||
|
uint8_t rcvToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||||
|
/* not sure if both are necessary */
|
||||||
|
} EP_RECORD;
|
||||||
|
|
||||||
|
// 7 6 5 4 3 2 1 0
|
||||||
|
// ---------------------------------
|
||||||
|
// | | H | P | P | P | A | A | A |
|
||||||
|
// ---------------------------------
|
||||||
|
//
|
||||||
|
// H - if 1 the address is a hub address
|
||||||
|
// P - parent hub address
|
||||||
|
// A - device address / port number in case of hub
|
||||||
|
//
|
||||||
|
struct UsbDeviceAddress
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t bmAddress : 3; // device address/port number
|
||||||
|
uint8_t bmParent : 3; // parent hub address
|
||||||
|
uint8_t bmHub : 1; // hub flag
|
||||||
|
uint8_t bmReserved : 1; // reserved, must be zerro
|
||||||
|
};
|
||||||
|
uint8_t devAddress;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define bmUSB_DEV_ADDR_ADDRESS 0x07
|
||||||
|
#define bmUSB_DEV_ADDR_PARENT 0x38
|
||||||
|
#define bmUSB_DEV_ADDR_HUB 0x40
|
||||||
|
|
||||||
|
struct UsbDevice
|
||||||
|
{
|
||||||
|
EP_RECORD *epinfo; // endpoint info pointer
|
||||||
|
uint8_t address; // address
|
||||||
|
uint8_t devclass; // device class
|
||||||
|
};
|
||||||
|
|
||||||
|
class AddressPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual uint8_t AllocAddress(UsbDeviceAddress parent, bool is_hub = false, uint8_t port = 0) = 0;
|
||||||
|
virtual void FreeAddress(UsbDeviceAddress addr) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
|
||||||
|
|
||||||
|
#define ADDR_ERROR_INVALID_INDEX 0xFF
|
||||||
|
#define ADDR_ERROR_INVALID_ADDRESS 0xFF
|
||||||
|
|
||||||
|
template <const uint8_t MAX_DEVICES_ALLOWED>
|
||||||
|
class AddressPoolImpl
|
||||||
|
{
|
||||||
|
EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
||||||
|
|
||||||
|
uint8_t hubCounter; // hub counter is kept
|
||||||
|
// in order to avoid hub address duplication
|
||||||
|
|
||||||
|
UsbDevice thePool[MAX_DEVICES_ALLOWED];
|
||||||
|
|
||||||
|
// Initializes address pool entry
|
||||||
|
void InitEntry(uint8_t index)
|
||||||
|
{
|
||||||
|
thePool[index].address = 0;
|
||||||
|
thePool[index].devclass = 0;
|
||||||
|
thePool[index].epinfo = &dev0ep;
|
||||||
|
};
|
||||||
|
// Returns thePool index for a given address
|
||||||
|
uint8_t FindAddressIndex(uint8_t address = 0)
|
||||||
|
{
|
||||||
|
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||||
|
{
|
||||||
|
if (thePool[i].address == address)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
// Returns thePool child index for a given parent
|
||||||
|
uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1)
|
||||||
|
{
|
||||||
|
for (uint8_t i=(start<1 || start>=MAX_DEVICES_ALLOWED) ? 1 : start; i<MAX_DEVICES_ALLOWED; i++)
|
||||||
|
{
|
||||||
|
if (((UsbDeviceAddress*)&thePool[i].address)->bmParent == addr.bmAddress)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
// Frees address entry specified by index parameter
|
||||||
|
void FreeAddressByIndex(uint8_t index)
|
||||||
|
{
|
||||||
|
// Zerro field is reserved and should not be affected
|
||||||
|
if (index == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If a hub was switched off all port addresses should be freed
|
||||||
|
if (((UsbDeviceAddress*)&thePool[index].address)->bmHub == 1)
|
||||||
|
{
|
||||||
|
for (uint8_t i=1; i = FindChildIndex(*((UsbDeviceAddress*)&thePool[index].address), i); )
|
||||||
|
FreeAddressByIndex(i);
|
||||||
|
|
||||||
|
// If the hub had the last allocated address, hubCounter should be decremented
|
||||||
|
if (hubCounter == ((UsbDeviceAddress*)&thePool[index].address)->bmAddress)
|
||||||
|
hubCounter --;
|
||||||
|
}
|
||||||
|
InitEntry(index);
|
||||||
|
}
|
||||||
|
// Initializes the whole address pool at once
|
||||||
|
void InitAllAddresses()
|
||||||
|
{
|
||||||
|
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||||
|
InitEntry(i);
|
||||||
|
|
||||||
|
hubCounter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
AddressPoolImpl() : hubCounter(0)
|
||||||
|
{
|
||||||
|
// Zerro address is reserved
|
||||||
|
InitEntry(0);
|
||||||
|
|
||||||
|
thePool[0].address = 0;
|
||||||
|
thePool[0].epinfo = &dev0ep;
|
||||||
|
dev0ep.epAddr = 0;
|
||||||
|
dev0ep.MaxPktSize = 8;
|
||||||
|
dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||||
|
dev0ep.rcvToggle = bmRCVTOG0;
|
||||||
|
|
||||||
|
InitAllAddresses();
|
||||||
|
};
|
||||||
|
// Returns a pointer to a specified address entry
|
||||||
|
UsbDevice* GetUsbDevicePtr(uint8_t addr)
|
||||||
|
{
|
||||||
|
if (!addr)
|
||||||
|
return thePool;
|
||||||
|
|
||||||
|
uint8_t index = FindAddressIndex(addr);
|
||||||
|
|
||||||
|
return (!index) ? NULL : thePool + index;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Performs an operation specified by pfunc for each addressed device
|
||||||
|
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
|
||||||
|
{
|
||||||
|
if (!pfunc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||||
|
if (thePool[i].address)
|
||||||
|
pfunc(thePool + i);
|
||||||
|
};
|
||||||
|
// Allocates new address
|
||||||
|
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0)
|
||||||
|
{
|
||||||
|
if (parent > 127 || port > 7)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// finds first empty address entry starting from one
|
||||||
|
uint8_t index = FindAddressIndex(0);
|
||||||
|
|
||||||
|
Serial.println(index, DEC);
|
||||||
|
|
||||||
|
if (!index) // if empty entry is not found
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (parent == 0)
|
||||||
|
{
|
||||||
|
thePool[index].address = (is_hub) ? 0x41 : 1;
|
||||||
|
return thePool[index].address;
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbDeviceAddress addr;
|
||||||
|
|
||||||
|
addr.bmParent = ((UsbDeviceAddress*)&parent)->bmAddress;
|
||||||
|
|
||||||
|
if (is_hub)
|
||||||
|
{
|
||||||
|
addr.bmHub = 1;
|
||||||
|
addr.bmAddress = ++hubCounter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr.bmHub = 0;
|
||||||
|
addr.bmAddress = port;
|
||||||
|
}
|
||||||
|
thePool[index].address = *((uint8_t*)&addr);
|
||||||
|
|
||||||
|
return thePool[index].address;
|
||||||
|
};
|
||||||
|
// Empties pool entry
|
||||||
|
virtual void FreeAddress(uint8_t addr)
|
||||||
|
{
|
||||||
|
// if the root hub is disconnected all the addresses should be initialized
|
||||||
|
if (addr == 0x41)
|
||||||
|
{
|
||||||
|
InitAllAddresses();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t index = FindAddressIndex(addr);
|
||||||
|
FreeAddressByIndex(index);
|
||||||
|
};
|
||||||
|
// Returns number of hubs attached
|
||||||
|
// It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
|
||||||
|
uint8_t GetNumHubs()
|
||||||
|
{
|
||||||
|
return hubCounter;
|
||||||
|
};
|
||||||
|
uint8_t GetNumDevices()
|
||||||
|
{
|
||||||
|
uint8_t counter = 0;
|
||||||
|
|
||||||
|
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
|
||||||
|
if (thePool[i].address != 0);
|
||||||
|
counter ++;
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __ADDRESS_H__
|
92
avrpins.h
92
avrpins.h
|
@ -106,6 +106,27 @@ MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D')
|
||||||
#ifdef USE_PORTE
|
#ifdef USE_PORTE
|
||||||
MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E')
|
MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E')
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_PORTF
|
||||||
|
MAKE_PORT(PORTF, DDRF, PINF, Portf, 'F')
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PORTG
|
||||||
|
MAKE_PORT(PORTG, DDRG, PING, Portg, 'G')
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PORTH
|
||||||
|
MAKE_PORT(PORTH, DDRH, PINH, Porth, 'H')
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PORTJ
|
||||||
|
MAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J')
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PORTK
|
||||||
|
MAKE_PORT(PORTK, DDRK, PINK, Portk, 'K')
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PORTQ
|
||||||
|
MAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q')
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PORTR
|
||||||
|
MAKE_PORT(PORTR, DDRR, PINR, Portr, 'R')
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TCCR0A
|
#ifdef USE_TCCR0A
|
||||||
MAKE_TCCR(TCCR0A, Tccr0a)
|
MAKE_TCCR(TCCR0A, Tccr0a)
|
||||||
|
@ -348,7 +369,74 @@ template<typename Tp_pin, typename Tc_bit>
|
||||||
//typedef Tp_Tc<Pb2, Tc1b> P10; //Arduino pin 10
|
//typedef Tp_Tc<Pb2, Tc1b> P10; //Arduino pin 10
|
||||||
//typedef Tp_Tc<Pb3, Tc2a> P11; //Arduino pin 11
|
//typedef Tp_Tc<Pb3, Tc2a> P11; //Arduino pin 11
|
||||||
|
|
||||||
//Arduino pin numbers
|
/* Arduino pin definitions */
|
||||||
|
#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__)
|
||||||
|
|
||||||
|
// "Mega" Arduino pin numbers
|
||||||
|
|
||||||
|
#define P0 Pe0
|
||||||
|
#define P1 Pe1
|
||||||
|
#define P2 Pe4
|
||||||
|
#define P3 Pe5
|
||||||
|
#define P4 Pg5
|
||||||
|
#define P5 Pe5
|
||||||
|
#define P6 Ph3
|
||||||
|
#define P7 Ph4
|
||||||
|
|
||||||
|
#define P8 Ph5
|
||||||
|
#define P9 Ph6
|
||||||
|
#define P10 Pb4
|
||||||
|
#define P11 Pb5
|
||||||
|
#define P12 Pb6
|
||||||
|
#define P13 Pb7
|
||||||
|
|
||||||
|
#define P14 Pj1
|
||||||
|
#define P15 Pj0
|
||||||
|
#define P16 Ph1
|
||||||
|
#define P17 Ph0
|
||||||
|
#define P18 Pd3
|
||||||
|
#define P19 Pd2
|
||||||
|
#define P20 Pd1
|
||||||
|
#define P21 Pd0
|
||||||
|
|
||||||
|
#define P22 Pa0
|
||||||
|
#define P23 Pa1
|
||||||
|
#define P24 Pa2
|
||||||
|
#define P25 Pa3
|
||||||
|
#define P26 Pa4
|
||||||
|
#define P27 Pa5
|
||||||
|
#define P28 Pa6
|
||||||
|
#define P29 Pa7
|
||||||
|
#define P30 Pc7
|
||||||
|
#define P31 Pc6
|
||||||
|
#define P32 Pc5
|
||||||
|
#define P33 Pc4
|
||||||
|
#define P34 Pc3
|
||||||
|
#define P35 Pc2
|
||||||
|
#define P36 Pc1
|
||||||
|
#define P37 Pc0
|
||||||
|
|
||||||
|
#define P38 Pd7
|
||||||
|
#define P39 Pg2
|
||||||
|
#define P40 Pg1
|
||||||
|
#define P41 Pg0
|
||||||
|
#define P42 Pl7
|
||||||
|
#define P43 Pl6
|
||||||
|
#define P44 Pl5
|
||||||
|
#define P45 Pl4
|
||||||
|
#define P46 Pl3
|
||||||
|
#define P47 Pl2
|
||||||
|
#define P48 Pl1
|
||||||
|
#define P49 Pl0
|
||||||
|
#define P50 Pb3
|
||||||
|
#define P51 Pb2
|
||||||
|
#define P52 Pb1
|
||||||
|
#define P53 Pb0
|
||||||
|
|
||||||
|
#endif //"Mega" pin definitions
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
|
||||||
|
//"Classical" Arduino pin numbers
|
||||||
|
|
||||||
#define P0 Pd0
|
#define P0 Pd0
|
||||||
#define P1 Pd1
|
#define P1 Pd1
|
||||||
|
@ -373,4 +461,6 @@ template<typename Tp_pin, typename Tc_bit>
|
||||||
#define P18 Pc4
|
#define P18 Pc4
|
||||||
#define P19 Pc5
|
#define P19 Pc5
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif //_avrpins_h_
|
#endif //_avrpins_h_
|
||||||
|
|
12
max3421e.h
12
max3421e.h
|
@ -9,7 +9,9 @@
|
||||||
/* pin numbers to port numbers */
|
/* pin numbers to port numbers */
|
||||||
|
|
||||||
//#define MAX_SS 10
|
//#define MAX_SS 10
|
||||||
#define MAX_INT 9
|
//#define MAX_INT 3 // Black Widdow
|
||||||
|
#define MAX_INT 9 // Duemielanove
|
||||||
|
|
||||||
#define MAX_GPX 8
|
#define MAX_GPX 8
|
||||||
//#define MAX_RESET 7
|
//#define MAX_RESET 7
|
||||||
//
|
//
|
||||||
|
@ -144,7 +146,8 @@
|
||||||
#define bmFRAMEIRQ 0x40
|
#define bmFRAMEIRQ 0x40
|
||||||
#define bmHXFRDNIRQ 0x80
|
#define bmHXFRDNIRQ 0x80
|
||||||
|
|
||||||
#define rHIEN 0xd0 //26<<3
|
#define rHIEN 0xd0 //26<<3
|
||||||
|
|
||||||
/* HIEN Bits */
|
/* HIEN Bits */
|
||||||
#define bmBUSEVENTIE 0x01
|
#define bmBUSEVENTIE 0x01
|
||||||
#define bmRWUIE 0x02
|
#define bmRWUIE 0x02
|
||||||
|
@ -155,7 +158,8 @@
|
||||||
#define bmFRAMEIE 0x40
|
#define bmFRAMEIE 0x40
|
||||||
#define bmHXFRDNIE 0x80
|
#define bmHXFRDNIE 0x80
|
||||||
|
|
||||||
#define rMODE 0xd8 //27<<3
|
#define rMODE 0xd8 //27<<3
|
||||||
|
|
||||||
/* MODE Bits */
|
/* MODE Bits */
|
||||||
#define bmHOST 0x01
|
#define bmHOST 0x01
|
||||||
#define bmLOWSPEED 0x02
|
#define bmLOWSPEED 0x02
|
||||||
|
@ -191,6 +195,7 @@
|
||||||
#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0
|
#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0
|
||||||
|
|
||||||
#define rHRSL 0xf8 //31<<3
|
#define rHRSL 0xf8 //31<<3
|
||||||
|
|
||||||
/* HRSL Bits */
|
/* HRSL Bits */
|
||||||
#define bmRCVTOGRD 0x10
|
#define bmRCVTOGRD 0x10
|
||||||
#define bmSNDTOGRD 0x20
|
#define bmSNDTOGRD 0x20
|
||||||
|
@ -198,6 +203,7 @@
|
||||||
#define bmJSTATUS 0x80
|
#define bmJSTATUS 0x80
|
||||||
#define bmSE0 0x00 //SE0 - disconnect state
|
#define bmSE0 0x00 //SE0 - disconnect state
|
||||||
#define bmSE1 0xc0 //SE1 - illegal state
|
#define bmSE1 0xc0 //SE1 - illegal state
|
||||||
|
|
||||||
/* Host error result codes, the 4 LSB's in the HRSL register */
|
/* Host error result codes, the 4 LSB's in the HRSL register */
|
||||||
#define hrSUCCESS 0x00
|
#define hrSUCCESS 0x00
|
||||||
#define hrBUSY 0x01
|
#define hrBUSY 0x01
|
||||||
|
|
59
newusb.pde
Normal file
59
newusb.pde
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* new USB library tests */
|
||||||
|
|
||||||
|
//nclude <digitalWriteFast.h>
|
||||||
|
#include "usbhost.h"
|
||||||
|
|
||||||
|
MAX3421e<P10, P9> Max;
|
||||||
|
uint8_t buf[10] = {0};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// Max.regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL ));
|
||||||
|
// Max.regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator
|
||||||
|
// Max.regWr( rUSBCTL, 0x00 ); //Remove the reset
|
||||||
|
// delay( 100 );
|
||||||
|
Serial.begin( 115200 );
|
||||||
|
Serial.println("Start");
|
||||||
|
|
||||||
|
// pinModeFast2( 8, OUTPUT)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// uint16_t i;
|
||||||
|
// Max.regWr( rUSBCTL, bmCHIPRES );
|
||||||
|
// Max.regWr( rUSBCTL, 0x00 );
|
||||||
|
// for( i = 0; i < 65535; i++ ) {
|
||||||
|
// if( ( Max.regRd( rUSBIRQ ) & bmOSCOKIRQ )) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
Serial.println( Max.reset(), DEC );
|
||||||
|
//Max.reset();
|
||||||
|
//delay( 100 );
|
||||||
|
//Max.regRd( rREVISION );
|
||||||
|
//Serial.println( Max.regRd( rREVISION ), HEX );
|
||||||
|
|
||||||
|
//Serial.println("tick");
|
||||||
|
// uint8_t tmp;
|
||||||
|
// for( uint16_t i = 0; i < 256; i++ ) {
|
||||||
|
// tmp = Max.SPIxfer( i );
|
||||||
|
// if( tmp != i ) {
|
||||||
|
// Serial.println("error");
|
||||||
|
// }
|
||||||
|
// if( SPSR & 0x40 ) {
|
||||||
|
// Serial.println("WCOL");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// static bool oldintval = 0;
|
||||||
|
// if( Max.intval() != oldintval ) {
|
||||||
|
// oldintval = Max.intval();
|
||||||
|
// Serial.println( oldintval, DEC );
|
||||||
|
// }
|
||||||
|
// Max.sstoggle();
|
||||||
|
|
||||||
|
//digitalWriteFast2( 8, 0 );
|
||||||
|
//digitalWriteFast2( 8, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
22
usbhost.h
22
usbhost.h
|
@ -193,12 +193,12 @@ int8_t MAX3421e< SS, INTR >::Init()
|
||||||
regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host
|
regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host
|
||||||
|
|
||||||
regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection
|
regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection
|
||||||
|
|
||||||
/* check if device is connected */
|
/* check if device is connected */
|
||||||
regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus
|
regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus
|
||||||
while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish
|
while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish
|
||||||
busprobe(); //check if anything is connected
|
|
||||||
|
|
||||||
// Serial.println(getVbusState(), HEX);
|
busprobe(); //check if anything is connected
|
||||||
|
|
||||||
regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt
|
regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt
|
||||||
regWr( rCPUCTL, 0x01 ); //enable interrupt pin
|
regWr( rCPUCTL, 0x01 ); //enable interrupt pin
|
||||||
|
@ -210,33 +210,33 @@ template< typename SS, typename INTR >
|
||||||
void MAX3421e< SS, INTR >::busprobe()
|
void MAX3421e< SS, INTR >::busprobe()
|
||||||
{
|
{
|
||||||
byte bus_sample;
|
byte bus_sample;
|
||||||
bus_sample = regRd( rHRSL ); //Get J,K status
|
bus_sample = regRd( rHRSL ); //Get J,K status
|
||||||
bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte
|
bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte
|
||||||
switch( bus_sample ) { //start full-speed or low-speed host
|
switch( bus_sample ) { //start full-speed or low-speed host
|
||||||
case( bmJSTATUS ):
|
case( bmJSTATUS ):
|
||||||
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
|
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
|
||||||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
||||||
vbusState = FSHOST;
|
vbusState = FSHOST;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
regWr( rMODE, MODE_LS_HOST); //start low-speed host
|
regWr( rMODE, MODE_LS_HOST); //start low-speed host
|
||||||
vbusState = LSHOST;
|
vbusState = LSHOST;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case( bmKSTATUS ):
|
case( bmKSTATUS ):
|
||||||
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
|
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
|
||||||
regWr( rMODE, MODE_LS_HOST ); //start low-speed host
|
regWr( rMODE, MODE_LS_HOST ); //start low-speed host
|
||||||
vbusState = LSHOST;
|
vbusState = LSHOST;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
regWr( rMODE, MODE_FS_HOST ); //start full-speed host
|
||||||
vbusState = FSHOST;
|
vbusState = FSHOST;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case( bmSE1 ): //illegal state
|
case( bmSE1 ): //illegal state
|
||||||
vbusState = SE1;
|
vbusState = SE1;
|
||||||
break;
|
break;
|
||||||
case( bmSE0 ): //disconnected state
|
case( bmSE0 ): //disconnected state
|
||||||
vbusState = SE0;
|
vbusState = SE0;
|
||||||
break;
|
break;
|
||||||
}//end switch( bus_sample )
|
}//end switch( bus_sample )
|
||||||
|
|
520
usbhub.cpp
Normal file
520
usbhub.cpp
Normal file
|
@ -0,0 +1,520 @@
|
||||||
|
#include "usbhub.h"
|
||||||
|
|
||||||
|
USBHub::USBHub(USB *p) :
|
||||||
|
pUsb(p),
|
||||||
|
bAddress(0),
|
||||||
|
bNbrPorts(0),
|
||||||
|
bInitState(0),
|
||||||
|
bPortResetCounter(1),
|
||||||
|
qNextPollTime(0),
|
||||||
|
bPollEnable(false)
|
||||||
|
{
|
||||||
|
epInfo[0].epAddr = 0;
|
||||||
|
epInfo[0].MaxPktSize = 8;
|
||||||
|
epInfo[0].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||||
|
epInfo[0].rcvToggle = bmRCVTOG0;
|
||||||
|
|
||||||
|
epInfo[1].epAddr = 1;
|
||||||
|
epInfo[1].MaxPktSize = 1;
|
||||||
|
epInfo[1].Interval = 0xff;
|
||||||
|
epInfo[1].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
|
||||||
|
epInfo[1].rcvToggle = bmRCVTOG0;
|
||||||
|
|
||||||
|
if (pUsb)
|
||||||
|
pUsb->RegisterDeviceClass(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USBHub::Init(uint8_t addr)
|
||||||
|
{
|
||||||
|
uint8_t buf[8];
|
||||||
|
uint8_t rcode;
|
||||||
|
|
||||||
|
switch (bInitState)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Serial.println("Init");
|
||||||
|
|
||||||
|
bAddress = addr;
|
||||||
|
|
||||||
|
rcode = pUsb->getDevDescr( addr, 0, 8, (uint8_t*)buf );
|
||||||
|
|
||||||
|
if(rcode)
|
||||||
|
goto FailGetDevDescr;
|
||||||
|
|
||||||
|
// Return if the device is not a hub
|
||||||
|
if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass != 0x09)
|
||||||
|
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
rcode = pUsb->setDevTableEntry(addr, epInfo);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailSetDevTblEntry;
|
||||||
|
|
||||||
|
bInitState = 1;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// Get hub descriptor
|
||||||
|
rcode = pUsb->GetHubDescriptor(addr, 0, 0, 8, buf);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetHubDescr;
|
||||||
|
|
||||||
|
// Save number of ports for future use
|
||||||
|
bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts;
|
||||||
|
|
||||||
|
bInitState = 2;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// Read configuration Descriptor in Order To Obtain Proper Configuration Value
|
||||||
|
rcode = pUsb->getConfDescr(addr, 0, 8, 0, buf);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailGetConfDescr;
|
||||||
|
|
||||||
|
Serial.print("Conf val:");
|
||||||
|
Serial.println(buf[5], HEX);
|
||||||
|
|
||||||
|
// Set Configuration Value
|
||||||
|
rcode = pUsb->setConf(addr, 0, buf[5]);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
goto FailSetConfDescr;
|
||||||
|
|
||||||
|
Serial.println("Hub configured");
|
||||||
|
|
||||||
|
bInitState = 3;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
// Power on all ports
|
||||||
|
for (uint8_t j=1; j<=bNbrPorts; j++)
|
||||||
|
pUsb->HubPortPowerOn(addr, j);
|
||||||
|
|
||||||
|
Serial.println("Ports powered");
|
||||||
|
|
||||||
|
bPollEnable = true;
|
||||||
|
bInitState = 0;
|
||||||
|
// bInitState = 4;
|
||||||
|
|
||||||
|
//case 4:
|
||||||
|
// Serial.print("RC:");
|
||||||
|
// Serial.println(bPortResetCounter, DEC);
|
||||||
|
|
||||||
|
// for (; bPortResetCounter<=bNbrPorts; bPortResetCounter++)
|
||||||
|
// {
|
||||||
|
// HubEvent evt;
|
||||||
|
// rcode = pUsb->GetPortStatus(addr, 0, bPortResetCounter, 4, evt.evtBuff);
|
||||||
|
|
||||||
|
// if (rcode)
|
||||||
|
// goto FailGetPortStatus;
|
||||||
|
|
||||||
|
// Serial.print("RC:");
|
||||||
|
// Serial.println(bPortResetCounter, DEC);
|
||||||
|
// Serial.print("\tSt:");
|
||||||
|
// Serial.print(evt.bmStatus, BIN);
|
||||||
|
// Serial.print("\tCh:");
|
||||||
|
// Serial.println(evt.bmChange, BIN);
|
||||||
|
|
||||||
|
// // Initiate reset only if there is a device plugged into the port
|
||||||
|
// if (evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||||
|
// {
|
||||||
|
// Serial.print("Con:");
|
||||||
|
// Serial.println(bPortResetCounter, DEC);
|
||||||
|
|
||||||
|
// pUsb->HubPortReset(addr, bPortResetCounter);
|
||||||
|
// bPollEnable = true;
|
||||||
|
//
|
||||||
|
// if (bPortResetCounter < bNbrPorts)
|
||||||
|
// bPortResetCounter ++;
|
||||||
|
|
||||||
|
// return USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE;
|
||||||
|
// }
|
||||||
|
// } // for
|
||||||
|
// bPortResetCounter = 1;
|
||||||
|
}
|
||||||
|
bInitState = 0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
FailGetDevDescr:
|
||||||
|
Serial.print("getDevDescr:");
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
FailSetDevTblEntry:
|
||||||
|
Serial.print("setDevTblEn:");
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
FailGetHubDescr:
|
||||||
|
Serial.print("getHub:");
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
FailGetConfDescr:
|
||||||
|
Serial.print("getConf:");
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
FailSetConfDescr:
|
||||||
|
Serial.print("setConf:");
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
FailGetPortStatus:
|
||||||
|
Serial.print("GetPortStatus:");
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
Fail:
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USBHub::Release(uint8_t addr)
|
||||||
|
{
|
||||||
|
bAddress = 0;
|
||||||
|
bNbrPorts = 0;
|
||||||
|
bPortResetCounter = 0;
|
||||||
|
qNextPollTime = 0;
|
||||||
|
bPollEnable = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t USBHub::Poll()
|
||||||
|
{
|
||||||
|
uint8_t rcode = 0;
|
||||||
|
|
||||||
|
if (!bPollEnable)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (qNextPollTime <= millis())
|
||||||
|
{
|
||||||
|
Serial.println("Poll");
|
||||||
|
|
||||||
|
rcode = GetHubStatus(bAddress);
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("HubStatus:");
|
||||||
|
Serial.println(rcode,HEX);
|
||||||
|
}
|
||||||
|
qNextPollTime = millis() + 10;
|
||||||
|
}
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//bmHUB_PORT_STATUS_C_PORT_CONNECTION
|
||||||
|
//bmHUB_PORT_STATUS_C_PORT_ENABLE
|
||||||
|
//bmHUB_PORT_STATUS_C_PORT_SUSPEND
|
||||||
|
//bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT
|
||||||
|
//bmHUB_PORT_STATUS_C_PORT_RESET
|
||||||
|
|
||||||
|
uint8_t USBHub::GetHubStatus(uint8_t addr)
|
||||||
|
{
|
||||||
|
uint8_t rcode;
|
||||||
|
uint8_t buf[8];
|
||||||
|
|
||||||
|
// uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||||
|
//Serial.println(devtable[1].epinfo->epAddr, HEX);
|
||||||
|
|
||||||
|
rcode = pUsb->inTransfer(addr, 1, 1, buf, 1);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("inTransfer:");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
return rcode;
|
||||||
|
}
|
||||||
|
Serial.print("Int:");
|
||||||
|
Serial.println(buf[0],HEX);
|
||||||
|
|
||||||
|
//return 0;
|
||||||
|
|
||||||
|
if (buf[0] & 0x01) // Hub Status Change
|
||||||
|
{
|
||||||
|
pUsb->PrintHubStatus(addr);
|
||||||
|
//rcode = GetHubStatus(1, 0, 1, 4, buf);
|
||||||
|
//if (rcode)
|
||||||
|
//{
|
||||||
|
// Serial.print("GetHubStatus Error");
|
||||||
|
// Serial.println(rcode, HEX);
|
||||||
|
// return rcode;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
for (uint8_t port=1,mask=0x02; port<8; mask<<=1, port++)
|
||||||
|
{
|
||||||
|
if (buf[0] & mask)
|
||||||
|
{
|
||||||
|
HubEvent evt;
|
||||||
|
evt.bmEvent = 0;
|
||||||
|
|
||||||
|
rcode = pUsb->GetPortStatus(addr, 0, port, 4, evt.evtBuff);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.print("GetPortStatus err:");
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
Serial.print("on port:");
|
||||||
|
Serial.println(port, DEC);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
HubPortStatusChange(addr, port, evt);
|
||||||
|
}
|
||||||
|
} // for
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USBHub::HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt)
|
||||||
|
{
|
||||||
|
Serial.print("Prt:");
|
||||||
|
Serial.print(port,HEX);
|
||||||
|
|
||||||
|
Serial.print("\tEvt:");
|
||||||
|
Serial.println(evt.bmEvent,HEX);
|
||||||
|
Serial.print("\tSt:");
|
||||||
|
Serial.println(evt.bmStatus,HEX);
|
||||||
|
Serial.print("\tCh:");
|
||||||
|
Serial.println(evt.bmChange,HEX);
|
||||||
|
|
||||||
|
|
||||||
|
//Serial.print("Con:");
|
||||||
|
//Serial.println(bmHUB_PORT_EVENT_CONNECT, HEX);
|
||||||
|
|
||||||
|
Serial.print("Rc:");
|
||||||
|
Serial.println(bmHUB_PORT_EVENT_RESET_COMPLETE, HEX);
|
||||||
|
|
||||||
|
PrintHubPortStatus(pUsb, addr, port);
|
||||||
|
|
||||||
|
switch (evt.bmEvent)
|
||||||
|
{
|
||||||
|
//case (bmHUB_PORT_STATE_DISABLED | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_SUSPEND):
|
||||||
|
// Serial.println("DIS");
|
||||||
|
// pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_PORT_ENABLE | HUB_FEATURE_C_PORT_CONNECTION);
|
||||||
|
// pUsb->HubPortReset(addr, port);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// Device connected event
|
||||||
|
case bmHUB_PORT_EVENT_CONNECT:
|
||||||
|
Serial.println("CON");
|
||||||
|
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_ENABLE);
|
||||||
|
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION);
|
||||||
|
pUsb->HubPortReset(addr, port);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Reset complete event
|
||||||
|
case bmHUB_PORT_EVENT_RESET_COMPLETE:
|
||||||
|
Serial.println("RCMPL");
|
||||||
|
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_RESET | HUB_FEATURE_C_PORT_CONNECTION);
|
||||||
|
|
||||||
|
// Check if device is a low-speed device
|
||||||
|
|
||||||
|
{
|
||||||
|
uint8_t new_addr;
|
||||||
|
|
||||||
|
delay(20);
|
||||||
|
|
||||||
|
// Begin addressing
|
||||||
|
pUsb->Addressing(&new_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//uint8_t new_addr = addrPool.AllocAddress(addr, true, port);
|
||||||
|
//rcode = pUsb->setAddr(0, 0, new_addr);
|
||||||
|
//if (rcode)
|
||||||
|
//{
|
||||||
|
// Serial.print("ERR:");
|
||||||
|
// Serial.println(rcode, HEX);
|
||||||
|
//}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Suspended or resuming state
|
||||||
|
case bmHUB_PORT_STATE_SUSPENDED:
|
||||||
|
Serial.println("SUSP");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Resume complete event
|
||||||
|
case (bmHUB_PORT_STATE_ENABLED | HUB_FEATURE_C_PORT_SUSPEND):
|
||||||
|
break;
|
||||||
|
|
||||||
|
//case bmHUB_PORT_STATE_RESUMING:
|
||||||
|
// break;
|
||||||
|
|
||||||
|
} // switch (evt.bmEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port)
|
||||||
|
{
|
||||||
|
uint8_t rcode = 0;
|
||||||
|
HubEvent evt;
|
||||||
|
|
||||||
|
rcode = usbptr->GetPortStatus(addr, 0, port, 4, evt.evtBuff);
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.println("ERROR!!!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Serial.print("\r\nPort ");
|
||||||
|
Serial.println(port, DEC);
|
||||||
|
|
||||||
|
Serial.println("Status");
|
||||||
|
Serial.print("CONNECTION:\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC);
|
||||||
|
Serial.print("ENABLE:\t\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC);
|
||||||
|
Serial.print("SUSPEND:\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC);
|
||||||
|
Serial.print("OVER_CURRENT:\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC);
|
||||||
|
Serial.print("RESET:\t\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC);
|
||||||
|
Serial.print("POWER:\t\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC);
|
||||||
|
Serial.print("LOW_SPEED:\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC);
|
||||||
|
Serial.print("HIGH_SPEED:\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC);
|
||||||
|
Serial.print("TEST:\t\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC);
|
||||||
|
Serial.print("INDICATOR:\t");
|
||||||
|
Serial.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC);
|
||||||
|
|
||||||
|
Serial.println("\nChange");
|
||||||
|
Serial.print("CONNECTION:\t");
|
||||||
|
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);
|
||||||
|
Serial.print("ENABLE:\t\t");
|
||||||
|
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC);
|
||||||
|
Serial.print("SUSPEND:\t");
|
||||||
|
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC);
|
||||||
|
Serial.print("OVER_CURRENT:\t");
|
||||||
|
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC);
|
||||||
|
Serial.print("RESET:\t\t");
|
||||||
|
Serial.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case USB_STATE_ADDRESSING:
|
||||||
|
Serial.println("ADRESSING");
|
||||||
|
{
|
||||||
|
UsbDevice *p = addrPool.GetUsbDevicePtr(0);
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
uint8_t addr = addrPool.AllocAddress(0, (p->devclass == 0x09) ? true : false);
|
||||||
|
|
||||||
|
if (addr)
|
||||||
|
{
|
||||||
|
Serial.print("Addr:");
|
||||||
|
Serial.println(addr,HEX);
|
||||||
|
|
||||||
|
UsbDevice *p0 = p;
|
||||||
|
|
||||||
|
rcode = setAddr( 0, 0, addr );
|
||||||
|
|
||||||
|
if (rcode)
|
||||||
|
{
|
||||||
|
Serial.println(rcode, HEX);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = addrPool.GetUsbDevicePtr(addr);
|
||||||
|
|
||||||
|
usb_task_state = USB_STATE_CONFIGURING;
|
||||||
|
|
||||||
|
} // if (addr)
|
||||||
|
} // if (p)
|
||||||
|
}
|
||||||
|
// for( i = 1; i < USB_NUMDEVICES; i++ )
|
||||||
|
//{
|
||||||
|
// if ( devtable[ i ].epinfo == NULL )
|
||||||
|
// {
|
||||||
|
// devtable[ i ].epinfo = devtable[ 0 ].epinfo; //set correct MaxPktSize
|
||||||
|
// //temporary record
|
||||||
|
// //until plugged with real device endpoint structure
|
||||||
|
// devtable[ i ].devclass = devtable[ 0 ].devclass;
|
||||||
|
|
||||||
|
// rcode = setAddr( 0, 0, i );
|
||||||
|
|
||||||
|
// if( rcode == 0 )
|
||||||
|
// {
|
||||||
|
// tmpaddr = i;
|
||||||
|
|
||||||
|
// if (devtable[i].devclass == USB_CLASS_HUB)
|
||||||
|
// {
|
||||||
|
// Serial.println("USB_CLASS_HUB");
|
||||||
|
|
||||||
|
// uint8_t buf[8];
|
||||||
|
|
||||||
|
// rcode = GetHubDescriptor(i, 0, 0, 8, buf);
|
||||||
|
|
||||||
|
// if (rcode == 0)
|
||||||
|
// {
|
||||||
|
// // Increment number of hubs found
|
||||||
|
// numHubs ++;
|
||||||
|
|
||||||
|
// // Insert hub address into a first available hub array entry
|
||||||
|
// for (uint8_t j=0; j<HUB_MAX_HUBS; j++)
|
||||||
|
// {
|
||||||
|
// if (hubs[j].bAddress == 0)
|
||||||
|
// {
|
||||||
|
// hubs[j].bAddress = i;
|
||||||
|
// hubs[j].bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// } // for
|
||||||
|
//
|
||||||
|
// } // if (rcode == 0)
|
||||||
|
// }
|
||||||
|
// usb_task_state = USB_STATE_CONFIGURING;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// usb_error = USB_STATE_ADDRESSING; //set address error
|
||||||
|
// usb_task_state = USB_STATE_ERROR;
|
||||||
|
// }
|
||||||
|
// break; //break if address assigned or error occured during address assignment attempt
|
||||||
|
|
||||||
|
// } // if( devtable[ i ].epinfo == NULL )
|
||||||
|
// } //for( i = 1; i < USB_NUMDEVICES; i++)
|
||||||
|
|
||||||
|
if( usb_task_state == USB_STATE_ADDRESSING ) //no vacant place in devtable
|
||||||
|
{
|
||||||
|
usb_error = 0xfe;
|
||||||
|
usb_task_state = USB_STATE_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case USB_STATE_CONFIGURING:
|
||||||
|
Serial.print("CONFIGURING...");
|
||||||
|
|
||||||
|
//// Hub Configuration Code
|
||||||
|
//if (devtable[1].devclass == USB_CLASS_HUB)
|
||||||
|
//{
|
||||||
|
// Serial.println("HUB");
|
||||||
|
|
||||||
|
// // Read configuration Descriptor in Order To Obtain Proper Configuration Value
|
||||||
|
// uint8_t buf[8];
|
||||||
|
// rcode = getConfDescr(1, 0, 8, 0, buf);
|
||||||
|
|
||||||
|
// if (rcode)
|
||||||
|
// {
|
||||||
|
// Serial.print("getConfDescr:");
|
||||||
|
// Serial.println(rcode, HEX);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Serial.print("Conf val:");
|
||||||
|
// Serial.println(buf[5], HEX);
|
||||||
|
|
||||||
|
// // Set Configuration Value
|
||||||
|
// rcode = setConf(1, 0, buf[5]);
|
||||||
|
|
||||||
|
// if (rcode)
|
||||||
|
// {
|
||||||
|
// Serial.print("setConf:");
|
||||||
|
// Serial.println(rcode, HEX);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Serial.println("Hub configured");
|
||||||
|
|
||||||
|
// // Enter Port Configuring State
|
||||||
|
// usb_task_state = USB_STATE_HUB_PORT_POWERED_OFF;
|
||||||
|
// //usb_task_state = USB_STATE_HUB_PORT_DISABLED;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
//} //if (devtable[i].devclass == USB_CLASS_HUB)
|
||||||
|
usb_task_state = USB_STATE_RUNNING;
|
||||||
|
Serial.println("Configured");
|
||||||
|
break;
|
||||||
|
#endif
|
105
usbhub.h
Normal file
105
usbhub.h
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
#if !defined(__USBHUB_H__)
|
||||||
|
#define __USBHUB_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>
|
||||||
|
|
||||||
|
// Hub Port Configuring Substates
|
||||||
|
#define USB_STATE_HUB_PORT_CONFIGURING 0xb0
|
||||||
|
#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1
|
||||||
|
#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2
|
||||||
|
#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3
|
||||||
|
#define USB_STATE_HUB_PORT_DISABLED 0xb4
|
||||||
|
#define USB_STATE_HUB_PORT_RESETTING 0xb5
|
||||||
|
#define USB_STATE_HUB_PORT_ENABLED 0xb6
|
||||||
|
|
||||||
|
|
||||||
|
// The bit mask to check for all necessary state bits
|
||||||
|
#define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
|
||||||
|
|
||||||
|
// Hub Port States
|
||||||
|
//#define bmHUB_PORT_STATE_POWERED ((0UL | bmHUB_PORT_STATUS_PORT_POWER) << 16)
|
||||||
|
#define bmHUB_PORT_STATE_DISCONNECTED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE) << 16)
|
||||||
|
|
||||||
|
#define bmHUB_PORT_STATE_DISABLED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION))
|
||||||
|
|
||||||
|
#define bmHUB_PORT_STATE_RESETTING ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_RESET) << 16)
|
||||||
|
#define bmHUB_PORT_STATE_ENABLED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE) << 16)
|
||||||
|
#define bmHUB_PORT_STATE_SUSPENDED ((0UL | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_SUSPEND) << 16)
|
||||||
|
|
||||||
|
// Hub Port Events
|
||||||
|
#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATE_DISABLED)
|
||||||
|
#define bmHUB_PORT_EVENT_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||||
|
|
||||||
|
#define bmHUB_PORT_EVENT_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION)
|
||||||
|
|
||||||
|
struct HubEvent
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t bmStatus; // port status bits
|
||||||
|
uint16_t bmChange; // port status change bits
|
||||||
|
};
|
||||||
|
uint32_t bmEvent;
|
||||||
|
uint8_t evtBuff[4];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class USBHub : USBDeviceConfig
|
||||||
|
{
|
||||||
|
USB *pUsb; // USB class instance pointer
|
||||||
|
|
||||||
|
EP_RECORD epInfo[2]; // interrupt endpoint info structure
|
||||||
|
|
||||||
|
uint8_t bAddress; // address
|
||||||
|
uint8_t bNbrPorts; // number of ports
|
||||||
|
uint8_t bInitState; // initialization state variable
|
||||||
|
uint8_t bPortResetCounter; // number of ports reset
|
||||||
|
uint32_t qNextPollTime; // next poll time
|
||||||
|
bool bPollEnable; // poll enable flag
|
||||||
|
|
||||||
|
uint8_t GetHubStatus(uint8_t addr);
|
||||||
|
void HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt);
|
||||||
|
|
||||||
|
public:
|
||||||
|
USBHub(USB *p);
|
||||||
|
|
||||||
|
virtual uint8_t Init(uint8_t addr);
|
||||||
|
virtual uint8_t Release(uint8_t addr);
|
||||||
|
virtual uint8_t Poll();
|
||||||
|
};
|
||||||
|
|
||||||
|
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port);
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------
|
||||||
|
// | H | H | H | P | P | P | S | S |
|
||||||
|
// ---------------------------------
|
||||||
|
// H - hub ID
|
||||||
|
// P - port number
|
||||||
|
// S - port state
|
||||||
|
|
||||||
|
struct UsbHubPortState
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t bmState : 2;
|
||||||
|
uint8_t bmPort : 3;
|
||||||
|
uint8_t bmHub : 3;
|
||||||
|
};
|
||||||
|
uint8_t portState;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __USBHUB_H__
|
Loading…
Reference in a new issue