3 * - By John Hodge (thePowersGang)
10 #define MAX_PORTS 32 // Not actually a max, but used for DeviceRemovable
15 Uint8 DescType; // = 0x29
17 Uint16 HubCharacteristics;
18 Uint8 PwrOn2PwrGood; // 2 ms intervals
19 Uint8 HubContrCurrent; // Max internal current (mA)
20 Uint8 DeviceRemovable[MAX_PORTS];
26 int PowerOnDelay; // in ms
28 Uint8 DeviceRemovable[];
32 void Hub_Connected(tUSBInterface *Dev);
33 void Hub_Disconnected(tUSBInterface *Dev);
34 void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data);
37 tUSBDriver gUSBHub_Driver = {
39 .Match = {.Class = {0x090000, 0xFF0000}},
40 .Connected = Hub_Connected,
41 .Disconnected = Hub_Disconnected,
44 {0x83, Hub_PortStatusChange}
49 void Hub_Connected(tUSBInterface *Dev)
51 struct sHubDescriptor hub_desc;
52 struct sHubInfo *info;
54 // Read hub descriptor
55 USB_ReadDescriptor(Dev, 0x29, 0, sizeof(*hub_desc), hub_desc);
57 // Allocate infomation structure
58 info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8);
60 Log_Error("USBHub", "malloc() failed");
63 USB_SetDeviceDataPtr(Dev, info);
66 info->nPorts = hub_desc.NbrPorts;
67 info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2;
68 memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8);
70 info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
72 // Register poll on endpoint
73 USB_StartPollingEndpoint(Dev, 1);
76 void Hub_Disconnected(tUSBInterface *Dev)
81 void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
84 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
86 for( i = 0; i < info->nPorts; i += 8, status ++ )
88 if( i/8 >= Length ) break;
89 if( *status == 0 ) continue;
91 for( int j = 0; j < 8; j ++ )
92 if( *status & (1 << j) )
93 Hub_int_HandleChange(Dev, i+j);
97 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
99 Uint16 status[2]; // Status, Change
102 USB_Request(Dev, 0, 0xA3, 0, 0, Port, 4, status);
104 // Handle connections / disconnections