Modules/USB - Little work on hub code
[tpg/acess2.git] / Modules / USB / Core / hub.c
1 /*
2  * Acess2 USB Stack
3  * - By John Hodge (thePowersGang)
4  *
5  * hub.c
6  * - Basic hub driver
7  */
8 #include <usb_hub.h>
9
10 #define MAX_PORTS       32      // Not actually a max, but used for DeviceRemovable
11
12 #define GET_STATUS      0
13 #define SET_FEATURE     3
14
15 #define PORT_CONNECTION 0
16 #define PORT_ENABLE     1
17 #define PORT_RESET      4
18 #define PORT_POWER      8
19
20 struct sHubDescriptor
21 {
22         Uint8   DescLength;
23         Uint8   DescType;       // = 0x29
24         Uint8   NbrPorts;
25         Uint16  HubCharacteristics;
26         Uint8   PwrOn2PwrGood;  // 2 ms intervals
27         Uint8   HubContrCurrent;        // Max internal current (mA)
28         Uint8   DeviceRemovable[MAX_PORTS];
29 };
30
31 struct sHubInfo
32 {
33         tUSBHub *HubPtr;
34          int    PowerOnDelay;   // in ms
35          int    nPorts;
36         Uint8   DeviceRemovable[];
37 }
38
39 // === PROTOTYPES ===
40 void    Hub_Connected(tUSBInterface *Dev);
41 void    Hub_Disconnected(tUSBInterface *Dev);
42 void    Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data);
43
44 // === GLOBALS ===
45 tUSBDriver      gUSBHub_Driver = {
46         .Name = "Hub",
47         .Match = {.Class = {0x090000, 0xFF0000}},
48         .Connected = Hub_Connected,
49         .Disconnected = Hub_Disconnected,
50         .MaxEndpoints = 1,
51         .Endpoints = {
52                 {0x83, Hub_PortStatusChange}
53         };
54 };
55
56 // === CODE ===
57 void Hub_Connected(tUSBInterface *Dev)
58 {
59         struct sHubDescriptor   hub_desc;
60         struct sHubInfo *info;  
61
62         // Read hub descriptor
63         USB_ReadDescriptor(Dev, 0x29, 0, sizeof(*hub_desc), hub_desc);
64
65         // Allocate infomation structure
66         info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8);
67         if(!info) {
68                 Log_Error("USBHub", "malloc() failed");
69                 return ;
70         }
71         USB_SetDeviceDataPtr(Dev, info);
72
73         // Fill data
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);
77         // Register
78         info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
79
80         // Register poll on endpoint
81         USB_StartPollingEndpoint(Dev, 1);
82 }
83
84 void Hub_Disconnected(tUSBInterface *Dev)
85 {
86         USB_RemoveHub(Dev);
87 }
88
89 void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
90 {
91         Uint8   *status = Data;
92         struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
93          int    i;
94         for( i = 0; i < info->nPorts; i += 8, status ++ )
95         {
96                 if( i/8 >= Length )     break;
97                 if( *status == 0 )      continue;
98         
99                 for( int j = 0; j < 8; j ++ )
100                         if( *status & (1 << j) )
101                                 Hub_int_HandleChange(Dev, i+j);
102         }
103 }
104
105 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
106 {
107         struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
108         Uint16  status[2];      // Status, Change
109         
110         // Get port status
111         USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
112         
113         // Handle connections / disconnections
114         if( status[1] & 0x0001 )
115         {
116                 if( status[0] & 0x0001 ) {
117                         // Connected
118                         // - Power on port
119                         USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL);
120                         Time_Delay(info->PowerOnDelay);
121                         // - Reset
122                         USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL);
123                         Time_Delay(50);
124                         // - Enable
125                         USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_ENABLE, Port, 0, NULL);
126                         // - Poke USB Stack
127                         USB_DeviceConnected(info->HubPtr, Port);
128                 }
129                 else {
130                         // Disconnected
131                         USB_DeviceDisconnected(info->HubPtr, Port);
132                 }
133         }
134 }
135

UCC git Repository :: git.ucc.asn.au