--- /dev/null
+/*
+ * Acess2 USB Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * hub.c
+ * - Basic hub driver
+ */
+#include <usb_hub.h>
+
+struct sHubInfo
+{
+ int nPorts;
+};
+
+// === PROTOTYPES ===
+void Hub_Connected(tUSBInterface *Dev);
+void Hub_Disconnected(tUSBInterface *Dev);
+void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data);
+
+// === GLOBALS ===
+tUSBDriver gUSBHub_Driver = {
+ .Name = "Hub",
+ .Match = {.Class = {0x090000, 0xFF0000}},
+ .Connected = Hub_Connected,
+ .Disconnected = Hub_Disconnected,
+ .MaxEndpoints = 1,
+ .Endpoints = {
+ {0x83, Hub_PortStatusChange}
+ };
+};
+
+// === CODE ===
+void Hub_Connected(tUSBInterface *Dev)
+{
+ // Register poll on endpoint
+ USB_PollEndpoint(Dev, 0);
+
+ USB_RegisterHub(Dev, nPorts);
+}
+
+void Hub_Disconnected(tUSBInterface *Dev)
+{
+}
+
+void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
+{
+ int i;
+ Uint8 *status = Data;
+ for( i = 0; i < info->nPorts; i += 8, status ++ )
+ {
+ if( i/8 >= Length ) break;
+ if( *status == 0 ) continue;
+
+ for( int j = 0; j < 8; j ++ )
+ if( *status & (1 << j) )
+ Hub_int_HandleChange(Dev, i+j);
+ }
+}
+
+void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
+{
+ Uint16 status[2]; // Status, Change
+ // Get change status
+ USB_Request(Dev, 0, 0xA3, 0, 0, Port, 4, status);
+}
+
#ifndef _USB_CORE_H_
#define _USB_CORE_H_
-typedef struct sUSBDevice tUSBDevice;
+typedef struct sUSBInterface tUSBInterface;
typedef struct sUSBDriver tUSBDriver;
/**
tUSBDriver *Next;
const char *Name;
-
- // 23:16 - Interface Class
- // 15:8 - Interface Sub Class
- // 7:0 - Interface Protocol
- Uint32 ClassMask;
- Uint32 ClassCode;
- void (*Connected)(tUSBDevice *Dev);
- void (*Disconnected)(tUSBDevice *Dev);
+ int MatchType; // 0: Interface, 1: Device, 2: Vendor
+ union {
+ struct {
+ // 23:16 - Interface Class
+ // 15:8 - Interface Sub Class
+ // 7:0 - Interface Protocol
+ Uint32 ClassMask;
+ Uint32 ClassCode;
+ } Class;
+ struct {
+ Uint16 VendorID;
+ Uint16 DeviceID;
+ } VendorDev;
+ } Match;
+
+ void (*Connected)(tUSBInterface *Dev);
+ void (*Disconnected)(tUSBInterface *Dev);
int MaxEndpoints;
struct {
- // 0: Bulk, 1: Control, 2: Interrupt
- int Type;
+ // USB Attrbute byte
+ // NOTE: Top bit indicates the direction (1=Input)
+ Uint8 Attributes;
// Data availiable Callback
- void (*Interrupt)(tUSBDevice *Dev, int Length, void *Data);
+ void (*DataAvail)(tUSBInterface *Dev, int Length, void *Data);
} Endpoints[];
};
-extern void *USB_GetDeviceDataPtr(tUSBDevice *Dev);
-extern void USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr);
+extern void *USB_GetDeviceDataPtr(tUSBInterface *Dev);
+extern void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr);
-extern void USB_SendData(tUSBDevice *Dev, int Endpoint, int Length, void *Data);
+extern void USB_SendData(tUSBInterface *Dev, int Endpoint, int Length, void *Data);
#endif
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(tUSBDevice *Dev);
-void USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr);
+void *USB_GetDeviceDataPtr(tUSBInterface *Dev);
+void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr);
int USB_int_AllocateAddress(tUSBHost *Host);
int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address);
int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest);
host->Ptr = ControllerPtr;
memset(host->AddressBitmap, 0, sizeof(host->AddressBitmap));
- host->RootHubDev.Next = NULL;
+// host->RootHubDev.Next = NULL;
host->RootHubDev.ParentHub = NULL;
host->RootHubDev.Host = host;
host->RootHubDev.Address = 0;
- host->RootHubDev.Driver = NULL;
- host->RootHubDev.Data = NULL;
+// host->RootHubDev.Driver = NULL;
+// host->RootHubDev.Data = NULL;
host->RootHub.Device = &host->RootHubDev;
host->RootHub.CheckPorts = NULL;
// Create structure
dev = malloc(sizeof(tUSBDevice));
- dev->Next = NULL;
+// dev->Next = NULL;
dev->ParentHub = Hub;
dev->Host = Hub->Device->Host;
dev->Address = 0;
- dev->Driver = 0;
- dev->Data = 0;
+// dev->Driver = 0;
+// dev->Data = 0;
// 1. Assign an address
dev->Address = USB_int_AllocateAddress(dev->Host);
// TODO: Sanity check with remaining space
cur_ptr += sizeof(*iface);
- LOG("Interface %i/%i = {");
+ LOG("Interface %i/%i = {", i, j);
LOG(" .InterfaceNum = %i", iface->InterfaceNum);
LOG(" .NumEndpoints = %i", iface->NumEndpoints);
LOG(" .InterfaceClass = 0x%x", iface->InterfaceClass);
// 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("}");
}
}
}
-void *USB_GetDeviceDataPtr(tUSBDevice *Dev) { return Dev->Data; }
-void USB_SetDeviceDataPtr(tUSBDevice *Dev, void *Ptr) { Dev->Data = Ptr; }
+void *USB_GetDeviceDataPtr(tUSBInterface *Dev) { return Dev->Data; }
+void USB_SetDeviceDataPtr(tUSBInterface *Dev, void *Ptr) { Dev->Data = Ptr; }
int USB_int_AllocateAddress(tUSBHost *Host)
{
Host->AddressBitmap[Address/8] &= ~(1 << (Address%8));
}
+void *USB_int_Request(tUSBHost *Host, int Addr, int EndPt, int Type, int Req, int Val, int Indx, int Len, void *Data)
+{
+ void *hdl;
+ // TODO: Sanity check (and check that Type is valid)
+ struct sDeviceRequest req;
+ req.ReqType = Type;
+ req.Request = Req;
+ req.Value = LittleEndian16( Val );
+ req.Index = LittleEndian16( Indx );
+ req.Length = LittleEndian16( Len );
+
+ hdl = Host->HostDef->SendSETUP(Host->Ptr, Addr, EndPt, 0, NULL, &req, sizeof(req));
+
+ // TODO: Data toggle?
+ // TODO: Correct sequence? (Some OUT requests need an IN)
+ if( Type & 0x80 )
+ {
+ hdl = Host->HostDef->SendIN(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len);
+ while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
+ Time_Delay(1);
+ }
+ else
+ {
+ hdl = Host->HostDef->SendOUT(Host->Ptr, Addr, EndPt, 0, NULL, Data, Len);
+ }
+ return hdl;
+}
+
int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
{
void *hdl;
req.Length = LittleEndian16( 0 ); // wLength
// Addr 0:0, Data Toggle = 0, no interrupt
- hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, FALSE, &req, sizeof(req));
+ hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, NULL, &req, sizeof(req));
if(!hdl)
return 1;
- // TODO: Data toggle?
- hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, FALSE, NULL, 0);
+ hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, NULL, NULL, 0);
while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
Time_Delay(1);
char *ret;
USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str);
- if(str.Length > sizeof(str)) {
- Log_Notice("USB", "String is %i bytes, which is over prealloc size (%i)",
- str.Length, sizeof(str)
- );
- // HACK:
- str.Length = sizeof(str);
- }
+// if(str.Length > sizeof(str)) {
+// // IMPOSSIBLE!
+// Log_Error("USB", "String is %i bytes, which is over prealloc size (%i)",
+// str.Length, sizeof(str)
+// );
+// }
src_len = (str.Length - 2) / sizeof(str.Data[0]);
new_len = _UTF16to8(str.Data, src_len, NULL);