3 * - By John Hodge (thePowersGang)
11 #define MAX_PORTS 32 // Not actually a max, but used for DeviceRemovable
15 #define CLEAR_FEATURE 1
19 #define PORT_CONNECTION 0
21 #define PORT_SUSPEND 2
22 #define PORT_OVER_CURRENT 3
25 #define PORT_LOW_SPEED 9
26 #define C_PORT_CONNECTION 16
27 #define C_PORT_ENABLE 17
28 #define C_PORT_SUSPEND 18
29 #define C_PORT_OVER_CURRENT 19
30 #define C_PORT_RESET 20
32 #define PORT_INDICATOR 21
37 Uint8 DescType; // = 0x29
39 Uint16 HubCharacteristics;
40 Uint8 PwrOn2PwrGood; // 2 ms intervals
41 Uint8 HubContrCurrent; // Max internal current (mA)
42 Uint8 DeviceRemovable[MAX_PORTS];
48 int PowerOnDelay; // in ms
50 Uint8 DeviceRemovable[];
54 void Hub_Connected(tUSBInterface *Dev);
55 void Hub_Disconnected(tUSBInterface *Dev);
56 void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data);
57 void Hub_int_HandleChange(tUSBInterface *Dev, int Port);
60 tUSBDriver gUSBHub_Driver = {
62 .Match = {.Class = {0x090000, 0xFF0000}},
63 .Connected = Hub_Connected,
64 .Disconnected = Hub_Disconnected,
67 {0x83, Hub_PortStatusChange}
73 int Hub_DriverInitialise(char **Arguments)
75 USB_RegisterDriver( &gUSBHub_Driver );
80 void Hub_Connected(tUSBInterface *Dev)
82 struct sHubDescriptor hub_desc;
83 struct sHubInfo *info;
85 // Read hub descriptor (Class descriptor 0x29)
86 USB_ReadDescriptor(Dev, 0x129, 0, sizeof(hub_desc), &hub_desc);
88 LOG("%i Ports", hub_desc.NbrPorts);
89 LOG("Takes %i ms for power to stabilise", hub_desc.PwrOn2PwrGood*2);
91 // Allocate infomation structure
92 info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8);
94 Log_Error("USBHub", "malloc() failed");
97 USB_SetDeviceDataPtr(Dev, info);
100 info->nPorts = hub_desc.NbrPorts;
101 info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2;
102 memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8);
104 info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
106 // Register poll on endpoint
107 USB_StartPollingEndpoint(Dev, 1);
110 void Hub_Disconnected(tUSBInterface *Dev)
112 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
113 USB_RemoveHub(info->HubPtr);
117 void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data)
119 Uint8 *status = Data;
120 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
122 for( i = 0; i < info->nPorts; i += 8, status ++ )
124 if( i/8 >= Length ) break;
125 if( *status == 0 ) continue;
127 for( int j = 0; j < 8; j ++ )
128 if( *status & (1 << j) )
129 Hub_int_HandleChange(Dev, i+j);
133 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
135 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
136 Uint16 status[2]; // Status, Change
139 USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
141 LOG("Port %i: status = {0b%b, 0b%b}", Port, status[0], status[1]);
143 // Handle connections / disconnections
144 if( status[1] & 0x0001 )
146 if( status[0] & 0x0001 ) {
149 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL);
150 Time_Delay(info->PowerOnDelay);
152 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL);
153 Time_Delay(20); // Spec says 10ms after reset, but how long is reset?
155 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_ENABLE, Port, 0, NULL);
157 USB_DeviceConnected(info->HubPtr, Port);
161 USB_DeviceDisconnected(info->HubPtr, Port);
164 USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, Port, 0, NULL);
168 if( status[1] & 0x0010 )
170 if( status[0] & 0x0010 ) {
177 USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_RESET, Port, 0, NULL);