3 * - By John Hodge (thePowersGang)
12 #define MAX_PORTS 32 // Not actually a max, but used for DeviceRemovable
16 #define CLEAR_FEATURE 1
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, void *Descriptors, size_t Length);
41 void Hub_Disconnected(tUSBInterface *Dev);
42 void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data);
43 void Hub_int_HandleChange(tUSBInterface *Dev, int Port);
44 void Hub_SetPortFeature(tUSBInterface *Dev, int Port, int Feat);
45 void Hub_ClearPortFeature(tUSBInterface *HubDev, int Port, int Feat);
46 int Hub_GetPortStatus(tUSBInterface *HubDev, int Port, int Flag);
49 tUSBDriver gUSBHub_Driver = {
51 .Match = {.Class = {0x090000, 0xFF0000}},
52 .Connected = Hub_Connected,
53 .Disconnected = Hub_Disconnected,
56 {0x83, Hub_PortStatusChange}
62 int Hub_DriverInitialise(char **Arguments)
64 USB_RegisterDriver( &gUSBHub_Driver );
69 void Hub_Connected(tUSBInterface *Dev, void *Descriptors, size_t Length)
71 struct sHubDescriptor hub_desc;
72 struct sHubInfo *info;
74 // Read hub descriptor (Class descriptor 0x9, destined for device)
75 USB_ReadDescriptor(Dev, 0x0129, 0, sizeof(hub_desc), &hub_desc);
77 LOG("%i Ports", hub_desc.NbrPorts);
78 LOG("Takes %i ms for power to stabilise", hub_desc.PwrOn2PwrGood*2);
80 // Allocate infomation structure
81 info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8);
83 Log_Error("USBHub", "malloc() failed");
86 USB_SetDeviceDataPtr(Dev, info);
89 info->nPorts = hub_desc.NbrPorts;
90 info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2;
91 memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8);
93 info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
95 // Register poll on endpoint
96 USB_StartPollingEndpoint(Dev, 1);
99 void Hub_Disconnected(tUSBInterface *Dev)
101 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
102 USB_RemoveHub(info->HubPtr);
106 void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data)
108 Uint8 *status = Data;
109 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
111 for( i = 0; i < info->nPorts; i += 8, status ++ )
113 if( i/8 >= Length ) break;
114 LOG("status[%i] = %x", i/8, *status);
115 if( *status == 0 ) continue;
117 for( int j = 0; j < 8; j ++ )
118 if( *status & (1 << j) )
119 Hub_int_HandleChange(Dev, i+j);
123 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
125 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
126 Uint16 status[2]; // Status, Change
129 USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
131 LOG("Port %i: status = {0b%b, 0b%b}", Port, status[0], status[1]);
133 // Handle connections / disconnections
134 if( status[1] & 0x0001 )
136 if( status[0] & 0x0001 ) {
139 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL);
140 Time_Delay(info->PowerOnDelay);
141 // - Start reset process
142 USB_PortCtl_BeginReset(info->HubPtr, Port);
146 USB_DeviceDisconnected(info->HubPtr, Port);
149 USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, Port, 0, NULL);
153 if( status[1] & 0x0010 )
155 if( status[0] & 0x0010 ) {
162 USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_RESET, Port, 0, NULL);
166 void Hub_SetPortFeature(tUSBInterface *Dev, int Port, int Feat)
168 USB_Request(Dev, 0, 0x23, SET_FEATURE, Feat, Port, 0, NULL);
171 void Hub_ClearPortFeature(tUSBInterface *Dev, int Port, int Feat)
173 USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, Feat, Port, 0, NULL);
176 int Hub_GetPortStatus(tUSBInterface *Dev, int Port, int Flag)
178 Uint16 status[2]; // Status, Change
179 USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
180 return !!(status[0] & (1 << Flag));