next big change

This commit is contained in:
unknown 2011-04-15 23:24:10 -06:00
parent d3a52a7616
commit 2be575ffc0
8 changed files with 1071 additions and 1384 deletions

845
Usb.cpp

File diff suppressed because it is too large Load diff

225
Usb.h
View file

@ -138,32 +138,26 @@
#define USB_ERROR_EPINFO_IS_NULL 0xD6
#define USB_ERROR_INVALID_ARGUMENT 0xD7
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD8
//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_ERROR_INVALID_MAX_PKT_SIZE 0xD9
#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDA
class USBDeviceConfig
{
public:
virtual uint8_t Init(uint8_t parent, uint8_t port) = 0;
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) = 0;
virtual uint8_t Release() = 0;
virtual uint8_t Poll() = 0;
virtual uint8_t GetAddress() = 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 USB_NUMDEVICES 64 //number of USB devices
#define HUB_MAX_HUBS 7 // 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 */
@ -208,12 +202,12 @@ typedef struct {
unsigned int wLength; // 6 Depends on bRequest
} SETUP_PKT, *PSETUP_PKT;
/* device record structure */
typedef struct
{
EP_RECORD *epinfo; //device endpoint information
uint8_t devclass; //device class
} DEV_RECORD;
///* device record structure */
//typedef struct
//{
// EpInfo *epinfo; //device endpoint information
// uint8_t devclass; //device class
//} DEV_RECORD;
struct HubDescriptor
@ -237,30 +231,30 @@ struct HubDescriptor
};
// Base class for incomming data parser
class UsbReadParser
{
public:
virtual void Parse(const uint8_t len, const uint8_t *pbuf, const uint16_t &offset) = 0;
};
//typedef MAX3421e<P6, P3> MAX3421E; // Black Widdow
typedef MAX3421e<P10, P9> MAX3421E; // Duemielanove
class USB : public MAX3421E
{
//data structures
/* device table. Filled during enumeration */
/* index corresponds to device address */
/* each entry contains pointer to endpoint structure */
/* and device class to use in various places */
//DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
//EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
//byte usb_task_state;
AddressPoolImpl<USB_NUMDEVICES> addrPool;
USBDeviceConfig* devConfig[USB_NUMDEVICES];
uint8_t devConfigIndex;
uint8_t bmHubPre;
public:
USB( void );
void SetHubPreMask() { bmHubPre |= bmHUBPRE; };
void ResetHubPreMask() { bmHubPre &= (~bmHUBPRE); };
AddressPool& GetAddressPool()
{
return (AddressPool&)addrPool;
@ -284,163 +278,156 @@ class USB : public MAX3421E
uint8_t getUsbTaskState( void );
void setUsbTaskState( uint8_t state );
EP_RECORD* getDevTableEntry( uint8_t addr, uint8_t ep );
uint8_t setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr );
EpInfo* getEpInfoEntry( uint8_t addr, uint8_t ep );
uint8_t setEpInfoEntry( uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr );
uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, unsigned int wInd, unsigned int nbytes, uint8_t* dataptr, 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);
/* 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 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 setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr, unsigned int nak_limit = USB_NAK_LIMIT );
uint8_t setConf( uint8_t addr, uint8_t ep, uint8_t conf_value, unsigned int nak_limit = USB_NAK_LIMIT );
uint8_t getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr );
uint8_t getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr );
uint8_t getStrDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t index, unsigned int langid, uint8_t* dataptr );
uint8_t setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr );
uint8_t setConf( uint8_t addr, uint8_t ep, uint8_t conf_value );
/**/
uint8_t setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol, 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 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 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 setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol );
uint8_t getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr );
uint8_t getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr );
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 );
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 );
uint8_t getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr );
uint8_t setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration );
/**/
uint8_t ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT );
uint8_t ctrlStatus( uint8_t ep, boolean direction, 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 dispatchPkt( uint8_t token, uint8_t ep, unsigned int nak_limit = USB_NAK_LIMIT );
uint8_t ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction );
uint8_t ctrlStatus( uint8_t ep, boolean direction, uint16_t nak_limit );
uint8_t inTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data );
uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data );
uint8_t dispatchPkt( uint8_t token, uint8_t ep, uint16_t 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 ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid );
uint8_t ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0 );
uint8_t GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr );
uint8_t GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr );
uint8_t GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr );
uint8_t SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr );
uint8_t SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid );
uint8_t SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel = 0 );
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 );
uint8_t DefaultAddressing();
uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed);
uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed);
uint8_t ReleaseDevice(uint8_t addr);
uint8_t Configuring(uint8_t parent, uint8_t port);
//typedef void (*USBREADCALLBACK)(uint16_t nbytes, uint8_t *data, uint16_t offset);
//uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
// uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBREADCALLBACK pf);
uint8_t ctrlReq( uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, UsbReadParser *p);
private:
void init();
uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit);
uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t *data);
uint8_t InTransfer (EpInfo *pep, uint16_t nak_limit, unsigned int nbytes, uint8_t* data);
};
#if defined(USB_METHODS_INLINE)
//#if defined(USB_METHODS_INLINE)
//get device descriptor
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 ));
inline uint8_t USB::getDevDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ) {
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr ));
}
//get configuration descriptor
inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr, unsigned int nak_limit ) {
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit ));
inline uint8_t USB::getConfDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t conf, uint8_t* dataptr ) {
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr ));
}
//get string descriptor
inline uint8_t USB::getStrDescr( uint8_t addr, uint8_t ep, unsigned int nuint8_ts, uint8_t index, unsigned int langid, uint8_t* dataptr, unsigned int nak_limit ) {
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr, 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 ) {
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr ));
}
//set address
inline uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr, unsigned int nak_limit ) {
return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit ));
inline uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr ) {
return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL ));
}
//set configuration
inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value, unsigned int nak_limit ) {
return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit ));
inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value ) {
return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL ));
}
//class requests
inline uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol, unsigned int nak_limit ) {
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit ));
inline uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol ) {
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL ));
}
inline uint8_t USB::getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr, unsigned int nak_limit ) {
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit ));
inline uint8_t USB::getProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t* dataptr ) {
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr ));
}
//get HID report descriptor
inline uint8_t USB::getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, unsigned int nak_limit ) {
return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit ));
inline uint8_t USB::getReportDescr( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr ) {
return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr ));
}
inline uint8_t USB::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 ) {
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));
inline uint8_t USB::setReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ) {
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr ));
}
inline uint8_t USB::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 ) { // ** RI 04/11/09
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));
inline uint8_t USB::getReport( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr ) {
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr ));
}
/* returns one byte of data in dataptr */
inline uint8_t USB::getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, unsigned int nak_limit ) {
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit ));
inline uint8_t USB::getIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr ) {
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr ));
}
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 ));
inline uint8_t USB::setIdle( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t reportID, uint8_t duration ) {
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL ));
}
// 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 )
inline uint8_t USB::ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid )
{
return( ctrlReq( addr, ep, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL, nak_limit ));
return( ctrlReq( addr, ep, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, NULL ));
}
// 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 )
inline uint8_t USB::ClearPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel )
{
return( ctrlReq( addr, ep, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL, nak_limit ));
return( ctrlReq( addr, ep, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000|port)|(sel<<8)), 0, NULL ));
}
// 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 )
inline uint8_t USB::GetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t index, uint16_t nbytes, uint8_t *dataptr )
{
return( ctrlReq( addr, ep, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, dataptr, nak_limit ));
return( ctrlReq( addr, ep, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, dataptr ));
}
// Get Hub Status
inline uint8_t USB::GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, unsigned int nak_limit )
inline uint8_t USB::GetHubStatus( uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr )
{
return( ctrlReq( addr, ep, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, dataptr, nak_limit ));
return( ctrlReq( addr, ep, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, dataptr ));
}
// 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 )
inline uint8_t USB::GetPortStatus( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr )
{
//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 ));
return( ctrlReq( addr, ep, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr ));
}
// 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 )
inline uint8_t USB::SetHubDescriptor( uint8_t addr, uint8_t ep, uint8_t port, uint16_t nbytes, uint8_t* dataptr )
{
return( ctrlReq( addr, ep, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, dataptr, nak_limit ));
return( ctrlReq( addr, ep, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, dataptr ));
}
// Set Hub Feature
inline uint8_t USB::SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, unsigned int nak_limit )
inline uint8_t USB::SetHubFeature( uint8_t addr, uint8_t ep, uint8_t fid )
{
return( ctrlReq( addr, ep, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, NULL, nak_limit ));
return( ctrlReq( addr, ep, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, NULL ));
}
// 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 )
inline uint8_t USB::SetPortFeature( uint8_t addr, uint8_t ep, uint8_t fid, uint8_t port, uint8_t sel )
{
return( ctrlReq( addr, ep, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL, nak_limit ));
return( ctrlReq( addr, ep, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000|sel)<<8)|port), 0, NULL ));
}
#endif // defined(USB_METHODS_INLINE)
//#endif // defined(USB_METHODS_INLINE)
#endif //_usb_h_

View file

@ -4,19 +4,25 @@
#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
#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value
struct EpInfo
{
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;
uint8_t epAddr; // Endpoint address
uint8_t maxPktSize; // Maximum packet size
union
{
uint8_t epAttribs;
struct
{
uint8_t bmSndToggle : 1; // Send toggle, when zerro bmSNDTOG0, bmSNDTOG1 otherwise
uint8_t bmRcvToggle : 1; // Send toggle, when zerro bmRCVTOG0, bmRCVTOG1 otherwise
uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
};
};
};
// 7 6 5 4 3 2 1 0
// ---------------------------------
@ -48,10 +54,11 @@ struct UsbDeviceAddress
struct UsbDevice
{
EP_RECORD *epinfo; // endpoint info pointer
EpInfo *epinfo; // endpoint info pointer
uint8_t address; // address
uint8_t epcount; // number of endpoints
bool lowspeed; // indicates if a device is the low speed one
uint8_t devclass; // device class
// uint8_t devclass; // device class
};
class AddressPool
@ -70,7 +77,7 @@ typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
template <const uint8_t MAX_DEVICES_ALLOWED>
class AddressPoolImpl : public AddressPool
{
EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
uint8_t hubCounter; // hub counter is kept
// in order to avoid hub address duplication
@ -81,6 +88,7 @@ class AddressPoolImpl : public AddressPool
void InitEntry(uint8_t index)
{
thePool[index].address = 0;
thePool[index].epcount = 1;
thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep;
};
@ -141,9 +149,9 @@ public:
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;
dev0ep.maxPktSize = 8;
dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
dev0ep.bmNakPower = USB_NAK_MAX_POWER;
InitAllAddresses();
};
@ -171,20 +179,28 @@ public:
// Allocates new address
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0)
{
if (parent != 0 && port == 0)
Serial.println("PRT: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;
if (is_hub)
{
thePool[index].address = 0x41;
hubCounter ++;
}
else
thePool[index].address = 1;
return thePool[index].address;
}
@ -204,6 +220,13 @@ public:
}
thePool[index].address = *((uint8_t*)&addr);
Serial.print("Addr:");
Serial.print(addr.bmHub, HEX);
Serial.print(".");
Serial.print(addr.bmParent, HEX);
Serial.print(".");
Serial.println(addr.bmAddress, HEX);
return thePool[index].address;
};
// Empties pool entry
@ -220,20 +243,20 @@ public:
};
// 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;
//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 ++;
// for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
// if (thePool[i].address != 0);
// counter ++;
return counter;
};
// return counter;
//};
};
#endif // __ADDRESS_H__

View file

@ -9,8 +9,8 @@
/* pin numbers to port numbers */
//#define MAX_SS 10
//#define MAX_INT 3 // Black Widdow
#define MAX_INT 9 // Duemielanove
#define MAX_INT 3 // Black Widdow
//#define MAX_INT 9 // Duemielanove
#define MAX_GPX 8
//#define MAX_RESET 7

View file

@ -249,7 +249,7 @@ uint8_t MAX3421e< SS, INTR >::Task( void )
uint8_t pinvalue;
//Serial.print("Vbus state: ");
//Serial.println( vbusState, HEX );
pinvalue = INTR::Read();
pinvalue = INTR::IsSet(); //Read();
//pinvalue = digitalRead( MAX_INT );
if( pinvalue == LOW ) {
rcode = IntHandler();

View file

@ -1,35 +1,34 @@
#include "usbhub.h"
bool USBHub::bResetInitiated = false;
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[0].maxPktSize = 8;
epInfo[0].epAttribs = 0;
epInfo[0].bmNakPower = USB_NAK_MAX_POWER;
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;
epInfo[1].maxPktSize = 1;
epInfo[1].epAttribs = 0;
if (pUsb)
pUsb->RegisterDeviceClass(this);
}
uint8_t USBHub::Init(uint8_t parent, uint8_t port)
uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed)
{
uint8_t buf[32];
uint8_t rcode;
UsbDevice *p = NULL;
EP_RECORD *oldep_ptr = NULL;
EpInfo *oldep_ptr = NULL;
uint8_t len = 0;
uint16_t cd_len = 0;
@ -38,8 +37,6 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
switch (bInitState)
{
case 0:
Serial.println("Init");
if (bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
@ -50,10 +47,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo)
{
Serial.println("epinfo");
return USB_ERROR_EPINFO_IS_NULL;
}
// Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo;
@ -61,9 +55,13 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo;
p->lowspeed = lowspeed;
// Get device descriptor
rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf );
p->lowspeed = false;
if (!rcode)
len = (buf[0] > 32) ? 32 : buf[0];
@ -71,8 +69,6 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
{
// Restore p->epinfo
p->epinfo = oldep_ptr;
Serial.println("getDevDesc:");
return rcode;
}
@ -88,7 +84,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor
epInfo[0].MaxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device
rcode = pUsb->setAddr( 0, 0, bAddress );
@ -99,14 +95,9 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
p->epinfo = oldep_ptr;
addrPool.FreeAddress(bAddress);
bAddress = 0;
Serial.print("setAddr:");
Serial.println(rcode, HEX);
return rcode;
}
Serial.print("Addr:");
Serial.println(bAddress, HEX);
// Restore p->epinfo
p->epinfo = oldep_ptr;
@ -117,7 +108,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
goto FailGetDevDescr;
// Assign epInfo to epinfo pointer
rcode = pUsb->setDevTableEntry(bAddress, epInfo);
rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);
if (rcode)
goto FailSetDevTblEntry;
@ -159,17 +150,12 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
goto FailGetConfDescr;
}
Serial.print("Conf val:");
Serial.println(buf[5], HEX);
// Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, buf[5]);
if (rcode)
goto FailSetConfDescr;
Serial.println("Hub configured");
bInitState = 3;
case 3:
@ -177,8 +163,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
for (uint8_t j=1; j<=bNbrPorts; j++)
pUsb->HubPortPowerOn(bAddress, j);
Serial.println("Ports powered");
pUsb->SetHubPreMask();
bPollEnable = true;
bInitState = 0;
}
@ -186,31 +171,24 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
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;
}
@ -218,9 +196,11 @@ uint8_t USBHub::Release()
{
pUsb->GetAddressPool().FreeAddress(bAddress);
if (bAddress == 0x41)
pUsb->SetHubPreMask();
bAddress = 0;
bNbrPorts = 0;
// bPortResetCounter = 0;
qNextPollTime = 0;
bPollEnable = false;
return 0;
@ -235,51 +215,27 @@ uint8_t USBHub::Poll()
if (qNextPollTime <= millis())
{
Serial.print("Poll:");
Serial.println(bAddress, HEX);
rcode = GetHubStatus(bAddress);
if (rcode)
{
Serial.print("HubStatus:");
Serial.println(rcode,HEX);
}
qNextPollTime = millis() + 100;
}
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);
rcode = pUsb->inTransfer(addr, 1, 1, buf);
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);
//pUsb->PrintHubStatus(addr);
//rcode = GetHubStatus(1, 0, 1, 4, buf);
//if (rcode)
//{
@ -298,91 +254,91 @@ uint8_t USBHub::GetHubStatus(uint8_t addr)
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;
rcode = HubPortStatusChange(addr, port, evt);
if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
return 0;
if (rcode)
return rcode;
}
HubPortStatusChange(addr, port, evt);
}
} // for
for (uint8_t port=1; port<=bNbrPorts; port++)
{
HubEvent evt;
evt.bmEvent = 0;
rcode = pUsb->GetPortStatus(addr, 0, port, 4, evt.evtBuff);
if (rcode)
continue;
if ((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED)
continue;
// Emulate connection event for the port
evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION;
rcode = HubPortStatusChange(addr, port, evt);
if (rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
return 0;
if (rcode)
return rcode;
} // for
return 0;
}
void USBHub::HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt)
uint8_t 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, true);
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");
case bmHUB_PORT_EVENT_LS_CONNECT:
if (bResetInitiated)
return 0;
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_ENABLE);
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION);
pUsb->HubPortReset(addr, port);
break;
bResetInitiated = true;
return HUB_ERROR_PORT_HAS_BEEN_RESET;
// Device disconnected event
case bmHUB_PORT_EVENT_DISCONNECT:
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_ENABLE);
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION);
bResetInitiated = false;
UsbDeviceAddress a;
a.bmHub = 0;
a.bmParent = addr;
a.bmAddress = port;
pUsb->ReleaseDevice(a.devAddress);
return 0;
// Reset complete event
case bmHUB_PORT_EVENT_RESET_COMPLETE:
Serial.println("RCMPL");
case bmHUB_PORT_EVENT_LS_RESET_COMPLETE:
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_RESET | HUB_FEATURE_C_PORT_CONNECTION);
// Check if device is a low-speed device
if (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED)
{
UsbDevice *p = pUsb->GetAddressPool().GetUsbDevicePtr(addr);
delay(20);
if (p)
p->lowspeed = true;
}
a.devAddress = addr;
delay(50);
pUsb->Configuring(addr, port);
pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) );
bResetInitiated = false;
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)
return 0;
}
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes)
{
uint8_t rcode = 0;

View file

@ -19,25 +19,27 @@
#define USB_STATE_HUB_PORT_RESETTING 0xb5
#define USB_STATE_HUB_PORT_ENABLED 0xb6
// Additional Error Codes
#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1
// 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)
// Bit mask to check for DISABLED state in HubEvent::bmStatus field
#define bmHUB_PORT_STATE_CHECK_DISABLED (0x0000 | 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)
#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
// Hub Port Events
#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATE_DISABLED)
#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER)
#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)
#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
#define bmHUB_PORT_EVENT_LS_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 | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
#define bmHUB_PORT_EVENT_LS_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 | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
struct HubEvent
{
@ -56,50 +58,30 @@ struct HubEvent
class USBHub : USBDeviceConfig
{
static bool bResetInitiated; // True when reset is triggered
USB *pUsb; // USB class instance pointer
EP_RECORD epInfo[2]; // interrupt endpoint info structure
EpInfo 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);
uint8_t HubPortStatusChange(uint8_t addr, uint8_t port, HubEvent &evt);
public:
USBHub(USB *p);
virtual uint8_t Init(uint8_t parent, uint8_t port);
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
virtual uint8_t Release();
virtual uint8_t Poll();
virtual uint8_t GetAddress() { return bAddress; };
};
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false);
// ---------------------------------
// | 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__