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

835
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_EPINFO_IS_NULL 0xD6
#define USB_ERROR_INVALID_ARGUMENT 0xD7 #define USB_ERROR_INVALID_ARGUMENT 0xD7
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD8 #define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD8
#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xD9
//class USBDeviceConfig #define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDA
//{
//public:
// virtual uint8_t Init(uint8_t addr) = 0;
// virtual uint8_t Release(uint8_t addr) = 0;
// virtual uint8_t Poll() = 0;
//};
class USBDeviceConfig class USBDeviceConfig
{ {
public: 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 Release() = 0;
virtual uint8_t Poll() = 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_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_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_RETRY_LIMIT 3 //retry limit for a transfer
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds #define USB_SETTLE_DELAY 200 //settle delay in milliseconds
#define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code #define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code
#define USB_NUMDEVICES 6 //number of USB devices #define USB_NUMDEVICES 64 //number of USB devices
#define HUB_MAX_HUBS 5 // maximum number of hubs that can be attached to the host controller #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 #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 */
@ -208,12 +202,12 @@ typedef struct {
unsigned int wLength; // 6 Depends on bRequest unsigned int wLength; // 6 Depends on bRequest
} SETUP_PKT, *PSETUP_PKT; } SETUP_PKT, *PSETUP_PKT;
/* device record structure */ ///* device record structure */
typedef struct //typedef struct
{ //{
EP_RECORD *epinfo; //device endpoint information // EpInfo *epinfo; //device endpoint information
uint8_t devclass; //device class // uint8_t devclass; //device class
} DEV_RECORD; //} DEV_RECORD;
struct HubDescriptor 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<P6, P3> MAX3421E; // Black Widdow
typedef MAX3421e<P10, P9> MAX3421E; // Duemielanove typedef MAX3421e<P10, P9> MAX3421E; // Duemielanove
class USB : public MAX3421E 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; AddressPoolImpl<USB_NUMDEVICES> addrPool;
USBDeviceConfig* devConfig[USB_NUMDEVICES]; USBDeviceConfig* devConfig[USB_NUMDEVICES];
uint8_t devConfigIndex; uint8_t devConfigIndex;
uint8_t bmHubPre;
public: public:
USB( void ); USB( void );
void SetHubPreMask() { bmHubPre |= bmHUBPRE; };
void ResetHubPreMask() { bmHubPre &= (~bmHUBPRE); };
AddressPool& GetAddressPool() AddressPool& GetAddressPool()
{ {
return (AddressPool&)addrPool; return (AddressPool&)addrPool;
@ -284,163 +278,156 @@ class USB : public MAX3421E
uint8_t getUsbTaskState( void ); uint8_t getUsbTaskState( void );
void setUsbTaskState( uint8_t state ); void setUsbTaskState( uint8_t state );
EP_RECORD* getDevTableEntry( uint8_t addr, uint8_t ep ); EpInfo* getEpInfoEntry( uint8_t addr, uint8_t ep );
uint8_t setDevTableEntry( uint8_t addr, EP_RECORD* eprecord_ptr ); 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 */ /* 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 );
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 );
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 );
uint8_t setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr, unsigned int nak_limit = USB_NAK_LIMIT ); 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, unsigned int nak_limit = USB_NAK_LIMIT ); 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 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, unsigned int nak_limit = USB_NAK_LIMIT ); 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, unsigned int nak_limit = USB_NAK_LIMIT ); 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, 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 );
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 );
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 );
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 );
/**/ /**/
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 ctrlData( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* dataptr, boolean direction );
uint8_t ctrlStatus( uint8_t ep, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT ); 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, unsigned int nak_limit = USB_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, unsigned int nak_limit = USB_NAK_LIMIT ); uint8_t outTransfer( uint8_t addr, uint8_t ep, unsigned int nbytes, uint8_t* data );
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, uint16_t nak_limit );
// Hub Methods // Hub Methods
uint8_t ClearHubFeature( uint8_t addr, uint8_t ep, uint8_t fid, 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, 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 );
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 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, unsigned int nak_limit = USB_NAK_LIMIT ); 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, 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 );
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 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, unsigned int nak_limit = USB_NAK_LIMIT ); 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, 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 );
uint8_t HubPortPowerOn(uint8_t addr, uint8_t port); uint8_t HubPortPowerOn(uint8_t addr, uint8_t port);
uint8_t HubPortReset(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 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 PrintHubStatus(/*USB *usbptr,*/ uint8_t addr);
void Task( void ); 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: private:
void init(); 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 //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 ) {
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 ));
} }
//get configuration descriptor //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 ) { 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, nak_limit )); return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr ));
} }
//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 ) {
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr, nak_limit )); return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr ));
} }
//set address //set address
inline uint8_t USB::setAddr( uint8_t oldaddr, uint8_t ep, uint8_t newaddr, unsigned int 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, nak_limit )); return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL ));
} }
//set configuration //set configuration
inline uint8_t USB::setConf( uint8_t addr, uint8_t ep, uint8_t conf_value, unsigned int 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, nak_limit )); return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL ));
} }
//class requests //class requests
inline uint8_t USB::setProto( uint8_t addr, uint8_t ep, uint8_t interface, uint8_t protocol, unsigned int 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, nak_limit )); 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 ) { 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, nak_limit )); return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr ));
} }
//get HID report descriptor //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 ) { 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, nak_limit )); 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 ) { 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, nak_limit )); 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 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, nak_limit )); return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr ));
} }
/* returns one byte of data in 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 ) { 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, nak_limit )); 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 ) { 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, nak_limit )); 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 // 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 // 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 // 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 // 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 // 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 ));
return( ctrlReq( addr, ep, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, dataptr, nak_limit ));
} }
// Set Hub Descriptor // 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 // 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 // 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_ #endif //_usb_h_

View file

@ -4,19 +4,25 @@
#include <inttypes.h> #include <inttypes.h>
#include "max3421e.h" #include "max3421e.h"
/* Endpoint information structure */ #define USB_NAK_MAX_POWER 15 //NAK binary order maximum value
/* bToggle of endpoint 0 initialized to 0xff */
/* during enumeration bToggle is set to 00 */ struct EpInfo
typedef struct
{ {
uint8_t epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints ) uint8_t epAddr; // Endpoint address
uint8_t Attr; // Endpoint transfer type. uint8_t maxPktSize; // Maximum packet size
unsigned int MaxPktSize; // Maximum packet size.
uint8_t Interval; // Polling interval in frames. union
uint8_t sndToggle; //last toggle value, bitmask for HCTL toggle bits {
uint8_t rcvToggle; //last toggle value, bitmask for HCTL toggle bits uint8_t epAttribs;
/* not sure if both are necessary */
} EP_RECORD; 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 // 7 6 5 4 3 2 1 0
// --------------------------------- // ---------------------------------
@ -48,10 +54,11 @@ struct UsbDeviceAddress
struct UsbDevice struct UsbDevice
{ {
EP_RECORD *epinfo; // endpoint info pointer EpInfo *epinfo; // endpoint info pointer
uint8_t address; // address uint8_t address; // address
uint8_t epcount; // number of endpoints
bool lowspeed; // indicates if a device is the low speed one bool lowspeed; // indicates if a device is the low speed one
uint8_t devclass; // device class // uint8_t devclass; // device class
}; };
class AddressPool class AddressPool
@ -70,7 +77,7 @@ typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
template <const uint8_t MAX_DEVICES_ALLOWED> template <const uint8_t MAX_DEVICES_ALLOWED>
class AddressPoolImpl : public AddressPool 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 uint8_t hubCounter; // hub counter is kept
// in order to avoid hub address duplication // in order to avoid hub address duplication
@ -81,6 +88,7 @@ class AddressPoolImpl : public AddressPool
void InitEntry(uint8_t index) void InitEntry(uint8_t index)
{ {
thePool[index].address = 0; thePool[index].address = 0;
thePool[index].epcount = 1;
thePool[index].lowspeed = 0; thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep; thePool[index].epinfo = &dev0ep;
}; };
@ -141,9 +149,9 @@ public:
thePool[0].address = 0; thePool[0].address = 0;
thePool[0].epinfo = &dev0ep; thePool[0].epinfo = &dev0ep;
dev0ep.epAddr = 0; dev0ep.epAddr = 0;
dev0ep.MaxPktSize = 8; dev0ep.maxPktSize = 8;
dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
dev0ep.rcvToggle = bmRCVTOG0; dev0ep.bmNakPower = USB_NAK_MAX_POWER;
InitAllAddresses(); InitAllAddresses();
}; };
@ -171,20 +179,28 @@ public:
// Allocates new address // Allocates new address
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) 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) if (parent > 127 || port > 7)
return 0; return 0;
// finds first empty address entry starting from one // finds first empty address entry starting from one
uint8_t index = FindAddressIndex(0); uint8_t index = FindAddressIndex(0);
Serial.println(index, DEC);
if (!index) // if empty entry is not found if (!index) // if empty entry is not found
return 0; return 0;
if (parent == 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; return thePool[index].address;
} }
@ -204,6 +220,13 @@ public:
} }
thePool[index].address = *((uint8_t*)&addr); 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; return thePool[index].address;
}; };
// Empties pool entry // Empties pool entry
@ -220,20 +243,20 @@ public:
}; };
// Returns number of hubs attached // 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. // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
uint8_t GetNumHubs() //uint8_t GetNumHubs()
{ //{
return hubCounter; // return hubCounter;
}; //};
uint8_t GetNumDevices() //uint8_t GetNumDevices()
{ //{
uint8_t counter = 0; // uint8_t counter = 0;
for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++) // for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
if (thePool[i].address != 0); // if (thePool[i].address != 0);
counter ++; // counter ++;
return counter; // return counter;
}; //};
}; };
#endif // __ADDRESS_H__ #endif // __ADDRESS_H__

View file

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

View file

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

View file

@ -1,35 +1,34 @@
#include "usbhub.h" #include "usbhub.h"
bool USBHub::bResetInitiated = false;
USBHub::USBHub(USB *p) : USBHub::USBHub(USB *p) :
pUsb(p), pUsb(p),
bAddress(0), bAddress(0),
bNbrPorts(0), bNbrPorts(0),
bInitState(0), bInitState(0),
// bPortResetCounter(1),
qNextPollTime(0), qNextPollTime(0),
bPollEnable(false) bPollEnable(false)
{ {
epInfo[0].epAddr = 0; epInfo[0].epAddr = 0;
epInfo[0].MaxPktSize = 8; epInfo[0].maxPktSize = 8;
epInfo[0].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 epInfo[0].epAttribs = 0;
epInfo[0].rcvToggle = bmRCVTOG0; epInfo[0].bmNakPower = USB_NAK_MAX_POWER;
epInfo[1].epAddr = 1; epInfo[1].epAddr = 1;
epInfo[1].MaxPktSize = 1; epInfo[1].maxPktSize = 1;
epInfo[1].Interval = 0xff; epInfo[1].epAttribs = 0;
epInfo[1].sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0
epInfo[1].rcvToggle = bmRCVTOG0;
if (pUsb) if (pUsb)
pUsb->RegisterDeviceClass(this); 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 buf[32];
uint8_t rcode; uint8_t rcode;
UsbDevice *p = NULL; UsbDevice *p = NULL;
EP_RECORD *oldep_ptr = NULL; EpInfo *oldep_ptr = NULL;
uint8_t len = 0; uint8_t len = 0;
uint16_t cd_len = 0; uint16_t cd_len = 0;
@ -38,8 +37,6 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
switch (bInitState) switch (bInitState)
{ {
case 0: case 0:
Serial.println("Init");
if (bAddress) if (bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; 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; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) if (!p->epinfo)
{
Serial.println("epinfo");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
}
// Save old pointer to EP_RECORD of address 0 // Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo; 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 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo; p->epinfo = epInfo;
p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf );
p->lowspeed = false;
if (!rcode) if (!rcode)
len = (buf[0] > 32) ? 32 : buf[0]; len = (buf[0] > 32) ? 32 : buf[0];
@ -71,8 +69,6 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
{ {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
Serial.println("getDevDesc:");
return rcode; 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; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // 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 // Assign new address to the device
rcode = pUsb->setAddr( 0, 0, bAddress ); rcode = pUsb->setAddr( 0, 0, bAddress );
@ -99,14 +95,9 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
Serial.print("setAddr:");
Serial.println(rcode, HEX);
return rcode; return rcode;
} }
Serial.print("Addr:");
Serial.println(bAddress, HEX);
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -117,7 +108,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
goto FailGetDevDescr; goto FailGetDevDescr;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setDevTableEntry(bAddress, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);
if (rcode) if (rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
@ -159,17 +150,12 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
goto FailGetConfDescr; goto FailGetConfDescr;
} }
Serial.print("Conf val:");
Serial.println(buf[5], HEX);
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, buf[5]); rcode = pUsb->setConf(bAddress, 0, buf[5]);
if (rcode) if (rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
Serial.println("Hub configured");
bInitState = 3; bInitState = 3;
case 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++) for (uint8_t j=1; j<=bNbrPorts; j++)
pUsb->HubPortPowerOn(bAddress, j); pUsb->HubPortPowerOn(bAddress, j);
Serial.println("Ports powered"); pUsb->SetHubPreMask();
bPollEnable = true; bPollEnable = true;
bInitState = 0; bInitState = 0;
} }
@ -186,31 +171,24 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port)
return 0; return 0;
FailGetDevDescr: FailGetDevDescr:
Serial.print("getDevDescr:");
goto Fail; goto Fail;
FailSetDevTblEntry: FailSetDevTblEntry:
Serial.print("setDevTblEn:");
goto Fail; goto Fail;
FailGetHubDescr: FailGetHubDescr:
Serial.print("getHub:");
goto Fail; goto Fail;
FailGetConfDescr: FailGetConfDescr:
Serial.print("getConf:");
goto Fail; goto Fail;
FailSetConfDescr: FailSetConfDescr:
Serial.print("setConf:");
goto Fail; goto Fail;
FailGetPortStatus: FailGetPortStatus:
Serial.print("GetPortStatus:");
goto Fail; goto Fail;
Fail: Fail:
Serial.println(rcode, HEX);
return rcode; return rcode;
} }
@ -218,9 +196,11 @@ uint8_t USBHub::Release()
{ {
pUsb->GetAddressPool().FreeAddress(bAddress); pUsb->GetAddressPool().FreeAddress(bAddress);
if (bAddress == 0x41)
pUsb->SetHubPreMask();
bAddress = 0; bAddress = 0;
bNbrPorts = 0; bNbrPorts = 0;
// bPortResetCounter = 0;
qNextPollTime = 0; qNextPollTime = 0;
bPollEnable = false; bPollEnable = false;
return 0; return 0;
@ -235,51 +215,27 @@ uint8_t USBHub::Poll()
if (qNextPollTime <= millis()) if (qNextPollTime <= millis())
{ {
Serial.print("Poll:");
Serial.println(bAddress, HEX); Serial.println(bAddress, HEX);
rcode = GetHubStatus(bAddress); rcode = GetHubStatus(bAddress);
if (rcode)
{
Serial.print("HubStatus:");
Serial.println(rcode,HEX);
}
qNextPollTime = millis() + 100; qNextPollTime = millis() + 100;
} }
return rcode; 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 USBHub::GetHubStatus(uint8_t addr)
{ {
uint8_t rcode; uint8_t rcode;
uint8_t buf[8]; 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 ); rcode = pUsb->inTransfer(addr, 1, 1, buf);
//Serial.println(devtable[1].epinfo->epAddr, HEX);
rcode = pUsb->inTransfer(addr, 1, 1, buf, 1);
if (rcode) if (rcode)
{
Serial.print("inTransfer:");
Serial.println(rcode, HEX);
return rcode; return rcode;
}
Serial.print("Int:");
Serial.println(buf[0],HEX);
//return 0;
if (buf[0] & 0x01) // Hub Status Change if (buf[0] & 0x01) // Hub Status Change
{ {
pUsb->PrintHubStatus(addr); //pUsb->PrintHubStatus(addr);
//rcode = GetHubStatus(1, 0, 1, 4, buf); //rcode = GetHubStatus(1, 0, 1, 4, buf);
//if (rcode) //if (rcode)
//{ //{
@ -298,91 +254,91 @@ uint8_t USBHub::GetHubStatus(uint8_t addr)
rcode = pUsb->GetPortStatus(addr, 0, port, 4, evt.evtBuff); rcode = pUsb->GetPortStatus(addr, 0, port, 4, evt.evtBuff);
if (rcode) if (rcode)
{
Serial.print("GetPortStatus err:");
Serial.println(rcode, HEX);
Serial.print("on port:");
Serial.println(port, DEC);
continue; 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 } // for
return 0; 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) 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 // Device connected event
case bmHUB_PORT_EVENT_CONNECT: 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_ENABLE);
pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION); pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_CONNECTION);
pUsb->HubPortReset(addr, port); 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 // Reset complete event
case bmHUB_PORT_EVENT_RESET_COMPLETE: 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); pUsb->HubClearPortFeatures(addr, port, HUB_FEATURE_C_PORT_RESET | HUB_FEATURE_C_PORT_CONNECTION);
// Check if device is a low-speed device delay(20);
if (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED)
{
UsbDevice *p = pUsb->GetAddressPool().GetUsbDevicePtr(addr);
if (p) a.devAddress = addr;
p->lowspeed = true;
}
delay(50); pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) );
bResetInitiated = false;
pUsb->Configuring(addr, port);
break; 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) } // switch (evt.bmEvent)
return 0;
} }
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes) void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes)
{ {
uint8_t rcode = 0; uint8_t rcode = 0;

View file

@ -19,25 +19,27 @@
#define USB_STATE_HUB_PORT_RESETTING 0xb5 #define USB_STATE_HUB_PORT_RESETTING 0xb5
#define USB_STATE_HUB_PORT_ENABLED 0xb6 #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 // 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) #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 // Hub Port States
//#define bmHUB_PORT_STATE_POWERED ((0UL | bmHUB_PORT_STATUS_PORT_POWER) << 16) #define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
#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 // 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_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 struct HubEvent
{ {
@ -56,50 +58,30 @@ struct HubEvent
class USBHub : USBDeviceConfig class USBHub : USBDeviceConfig
{ {
static bool bResetInitiated; // True when reset is triggered
USB *pUsb; // USB class instance pointer 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 bAddress; // address
uint8_t bNbrPorts; // number of ports uint8_t bNbrPorts; // number of ports
uint8_t bInitState; // initialization state variable uint8_t bInitState; // initialization state variable
// uint8_t bPortResetCounter; // number of ports reset
uint32_t qNextPollTime; // next poll time uint32_t qNextPollTime; // next poll time
bool bPollEnable; // poll enable flag bool bPollEnable; // poll enable flag
uint8_t GetHubStatus(uint8_t addr); 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: public:
USBHub(USB *p); 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 Release();
virtual uint8_t Poll(); virtual uint8_t Poll();
virtual uint8_t GetAddress() { return bAddress; };
}; };
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); 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__ #endif // __USBHUB_H__