X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FUSB%2FCore%2Fhub.c;h=849e8a3fd6c58a69149c6c2a54d43ce037ab9800;hb=a79a695585e69376330fd6b83b32a573d7df9dc7;hp=552ab96e1403b6ada8a2a198eb83f3702ae3e0c7;hpb=34c3e84b154675d1cef9098ba05b8b291241c37e;p=tpg%2Facess2.git diff --git a/Modules/USB/Core/hub.c b/Modules/USB/Core/hub.c index 552ab96e..849e8a3f 100644 --- a/Modules/USB/Core/hub.c +++ b/Modules/USB/Core/hub.c @@ -5,10 +5,32 @@ * hub.c * - Basic hub driver */ +#define DEBUG 1 #include #define MAX_PORTS 32 // Not actually a max, but used for DeviceRemovable + +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 +// resvd +#define SET_FEATURE 3 + +#define PORT_CONNECTION 0 +#define PORT_ENABLE 1 +#define PORT_SUSPEND 2 +#define PORT_OVER_CURRENT 3 +#define PORT_RESET 4 +#define PORT_POWER 8 +#define PORT_LOW_SPEED 9 +#define C_PORT_CONNECTION 16 +#define C_PORT_ENABLE 17 +#define C_PORT_SUSPEND 18 +#define C_PORT_OVER_CURRENT 19 +#define C_PORT_RESET 20 +#define PORT_TEST 21 +#define PORT_INDICATOR 21 + struct sHubDescriptor { Uint8 DescLength; @@ -20,10 +42,19 @@ struct sHubDescriptor Uint8 DeviceRemovable[MAX_PORTS]; }; +struct sHubInfo +{ + tUSBHub *HubPtr; + int PowerOnDelay; // in ms + int nPorts; + Uint8 DeviceRemovable[]; +}; + // === PROTOTYPES === void Hub_Connected(tUSBInterface *Dev); void Hub_Disconnected(tUSBInterface *Dev); -void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data); +void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data); +void Hub_int_HandleChange(tUSBInterface *Dev, int Port); // === GLOBALS === tUSBDriver gUSBHub_Driver = { @@ -34,39 +65,61 @@ tUSBDriver gUSBHub_Driver = { .MaxEndpoints = 1, .Endpoints = { {0x83, Hub_PortStatusChange} - }; + } }; // === CODE === +#if 0 +int Hub_DriverInitialise(char **Arguments) +{ + USB_RegisterDriver( &gUSBHub_Driver ); + return 0; +} +#endif + void Hub_Connected(tUSBInterface *Dev) { - struct sHubDescriptor *hub_desc; - - hub_desc = malloc(sizeof(*hub_desc)); - if(!hub_desc) { + struct sHubDescriptor hub_desc; + struct sHubInfo *info; + + // Read hub descriptor (Class descriptor 0x29) + USB_ReadDescriptor(Dev, 0x129, 0, sizeof(hub_desc), &hub_desc); + + LOG("%i Ports", hub_desc.NbrPorts); + LOG("Takes %i ms for power to stabilise", hub_desc.PwrOn2PwrGood*2); + + // Allocate infomation structure + info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8); + if(!info) { Log_Error("USBHub", "malloc() failed"); return ; } - USB_SetDeviceDataPtr(Dev, hub_desc); + USB_SetDeviceDataPtr(Dev, info); - USB_ReadDescriptor(Dev, 0, 0x29, 0, sizeof(hub_desc), hub_desc); + // Fill data + info->nPorts = hub_desc.NbrPorts; + info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2; + memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8); + // Register + info->HubPtr = USB_RegisterHub(Dev, info->nPorts); // Register poll on endpoint - USB_PollEndpoint(Dev, 1); - - USB_RegisterHub(Dev, hub_desc->NbrPorts); + USB_StartPollingEndpoint(Dev, 1); } void Hub_Disconnected(tUSBInterface *Dev) { + struct sHubInfo *info = USB_GetDeviceDataPtr(Dev); + USB_RemoveHub(info->HubPtr); + free(info); } -void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data) +void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data) { Uint8 *status = Data; - struct sHubDescriptor *info = USB_GetDeviceDataPtr(Dev); + struct sHubInfo *info = USB_GetDeviceDataPtr(Dev); int i; - for( i = 0; i < info->NbrPorts; i += 8, status ++ ) + for( i = 0; i < info->nPorts; i += 8, status ++ ) { if( i/8 >= Length ) break; if( *status == 0 ) continue; @@ -79,8 +132,48 @@ void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data) void Hub_int_HandleChange(tUSBInterface *Dev, int Port) { + struct sHubInfo *info = USB_GetDeviceDataPtr(Dev); Uint16 status[2]; // Status, Change - // Get change status - USB_Request(Dev, 0, 0xA3, 0, 0, Port, 4, status); -} + + // Get port status + USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status); + LOG("Port %i: status = {0b%b, 0b%b}", Port, status[0], status[1]); + + // Handle connections / disconnections + if( status[1] & 0x0001 ) + { + if( status[0] & 0x0001 ) { + // Connected + // - Power on port + USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL); + Time_Delay(info->PowerOnDelay); + // - Reset + USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL); + Time_Delay(20); // Spec says 10ms after reset, but how long is reset? + // - Enable + USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_ENABLE, Port, 0, NULL); + // - Poke USB Stack + USB_DeviceConnected(info->HubPtr, Port); + } + else { + // Disconnected + USB_DeviceDisconnected(info->HubPtr, Port); + } + + USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, Port, 0, NULL); + } + + // Reset change + if( status[1] & 0x0010 ) + { + if( status[0] & 0x0010 ) { + // Reset complete + } + else { + // Useful? + } + // ACK + USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_RESET, Port, 0, NULL); + } +}