Modules/USB - Working on driver support, little headache
authorJohn Hodge <[email protected]>
Mon, 28 Nov 2011 10:28:47 +0000 (18:28 +0800)
committerJohn Hodge <[email protected]>
Mon, 28 Nov 2011 10:28:47 +0000 (18:28 +0800)
Modules/USB/Core/hub.c [new file with mode: 0644]
Modules/USB/Core/include/usb_core.h
Modules/USB/Core/include/usb_hub.h
Modules/USB/Core/main.c
Modules/USB/Core/usb.c
Modules/USB/Core/usb.h
Modules/USB/Core/usb_proto.h
Modules/USB/UHCI/uhci.c

diff --git a/Modules/USB/Core/hub.c b/Modules/USB/Core/hub.c
new file mode 100644 (file)
index 0000000..4afde69
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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);
+}
+
index d8d1636..2a8ce9d 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef _USB_CORE_H_
 #define _USB_CORE_H_
 
-typedef struct sUSBDevice      tUSBDevice;
+typedef struct sUSBInterface   tUSBInterface;
 typedef struct sUSBDriver      tUSBDriver;
 
 /**
@@ -18,29 +18,39 @@ struct sUSBDriver
        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
 
index f48936b..42fbeab 100644 (file)
 
 typedef struct sUSBHub tUSBHub;
 
-typedef void   (*tUSB_HubPoll)(tUSBHub *Hub, tUSBDevice *HubDev);
-
 /**
  * \brief Register a device as a hub
  * 
  * Used by the hub class initialisation routine.
  */
-extern tUSBHub USB_RegisterHub(tUSBDevice *Device, int nPorts, tUSB_HubPoll PollCallback);
+extern tUSBHub USB_RegisterHub(tUSBInterface *Device, int nPorts);
 
 extern void    USB_DeviceConnected(tUSBHub *Hub, int Port);
 extern void    USB_DeviceDisconnected(tUSBHub *Hub, int Port);
index d99ef3a..277cf7c 100644 (file)
@@ -30,8 +30,8 @@ tDevFS_Driver gUSB_DrvInfo = {
        }
 };
 tUSBHost       *gUSB_Hosts = NULL;
-tUSBDevice     *gUSB_InterruptDevs = NULL;
-tUSBDevice     *gUSB_InterruptLast = NULL;
+tUSBInterface  *gUSB_InterruptDevs = NULL;
+tUSBInterface  *gUSB_InterruptLast = NULL;
 
 // === CODE ===
 /**
@@ -50,7 +50,7 @@ int USB_PollThread(void *unused)
 {
        for(;;)
        {
-               for( tUSBDevice *dev = gUSB_InterruptDevs; dev; dev = dev->Next )
+               for( tUSBInterface *dev = gUSB_InterruptDevs; dev; dev = dev->Next )
                {
 //                     hub->CheckPorts(hub, hub->Device);
                }
index 52968e3..7713435 100644 (file)
@@ -18,8 +18,8 @@ extern tUSBHost       *gUSB_Hosts;
 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);
@@ -41,12 +41,12 @@ tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
        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;
@@ -72,12 +72,12 @@ void USB_DeviceConnected(tUSBHub *Hub, int Port)
        
        // 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);
@@ -171,7 +171,7 @@ void USB_DeviceConnected(tUSBHub *Hub, int Port)
                        // 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);
@@ -192,7 +192,12 @@ void USB_DeviceConnected(tUSBHub *Hub, int Port)
                                // 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("}");
                        }
                }
                
@@ -208,8 +213,8 @@ void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
        
 }
 
-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)
 {
@@ -229,6 +234,34 @@ void USB_int_DeallocateAddress(tUSBHost *Host, int Address)
        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;
@@ -241,12 +274,11 @@ int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
        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);
@@ -304,13 +336,12 @@ char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index)
        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);   
index 177d7c7..c293c7d 100644 (file)
@@ -10,6 +10,8 @@
 #include <usb_host.h>
 
 typedef struct sUSBHost        tUSBHost;
+typedef struct sUSBDevice      tUSBDevice;
+typedef struct sUSBEndpoint    tUSBEndpoint;
 
 // === STRUCTURES ===
 /**
@@ -25,12 +27,38 @@ struct sUSBHub
        tUSBDevice      *Devices[];
 };
 
+struct sUSBEndpoint
+{
+       tUSBInterface   *Interface;
+       tUSBEndpoint    *Next;  // In the poll list
+        int    PollingPeriod;  // In 1ms intervals
+        int    MaxPacketSize;  // In bytes
+
+       char    Direction;      // 1 Polled Input, 0 Output
+       
+       Uint8   Type;   // Same as sDescriptor_Endpoint.Type
+};
+
+/**
+ * \brief Structure for a device's interface
+ */
+struct sUSBInterface
+{
+       tUSBInterface   *Next;
+       tUSBDevice      *Dev;
+
+       tUSBDriver      *Driver;
+       void    *Data;
+       
+        int    nEndpoints;
+       tUSBEndpoint    Endpoints[];
+};
+
 /**
  * \brief Defines a single device on the USB Bus
  */
 struct sUSBDevice
 {
-       tUSBDevice      *Next;
        tUSBHub *ParentHub;
 
        /**
@@ -38,9 +66,9 @@ struct sUSBDevice
         */
        tUSBHost        *Host;
         int    Address;
-       
-       tUSBDriver      *Driver;
-       void    *Data;
+
+        int    nInterfaces;
+       tUSBInterface   *Interfaces[];
 };
 
 struct sUSBHost
index b5399e8..2ac2781 100644 (file)
@@ -53,7 +53,7 @@ struct sDescriptor_String
        Uint8   Length;
        Uint8   Type;   // = 3
        
-       Uint16  Data[62];       // 62 is arbitary
+       Uint16  Data[128-1];    // (256 bytes - 2 bytes) / Uint16
 } PACKED;
 
 struct sDescriptor_Interface
@@ -76,7 +76,7 @@ struct sDescriptor_Endpoint
 {
        Uint8   Length;
        Uint8   Type;   // = 5
-       Uint8   Address;        // 3:0 Endpoint Num, 7: Direction (IN/OUT)
+       Uint8   Address;        // 3:0 Endpoint Num, 7: Direction (1=IN)
        /**
         * 1:0 - Transfer Type
         * - 00 = Control
index aa1dd12..9fd8230 100644 (file)
@@ -27,7 +27,6 @@ void  *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, voi
 void   *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length);
 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);
-void   UHCI_Hub_Poll(tUSBHub *Hub, tUSBDevice *Dev);
  int   UHCI_Int_InitHost(tUHCI_Controller *Host);
 void   UHCI_CheckPortUpdate(tUHCI_Controller *Host);
 void   UHCI_InterruptHandler(int IRQ, void *Ptr);
@@ -245,13 +244,6 @@ int UHCI_IsTransferComplete(void *Ptr, void *Handle)
        return !(td->Control & (1 << 23));
 }
 
-void UHCI_Hub_Poll(tUSBHub *Hub, tUSBDevice *Dev)
-{
-       tUHCI_Controller *cont = USB_GetDeviceDataPtr(Dev);
-       
-       UHCI_CheckPortUpdate(cont);
-}
-
 // === INTERNAL FUNCTIONS ===
 /**
  * \fn int UHCI_Int_InitHost(tUCHI_Controller *Host)

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