Modules/USB - Coming along, reading descriptors now
authorJohn Hodge <[email protected]>
Sat, 26 Nov 2011 13:50:22 +0000 (21:50 +0800)
committerJohn Hodge <[email protected]>
Sat, 26 Nov 2011 13:50:22 +0000 (21:50 +0800)
- Updated WriteUTF8 to accept NULL as a destination

Kernel/lib.c
Modules/USB/Core/usb.c
Modules/USB/Core/usb_proto.h
Modules/USB/UHCI/uhci.c
Modules/USB/UHCI/uhci.h

index c1e2807..2b786ec 100644 (file)
@@ -720,37 +720,39 @@ int WriteUTF8(Uint8 *str, Uint32 Val)
 {
        // ASCII
        if( Val < 128 ) {
-               *str = Val;
+               if( str ) {
+                       *str = Val;
+               }
                return 1;
        }
        
        // Two Byte
        if( Val < 0x8000 ) {
-               *str = 0xC0 | (Val >> 6);
-               str ++;
-               *str = 0x80 | (Val & 0x3F);
+               if( str ) {
+                       *str++ = 0xC0 | (Val >> 6);
+                       *str++ = 0x80 | (Val & 0x3F);
+               }
                return 2;
        }
        
        // Three Byte
        if( Val < 0x10000 ) {
-               *str = 0xE0 | (Val >> 12);
-               str ++;
-               *str = 0x80 | ((Val >> 6) & 0x3F);
-               str ++;
-               *str = 0x80 | (Val & 0x3F);
+               if( str ) {
+                       *str++ = 0xE0 | (Val >> 12);
+                       *str++ = 0x80 | ((Val >> 6) & 0x3F);
+                       *str++ = 0x80 | (Val & 0x3F);
+               }
                return 3;
        }
        
        // Four Byte
        if( Val < 0x110000 ) {
-               *str = 0xF0 | (Val >> 18);
-               str ++;
-               *str = 0x80 | ((Val >> 12) & 0x3F);
-               str ++;
-               *str = 0x80 | ((Val >> 6) & 0x3F);
-               str ++;
-               *str = 0x80 | (Val & 0x3F);
+               if( str ) {
+                       *str++ = 0xF0 | (Val >> 18);
+                       *str++ = 0x80 | ((Val >> 12) & 0x3F);
+                       *str++ = 0x80 | ((Val >> 6) & 0x3F);
+                       *str++ = 0x80 | (Val & 0x3F);
+               }
                return 4;
        }
        
index 272ff6c..b43aae4 100644 (file)
@@ -22,6 +22,10 @@ void *USB_GetDeviceDataPtr(tUSBDevice *Dev);
 void   USB_SetDeviceDataPtr(tUSBDevice *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);
+char   *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index);
+
+ int   _UTF16to8(Uint16 *Input, int InputLen, char *Dest);
 
 // === CODE ===
 tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
@@ -44,7 +48,7 @@ tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
        host->RootHubDev.Driver = NULL;
        host->RootHubDev.Data = NULL;
 
-       host->RootHub.Device = NULL;
+       host->RootHub.Device = &host->RootHubDev;
        host->RootHub.CheckPorts = NULL;
        host->RootHub.nPorts = nPorts;
        memset(host->RootHub.Devices, 0, sizeof(void*)*nPorts);
@@ -53,9 +57,6 @@ tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts)
        host->Next = gUSB_Hosts;
        gUSB_Hosts = host;
 
-       // Initialise?
-       HostDef->CheckPorts(ControllerPtr);
-       
        return &host->RootHub;
 }
 
@@ -90,6 +91,74 @@ void USB_DeviceConnected(tUSBHub *Hub, int Port)
        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;
+               
+               USB_int_ReadDescriptor(dev, 0, 2, 0, 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);
+               }
+               
+               // TODO: Interfaces
+       }
 
        // Done.
        LEAVE('-');
@@ -108,24 +177,42 @@ int USB_int_AllocateAddress(tUSBHost *Host)
         int    i;
        for( i = 1; i < 128; i ++ )
        {
-               if(Host->AddressBitmap[i/8] & (1 << 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));
+}
+
 int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
 {
+       void    *hdl;
        struct sDeviceRequest   req;
        req.ReqType = 0;        // bmRequestType
        req.Request = 5;        // SET_ADDRESS
-       req.Value = Address & 0x7F;     // wValue
-       req.Index = 0;  // wIndex
-       req.Length = 0; // wLength
+       // TODO: Endian
+       req.Value = LittleEndian16( Address & 0x7F );   // wValue
+       req.Index = LittleEndian16( 0 );        // wIndex
+       req.Length = LittleEndian16( 0 );       // wLength
        
        // Addr 0:0, Data Toggle = 0, no interrupt
-       return Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, FALSE, &req, sizeof(req)) == NULL;
+       hdl = Host->HostDef->SendSETUP(Host->Ptr, 0, 0, 0, FALSE, &req, sizeof(req));
+       if(!hdl)
+               return 1;
+
+       // TODO: Data toggle?
+       hdl = Host->HostDef->SendIN(Host->Ptr, 0, 0, 0, FALSE, NULL, 0);
+       
+       while( Host->HostDef->IsOpComplete(Host->Ptr, hdl) == 0 )
+               Time_Delay(1);
+       
+       return 0;
 }
 
 int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, int Length, void *Dest)
@@ -137,9 +224,9 @@ int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, i
 
        req.ReqType = 0x80;
        req.Request = 6;        // GET_DESCRIPTOR
-       req.Value = ((Type & 0xFF) << 8) | (Index & 0xFF);
-       req.Index = 0;  // TODO: Language ID
-       req.Length = Length;
+       req.Value = LittleEndian16( ((Type & 0xFF) << 8) | (Index & 0xFF) );
+       req.Index = LittleEndian16( 0 );        // TODO: Language ID
+       req.Length = LittleEndian16( Length );
        
        Dev->Host->HostDef->SendSETUP(
                Dev->Host->Ptr, Dev->Address, Endpoint,
@@ -170,3 +257,72 @@ int USB_int_ReadDescriptor(tUSBDevice *Dev, int Endpoint, int Type, int Index, i
 
        return 0;
 }
+
+char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index)
+{
+       struct sDescriptor_String       str;
+        int    src_len, new_len;
+       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);
+       }
+       src_len = (str.Length - 2) / sizeof(str.Data[0]);
+
+       new_len = _UTF16to8(str.Data, src_len, NULL);   
+       ret = malloc( new_len + 1 );
+       _UTF16to8(str.Data, src_len, ret);
+       ret[new_len] = 0;
+       return ret;
+}
+
+int _UTF16to8(Uint16 *Input, int InputLen, char *Dest)
+{
+        int    str_len, cp_len;
+       Uint32  saved_bits = 0;
+       str_len = 0;
+       for( int i = 0; i < InputLen; i ++)
+       {
+               Uint32  cp;
+               Uint16  val = Input[i];
+               if( val >= 0xD800 && val <= 0xDBFF )
+               {
+                       // Multibyte - Leading
+                       if(i + 1 > InputLen) {
+                               cp = '?';
+                       }
+                       else {
+                               saved_bits = (val - 0xD800) << 10;
+                               saved_bits += 0x10000;
+                               continue ;
+                       }
+               }
+               else if( val >= 0xDC00 && val <= 0xDFFF )
+               {
+                       if( !saved_bits ) {
+                               cp = '?';
+                       }
+                       else {
+                               saved_bits |= (val - 0xDC00);
+                               cp = saved_bits;
+                       }
+               }
+               else
+                       cp = val;
+
+               cp_len = WriteUTF8((Uint8*)Dest, cp);
+               if(Dest)
+                       Dest += cp_len;
+               str_len += cp_len;
+
+               saved_bits = 0;
+       }
+       
+       return str_len;
+}
+
index 3a98e47..776237d 100644 (file)
@@ -17,7 +17,7 @@ struct sDeviceRequest
 struct sDescriptor_Device
 {
        Uint8   Length;
-       Uint8   Type;   // =
+       Uint8   Type;   // = 1
        Uint16  USBVersion;     // BCD, 0x210 = 2.10
        Uint8   DeviceClass;
        Uint8   DeviceSubClass;
@@ -26,6 +26,7 @@ struct sDescriptor_Device
        
        Uint16  VendorID;
        Uint16  ProductID;
+       Uint16  DeviceID;       // BCD
        
        Uint8   ManufacturerStr;
        Uint8   ProductStr;
@@ -34,5 +35,72 @@ struct sDescriptor_Device
        Uint8   NumConfigurations;
 };
 
+struct sDescriptor_Configuration
+{
+       Uint8   Length;
+       Uint8   Type;   // = 2
+       
+       Uint16  TotalLength;
+       Uint8   NumInterfaces;
+       Uint8   ConfigurationValue;
+       Uint8   ConfigurationStr;
+       Uint8   AttributesBmp;
+       Uint8   MaxPower;       // in units of 2 mA
+};
+
+struct sDescriptor_String
+{
+       Uint8   Length;
+       Uint8   Type;   // = 3
+       
+       Uint16  Data[62];       // 62 is arbitary
+};
+
+struct sDescriptor_Interface
+{
+       Uint8   Length;
+       Uint8   Type;   // = 4
+       
+       Uint8   InterfaceNum;
+       Uint8   AlternateSetting;
+       Uint8   NumEndpoints;   // Excludes endpoint 0
+       
+       Uint8   InterfaceClass; // 
+       Uint8   InterfaceSubClass;
+       Uint8   InterfaceProtocol;
+       
+       Uint8   InterfaceStr;
+};
+
+struct sDescriptor_Endpoint
+{
+       Uint8   Length;
+       Uint8   Type;   // = 5
+       Uint8   Address;        // 3:0 Endpoint Num, 7: Direction (IN/OUT)
+       /**
+        * 1:0 - Transfer Type
+        * - 00 = Control
+        * - 01 = Isochronous
+        * - 10 = Bulk
+        * - 11 = Interrupt
+        * 3:2 - Synchronisation type (Isonchronous only)
+        * - 00 = No Synchronisation
+        * - 01 = Asynchronous
+        * - 10 = Adaptive
+        * - 11 = Synchronous
+        * 5:4 - Usage type (Isonchronous only)
+        * - 00 = Data endpoint
+        * - 01 = Feedback endpoint
+        */
+       Uint8   Attributes;
+       
+       Uint16  MaxPacketSize;
+       
+       /**
+        * 
+        */
+       Uint8   PollingInterval;
+};
+
 #endif
 
index 2018d5f..9d68ac0 100644 (file)
@@ -24,6 +24,7 @@ void  *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int
 void   *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb, void *Data, size_t Length);
 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);
@@ -37,7 +38,8 @@ tUSBHostDef   gUHCI_HostDef = {
        .SendIN = UHCI_DataIN,
        .SendOUT = UHCI_DataOUT,
        .SendSETUP = UHCI_SendSetup,
-       .CheckPorts = (void*)UHCI_CheckPortUpdate
+       .CheckPorts = (void*)UHCI_CheckPortUpdate,
+       .IsOpComplete = UHCI_IsTransferComplete
        };
 
 // === CODE ===
@@ -64,6 +66,7 @@ int UHCI_Initialise(const char **Arguments)
                        Log_Warning("UHCI", "MMIO is not supported");
                        continue ;
                }
+               cinfo->IOBase &= ~1;
                cinfo->IRQNum = PCI_GetIRQ(id);
                
                Log_Debug("UHCI", "Controller PCI #%i: IO Base = 0x%x, IRQ %i",
@@ -82,6 +85,8 @@ int UHCI_Initialise(const char **Arguments)
                cinfo->RootHub = USB_RegisterHost(&gUHCI_HostDef, cinfo, 2);
                LOG("cinfo->RootHub = %p", cinfo->RootHub);
 
+               UHCI_CheckPortUpdate(cinfo);
+
                i ++;
        }
        if(i == MAX_CONTROLLERS) {
@@ -106,15 +111,56 @@ tUHCI_TD *UHCI_int_AllocateTD(tUHCI_Controller *Cont)
        {
                if(gaUHCI_TDPool[i].Link == 0) {
                        gaUHCI_TDPool[i].Link = 1;
+                       gaUHCI_TDPool[i].Control = 1 << 23;
                        return &gaUHCI_TDPool[i];
                }
+               // Still in use? Skip
+               if( gaUHCI_TDPool[i].Control & (1 << 23) )
+                       continue ;
+               // Is there a callback on it? Skip
+               if( gaUHCI_TDPool[i]._info.Callback )
+                       continue ;
+               // TODO: Garbage collect, but that means removing from the list too
+               #if 0
+               // Ok, this is actually unused
+               gaUHCI_TDPool[i].Link = 1;
+               gaUHCI_TDPool[i].Control = 1 << 23;
+               return &gaUHCI_TDPool[i];
+               #endif
        }
        return NULL;
 }
 
 void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD)
 {
-       Log_Warning("UHCI", "TODO: Implement AppendTD");
+        int    next_frame = (inw(Cont->IOBase + FRNUM) + 2) & (1024-1);
+       tPAddr  td_pool_base = MM_GetPhysAddr( (tVAddr)gaUHCI_TDPool );
+       tUHCI_TD        *prev_td;
+       Uint32  link;
+
+       // TODO: How to handle FRNUM incrementing while we are in this function?
+
+       // Empty list
+       if( Cont->FrameList[next_frame] & 1 )
+       {
+               // TODO: Ensure 32-bit paddr
+               Cont->FrameList[next_frame] = MM_GetPhysAddr( (tVAddr)TD );
+               LOG("next_frame = %i", next_frame);     
+               return;
+       }
+
+       // Find the end of the list
+       link = Cont->FrameList[next_frame];
+       do {
+               // TODO: Fix this to work with a non-contiguous pool
+               prev_td = gaUHCI_TDPool + (link - td_pool_base) / sizeof(gaUHCI_TDPool[0]);
+               link = prev_td->Link;
+       } while( !(link & 1) );
+       
+       // Append
+       prev_td->Link = MM_GetPhysAddr( (tVAddr)TD );
+
+       LOG("next_frame = %i, prev_td = %p", next_frame, prev_td);
 }
 
 /**
@@ -131,8 +177,15 @@ void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int
 
        td = UHCI_int_AllocateTD(Cont);
 
+       if( !td ) {
+               // 
+               Log_Error("UHCI", "No avaliable TDs, transaction dropped");
+               return NULL;
+       }
+
        td->Link = 1;
        td->Control = (Length - 1) & 0x7FF;
+       td->Control |= (1 << 23);
        td->Token  = ((Length - 1) & 0x7FF) << 21;
        td->Token |= (bTgl & 1) << 19;
        td->Token |= (Addr & 0xF) << 15;
@@ -140,8 +193,10 @@ void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int
        td->Token |= Type;
 
        // TODO: Ensure 32-bit paddr
-       if( ((tVAddr)Data & PAGE_SIZE) + Length > PAGE_SIZE ) {
-               Log_Warning("UHCI", "TODO: Support non single page transfers");
+       if( ((tVAddr)Data & (PAGE_SIZE-1)) + Length > PAGE_SIZE ) {
+               Log_Warning("UHCI", "TODO: Support non single page transfers (%x + %x > %x)",
+                       (tVAddr)Data & (PAGE_SIZE-1), Length, PAGE_SIZE
+                       );
                // TODO: Need to enable IOC to copy the data back
 //             td->BufferPointer = 
                return NULL;
@@ -153,12 +208,14 @@ void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int
        // Interrupt on completion
        if( Cb ) {
                td->Control |= (1 << 24);
-               td->Avaliable[0] = (tVAddr)Cb;  // NOTE: if ERRPTR then the TD is kept allocated until checked
-               #if BITS > 32
-               td->Avaliable[1] = (tVAddr)Cb >> 32;
-               #endif
-               Log_Warning("UHCI", "TODO: Support IOC... somehow");
+               td->_info.Callback = Cb;        // NOTE: if ERRPTR then the TD is kept allocated until checked
+               if( Cb != INVLPTR )
+               {
+                       Log_Warning("UHCI", "TODO: Support IOC... somehow");
+               }
        }
+       
+       td->_info.DestPtr = Data;
 
        UHCI_int_AppendTD(Cont, td);
 
@@ -180,6 +237,12 @@ void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, tUSBHostCb Cb,
        return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x2D, DataTgl, Cb, Data, Length);
 }
 
+int UHCI_IsTransferComplete(void *Ptr, void *Handle)
+{
+       tUHCI_TD        *td = Handle;
+       return !(td->Control & (1 << 23));
+}
+
 void UHCI_Hub_Poll(tUSBHub *Hub, tUSBDevice *Dev)
 {
        tUHCI_Controller *cont = USB_GetDeviceDataPtr(Dev);
@@ -227,6 +290,7 @@ int UHCI_Int_InitHost(tUHCI_Controller *Host)
        outw( Host->IOBase + USBINTR, 0x000F );
        PCI_ConfigWrite( Host->PciId, 0xC0, 2, 0x2000 );
 
+       // Enable processing
        outw( Host->IOBase + USBCMD, 0x0001 );
 
        LEAVE('i', 0);
@@ -255,13 +319,13 @@ void UHCI_CheckPortUpdate(tUHCI_Controller *Host)
                        LOG("Port %i has something", i);
                        // Reset port (set bit 9)
                        LOG("Reset");
-                       outw( port, 0x0100 );
+                       outw( port, 0x0200 );
                        Time_Delay(50); // 50ms delay
-                       outw( port, inw(port) & ~0x0100 );
+                       outw( port, inw(port) & ~0x0200 );
                        // Enable port
                        LOG("Enable");
                        Time_Delay(50); // 50ms delay
-                       outw( port, inw(port) & 0x0004 );
+                       outw( port, inw(port) | 0x0004 );
                        // Tell USB there's a new device
                        USB_DeviceConnected(Host->RootHub, i);
                }
@@ -270,5 +334,14 @@ void UHCI_CheckPortUpdate(tUHCI_Controller *Host)
 
 void UHCI_InterruptHandler(int IRQ, void *Ptr)
 {
-       Log_Debug("UHCI", "UHIC Interrupt");
+       tUHCI_Controller *Host = Ptr;
+       Uint16  status = inw(Host->IOBase + USBSTS);
+       Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x", status);
+       
+       if( status & 1 )
+       {
+               // Interrupt-on-completion
+       }
+
+       outw(Host->IOBase + USBSTS, status);
 }
index 7d88d35..6056c98 100644 (file)
@@ -104,10 +104,19 @@ struct sUHCI_TD
         */
        Uint32  BufferPointer;
 
-       /**
-        * \brief Avaliable for use by software
-        */
-       Uint32  Avaliable[4];
+       union
+       {
+               /**
+                * \brief Avaliable for use by software
+                */
+               Uint32  Avaliable[4];
+               
+               struct
+               {
+                       void    *Callback;
+                       void    *DestPtr;
+               } _info;
+       };
 };
 
 struct sUHCI_QH

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