22fed9dd912afb0088f4090bae83227b8673075d
[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 struct sHubDescriptor
13 {
14         Uint8   DescLength;
15         Uint8   DescType;       // = 0x29
16         Uint8   NbrPorts;
17         Uint16  HubCharacteristics;
18         Uint8   PwrOn2PwrGood;  // 2 ms intervals
19         Uint8   HubContrCurrent;        // Max internal current (mA)
20         Uint8   DeviceRemovable[MAX_PORTS];
21 };
22
23 struct sHubInfo
24 {
25         tUSBHub *HubPtr;
26          int    PowerOnDelay;   // in ms
27          int    nPorts;
28         Uint8   DeviceRemovable[];
29 }
30
31 // === PROTOTYPES ===
32 void    Hub_Connected(tUSBInterface *Dev);
33 void    Hub_Disconnected(tUSBInterface *Dev);
34 void    Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data);
35
36 // === GLOBALS ===
37 tUSBDriver      gUSBHub_Driver = {
38         .Name = "Hub",
39         .Match = {.Class = {0x090000, 0xFF0000}},
40         .Connected = Hub_Connected,
41         .Disconnected = Hub_Disconnected,
42         .MaxEndpoints = 1,
43         .Endpoints = {
44                 {0x83, Hub_PortStatusChange}
45         };
46 };
47
48 // === CODE ===
49 void Hub_Connected(tUSBInterface *Dev)
50 {
51         struct sHubDescriptor   hub_desc;
52         struct sHubInfo *info;  
53
54         // Read hub descriptor
55         USB_ReadDescriptor(Dev, 0x29, 0, sizeof(*hub_desc), hub_desc);
56
57         // Allocate infomation structure
58         info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8);
59         if(!info) {
60                 Log_Error("USBHub", "malloc() failed");
61                 return ;
62         }
63         USB_SetDeviceDataPtr(Dev, info);
64
65         // Fill data
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);
69         // Register
70         info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
71
72         // Register poll on endpoint
73         USB_StartPollingEndpoint(Dev, 1);
74 }
75
76 void Hub_Disconnected(tUSBInterface *Dev)
77 {
78         USB_RemoveHub(Dev);
79 }
80
81 void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
82 {
83         Uint8   *status = Data;
84         struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
85          int    i;
86         for( i = 0; i < info->nPorts; i += 8, status ++ )
87         {
88                 if( i/8 >= Length )     break;
89                 if( *status == 0 )      continue;
90         
91                 for( int j = 0; j < 8; j ++ )
92                         if( *status & (1 << j) )
93                                 Hub_int_HandleChange(Dev, i+j);
94         }
95 }
96
97 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
98 {
99         Uint16  status[2];      // Status, Change
100         
101         // Get port status
102         USB_Request(Dev, 0, 0xA3, 0, 0, Port, 4, status);
103         
104         // Handle connections / disconnections
105 }
106

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