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

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