* - USB Device Initialisation
*/
#define DEBUG 1
-
#include <acess.h>
#include <vfs.h>
#include <drv_pci.h>
#include "usb_proto.h"
#include "usb_lowlevel.h"
+#define DUMP_DESCRIPTORS 1
+
// === PROTOTYPES ===
void USB_DeviceConnected(tUSBHub *Hub, int Port);
void USB_DeviceDisconnected(tUSBHub *Hub, int Port);
LOG("Getting device descriptor");
// Endpoint 0, Desc Type 1, Index 0
USB_int_ReadDescriptor(dev, 0, 1, 0, sizeof(desc), &desc);
-
+
+ #if DUMP_DESCRIPTORS
LOG("Device Descriptor = {");
LOG(" .Length = %i", desc.Length);
LOG(" .Type = %i", desc.Type);
LOG(" .SerialNumberStr = Str %i", desc.SerialNumberStr);
LOG(" .NumConfigurations = %i", desc.SerialNumberStr);
LOG("}");
-
+
+ #if DEBUG
if( desc.ManufacturerStr )
{
char *tmp = USB_int_GetDeviceString(dev, 0, desc.ManufacturerStr);
- LOG("ManufacturerStr = '%s'", tmp);
- free(tmp);
+ if( tmp ) {
+ LOG("ManufacturerStr = '%s'", tmp);
+ free(tmp);
+ }
}
if( desc.ProductStr )
{
char *tmp = USB_int_GetDeviceString(dev, 0, desc.ProductStr);
- LOG("ProductStr = '%s'", tmp);
- free(tmp);
+ if( tmp ) {
+ LOG("ProductStr = '%s'", tmp);
+ free(tmp);
+ }
}
if( desc.SerialNumberStr )
{
char *tmp = USB_int_GetDeviceString(dev, 0, desc.SerialNumberStr);
- LOG("SerialNumbertStr = '%s'", tmp);
- free(tmp);
+ if( tmp ) {
+ LOG("SerialNumbertStr = '%s'", tmp);
+ free(tmp);
+ }
}
+ #endif
+ #endif
+
+ memcpy(&dev->DevDesc, &desc, sizeof(desc));
}
// TODO: Support alternate configurations
for( int i = 0; i < 1; i ++ )
{
struct sDescriptor_Configuration desc;
- void *full_buf;
- char *cur_ptr;
+ Uint8 *full_buf;
+ size_t ptr_ofs = 0;
+ size_t total_length;
USB_int_ReadDescriptor(dev, 0, 2, i, sizeof(desc), &desc);
+ // TODO: Check return length? (Do we get a length?)
+ #if DUMP_DESCRIPTORS
LOG("Configuration Descriptor %i = {", i);
LOG(" .Length = %i", desc.Length);
LOG(" .Type = %i", desc.Type);
LOG("ConfigurationStr = '%s'", tmp);
free(tmp);
}
+ #endif
+
+ if( desc.NumInterfaces == 0 ) {
+ Log_Notice("USB", "Device does not have any interfaces");
+ continue ;
+ }
// TODO: Split here and allow some method of selection
dev->nInterfaces = desc.NumInterfaces;
// Allocate a temp buffer for config info
- cur_ptr = full_buf = malloc( LittleEndian16(desc.TotalLength) );
- USB_int_ReadDescriptor(dev, 0, 2, i, desc.TotalLength, full_buf);
+ total_length = LittleEndian16(desc.TotalLength);
+ full_buf = malloc( total_length );
+ USB_int_ReadDescriptor(dev, 0, 2, i, total_length, full_buf);
+ ptr_ofs += desc.Length;
- cur_ptr += desc.Length;
- // TODO: Interfaces
- for( int j = 0; j < desc.NumInterfaces; j ++ )
+ // Interfaces!
+ for( int j = 0; ptr_ofs < total_length && j < desc.NumInterfaces; j ++ )
{
struct sDescriptor_Interface *iface;
tUSBInterface *dev_if;
- iface = (void*)cur_ptr;
- // TODO: Sanity check with remaining space
- cur_ptr += sizeof(*iface);
+ size_t iface_base_ofs;
+
+ iface = (void*)(full_buf + ptr_ofs);
+ if( iface->Length == 0 ) {
+ Log_Warning("USB", "Bad USB descriptor (length = 0)");
+ break ;
+ }
+ ptr_ofs += iface->Length;
+ if( ptr_ofs > total_length ) {
+ // Sanity fail
+ break;
+ }
+ iface_base_ofs = ptr_ofs;
+ // Check type
+ if( iface->Type != 4 ) {
+ LOG("Not an interface (type = %i)", iface->Type);
+ j --; // Counteract j++ in loop
+ continue ;
+ }
+ #if DUMP_DESCRIPTORS
LOG("Interface %i/%i = {", i, j);
LOG(" .InterfaceNum = %i", iface->InterfaceNum);
LOG(" .NumEndpoints = %i", iface->NumEndpoints);
LOG(" .InterfaceClass = 0x%x", iface->InterfaceClass);
LOG(" .InterfaceSubClass = 0x%x", iface->InterfaceSubClass);
LOG(" .InterfaceProcol = 0x%x", iface->InterfaceProtocol);
-
if( iface->InterfaceStr ) {
char *tmp = USB_int_GetDeviceString(dev, 0, iface->InterfaceStr);
LOG(" .InterfaceStr = %i '%s'", iface->InterfaceStr, tmp);
free(tmp);
}
LOG("}");
+ #endif
- dev_if = malloc(sizeof(tUSBInterface) + iface->NumEndpoints*sizeof(dev_if->Endpoints[0]));
+ dev_if = malloc(
+ sizeof(tUSBInterface)
+ + iface->NumEndpoints*sizeof(dev_if->Endpoints[0])
+ );
dev_if->Dev = dev;
dev_if->Driver = NULL;
dev_if->Data = NULL;
dev_if->nEndpoints = iface->NumEndpoints;
+ memcpy(&dev_if->IfaceDesc, iface, sizeof(*iface));
dev->Interfaces[j] = dev_if;
// Copy interface data
- for( int k = 0; k < iface->NumEndpoints; k ++ )
+ for( int k = 0; ptr_ofs < total_length && k < iface->NumEndpoints; k ++ )
{
struct sDescriptor_Endpoint *endpt;
- endpt = (void*)cur_ptr;
- // TODO: Sanity check with remaining space
- cur_ptr += sizeof(*endpt);
+ endpt = (void*)(full_buf + ptr_ofs);
+ ptr_ofs += endpt->Length;
+ if( ptr_ofs > total_length ) {
+ // Sanity fail
+ break;
+ }
+
+ // Check type
+ if( endpt->Type != 5 ) {
+ // Oops?
+ LOG("Not endpoint, Type = %i", endpt->Type);
+ k --;
+ continue ;
+ }
+
LOG("Endpoint %i/%i/%i = {", i, j, k);
LOG(" .Address = 0x%2x", endpt->Address);
LOG(" .Attributes = 0b%8b", endpt->Attributes);
);
}
else {
- dev_if->Driver->Connected( dev_if );
+ LOG("Driver '%s' in use", dev_if->Driver->Name);
+ dev_if->Driver->Connected(
+ dev_if,
+ full_buf + iface_base_ofs, ptr_ofs - iface_base_ofs
+ );
}
}