Modules/USB - Cleaning up protocol code, working on device API
[tpg/acess2.git] / Modules / USB / Core / usb.c
1 /*
2  * Acess 2 USB Stack
3  * - By John Hodge (thePowersGang)
4  *
5  * usb.c
6  * - USB Packet Control
7  */
8 #define DEBUG   1
9 #include <acess.h>
10 #include <vfs.h>
11 #include <drv_pci.h>
12 #include "usb.h"
13 #include "usb_proto.h"
14 #include "usb_lowlevel.h"
15
16 // === IMPORTS ===
17 extern tUSBHost *gUSB_Hosts;
18
19 // === STRUCTURES ===
20
21 // === PROTOTYPES ===
22 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts);
23 void    USB_DeviceConnected(tUSBHub *Hub, int Port);
24 void    USB_DeviceDisconnected(tUSBHub *Hub, int Port);
25 void    *USB_GetDeviceDataPtr(tUSBInterface *Dev);
26 void    USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr);
27  int    USB_int_AllocateAddress(tUSBHost *Host);
28
29 // === CODE ===
30 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
31 {
32         tUSBHost        *host;
33         
34         host = malloc(sizeof(tUSBHost) + nPorts*sizeof(void*));
35         if(!host) {
36                 // Oh, bugger.
37                 return NULL;
38         }
39         host->HostDef = HostDef;
40         host->Ptr = ControllerPtr;
41         memset(host->AddressBitmap, 0, sizeof(host->AddressBitmap));
42
43         host->RootHubDev.ParentHub = NULL;
44         host->RootHubDev.Host = host;
45         host->RootHubDev.Address = 0;
46
47         host->RootHubIf.Next = NULL;
48         host->RootHubIf.Dev = &host->RootHubDev;
49         host->RootHubIf.Driver = NULL;
50         host->RootHubIf.Data = NULL;
51         host->RootHubIf.nEndpoints = 0;
52
53         host->RootHub.Interface = &host->RootHubIf;
54         host->RootHub.nPorts = nPorts;
55         memset(host->RootHub.Devices, 0, sizeof(void*)*nPorts);
56
57         // TODO: Lock
58         host->Next = gUSB_Hosts;
59         gUSB_Hosts = host;
60
61         return &host->RootHub;
62 }
63
64 void USB_DeviceConnected(tUSBHub *Hub, int Port)
65 {
66         tUSBDevice      *dev;
67         if( Port >= Hub->nPorts )       return ;
68         if( Hub->Devices[Port] )        return ;
69
70         ENTER("pHub iPort", Hub, Port);
71
72         // 0. Perform port init? (done in hub?) 
73         
74         // Create structure
75         dev = malloc(sizeof(tUSBDevice));
76         dev->ParentHub = Hub;
77         dev->Host = Hub->Interface->Dev->Host;
78         dev->Address = 0;
79
80         // 1. Assign an address
81         dev->Address = USB_int_AllocateAddress(dev->Host);
82         if(dev->Address == 0) {
83                 Log_Error("USB", "No addresses avaliable on host %p", dev->Host);
84                 free(dev);
85                 LEAVE('-');
86                 return ;
87         }
88         USB_int_SendSetupSetAddress(dev->Host, dev->Address);
89         LOG("Assigned address %i", dev->Address);
90         
91         // 2. Get device information
92         {
93                 struct sDescriptor_Device       desc;
94                 LOG("Getting device descriptor");
95                 // Endpoint 0, Desc Type 1, Index 0
96                 USB_int_ReadDescriptor(dev, 0, 1, 0, sizeof(desc), &desc);
97                 
98                 LOG("Device Descriptor = {");
99                 LOG(" .Length = %i", desc.Length);
100                 LOG(" .Type = %i", desc.Type);
101                 LOG(" .USBVersion = 0x%04x", desc.USBVersion);
102                 LOG(" .DeviceClass = 0x%02x", desc.DeviceClass);
103                 LOG(" .DeviceSubClass = 0x%02x", desc.DeviceSubClass);
104                 LOG(" .DeviceProtocol = 0x%02x", desc.DeviceProtocol);
105                 LOG(" .MaxPacketSize = 0x%02x", desc.MaxPacketSize);
106                 LOG(" .VendorID = 0x%04x", desc.VendorID);
107                 LOG(" .ProductID = 0x%04x", desc.ProductID);
108                 LOG(" .DeviceID = 0x%04x", desc.DeviceID);
109                 LOG(" .ManufacturerStr = Str %i", desc.ManufacturerStr);
110                 LOG(" .ProductStr = Str %i", desc.ProductStr);
111                 LOG(" .SerialNumberStr = Str %i", desc.SerialNumberStr);
112                 LOG(" .NumConfigurations = %i", desc.SerialNumberStr);
113                 LOG("}");
114                 
115                 if( desc.ManufacturerStr )
116                 {
117                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.ManufacturerStr);
118                         LOG("ManufacturerStr = '%s'", tmp);
119                         free(tmp);
120                 }
121                 if( desc.ProductStr )
122                 {
123                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.ProductStr);
124                         LOG("ProductStr = '%s'", tmp);
125                         free(tmp);
126                 }
127                 if( desc.SerialNumberStr )
128                 {
129                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.SerialNumberStr);
130                         LOG("SerialNumbertStr = '%s'", tmp);
131                         free(tmp);
132                 }
133         }
134         
135         // 3. Get configurations
136         for( int i = 0; i < 1; i ++ )
137         {
138                 struct sDescriptor_Configuration        desc;
139                 void    *full_buf;
140                 char    *cur_ptr;
141                 
142                 USB_int_ReadDescriptor(dev, 0, 2, i, sizeof(desc), &desc);
143                 LOG("Configuration Descriptor %i = {", i);
144                 LOG(" .Length = %i", desc.Length);
145                 LOG(" .Type = %i", desc.Type);
146                 LOG(" .TotalLength = 0x%x", LittleEndian16(desc.TotalLength));
147                 LOG(" .NumInterfaces = %i", desc.NumInterfaces);
148                 LOG(" .ConfigurationValue = %i", desc.ConfigurationValue);
149                 LOG(" .ConfigurationStr = %i", desc.ConfigurationStr);
150                 LOG(" .AttributesBmp = 0b%b", desc.AttributesBmp);
151                 LOG(" .MaxPower = %i (*2mA)", desc.MaxPower);
152                 LOG("}");
153                 if( desc.ConfigurationStr ) {
154                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.ConfigurationStr);
155                         LOG("ConfigurationStr = '%s'", tmp);
156                         free(tmp);
157                 }
158
159                 cur_ptr = full_buf = malloc( LittleEndian16(desc.TotalLength) );
160                 USB_int_ReadDescriptor(dev, 0, 2, i, desc.TotalLength, full_buf);
161
162                 cur_ptr += desc.Length;
163
164                 // TODO: Interfaces
165                 for( int j = 0; j < desc.NumInterfaces; j ++ )
166                 {
167                         struct sDescriptor_Interface *iface;
168                         iface = (void*)cur_ptr;
169                         // TODO: Sanity check with remaining space
170                         cur_ptr += sizeof(*iface);
171                         
172                         LOG("Interface %i/%i = {", i, j);
173                         LOG(" .InterfaceNum = %i", iface->InterfaceNum);
174                         LOG(" .NumEndpoints = %i", iface->NumEndpoints);
175                         LOG(" .InterfaceClass = 0x%x", iface->InterfaceClass);
176                         LOG(" .InterfaceSubClass = 0x%x", iface->InterfaceSubClass);
177                         LOG(" .InterfaceProcol = 0x%x", iface->InterfaceProtocol);
178
179                         if( iface->InterfaceStr ) {
180                                 char    *tmp = USB_int_GetDeviceString(dev, 0, iface->InterfaceStr);
181                                 LOG(" .InterfaceStr = %i '%s'", iface->InterfaceStr, tmp);
182                                 free(tmp);
183                         }
184                         LOG("}");
185
186                         for( int k = 0; k < iface->NumEndpoints; k ++ )
187                         {
188                                 struct sDescriptor_Endpoint *endpt;
189                                 endpt = (void*)cur_ptr;
190                                 // TODO: Sanity check with remaining space
191                                 cur_ptr += sizeof(*endpt);
192                                 
193                                 LOG("Endpoint %i/%i/%i = {", i, j, k);
194                                 LOG(" .Address = 0x%2x", endpt->Address);
195                                 LOG(" .Attributes = 0b%8b", endpt->Attributes);
196                                 LOG(" .MaxPacketSize = %i", LittleEndian16(endpt->MaxPacketSize));
197                                 LOG(" .PollingInterval = %i", endpt->PollingInterval);
198                                 LOG("}");
199                         }
200                 }
201                 
202                 free(full_buf);
203         }
204
205         // Done.
206         LEAVE('-');
207 }
208
209 void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
210 {
211         
212 }
213
214 void *USB_GetDeviceDataPtr(tUSBInterface *Dev) { return Dev->Data; }
215 void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr) { Dev->Data = Ptr; }
216
217 int USB_int_AllocateAddress(tUSBHost *Host)
218 {
219          int    i;
220         for( i = 1; i < 128; i ++ )
221         {
222                 if(Host->AddressBitmap[i/8] & (1 << (i%8)))
223                         continue ;
224                 Host->AddressBitmap[i/8] |= 1 << (i%8);
225                 return i;
226         }
227         return 0;
228 }
229
230 void USB_int_DeallocateAddress(tUSBHost *Host, int Address)
231 {
232         Host->AddressBitmap[Address/8] &= ~(1 << (Address%8));
233 }
234

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