Modules/USB - Cleanup mostly
[tpg/acess2.git] / Modules / USB / Core / hub.c
index 552ab96..849e8a3 100644 (file)
@@ -5,10 +5,32 @@
  * hub.c
  * - Basic hub driver
  */
+#define DEBUG  1
 #include <usb_hub.h>
 
 #define MAX_PORTS      32      // Not actually a max, but used for DeviceRemovable
 
+
+#define GET_STATUS     0
+#define CLEAR_FEATURE  1
+// resvd
+#define SET_FEATURE    3
+
+#define PORT_CONNECTION        0
+#define PORT_ENABLE    1
+#define PORT_SUSPEND   2
+#define PORT_OVER_CURRENT      3
+#define PORT_RESET     4
+#define PORT_POWER     8
+#define PORT_LOW_SPEED 9
+#define C_PORT_CONNECTION      16
+#define C_PORT_ENABLE  17
+#define C_PORT_SUSPEND 18
+#define C_PORT_OVER_CURRENT    19
+#define C_PORT_RESET   20
+#define PORT_TEST      21
+#define PORT_INDICATOR 21
+
 struct sHubDescriptor
 {
        Uint8   DescLength;
@@ -20,10 +42,19 @@ struct sHubDescriptor
        Uint8   DeviceRemovable[MAX_PORTS];
 };
 
+struct sHubInfo
+{
+       tUSBHub *HubPtr;
+        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_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data);
+void   Hub_int_HandleChange(tUSBInterface *Dev, int Port);
 
 // === GLOBALS ===
 tUSBDriver     gUSBHub_Driver = {
@@ -34,39 +65,61 @@ 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;
-       
-       hub_desc = malloc(sizeof(*hub_desc));
-       if(!hub_desc) {
+       struct sHubDescriptor   hub_desc;
+       struct sHubInfo *info;  
+
+       // Read hub descriptor (Class descriptor 0x29)
+       USB_ReadDescriptor(Dev, 0x129, 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);
+       if(!info) {
                Log_Error("USBHub", "malloc() failed");
                return ;
        }
-       USB_SetDeviceDataPtr(Dev, hub_desc);
+       USB_SetDeviceDataPtr(Dev, info);
 
-       USB_ReadDescriptor(Dev, 0, 0x29, 0, sizeof(hub_desc), hub_desc);
+       // Fill data
+       info->nPorts = hub_desc.NbrPorts;
+       info->PowerOnDelay = hub_desc.PwrOn2PwrGood * 2;
+       memcpy(info->DeviceRemovable, hub_desc.DeviceRemovable, (hub_desc.NbrPorts+7)/8);
+       // Register
+       info->HubPtr = USB_RegisterHub(Dev, info->nPorts);
 
        // Register poll on endpoint
-       USB_PollEndpoint(Dev, 1);
-       
-       USB_RegisterHub(Dev, hub_desc->NbrPorts);
+       USB_StartPollingEndpoint(Dev, 1);
 }
 
 void Hub_Disconnected(tUSBInterface *Dev)
 {
+       struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
+       USB_RemoveHub(info->HubPtr);
+       free(info);
 }
 
-void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
+void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data)
 {
        Uint8   *status = Data;
-       struct sHubDescriptor   *info = USB_GetDeviceDataPtr(Dev);
+       struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
         int    i;
-       for( i = 0; i < info->NbrPorts; i += 8, status ++ )
+       for( i = 0; i < info->nPorts; i += 8, status ++ )
        {
                if( i/8 >= Length )     break;
                if( *status == 0 )      continue;
@@ -79,8 +132,48 @@ void Hub_PortStatusChange(tUSBInterface *Dev, int Length, void *Data)
 
 void Hub_int_HandleChange(tUSBInterface *Dev, int Port)
 {
+       struct sHubInfo *info = USB_GetDeviceDataPtr(Dev);
        Uint16  status[2];      // Status, Change
-       // Get change status
-       USB_Request(Dev, 0, 0xA3, 0, 0, Port, 4, status);
-}
+       
+       // Get port status
+       USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
 
+       LOG("Port %i: status = {0b%b, 0b%b}", Port, status[0], status[1]);
+       
+       // Handle connections / disconnections
+       if( status[1] & 0x0001 )
+       {
+               if( status[0] & 0x0001 ) {
+                       // Connected
+                       // - Power on port
+                       USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL);
+                       Time_Delay(info->PowerOnDelay);
+                       // - Reset
+                       USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL);
+                       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
+                       USB_DeviceConnected(info->HubPtr, Port);
+               }
+               else {
+                       // Disconnected
+                       USB_DeviceDisconnected(info->HubPtr, Port);
+               }
+               
+               USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_CONNECTION, Port, 0, NULL);
+       }
+       
+       // Reset change
+       if( status[1] & 0x0010 )
+       {
+               if( status[0] & 0x0010 ) {
+                       // Reset complete
+               }
+               else {
+                       // Useful?
+               }
+               // ACK
+               USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_RESET, Port, 0, NULL);
+       }
+}

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