From 9c8d1751ca2eb1470a1707e42896262d19efe31d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 29 Nov 2011 11:22:59 +0800 Subject: [PATCH] Modules/USB - Cleanup and sorting, added hub code to build - Polling code in the works - TODO: Better Async support --- Modules/USB/Core/Makefile | 4 +- Modules/USB/Core/hub.c | 24 +++- Modules/USB/Core/include/usb_core.h | 3 + Modules/USB/Core/main.c | 18 --- Modules/USB/Core/usb.c | 192 ++++----------------------- Modules/USB/Core/usb.h | 10 +- Modules/USB/Core/usb_devinit.c | 195 ++++++++++++++++++++++++++++ Modules/USB/Core/usb_io.c | 42 ++++++ Modules/USB/Core/usb_lowlevel.c | 1 + Modules/USB/Core/usb_lowlevel.h | 1 + Modules/USB/Core/usb_poll.c | 102 +++++++++++++++ Modules/USB/UHCI/uhci.c | 7 +- 12 files changed, 401 insertions(+), 198 deletions(-) create mode 100644 Modules/USB/Core/usb_devinit.c create mode 100644 Modules/USB/Core/usb_io.c create mode 100644 Modules/USB/Core/usb_poll.c diff --git a/Modules/USB/Core/Makefile b/Modules/USB/Core/Makefile index 6ef0f03b..4d6e6845 100644 --- a/Modules/USB/Core/Makefile +++ b/Modules/USB/Core/Makefile @@ -1,7 +1,9 @@ # # -OBJ = main.o usb.o usb_lowlevel.o +OBJ = main.o +OBJ += usb.o usb_lowlevel.o usb_devinit.o usb_io.o usb_poll.o +OBJ += hub.o CPPFLAGS = -Iinclude NAME = Core diff --git a/Modules/USB/Core/hub.c b/Modules/USB/Core/hub.c index 1e56beeb..08295b1f 100644 --- a/Modules/USB/Core/hub.c +++ b/Modules/USB/Core/hub.c @@ -34,12 +34,13 @@ struct sHubInfo int PowerOnDelay; // in ms int nPorts; Uint8 DeviceRemovable[]; -} +}; // === PROTOTYPES === void Hub_Connected(tUSBInterface *Dev); void Hub_Disconnected(tUSBInterface *Dev); void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data); +void Hub_int_HandleChange(tUSBInterface *Dev, int Port); // === GLOBALS === tUSBDriver gUSBHub_Driver = { @@ -50,17 +51,28 @@ tUSBDriver gUSBHub_Driver = { .MaxEndpoints = 1, .Endpoints = { {0x83, Hub_PortStatusChange} - }; + } }; // === CODE === +#if 0 +int Hub_DriverInitialise(char **Arguments) +{ + USB_RegisterDriver( &gUSBHub_Driver ); + return 0; +} +#endif + void Hub_Connected(tUSBInterface *Dev) { struct sHubDescriptor hub_desc; struct sHubInfo *info; // Read hub descriptor - USB_ReadDescriptor(Dev, 0x29, 0, sizeof(*hub_desc), hub_desc); + USB_ReadDescriptor(Dev, 0x29, 0, sizeof(hub_desc), &hub_desc); + + LOG("%i Ports", hub_desc.NbrPorts); + LOG("Takes %i ms for power to stabilise", hub_desc.PwrOn2PwrGood*2); // Allocate infomation structure info = malloc(sizeof(*info) + (hub_desc.NbrPorts+7)/8); @@ -83,7 +95,9 @@ void Hub_Connected(tUSBInterface *Dev) void Hub_Disconnected(tUSBInterface *Dev) { - USB_RemoveHub(Dev); + struct sHubInfo *info = USB_GetDeviceDataPtr(Dev); + USB_RemoveHub(info->HubPtr); + free(info); } void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data) @@ -120,7 +134,7 @@ void Hub_int_HandleChange(tUSBInterface *Dev, int Port) Time_Delay(info->PowerOnDelay); // - Reset USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL); - Time_Delay(50); + Time_Delay(20); // Spec says 10ms after reset, but how long is reset? // - Enable USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_ENABLE, Port, 0, NULL); // - Poke USB Stack diff --git a/Modules/USB/Core/include/usb_core.h b/Modules/USB/Core/include/usb_core.h index 104d0e3d..369de5ea 100644 --- a/Modules/USB/Core/include/usb_core.h +++ b/Modules/USB/Core/include/usb_core.h @@ -8,6 +8,8 @@ #ifndef _USB_CORE_H_ #define _USB_CORE_H_ +#include + typedef struct sUSBInterface tUSBInterface; typedef struct sUSBDriver tUSBDriver; @@ -52,6 +54,7 @@ extern void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr); extern void USB_StartPollingEndpoint(tUSBInterface *Dev, int Endpoint); extern void USB_ReadDescriptor(tUSBInterface *Dev, int Type, int Index, int Length, void *Data); +extern void USB_Request(tUSBInterface *Dev, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data); // TODO: Async extern void USB_SendData(tUSBInterface *Dev, int Endpoint, int Length, void *Data); extern void USB_RecvData(tUSBInterface *Dev, int Endpoint, int Length, void *Data); diff --git a/Modules/USB/Core/main.c b/Modules/USB/Core/main.c index 277cf7c6..d92c7729 100644 --- a/Modules/USB/Core/main.c +++ b/Modules/USB/Core/main.c @@ -30,8 +30,6 @@ tDevFS_Driver gUSB_DrvInfo = { } }; tUSBHost *gUSB_Hosts = NULL; -tUSBInterface *gUSB_InterruptDevs = NULL; -tUSBInterface *gUSB_InterruptLast = NULL; // === CODE === /** @@ -43,22 +41,6 @@ int USB_Install(char **Arguments) return MODULE_ERR_OK; } -/** - * \brief USB polling thread - */ -int USB_PollThread(void *unused) -{ - for(;;) - { - for( tUSBInterface *dev = gUSB_InterruptDevs; dev; dev = dev->Next ) - { -// hub->CheckPorts(hub, hub->Device); - } - // TODO: Fine tune - Time_Delay(250); - } -} - /** * \brief Called just before module is unloaded */ diff --git a/Modules/USB/Core/usb.c b/Modules/USB/Core/usb.c index ca86a2b4..ae80a113 100644 --- a/Modules/USB/Core/usb.c +++ b/Modules/USB/Core/usb.c @@ -1,30 +1,27 @@ /* - * Acess 2 USB Stack + * Acess2 USB Stack * - By John Hodge (thePowersGang) * * usb.c - * - USB Packet Control + * - USB Structure */ #define DEBUG 1 #include #include #include #include "usb.h" -#include "usb_proto.h" -#include "usb_lowlevel.h" // === IMPORTS === extern tUSBHost *gUSB_Hosts; +extern tUSBDriver gUSBHub_Driver; // === STRUCTURES === // === PROTOTYPES === tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts); -void USB_DeviceConnected(tUSBHub *Hub, int Port); -void USB_DeviceDisconnected(tUSBHub *Hub, int Port); -void *USB_GetDeviceDataPtr(tUSBInterface *Dev); -void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr); - int USB_int_AllocateAddress(tUSBHost *Host); + +// === GLOBALS === +tUSBDriver *gUSB_InterfaceDrivers = &gUSBHub_Driver; // === CODE === tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts) @@ -61,174 +58,33 @@ tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts) return &host->RootHub; } -void USB_DeviceConnected(tUSBHub *Hub, int Port) +void USB_RegisterDriver(tUSBDriver *Driver) { - tUSBDevice *dev; - if( Port >= Hub->nPorts ) return ; - if( Hub->Devices[Port] ) return ; - - ENTER("pHub iPort", Hub, Port); - - // 0. Perform port init? (done in hub?) - - // Create structure - dev = malloc(sizeof(tUSBDevice)); - dev->ParentHub = Hub; - dev->Host = Hub->Interface->Dev->Host; - dev->Address = 0; - - // 1. Assign an address - dev->Address = USB_int_AllocateAddress(dev->Host); - if(dev->Address == 0) { - Log_Error("USB", "No addresses avaliable on host %p", dev->Host); - free(dev); - LEAVE('-'); - return ; - } - USB_int_SendSetupSetAddress(dev->Host, dev->Address); - LOG("Assigned address %i", dev->Address); - - // 2. Get device information - { - struct sDescriptor_Device desc; - LOG("Getting device descriptor"); - // Endpoint 0, Desc Type 1, Index 0 - USB_int_ReadDescriptor(dev, 0, 1, 0, sizeof(desc), &desc); - - LOG("Device Descriptor = {"); - LOG(" .Length = %i", desc.Length); - LOG(" .Type = %i", desc.Type); - LOG(" .USBVersion = 0x%04x", desc.USBVersion); - LOG(" .DeviceClass = 0x%02x", desc.DeviceClass); - LOG(" .DeviceSubClass = 0x%02x", desc.DeviceSubClass); - LOG(" .DeviceProtocol = 0x%02x", desc.DeviceProtocol); - LOG(" .MaxPacketSize = 0x%02x", desc.MaxPacketSize); - LOG(" .VendorID = 0x%04x", desc.VendorID); - LOG(" .ProductID = 0x%04x", desc.ProductID); - LOG(" .DeviceID = 0x%04x", desc.DeviceID); - LOG(" .ManufacturerStr = Str %i", desc.ManufacturerStr); - LOG(" .ProductStr = Str %i", desc.ProductStr); - LOG(" .SerialNumberStr = Str %i", desc.SerialNumberStr); - LOG(" .NumConfigurations = %i", desc.SerialNumberStr); - LOG("}"); - - if( desc.ManufacturerStr ) - { - char *tmp = USB_int_GetDeviceString(dev, 0, desc.ManufacturerStr); - 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( desc.SerialNumberStr ) - { - char *tmp = USB_int_GetDeviceString(dev, 0, desc.SerialNumberStr); - LOG("SerialNumbertStr = '%s'", tmp); - free(tmp); - } - } - - // 3. Get configurations - for( int i = 0; i < 1; i ++ ) - { - struct sDescriptor_Configuration desc; - void *full_buf; - char *cur_ptr; - - USB_int_ReadDescriptor(dev, 0, 2, i, sizeof(desc), &desc); - LOG("Configuration Descriptor %i = {", i); - LOG(" .Length = %i", desc.Length); - LOG(" .Type = %i", desc.Type); - LOG(" .TotalLength = 0x%x", LittleEndian16(desc.TotalLength)); - LOG(" .NumInterfaces = %i", desc.NumInterfaces); - LOG(" .ConfigurationValue = %i", desc.ConfigurationValue); - LOG(" .ConfigurationStr = %i", desc.ConfigurationStr); - LOG(" .AttributesBmp = 0b%b", desc.AttributesBmp); - LOG(" .MaxPower = %i (*2mA)", desc.MaxPower); - LOG("}"); - if( desc.ConfigurationStr ) { - char *tmp = USB_int_GetDeviceString(dev, 0, desc.ConfigurationStr); - LOG("ConfigurationStr = '%s'", tmp); - free(tmp); - } - - cur_ptr = full_buf = malloc( LittleEndian16(desc.TotalLength) ); - USB_int_ReadDescriptor(dev, 0, 2, i, desc.TotalLength, full_buf); - - cur_ptr += desc.Length; - - // TODO: Interfaces - for( int j = 0; j < desc.NumInterfaces; j ++ ) - { - struct sDescriptor_Interface *iface; - iface = (void*)cur_ptr; - // TODO: Sanity check with remaining space - cur_ptr += sizeof(*iface); - - 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("}"); - - for( int k = 0; k < iface->NumEndpoints; k ++ ) - { - struct sDescriptor_Endpoint *endpt; - endpt = (void*)cur_ptr; - // TODO: Sanity check with remaining space - cur_ptr += sizeof(*endpt); - - LOG("Endpoint %i/%i/%i = {", i, j, k); - LOG(" .Address = 0x%2x", endpt->Address); - LOG(" .Attributes = 0b%8b", endpt->Attributes); - LOG(" .MaxPacketSize = %i", LittleEndian16(endpt->MaxPacketSize)); - LOG(" .PollingInterval = %i", endpt->PollingInterval); - LOG("}"); - } - } - - free(full_buf); - } - - // Done. - LEAVE('-'); + Log_Warning("USB", "TODO: Implement USB_RegisterDriver"); } -void USB_DeviceDisconnected(tUSBHub *Hub, int Port) +// --- Hub Registration --- +// NOTE: Doesn't do much nowdays +tUSBHub *USB_RegisterHub(tUSBInterface *Device, int PortCount) { + tUSBHub *ret; + ret = malloc(sizeof(tUSBHub) + sizeof(ret->Devices[0])*PortCount); + ret->Interface = Device; + ret->nPorts = PortCount; + memset(ret->Devices, 0, sizeof(ret->Devices[0])*PortCount); + return ret; } -void *USB_GetDeviceDataPtr(tUSBInterface *Dev) { return Dev->Data; } -void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr) { Dev->Data = Ptr; } - -int USB_int_AllocateAddress(tUSBHost *Host) +void USB_RemoveHub(tUSBHub *Hub) { - int i; - for( i = 1; i < 128; i ++ ) + for( int i = 0; i < Hub->nPorts; i ++ ) { - if(Host->AddressBitmap[i/8] & (1 << (i%8))) - continue ; - Host->AddressBitmap[i/8] |= 1 << (i%8); - return i; + if( Hub->Devices[i] ) + { + USB_DeviceDisconnected( Hub, i ); + } } - return 0; -} - -void USB_int_DeallocateAddress(tUSBHost *Host, int Address) -{ - Host->AddressBitmap[Address/8] &= ~(1 << (Address%8)); + free(Hub); } diff --git a/Modules/USB/Core/usb.h b/Modules/USB/Core/usb.h index 8759ee1d..a61ce000 100644 --- a/Modules/USB/Core/usb.h +++ b/Modules/USB/Core/usb.h @@ -1,6 +1,9 @@ /* - * AcessOS Version 1 - * USB Stack + * Acess2 USB Stack + * - By John Hodge (thePowersGang) + * + * usb.h + * - USB Internal definitions */ #ifndef _USB_H_ #define _USB_H_ @@ -27,11 +30,12 @@ struct sUSBHub struct sUSBEndpoint { - tUSBEndpoint *Next; // In the poll list + tUSBEndpoint *Next; // In the segmented list tUSBInterface *Interface; int EndpointNum; int PollingPeriod; // In 1ms intervals + int PollingAtoms; // *INTERNAL* usb_poll.c int MaxPacketSize; // In bytes Uint8 Type; // Same as sUSBDriver.Endpoints.Type diff --git a/Modules/USB/Core/usb_devinit.c b/Modules/USB/Core/usb_devinit.c new file mode 100644 index 00000000..8d901a53 --- /dev/null +++ b/Modules/USB/Core/usb_devinit.c @@ -0,0 +1,195 @@ +/* + * Acess 2 USB Stack + * - By John Hodge (thePowersGang) + * + * usb_devinit.c + * - USB Device Initialisation + */ +#define DEBUG 1 + +#include +#include +#include +#include "usb.h" +#include "usb_proto.h" +#include "usb_lowlevel.h" + +// === PROTOTYPES === +void USB_DeviceConnected(tUSBHub *Hub, int Port); +void USB_DeviceDisconnected(tUSBHub *Hub, int Port); +void *USB_GetDeviceDataPtr(tUSBInterface *Dev); +void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr); + int USB_int_AllocateAddress(tUSBHost *Host); + +// === CODE === +void USB_DeviceConnected(tUSBHub *Hub, int Port) +{ + tUSBDevice *dev; + if( Port >= Hub->nPorts ) return ; + if( Hub->Devices[Port] ) return ; + + ENTER("pHub iPort", Hub, Port); + + // Device should be in 'Default' state + + // Create structure + dev = malloc(sizeof(tUSBDevice)); + dev->ParentHub = Hub; + dev->Host = Hub->Interface->Dev->Host; + dev->Address = 0; + + // 1. Assign an address + dev->Address = USB_int_AllocateAddress(dev->Host); + if(dev->Address == 0) { + Log_Error("USB", "No addresses avaliable on host %p", dev->Host); + free(dev); + LEAVE('-'); + return ; + } + USB_int_SendSetupSetAddress(dev->Host, dev->Address); + LOG("Assigned address %i", dev->Address); + + // 2. Get device information + { + struct sDescriptor_Device desc; + LOG("Getting device descriptor"); + // Endpoint 0, Desc Type 1, Index 0 + USB_int_ReadDescriptor(dev, 0, 1, 0, sizeof(desc), &desc); + + LOG("Device Descriptor = {"); + LOG(" .Length = %i", desc.Length); + LOG(" .Type = %i", desc.Type); + LOG(" .USBVersion = 0x%04x", desc.USBVersion); + LOG(" .DeviceClass = 0x%02x", desc.DeviceClass); + LOG(" .DeviceSubClass = 0x%02x", desc.DeviceSubClass); + LOG(" .DeviceProtocol = 0x%02x", desc.DeviceProtocol); + LOG(" .MaxPacketSize = 0x%02x", desc.MaxPacketSize); + LOG(" .VendorID = 0x%04x", desc.VendorID); + LOG(" .ProductID = 0x%04x", desc.ProductID); + LOG(" .DeviceID = 0x%04x", desc.DeviceID); + LOG(" .ManufacturerStr = Str %i", desc.ManufacturerStr); + LOG(" .ProductStr = Str %i", desc.ProductStr); + LOG(" .SerialNumberStr = Str %i", desc.SerialNumberStr); + LOG(" .NumConfigurations = %i", desc.SerialNumberStr); + LOG("}"); + + if( desc.ManufacturerStr ) + { + char *tmp = USB_int_GetDeviceString(dev, 0, desc.ManufacturerStr); + 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( desc.SerialNumberStr ) + { + char *tmp = USB_int_GetDeviceString(dev, 0, desc.SerialNumberStr); + LOG("SerialNumbertStr = '%s'", tmp); + free(tmp); + } + } + + // 3. Get configurations + for( int i = 0; i < 1; i ++ ) + { + struct sDescriptor_Configuration desc; + void *full_buf; + char *cur_ptr; + + USB_int_ReadDescriptor(dev, 0, 2, i, sizeof(desc), &desc); + LOG("Configuration Descriptor %i = {", i); + LOG(" .Length = %i", desc.Length); + LOG(" .Type = %i", desc.Type); + LOG(" .TotalLength = 0x%x", LittleEndian16(desc.TotalLength)); + LOG(" .NumInterfaces = %i", desc.NumInterfaces); + LOG(" .ConfigurationValue = %i", desc.ConfigurationValue); + LOG(" .ConfigurationStr = %i", desc.ConfigurationStr); + LOG(" .AttributesBmp = 0b%b", desc.AttributesBmp); + LOG(" .MaxPower = %i (*2mA)", desc.MaxPower); + LOG("}"); + if( desc.ConfigurationStr ) { + char *tmp = USB_int_GetDeviceString(dev, 0, desc.ConfigurationStr); + LOG("ConfigurationStr = '%s'", tmp); + free(tmp); + } + + cur_ptr = full_buf = malloc( LittleEndian16(desc.TotalLength) ); + USB_int_ReadDescriptor(dev, 0, 2, i, desc.TotalLength, full_buf); + + cur_ptr += desc.Length; + + // TODO: Interfaces + for( int j = 0; j < desc.NumInterfaces; j ++ ) + { + struct sDescriptor_Interface *iface; + iface = (void*)cur_ptr; + // TODO: Sanity check with remaining space + cur_ptr += sizeof(*iface); + + 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("}"); + + for( int k = 0; k < iface->NumEndpoints; k ++ ) + { + struct sDescriptor_Endpoint *endpt; + endpt = (void*)cur_ptr; + // TODO: Sanity check with remaining space + cur_ptr += sizeof(*endpt); + + LOG("Endpoint %i/%i/%i = {", i, j, k); + LOG(" .Address = 0x%2x", endpt->Address); + LOG(" .Attributes = 0b%8b", endpt->Attributes); + LOG(" .MaxPacketSize = %i", LittleEndian16(endpt->MaxPacketSize)); + LOG(" .PollingInterval = %i", endpt->PollingInterval); + LOG("}"); + } + } + + free(full_buf); + } + + // Done. + LEAVE('-'); +} + +void USB_DeviceDisconnected(tUSBHub *Hub, int Port) +{ + +} + +void *USB_GetDeviceDataPtr(tUSBInterface *Dev) { return Dev->Data; } +void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr) { Dev->Data = Ptr; } + +int USB_int_AllocateAddress(tUSBHost *Host) +{ + int i; + for( i = 1; i < 128; i ++ ) + { + if(Host->AddressBitmap[i/8] & (1 << (i%8))) + continue ; + Host->AddressBitmap[i/8] |= 1 << (i%8); + return i; + } + return 0; +} + +void USB_int_DeallocateAddress(tUSBHost *Host, int Address) +{ + Host->AddressBitmap[Address/8] &= ~(1 << (Address%8)); +} + diff --git a/Modules/USB/Core/usb_io.c b/Modules/USB/Core/usb_io.c new file mode 100644 index 00000000..ec88d753 --- /dev/null +++ b/Modules/USB/Core/usb_io.c @@ -0,0 +1,42 @@ +/* + * Acess2 USB Stack + * - By John Hodge (thePowersGang) + * + * usb_io.c + * - High-level IO + */ +#define DEBUG 1 + +#include +#include "usb.h" +#include "usb_lowlevel.h" + +// === PROTOTYPES === +void USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data); +void USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data); + +// === GLOBALS === + +// === CODE === +void USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data) +{ + USB_int_ReadDescriptor(Iface->Dev, 0, Type, Index, Length, Data); +} + +void USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data) +{ + int endpt; + + // Sanity check + if(Endpoint < 0 || Endpoint >= Iface->nEndpoints) + return ; + + // Get endpoint number + if(Endpoint) + endpt = Iface->Endpoints[Endpoint-1].EndpointNum; + else + endpt = 0; + + USB_int_Request(Iface->Dev->Host, Iface->Dev->Address, endpt, Type, Req, Value, Index, Len, Data); +} + diff --git a/Modules/USB/Core/usb_lowlevel.c b/Modules/USB/Core/usb_lowlevel.c index 7cde67ff..4c0fb730 100644 --- a/Modules/USB/Core/usb_lowlevel.c +++ b/Modules/USB/Core/usb_lowlevel.c @@ -12,6 +12,7 @@ #include "usb_lowlevel.h" // === PROTOTYPES === +void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data); int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address); int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest); char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index); diff --git a/Modules/USB/Core/usb_lowlevel.h b/Modules/USB/Core/usb_lowlevel.h index 903dd2e7..9159cbac 100644 --- a/Modules/USB/Core/usb_lowlevel.h +++ b/Modules/USB/Core/usb_lowlevel.h @@ -8,6 +8,7 @@ #ifndef _USB_LOWLEVEL_H_ #define _USB_LOWLEVEL_H_ +extern void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data); extern int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address); extern int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest); extern char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index); diff --git a/Modules/USB/Core/usb_poll.c b/Modules/USB/Core/usb_poll.c new file mode 100644 index 00000000..a4e8d448 --- /dev/null +++ b/Modules/USB/Core/usb_poll.c @@ -0,0 +1,102 @@ +/* + * Acess2 USB Stack + * - By John Hodge (thePowersGang) + * + * usb_poll.c + * - Endpoint polling + */ +#define DEBUG 1 +#include +#include "usb.h" + +#define POLL_ATOM 25 // 25ms atom +#define POLL_MAX 256 // Max period that can be nominated +#define POLL_SLOTS ((int)(POLL_MAX/POLL_ATOM)) + +// === PROTOTYPES === +void USB_StartPollingEndpoint(tUSBInterface *Iface, int Endpoint); + +// === GLOBALS === +tUSBEndpoint *gUSB_PollQueues[POLL_MAX/POLL_ATOM]; + int giUSB_PollPosition; // Index into gUSB_PollQueues + +// === CODE === +void USB_StartPollingEndpoint(tUSBInterface *Iface, int Endpoint) +{ + tUSBEndpoint *endpt; + + // Some sanity checks + if(Endpoint <= 0 || Endpoint >= Iface->nEndpoints) return ; + endpt = &Iface->Endpoints[Endpoint-1]; + if(endpt->PollingPeriod > POLL_MAX || endpt->PollingPeriod <= 0) + return ; + + // TODO: Check that this endpoint isn't already on the queue + + // Determine polling period in atoms + endpt->PollingAtoms = (endpt->PollingPeriod + POLL_ATOM-1) / POLL_ATOM; + if(endpt->PollingAtoms > POLL_SLOTS) endpt->PollingAtoms = POLL_SLOTS; + // Add to poll queue + endpt->Next = gUSB_PollQueues[endpt->PollingAtoms]; + gUSB_PollQueues[endpt->PollingAtoms] = endpt; +} + +/** + * \brief USB polling thread + */ +int USB_PollThread(void *unused) +{ + for(;;) + { + tUSBEndpoint *ep, *prev; + + // A little evil for neater code + prev = (void*)( (tVAddr)&gUSB_PollQueues[giUSB_PollPosition] - offsetof(tUSBEndpoint, Next) ); + + // Process queue + for( ep = gUSB_PollQueues[giUSB_PollPosition]; ep; prev = ep, ep = ep->Next ) + { + int period_in_atoms = ep->PollingAtoms; + + // Check for invalid entries + if(period_in_atoms < 0 || period_in_atoms > POLL_ATOM) + { + Log_Warning("USB", "Endpoint on polling queue with invalid period"); + continue ; + } + // Check for entries to delete + if(period_in_atoms == 0) + { + // Remove + prev->Next = ep->Next; + ep->PollingAtoms = -1; // Mark as removed + ep = prev; // Make sure prev is kept valid + continue ; + } + + // Read data + // TODO: Check the endpoint + // TODO: Async checking? + // - Send the read request on all of them then wait for the first to complete + // Call callback + + // Reschedule + if( period_in_atoms != POLL_SLOTS ) + { + int newqueue_id = (giUSB_PollPosition + period_in_atoms) % POLL_SLOTS; + tUSBEndpoint **newqueue = &gUSB_PollQueues[newqueue_id]; + + prev->Next = ep->Next; + + ep->Next = *newqueue; + *newqueue = ep; + } + } + giUSB_PollPosition ++; + if(giUSB_PollPosition == POLL_SLOTS) + giUSB_PollPosition = 0; + // TODO: Check for a longer delay + Time_Delay(POLL_ATOM); + } +} + diff --git a/Modules/USB/UHCI/uhci.c b/Modules/USB/UHCI/uhci.c index 9fd82303..18fd3e81 100644 --- a/Modules/USB/UHCI/uhci.c +++ b/Modules/USB/UHCI/uhci.c @@ -28,7 +28,7 @@ void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, vo void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length); int UHCI_IsTransferComplete(void *Ptr, void *Handle); int UHCI_Int_InitHost(tUHCI_Controller *Host); -void UHCI_CheckPortUpdate(tUHCI_Controller *Host); +void UHCI_CheckPortUpdate(void *Ptr); void UHCI_InterruptHandler(int IRQ, void *Ptr); // === GLOBALS === @@ -39,7 +39,7 @@ tUSBHostDef gUHCI_HostDef = { .SendIN = UHCI_DataIN, .SendOUT = UHCI_DataOUT, .SendSETUP = UHCI_SendSetup, - .CheckPorts = (void*)UHCI_CheckPortUpdate, + .CheckPorts = UHCI_CheckPortUpdate, .IsOpComplete = UHCI_IsTransferComplete }; @@ -291,8 +291,9 @@ int UHCI_Int_InitHost(tUHCI_Controller *Host) return 0; } -void UHCI_CheckPortUpdate(tUHCI_Controller *Host) +void UHCI_CheckPortUpdate(void *Ptr) { + tUHCI_Controller *Host = Ptr; // Enable ports for( int i = 0; i < 2; i ++ ) { -- 2.20.1