Modules/USB - Crash prevention in UHCI, VFS interface for HIDMouse
authorJohn Hodge <[email protected]>
Fri, 17 Feb 2012 03:18:15 +0000 (11:18 +0800)
committerJohn Hodge <[email protected]>
Fri, 17 Feb 2012 03:18:15 +0000 (11:18 +0800)
KernelLand/Modules/USB/Core/usb_poll.c
KernelLand/Modules/USB/HID/main.c
KernelLand/Modules/USB/HID/mouse.c
KernelLand/Modules/USB/UHCI/uhci.c

index 84703f8..6285a11 100644 (file)
@@ -5,7 +5,7 @@
  * usb_poll.c
  * - Endpoint polling
  */
-#define DEBUG  1
+#define DEBUG  0
 #include <usb_core.h>
 #include "usb.h"
 #include <timers.h>
@@ -29,9 +29,14 @@ void USB_StartPollingEndpoint(tUSBInterface *Iface, int Endpoint)
 {
        tUSBEndpoint    *endpt;
 
+       ENTER("pIface iEndpoint", Iface, Endpoint);
+       LEAVE('-');
+
        // Some sanity checks
-       if(Endpoint <= 0 || Endpoint > Iface->nEndpoints)       return ;
+       if(Endpoint <= 0 || Endpoint > Iface->nEndpoints)
+               return ;
        endpt = &Iface->Endpoints[Endpoint-1];
+       LOG("endpt(%p)->PollingPeriod = %i", endpt, endpt->PollingPeriod);
        if(endpt->PollingPeriod > POLL_MAX || endpt->PollingPeriod <= 0)
                return ;
 
@@ -42,6 +47,7 @@ void USB_StartPollingEndpoint(tUSBInterface *Iface, int Endpoint)
        // Determine polling period in atoms
        endpt->PollingAtoms = (endpt->PollingPeriod + POLL_ATOM-1) / POLL_ATOM;
        if(endpt->PollingAtoms > POLL_SLOTS)    endpt->PollingAtoms = POLL_SLOTS;
+       LOG("endpt(%p)->PollingAtoms = %i", endpt, endpt->PollingAtoms);
        // Add to poll queue
        // TODO: Locking
        {
@@ -81,7 +87,7 @@ int USB_PollThread(void *unused)
                for( ep = gUSB_PollQueues[giUSB_PollPosition]; ep; prev = ep, ep = ep->Next )
                {
                         int    period_in_atoms = ep->PollingAtoms;
-//                     LOG("%i: ep = %p", giUSB_PollPosition, ep);
+                       LOG("%i: ep = %p", giUSB_PollPosition, ep);
 
                        // Check for invalid entries
                        if(period_in_atoms < 0 || period_in_atoms > POLL_ATOM)
index 68e301e..25b533d 100644 (file)
@@ -12,6 +12,7 @@
 #include <usb_core.h>
 #include "hid.h"
 #include "hid_reports.h"
+#include <fs_devfs.h>
 
 // === TYPES ===
 typedef struct sHID_Device     tHID_Device;
@@ -23,6 +24,10 @@ struct sHID_Device
        // ... Device-specific data
 };
 
+// === IMPORTS ===
+extern tHID_ReportCallbacks    gHID_Mouse_ReportCBs;
+extern tDevFS_Driver   gHID_Mouse_DevFS;
+
 // === PROTOTYPES ===
  int   HID_Initialise(char **Arguments);
 void   HID_InterruptCallback(tUSBInterface *Dev, int EndPt, int Length, void *Data);
@@ -54,6 +59,9 @@ tHID_ReportCallbacks  gHID_RootCallbacks = {
 int HID_Initialise(char **Arguments)
 {
        USB_RegisterDriver( &gHID_USBDriver );
+       
+       DevFS_AddDevice( &gHID_Mouse_DevFS );
+       
        return 0;
 }
 
@@ -146,6 +154,19 @@ void HID_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t Descripto
        USB_ReadDescriptor(Dev, 0x1022, 0, report_len, report_data);
        HID_int_ParseReport(Dev, report_data, report_len, &gHID_RootCallbacks);
        
+       // --- Start polling ---
+       // Only if the device was initialised
+       if( USB_GetDeviceDataPtr(Dev) )
+       {
+               // Poll Endpoint .+1 (interupt)
+               USB_StartPollingEndpoint(Dev, 1);
+       }
+       else
+       {
+               Log_Log("USB_HID", "Device not intitialised");
+       }
+       
+       
        LEAVE('-');
 }
 
@@ -178,7 +199,7 @@ tHID_ReportCallbacks *HID_RootCollection(
                        break;
                case 0x0002:    // Mouse
                        LOG("Desktop->Mouse");
-                       break;
+                       return &gHID_Mouse_ReportCBs;
                case 0x0004:    // Joystick
                case 0x0005:    // Game Pad
                        LOG("Desktop->Gamepad");
index be015ad..233465a 100644 (file)
@@ -5,7 +5,7 @@
  * mouse.c
  * - USB Mouse driver
  */
-#define DEBUG  0
+#define DEBUG  1
 #include <acess.h>
 #include "hid_reports.h"
 #include <fs_devfs.h>
@@ -14,6 +14,7 @@
 // === CONSTANTS ===
 #define MAX_AXIES      3       // X, Y, Scroll
 #define MAX_BUTTONS    5       // Left, Right, Middle, ...
+#define FILE_SIZE      (sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS)
 
 // === TYPES ===
 typedef struct sHID_Mouse      tHID_Mouse;
@@ -26,7 +27,7 @@ struct sHID_Mouse
        tVFS_Node       Node;
         int    CollectionDepth;
        
-       Uint8   FileData[ sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS ];
+       Uint8   FileData[ FILE_SIZE ];
        tJoystick_FileHeader    *FileHeader;
        tJoystick_Axis  *Axies;
        Uint8   *Buttons;
@@ -41,17 +42,31 @@ struct sHID_Mouse
 };
 
 // === PROTOTYES ===
+char   *HID_Mouse_Root_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node      *HID_Mouse_Root_FindDir(tVFS_Node *Node, const char *Name);
+Uint64 HID_Mouse_Dev_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+ int   HID_Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data);
+void   HID_Mouse_Dev_Reference(tVFS_Node *Node);
+void   HID_Mouse_Dev_Close(tVFS_Node *Node);
+
 void   HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data);
+
 tHID_ReportCallbacks   *HID_Mouse_Report_Collection(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
 void   HID_Mouse_Report_EndCollection(tUSBInterface *Dev);
 void   HID_Mouse_Report_Input(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
 
 // === GLOBALS ===
 tVFS_NodeType  gHID_Mouse_RootNodeType = {
-       .TypeName = "HID Mouse Root"
+       .TypeName = "HID Mouse Root",
+       .ReadDir = HID_Mouse_Root_ReadDir,
+       .FindDir = HID_Mouse_Root_FindDir
 };
 tVFS_NodeType  gHID_Mouse_DevNodeType = {
-       .TypeName = "HID Mouse Dev"
+       .TypeName = "HID Mouse Dev",
+       .Read = HID_Mouse_Dev_Read,
+       .IOCtl = HID_Mouse_Dev_IOCtl,
+       .Reference = HID_Mouse_Dev_Reference,
+       .Close = HID_Mouse_Dev_Close,
 };
 tDevFS_Driver  gHID_Mouse_DevFS = {
        .Name = "USBMouse",
@@ -62,6 +77,7 @@ tHID_ReportCallbacks  gHID_Mouse_ReportCBs = {
        .EndCollection = HID_Mouse_Report_EndCollection,
        .Input = HID_Mouse_Report_Input,
 };
+tMutex glHID_MouseListLock;
 tHID_Mouse     *gpHID_FirstMouse;
 tHID_Mouse     *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse;
 
@@ -69,6 +85,68 @@ tHID_Mouse   *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse;
 // ----------------------------------------------------------------------------
 // VFS Interface
 // ----------------------------------------------------------------------------
+char *HID_Mouse_Root_ReadDir(tVFS_Node *Node, int Pos)
+{
+       char    data[3];
+       if(Pos < 0 || Pos >= Node->Size)        return NULL;
+       
+       snprintf(data, 3, "%i", Pos);
+       return strdup(data);
+}
+
+tVFS_Node *HID_Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
+{
+        int    ID;
+        int    ofs;
+       tHID_Mouse      *mouse;
+       
+       if( Name[0] == '\0' )
+               return NULL;
+       
+       ofs = ParseInt(Name, &ID);
+       if( ofs == 0 || Name[ofs] != '\0' )
+               return NULL;
+       
+       // Scan list, locate item
+       Mutex_Acquire(&glHID_MouseListLock);
+       for( mouse = gpHID_FirstMouse; mouse && ID --; mouse = mouse->Next ) ;
+       mouse->Node.ReferenceCount ++;  
+       Mutex_Release(&glHID_MouseListLock);
+
+       return &mouse->Node;
+}
+
+Uint64 HID_Mouse_Dev_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       tHID_Mouse      *info = Node->ImplPtr;
+       
+       if( Offset > FILE_SIZE )        return 0;
+       
+       if( Length > FILE_SIZE )        Length = FILE_SIZE;
+       if( Offset + Length > FILE_SIZE )       Length = FILE_SIZE - Offset;
+
+       memcpy( Buffer, info->FileData + Offset, Length );
+
+       return Length;
+}
+
+static const char *csaDevIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
+int HID_Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+       switch(ID)
+       {
+       BASE_IOCTLS(DRV_TYPE_JOYSTICK, "USBMouse", 0x050, csaDevIOCtls);
+       }
+       return -1;
+}
+void HID_Mouse_Dev_Reference(tVFS_Node *Node)
+{
+       Node->ReferenceCount ++;
+}
+void HID_Mouse_Dev_Close(tVFS_Node *Node)
+{
+       Node->ReferenceCount --;
+}
 
 // ----------------------------------------------------------------------------
 // Data input / Update
@@ -124,7 +202,8 @@ void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data)
        
        info = USB_GetDeviceDataPtr(Dev);
        if( !info )     return ;
-       
+
+       Log_Debug("USBMouse", "info = %p", info);       
        
        ofs = 0;
        for( int i = 0; i < info->nMappings; i ++ )
@@ -189,11 +268,14 @@ tHID_ReportCallbacks *HID_Mouse_Report_Collection(
                // New device!
                info = calloc( sizeof(tHID_Mouse), 1 );
                info->DataAvail = HID_Mouse_DataAvail;
+               info->Node.ImplPtr = info;
                info->Node.Type = &gHID_Mouse_DevNodeType;
                
                info->FileHeader = (void*)info->FileData;
                info->Axies = (void*)(info->FileHeader + 1);
                info->Buttons = (void*)(info->Axies + MAX_AXIES);
+       
+               LOG("Initialised new mouse at %p", info);
                
                USB_SetDeviceDataPtr(Dev, info);
        }
@@ -217,9 +299,12 @@ void HID_Mouse_Report_EndCollection(tUSBInterface *Dev)
 
        if( info->CollectionDepth == 0 )
        {
-               // TODO: Do final cleanup on device
+               // Perform final initialisation steps
+               Mutex_Acquire(&glHID_MouseListLock);
                gpHID_LastMouse->Next = info;
                gpHID_LastMouse = info;
+               gHID_Mouse_DevFS.RootNode.Size ++;
+               Mutex_Release(&glHID_MouseListLock);
        }
        else
        {
index 76b0ba4..b348a45 100644 (file)
@@ -191,6 +191,12 @@ void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD)
        link = Cont->FrameList[next_frame];
        do {
                prev_td = UHCI_int_GetTDFromPhys(link);
+               if(!prev_td) {
+                       Log_Error("UHCI", "ERROR: TD list is bad");
+                       TD->Link = 1;
+                       LEAVE('-');
+                       return ;
+               }
                link = prev_td->Link;
        } while( !(link & 1) );
        

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