3 * - By John Hodge (thePowersGang)
10 #define MAX_PORTS 32 // Not actually a max, but used for DeviceRemovable
15 #define PORT_CONNECTION 0
23 Uint8 DescType; // = 0x29
25 Uint16 HubCharacteristics;
26 Uint8 PwrOn2PwrGood; // 2 ms intervals
27 Uint8 HubContrCurrent; // Max internal current (mA)
28 Uint8 DeviceRemovable[MAX_PORTS];
34 int PowerOnDelay; // in ms
36 Uint8 DeviceRemovable[];
40 void Hub_Connected(tUSBInterface *Dev);
41 void Hub_Disconnected(tUSBInterface *Dev);
42 void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data);
43 void Hub_int_HandleChange(tUSBInterface *Dev, int Port);
46 tUSBDriver gUSBHub_Driver = {
48 .Match = {.Class = {0x090000, 0xFF0000}},
49 .Connected = Hub_Connected,
50 .Disconnected = Hub_Disconnected,
53 {0x83, Hub_PortStatusChange}
59 int Hub_DriverInitialise(char **Arguments)
61 USB_RegisterDriver( &gUSBHub_Driver );
66 void Hub_Connected(tUSBInterface *Dev)
68 struct sHubDescriptor hub_desc;
69 struct sHubInfo *info;
71 // Read hub descriptor
72 USB_ReadDescriptor(Dev, 0x29, 0, sizeof(hub_desc), &hub_desc);
74 LOG("%i Ports", hub_desc.NbrPorts);
75 LOG("Takes %i ms for power to stabilise", hub_desc.PwrOn2PwrGood*2);
77 // Allocate infomation structure
78 info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8);
80 Log_Error("USBHub", "malloc() failed");
83 USB_SetDeviceDataPtr(Dev, info);
86 info->nPorts = hub_desc.NbrPorts;
87 info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2;
88 memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8);
90 info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
92 // Register poll on endpoint
93 USB_StartPollingEndpoint(Dev, 1);
96 void Hub_Disconnected(tUSBInterface *Dev)
98 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
99 USB_RemoveHub(info->HubPtr);
103 void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
105 Uint8 *status = Data;
106 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
108 for( i = 0; i < info->nPorts; i += 8, status ++ )
110 if( i/8 >= Length ) break;
111 if( *status == 0 ) continue;
113 for( int j = 0; j < 8; j ++ )
114 if( *status & (1 << j) )
115 Hub_int_HandleChange(Dev, i+j);
119 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
121 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
122 Uint16 status[2]; // Status, Change
125 USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
127 // Handle connections / disconnections
128 if( status[1] & 0x0001 )
130 if( status[0] & 0x0001 ) {
133 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL);
134 Time_Delay(info->PowerOnDelay);
136 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL);
137 Time_Delay(20); // Spec says 10ms after reset, but how long is reset?
139 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_ENABLE, Port, 0, NULL);
141 USB_DeviceConnected(info->HubPtr, Port);
145 USB_DeviceDisconnected(info->HubPtr, Port);