10 #include "usb_proto.h"
13 extern tUSBHost *gUSB_Hosts;
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);
28 int _UTF16to8(Uint16 *Input, int InputLen, char *Dest);
31 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
35 host = malloc(sizeof(tUSBHost) + nPorts*sizeof(void*));
40 host->HostDef = HostDef;
41 host->Ptr = ControllerPtr;
42 memset(host->AddressBitmap, 0, sizeof(host->AddressBitmap));
44 host->RootHubDev.ParentHub = NULL;
45 host->RootHubDev.Host = host;
46 host->RootHubDev.Address = 0;
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;
54 host->RootHub.Interface = &host->RootHubIf;
55 host->RootHub.nPorts = nPorts;
56 memset(host->RootHub.Devices, 0, sizeof(void*)*nPorts);
59 host->Next = gUSB_Hosts;
62 return &host->RootHub;
65 void USB_DeviceConnected(tUSBHub *Hub, int Port)
68 if( Port >= Hub->nPorts ) return ;
69 if( Hub->Devices[Port] ) return ;
71 ENTER("pHub iPort", Hub, Port);
73 // 0. Perform port init? (done in hub?)
76 dev = malloc(sizeof(tUSBDevice));
78 dev->Host = Hub->Interface->Dev->Host;
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);
89 USB_int_SendSetupSetAddress(dev->Host, dev->Address);
90 LOG("Assigned address %i", dev->Address);
92 // 2. Get device information
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);
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);
116 if( desc.ManufacturerStr )
118 char *tmp = USB_int_GetDeviceString(dev, 0, desc.ManufacturerStr);
119 LOG("ManufacturerStr = '%s'", tmp);
122 if( desc.ProductStr )
124 char *tmp = USB_int_GetDeviceString(dev, 0, desc.ProductStr);
125 LOG("ProductStr = '%s'", tmp);
128 if( desc.SerialNumberStr )
130 char *tmp = USB_int_GetDeviceString(dev, 0, desc.SerialNumberStr);
131 LOG("SerialNumbertStr = '%s'", tmp);
136 // 3. Get configurations
137 for( int i = 0; i < 1; i ++ )
139 struct sDescriptor_Configuration desc;
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);
154 if( desc.ConfigurationStr ) {
155 char *tmp = USB_int_GetDeviceString(dev, 0, desc.ConfigurationStr);
156 LOG("ConfigurationStr = '%s'", tmp);
160 cur_ptr = full_buf = malloc( LittleEndian16(desc.TotalLength) );
161 USB_int_ReadDescriptor(dev, 0, 2, i, desc.TotalLength, full_buf);
163 cur_ptr += desc.Length;
166 for( int j = 0; j < desc.NumInterfaces; j ++ )
168 struct sDescriptor_Interface *iface;
169 iface = (void*)cur_ptr;
170 // TODO: Sanity check with remaining space
171 cur_ptr += sizeof(*iface);
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);
180 if( iface->InterfaceStr ) {
181 char *tmp = USB_int_GetDeviceString(dev, 0, iface->InterfaceStr);
182 LOG(" .InterfaceStr = %i '%s'", iface->InterfaceStr, tmp);
187 for( int k = 0; k < iface->NumEndpoints; k ++ )
189 struct sDescriptor_Endpoint *endpt;
190 endpt = (void*)cur_ptr;
191 // TODO: Sanity check with remaining space
192 cur_ptr += sizeof(*endpt);
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);
210 void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
215 void *USB_GetDeviceDataPtr(tUSBInterface *Dev) { return Dev->Data; }
216 void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr) { Dev->Data = Ptr; }
218 int USB_int_AllocateAddress(tUSBHost *Host)
221 for( i = 1; i < 128; i ++ )
223 if(Host->AddressBitmap[i/8] & (1 << (i%8)))
225 Host->AddressBitmap[i/8] |= 1 << (i%8);
231 void USB_int_DeallocateAddress(tUSBHost *Host, int Address)
233 Host->AddressBitmap[Address/8] &= ~(1 << (Address%8));
236 void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data)
239 // TODO: Sanity check (and check that Type is valid)
240 struct sDeviceRequest req;
243 req.Value = LittleEndian16( Val );
244 req.Index = LittleEndian16( Indx );
245 req.Length = LittleEndian16( Len );
247 hdl = Host->HostDef->SendSETUP(Host->Ptr, Addr, EndPt, 0, NULL, &req, sizeof(req));
249 // TODO: Data toggle?
250 // TODO: Correct sequence? (Some OUT requests need an IN)
253 hdl = Host->HostDef->SendIN(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len);
254 while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
259 hdl = Host->HostDef->SendOUT(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len);
264 int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
267 struct sDeviceRequest req;
268 req.ReqType = 0; // bmRequestType
269 req.Request = 5; // SET_ADDRESS
271 req.Value = LittleEndian16( Address & 0x7F ); // wValue
272 req.Index = LittleEndian16( 0 ); // wIndex
273 req.Length = LittleEndian16( 0 ); // wLength
275 // Addr 0:0, Data Toggle = 0, no interrupt
276 hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, NULL, &req, sizeof(req));
280 hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, NULL, NULL, 0);
282 while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
288 int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest)
290 const int ciMaxPacketSize = 0x400;
291 struct sDeviceRequest req;
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 );
301 Dev->Host->HostDef->SendSETUP(
302 Dev->Host->Ptr, Dev->Address, Endpoint,
308 while( Length > ciMaxPacketSize )
310 Dev->Host->HostDef->SendIN(
311 Dev->Host->Ptr, Dev->Address, Endpoint,
313 Dest, ciMaxPacketSize
316 Length -= ciMaxPacketSize;
319 final = Dev->Host->HostDef->SendIN(
320 Dev->Host->Ptr, Dev->Address, Endpoint,
325 while( Dev->Host->HostDef->IsOpComplete(Dev->Host->Ptr, final) == 0 )
331 char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index)
333 struct sDescriptor_String str;
334 int src_len, new_len;
337 USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str);
338 // if(str.Length > sizeof(str)) {
340 // Log_Error("USB", "String is %i bytes, which is over prealloc size (%i)",
341 // str.Length, sizeof(str)
344 src_len = (str.Length - 2) / sizeof(str.Data[0]);
346 new_len = _UTF16to8(str.Data, src_len, NULL);
347 ret = malloc( new_len + 1 );
348 _UTF16to8(str.Data, src_len, ret);
353 int _UTF16to8(Uint16 *Input, int InputLen, char *Dest)
356 Uint32 saved_bits = 0;
358 for( int i = 0; i < InputLen; i ++)
361 Uint16 val = Input[i];
362 if( val >= 0xD800 && val <= 0xDBFF )
364 // Multibyte - Leading
365 if(i + 1 > InputLen) {
369 saved_bits = (val - 0xD800) << 10;
370 saved_bits += 0x10000;
374 else if( val >= 0xDC00 && val <= 0xDFFF )
380 saved_bits |= (val - 0xDC00);
387 cp_len = WriteUTF8((Uint8*)Dest, cp);