Modules/USB - Coming along, reading descriptors now
[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                 
143                 USB_int_ReadDescriptor(dev, 0, 2, 0, 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                 // TODO: Interfaces
161         }
162
163         // Done.
164         LEAVE('-');
165 }
166
167 void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
168 {
169         
170 }
171
172 void *USB_GetDeviceDataPtr(tUSBDevice *Dev) { return Dev->Data; }
173 void USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr) { Dev->Data = Ptr; }
174
175 int USB_int_AllocateAddress(tUSBHost *Host)
176 {
177          int    i;
178         for( i = 1; i < 128; i ++ )
179         {
180                 if(Host->AddressBitmap[i/8] & (1 << (i%8)))
181                         continue ;
182                 Host->AddressBitmap[i/8] |= 1 << (i%8);
183                 return i;
184         }
185         return 0;
186 }
187
188 void USB_int_DeallocateAddress(tUSBHost *Host, int Address)
189 {
190         Host->AddressBitmap[Address/8] &= ~(1 << (Address%8));
191 }
192
193 int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
194 {
195         void    *hdl;
196         struct sDeviceRequest   req;
197         req.ReqType = 0;        // bmRequestType
198         req.Request = 5;        // SET_ADDRESS
199         // TODO: Endian
200         req.Value = LittleEndian16( Address & 0x7F );   // wValue
201         req.Index = LittleEndian16( 0 );        // wIndex
202         req.Length = LittleEndian16( 0 );       // wLength
203         
204         // Addr 0:0, Data Toggle = 0, no interrupt
205         hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, FALSE, &req, sizeof(req));
206         if(!hdl)
207                 return 1;
208
209         // TODO: Data toggle?
210         hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, FALSE, NULL, 0);
211         
212         while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
213                 Time_Delay(1);
214         
215         return 0;
216 }
217
218 int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest)
219 {
220         const int       ciMaxPacketSize = 0x400;
221         struct sDeviceRequest   req;
222          int    bToggle = 0;
223         void    *final;
224
225         req.ReqType = 0x80;
226         req.Request = 6;        // GET_DESCRIPTOR
227         req.Value = LittleEndian16( ((Type & 0xFF) << 8) | (Index & 0xFF) );
228         req.Index = LittleEndian16( 0 );        // TODO: Language ID
229         req.Length = LittleEndian16( Length );
230         
231         Dev->Host->HostDef->SendSETUP(
232                 Dev->Host->Ptr, Dev->Address, Endpoint,
233                 0, NULL,
234                 &req, sizeof(req)
235                 );
236         
237         bToggle = 1;
238         while( Length > ciMaxPacketSize )
239         {
240                 Dev->Host->HostDef->SendIN(
241                         Dev->Host->Ptr, Dev->Address, Endpoint,
242                         bToggle, NULL,
243                         Dest, ciMaxPacketSize
244                         );
245                 bToggle = !bToggle;
246                 Length -= ciMaxPacketSize;
247         }
248
249         final = Dev->Host->HostDef->SendIN(
250                 Dev->Host->Ptr, Dev->Address, Endpoint,
251                 bToggle, INVLPTR,
252                 Dest, Length
253                 );
254
255         while( Dev->Host->HostDef->IsOpComplete(Dev->Host->Ptr, final) == 0 )
256                 Time_Delay(1);
257
258         return 0;
259 }
260
261 char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index)
262 {
263         struct sDescriptor_String       str;
264          int    src_len, new_len;
265         char    *ret;
266         
267         USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str);
268         if(str.Length > sizeof(str)) {
269                 Log_Notice("USB", "String is %i bytes, which is over prealloc size (%i)",
270                         str.Length, sizeof(str)
271                         );
272                 // HACK: 
273                 str.Length = sizeof(str);
274         }
275         src_len = (str.Length - 2) / sizeof(str.Data[0]);
276
277         new_len = _UTF16to8(str.Data, src_len, NULL);   
278         ret = malloc( new_len + 1 );
279         _UTF16to8(str.Data, src_len, ret);
280         ret[new_len] = 0;
281         return ret;
282 }
283
284 int _UTF16to8(Uint16 *Input, int InputLen, char *Dest)
285 {
286          int    str_len, cp_len;
287         Uint32  saved_bits = 0;
288         str_len = 0;
289         for( int i = 0; i < InputLen; i ++)
290         {
291                 Uint32  cp;
292                 Uint16  val = Input[i];
293                 if( val >= 0xD800 && val <= 0xDBFF )
294                 {
295                         // Multibyte - Leading
296                         if(i + 1 > InputLen) {
297                                 cp = '?';
298                         }
299                         else {
300                                 saved_bits = (val - 0xD800) << 10;
301                                 saved_bits += 0x10000;
302                                 continue ;
303                         }
304                 }
305                 else if( val >= 0xDC00 && val <= 0xDFFF )
306                 {
307                         if( !saved_bits ) {
308                                 cp = '?';
309                         }
310                         else {
311                                 saved_bits |= (val - 0xDC00);
312                                 cp = saved_bits;
313                         }
314                 }
315                 else
316                         cp = val;
317
318                 cp_len = WriteUTF8((Uint8*)Dest, cp);
319                 if(Dest)
320                         Dest += cp_len;
321                 str_len += cp_len;
322
323                 saved_bits = 0;
324         }
325         
326         return str_len;
327 }
328

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