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);
45 tUSBDriver gUSBHub_Driver = {
47 .Match = {.Class = {0x090000, 0xFF0000}},
48 .Connected = Hub_Connected,
49 .Disconnected = Hub_Disconnected,
52 {0x83, Hub_PortStatusChange}
57 void Hub_Connected(tUSBInterface *Dev)
59 struct sHubDescriptor hub_desc;
60 struct sHubInfo *info;
62 // Read hub descriptor
63 USB_ReadDescriptor(Dev, 0x29, 0, sizeof(*hub_desc), hub_desc);
65 // Allocate infomation structure
66 info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8);
68 Log_Error("USBHub", "malloc() failed");
71 USB_SetDeviceDataPtr(Dev, info);
74 info->nPorts = hub_desc.NbrPorts;
75 info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2;
76 memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8);
78 info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
80 // Register poll on endpoint
81 USB_StartPollingEndpoint(Dev, 1);
84 void Hub_Disconnected(tUSBInterface *Dev)
89 void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
92 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
94 for( i = 0; i < info->nPorts; i += 8, status ++ )
96 if( i/8 >= Length ) break;
97 if( *status == 0 ) continue;
99 for( int j = 0; j < 8; j ++ )
100 if( *status & (1 << j) )
101 Hub_int_HandleChange(Dev, i+j);
105 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
107 struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
108 Uint16 status[2]; // Status, Change
111 USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
113 // Handle connections / disconnections
114 if( status[1] & 0x0001 )
116 if( status[0] & 0x0001 ) {
119 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL);
120 Time_Delay(info->PowerOnDelay);
122 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL);
125 USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_ENABLE, Port, 0, NULL);
127 USB_DeviceConnected(info->HubPtr, Port);
131 USB_DeviceDisconnected(info->HubPtr, Port);