Modules/USB - Commenting mostly
[tpg/acess2.git] / Modules / USB / Core / usb.c
1 /*
2  * Acess 2 USB Stack
3  * USB Packet Control
4  */
5 #define DEBUG   1
6 #include <acess.h>
7 #include <vfs.h>
8 #include <drv_pci.h>
9 #include "usb.h"
10 #include "usb_proto.h"
11
12 // === IMPORTS ===
13 extern tUSBHost *gUSB_Hosts;
14
15 // === STRUCTURES ===
16
17 // === PROTOTYPES ===
18 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts);
19 void    USB_DeviceConnected(tUSBHub *Hub, int Port);
20 void    USB_DeviceDisconnected(tUSBHub *Hub, int Port);
21 void    *USB_GetDeviceDataPtr(tUSBDevice *Dev);
22 void    USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr);
23  int    USB_int_AllocateAddress(tUSBHost *Host);
24  int    USB_int_SendSetupSetAddress(tUSBHost *Host, int Address);
25  int    USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest);
26 char    *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index);
27
28  int    _UTF16to8(Uint16 *Input, int InputLen, char *Dest);
29
30 // === CODE ===
31 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
32 {
33         tUSBHost        *host;
34         
35         host = malloc(sizeof(tUSBHost) + nPorts*sizeof(void*));
36         if(!host) {
37                 // Oh, bugger.
38                 return NULL;
39         }
40         host->HostDef = HostDef;
41         host->Ptr = ControllerPtr;
42         memset(host->AddressBitmap, 0, sizeof(host->AddressBitmap));
43
44         host->RootHubDev.Next = NULL;
45         host->RootHubDev.ParentHub = NULL;
46         host->RootHubDev.Host = host;
47         host->RootHubDev.Address = 0;
48         host->RootHubDev.Driver = NULL;
49         host->RootHubDev.Data = NULL;
50
51         host->RootHub.Device = &host->RootHubDev;
52         host->RootHub.CheckPorts = NULL;
53         host->RootHub.nPorts = nPorts;
54         memset(host->RootHub.Devices, 0, sizeof(void*)*nPorts);
55
56         // TODO: Lock
57         host->Next = gUSB_Hosts;
58         gUSB_Hosts = host;
59
60         return &host->RootHub;
61 }
62
63 void USB_DeviceConnected(tUSBHub *Hub, int Port)
64 {
65         tUSBDevice      *dev;
66         if( Port >= Hub->nPorts )       return ;
67         if( Hub->Devices[Port] )        return ;
68
69         ENTER("pHub iPort", Hub, Port);
70
71         // 0. Perform port init? (done in hub?) 
72         
73         // Create structure
74         dev = malloc(sizeof(tUSBDevice));
75         dev->Next = NULL;
76         dev->ParentHub = Hub;
77         dev->Host = Hub->Device->Host;
78         dev->Address = 0;
79         dev->Driver = 0;
80         dev->Data = 0;
81
82         // 1. Assign an address
83         dev->Address = USB_int_AllocateAddress(dev->Host);
84         if(dev->Address == 0) {
85                 Log_Error("USB", "No addresses avaliable on host %p", dev->Host);
86                 free(dev);
87                 LEAVE('-');
88                 return ;
89         }
90         USB_int_SendSetupSetAddress(dev->Host, dev->Address);
91         LOG("Assigned address %i", dev->Address);
92         
93         // 2. Get device information
94         {
95                 struct sDescriptor_Device       desc;
96                 LOG("Getting device descriptor");
97                 // Endpoint 0, Desc Type 1, Index 0
98                 USB_int_ReadDescriptor(dev, 0, 1, 0, sizeof(desc), &desc);
99                 
100                 LOG("Device Descriptor = {");
101                 LOG(" .Length = %i", desc.Length);
102                 LOG(" .Type = %i", desc.Type);
103                 LOG(" .USBVersion = 0x%04x", desc.USBVersion);
104                 LOG(" .DeviceClass = 0x%02x", desc.DeviceClass);
105                 LOG(" .DeviceSubClass = 0x%02x", desc.DeviceSubClass);
106                 LOG(" .DeviceProtocol = 0x%02x", desc.DeviceProtocol);
107                 LOG(" .MaxPacketSize = 0x%02x", desc.MaxPacketSize);
108                 LOG(" .VendorID = 0x%04x", desc.VendorID);
109                 LOG(" .ProductID = 0x%04x", desc.ProductID);
110                 LOG(" .DeviceID = 0x%04x", desc.DeviceID);
111                 LOG(" .ManufacturerStr = Str %i", desc.ManufacturerStr);
112                 LOG(" .ProductStr = Str %i", desc.ProductStr);
113                 LOG(" .SerialNumberStr = Str %i", desc.SerialNumberStr);
114                 LOG(" .NumConfigurations = %i", desc.SerialNumberStr);
115                 LOG("}");
116                 
117                 if( desc.ManufacturerStr )
118                 {
119                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.ManufacturerStr);
120                         LOG("ManufacturerStr = '%s'", tmp);
121                         free(tmp);
122                 }
123                 if( desc.ProductStr )
124                 {
125                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.ProductStr);
126                         LOG("ProductStr = '%s'", tmp);
127                         free(tmp);
128                 }
129                 if( desc.SerialNumberStr )
130                 {
131                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.SerialNumberStr);
132                         LOG("SerialNumbertStr = '%s'", tmp);
133                         free(tmp);
134                 }
135         }
136         
137         // 3. Get configurations
138         for( int i = 0; i < 1; i ++ )
139         {
140                 struct sDescriptor_Configuration        desc;
141                 void    *full_buf;
142                 char    *cur_ptr;
143                 
144                 USB_int_ReadDescriptor(dev, 0, 2, i, sizeof(desc), &desc);
145                 LOG("Configuration Descriptor %i = {", i);
146                 LOG(" .Length = %i", desc.Length);
147                 LOG(" .Type = %i", desc.Type);
148                 LOG(" .TotalLength = 0x%x", LittleEndian16(desc.TotalLength));
149                 LOG(" .NumInterfaces = %i", desc.NumInterfaces);
150                 LOG(" .ConfigurationValue = %i", desc.ConfigurationValue);
151                 LOG(" .ConfigurationStr = %i", desc.ConfigurationStr);
152                 LOG(" .AttributesBmp = 0b%b", desc.AttributesBmp);
153                 LOG(" .MaxPower = %i (*2mA)", desc.MaxPower);
154                 LOG("}");
155                 if( desc.ConfigurationStr ) {
156                         char    *tmp = USB_int_GetDeviceString(dev, 0, desc.ConfigurationStr);
157                         LOG("ConfigurationStr = '%s'", tmp);
158                         free(tmp);
159                 }
160
161                 cur_ptr = full_buf = malloc( LittleEndian16(desc.TotalLength) );
162                 USB_int_ReadDescriptor(dev, 0, 2, i, desc.TotalLength, full_buf);
163
164                 cur_ptr += desc.Length;
165
166                 // TODO: Interfaces
167                 for( int j = 0; j < desc.NumInterfaces; j ++ )
168                 {
169                         struct sDescriptor_Interface *iface;
170                         iface = (void*)cur_ptr;
171                         // TODO: Sanity check with remaining space
172                         cur_ptr += sizeof(*iface);
173                         
174                         LOG("Interface %i/%i = {");
175                         LOG(" .InterfaceNum = %i", iface->InterfaceNum);
176                         LOG(" .NumEndpoints = %i", iface->NumEndpoints);
177                         LOG(" .InterfaceClass = 0x%x", iface->InterfaceClass);
178                         LOG(" .InterfaceSubClass = 0x%x", iface->InterfaceSubClass);
179                         LOG(" .InterfaceProcol = 0x%x", iface->InterfaceProtocol);
180
181                         if( iface->InterfaceStr ) {
182                                 char    *tmp = USB_int_GetDeviceString(dev, 0, iface->InterfaceStr);
183                                 LOG(" .InterfaceStr = %i '%s'", iface->InterfaceStr, tmp);
184                                 free(tmp);
185                         }
186                         LOG("}");
187
188                         for( int k = 0; k < iface->NumEndpoints; k ++ )
189                         {
190                                 struct sDescriptor_Endpoint *endpt;
191                                 endpt = (void*)cur_ptr;
192                                 // TODO: Sanity check with remaining space
193                                 cur_ptr += sizeof(*endpt);
194                                 
195                                 
196                         }
197                 }
198                 
199                 free(full_buf);
200         }
201
202         // Done.
203         LEAVE('-');
204 }
205
206 void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
207 {
208         
209 }
210
211 void *USB_GetDeviceDataPtr(tUSBDevice *Dev) { return Dev->Data; }
212 void USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr) { Dev->Data = Ptr; }
213
214 int USB_int_AllocateAddress(tUSBHost *Host)
215 {
216          int    i;
217         for( i = 1; i < 128; i ++ )
218         {
219                 if(Host->AddressBitmap[i/8] & (1 << (i%8)))
220                         continue ;
221                 Host->AddressBitmap[i/8] |= 1 << (i%8);
222                 return i;
223         }
224         return 0;
225 }
226
227 void USB_int_DeallocateAddress(tUSBHost *Host, int Address)
228 {
229         Host->AddressBitmap[Address/8] &= ~(1 << (Address%8));
230 }
231
232 int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
233 {
234         void    *hdl;
235         struct sDeviceRequest   req;
236         req.ReqType = 0;        // bmRequestType
237         req.Request = 5;        // SET_ADDRESS
238         // TODO: Endian
239         req.Value = LittleEndian16( Address & 0x7F );   // wValue
240         req.Index = LittleEndian16( 0 );        // wIndex
241         req.Length = LittleEndian16( 0 );       // wLength
242         
243         // Addr 0:0, Data Toggle = 0, no interrupt
244         hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, FALSE, &req, sizeof(req));
245         if(!hdl)
246                 return 1;
247
248         // TODO: Data toggle?
249         hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, FALSE, NULL, 0);
250         
251         while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
252                 Time_Delay(1);
253         
254         return 0;
255 }
256
257 int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest)
258 {
259         const int       ciMaxPacketSize = 0x400;
260         struct sDeviceRequest   req;
261          int    bToggle = 0;
262         void    *final;
263
264         req.ReqType = 0x80;
265         req.Request = 6;        // GET_DESCRIPTOR
266         req.Value = LittleEndian16( ((Type & 0xFF) << 8) | (Index & 0xFF) );
267         req.Index = LittleEndian16( 0 );        // TODO: Language ID
268         req.Length = LittleEndian16( Length );
269         
270         Dev->Host->HostDef->SendSETUP(
271                 Dev->Host->Ptr, Dev->Address, Endpoint,
272                 0, NULL,
273                 &req, sizeof(req)
274                 );
275         
276         bToggle = 1;
277         while( Length > ciMaxPacketSize )
278         {
279                 Dev->Host->HostDef->SendIN(
280                         Dev->Host->Ptr, Dev->Address, Endpoint,
281                         bToggle, NULL,
282                         Dest, ciMaxPacketSize
283                         );
284                 bToggle = !bToggle;
285                 Length -= ciMaxPacketSize;
286         }
287
288         final = Dev->Host->HostDef->SendIN(
289                 Dev->Host->Ptr, Dev->Address, Endpoint,
290                 bToggle, INVLPTR,
291                 Dest, Length
292                 );
293
294         while( Dev->Host->HostDef->IsOpComplete(Dev->Host->Ptr, final) == 0 )
295                 Time_Delay(1);
296
297         return 0;
298 }
299
300 char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index)
301 {
302         struct sDescriptor_String       str;
303          int    src_len, new_len;
304         char    *ret;
305         
306         USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str);
307         if(str.Length > sizeof(str)) {
308                 Log_Notice("USB", "String is %i bytes, which is over prealloc size (%i)",
309                         str.Length, sizeof(str)
310                         );
311                 // HACK: 
312                 str.Length = sizeof(str);
313         }
314         src_len = (str.Length - 2) / sizeof(str.Data[0]);
315
316         new_len = _UTF16to8(str.Data, src_len, NULL);   
317         ret = malloc( new_len + 1 );
318         _UTF16to8(str.Data, src_len, ret);
319         ret[new_len] = 0;
320         return ret;
321 }
322
323 int _UTF16to8(Uint16 *Input, int InputLen, char *Dest)
324 {
325          int    str_len, cp_len;
326         Uint32  saved_bits = 0;
327         str_len = 0;
328         for( int i = 0; i < InputLen; i ++)
329         {
330                 Uint32  cp;
331                 Uint16  val = Input[i];
332                 if( val >= 0xD800 && val <= 0xDBFF )
333                 {
334                         // Multibyte - Leading
335                         if(i + 1 > InputLen) {
336                                 cp = '?';
337                         }
338                         else {
339                                 saved_bits = (val - 0xD800) << 10;
340                                 saved_bits += 0x10000;
341                                 continue ;
342                         }
343                 }
344                 else if( val >= 0xDC00 && val <= 0xDFFF )
345                 {
346                         if( !saved_bits ) {
347                                 cp = '?';
348                         }
349                         else {
350                                 saved_bits |= (val - 0xDC00);
351                                 cp = saved_bits;
352                         }
353                 }
354                 else
355                         cp = val;
356
357                 cp_len = WriteUTF8((Uint8*)Dest, cp);
358                 if(Dest)
359                         Dest += cp_len;
360                 str_len += cp_len;
361
362                 saved_bits = 0;
363         }
364         
365         return str_len;
366 }
367

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