Modules/USB - Working on driver support, little headache
[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(tUSBInterface *Dev);
22 void    USB_SetDeviceDataPtr(tUSBInterface *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 = {", i, j);
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                                 LOG("Endpoint %i/%i/%i = {", i, j, k);
196                                 LOG(" .Address = 0x%2x", endpt->Address);
197                                 LOG(" .Attributes = 0b%8b", endpt->Attributes);
198                                 LOG(" .MaxPacketSize = %i", LittleEndian16(endpt->MaxPacketSize));
199                                 LOG(" .PollingInterval = %i", endpt->PollingInterval);
200                                 LOG("}");
201                         }
202                 }
203                 
204                 free(full_buf);
205         }
206
207         // Done.
208         LEAVE('-');
209 }
210
211 void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
212 {
213         
214 }
215
216 void *USB_GetDeviceDataPtr(tUSBInterface *Dev) { return Dev->Data; }
217 void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr) { Dev->Data = Ptr; }
218
219 int USB_int_AllocateAddress(tUSBHost *Host)
220 {
221          int    i;
222         for( i = 1; i < 128; i ++ )
223         {
224                 if(Host->AddressBitmap[i/8] & (1 << (i%8)))
225                         continue ;
226                 Host->AddressBitmap[i/8] |= 1 << (i%8);
227                 return i;
228         }
229         return 0;
230 }
231
232 void USB_int_DeallocateAddress(tUSBHost *Host, int Address)
233 {
234         Host->AddressBitmap[Address/8] &= ~(1 << (Address%8));
235 }
236
237 void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data)
238 {
239         void    *hdl;
240         // TODO: Sanity check (and check that Type is valid)
241         struct sDeviceRequest   req;
242         req.ReqType = Type;
243         req.Request = Req;
244         req.Value = LittleEndian16( Val );
245         req.Index = LittleEndian16( Indx );
246         req.Length = LittleEndian16( Len );
247         
248         hdl = Host->HostDef->SendSETUP(Host->Ptr, Addr, EndPt, 0, NULL, &req, sizeof(req));
249
250         // TODO: Data toggle?
251         // TODO: Correct sequence? (Some OUT requests need an IN)
252         if( Type & 0x80 )
253         {
254                 hdl = Host->HostDef->SendIN(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len);
255                 while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
256                         Time_Delay(1);
257         }
258         else
259         {
260                 hdl = Host->HostDef->SendOUT(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len);
261         }
262         return hdl;
263 }
264
265 int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
266 {
267         void    *hdl;
268         struct sDeviceRequest   req;
269         req.ReqType = 0;        // bmRequestType
270         req.Request = 5;        // SET_ADDRESS
271         // TODO: Endian
272         req.Value = LittleEndian16( Address & 0x7F );   // wValue
273         req.Index = LittleEndian16( 0 );        // wIndex
274         req.Length = LittleEndian16( 0 );       // wLength
275         
276         // Addr 0:0, Data Toggle = 0, no interrupt
277         hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, NULL, &req, sizeof(req));
278         if(!hdl)
279                 return 1;
280
281         hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, NULL, NULL, 0);
282         
283         while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
284                 Time_Delay(1);
285         
286         return 0;
287 }
288
289 int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest)
290 {
291         const int       ciMaxPacketSize = 0x400;
292         struct sDeviceRequest   req;
293          int    bToggle = 0;
294         void    *final;
295
296         req.ReqType = 0x80;
297         req.Request = 6;        // GET_DESCRIPTOR
298         req.Value = LittleEndian16( ((Type & 0xFF) << 8) | (Index & 0xFF) );
299         req.Index = LittleEndian16( 0 );        // TODO: Language ID
300         req.Length = LittleEndian16( Length );
301         
302         Dev->Host->HostDef->SendSETUP(
303                 Dev->Host->Ptr, Dev->Address, Endpoint,
304                 0, NULL,
305                 &req, sizeof(req)
306                 );
307         
308         bToggle = 1;
309         while( Length > ciMaxPacketSize )
310         {
311                 Dev->Host->HostDef->SendIN(
312                         Dev->Host->Ptr, Dev->Address, Endpoint,
313                         bToggle, NULL,
314                         Dest, ciMaxPacketSize
315                         );
316                 bToggle = !bToggle;
317                 Length -= ciMaxPacketSize;
318         }
319
320         final = Dev->Host->HostDef->SendIN(
321                 Dev->Host->Ptr, Dev->Address, Endpoint,
322                 bToggle, INVLPTR,
323                 Dest, Length
324                 );
325
326         while( Dev->Host->HostDef->IsOpComplete(Dev->Host->Ptr, final) == 0 )
327                 Time_Delay(1);
328
329         return 0;
330 }
331
332 char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index)
333 {
334         struct sDescriptor_String       str;
335          int    src_len, new_len;
336         char    *ret;
337         
338         USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str);
339 //      if(str.Length > sizeof(str)) {
340 //              // IMPOSSIBLE!
341 //              Log_Error("USB", "String is %i bytes, which is over prealloc size (%i)",
342 //                      str.Length, sizeof(str)
343 //                      );
344 //      }
345         src_len = (str.Length - 2) / sizeof(str.Data[0]);
346
347         new_len = _UTF16to8(str.Data, src_len, NULL);   
348         ret = malloc( new_len + 1 );
349         _UTF16to8(str.Data, src_len, ret);
350         ret[new_len] = 0;
351         return ret;
352 }
353
354 int _UTF16to8(Uint16 *Input, int InputLen, char *Dest)
355 {
356          int    str_len, cp_len;
357         Uint32  saved_bits = 0;
358         str_len = 0;
359         for( int i = 0; i < InputLen; i ++)
360         {
361                 Uint32  cp;
362                 Uint16  val = Input[i];
363                 if( val >= 0xD800 && val <= 0xDBFF )
364                 {
365                         // Multibyte - Leading
366                         if(i + 1 > InputLen) {
367                                 cp = '?';
368                         }
369                         else {
370                                 saved_bits = (val - 0xD800) << 10;
371                                 saved_bits += 0x10000;
372                                 continue ;
373                         }
374                 }
375                 else if( val >= 0xDC00 && val <= 0xDFFF )
376                 {
377                         if( !saved_bits ) {
378                                 cp = '?';
379                         }
380                         else {
381                                 saved_bits |= (val - 0xDC00);
382                                 cp = saved_bits;
383                         }
384                 }
385                 else
386                         cp = val;
387
388                 cp_len = WriteUTF8((Uint8*)Dest, cp);
389                 if(Dest)
390                         Dest += cp_len;
391                 str_len += cp_len;
392
393                 saved_bits = 0;
394         }
395         
396         return str_len;
397 }
398

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