Kernel/PTYs - Add initial dims/mode to PTY_Create
[tpg/acess2.git] / KernelLand / Modules / USB / HID / main.c
index 336609d..c280273 100644 (file)
@@ -5,16 +5,32 @@
  * main.c
  * - Driver Core
  */
-#define DEBUG  1
+#define DEBUG  0
 #define VERSION        VER2(0,1)
 #include <acess.h>
 #include <modules.h>
 #include <usb_core.h>
 #include "hid.h"
 #include "hid_reports.h"
+#include <fs_devfs.h>
+
+// === TYPES ===
+typedef struct sHID_Device     tHID_Device;
+
+struct sHID_Device
+{
+       void    *Next;  // Used by sub-driver
+       tUSB_DataCallback       DataAvail;
+       // ... Device-specific data
+};
+
+// === IMPORTS ===
+extern tHID_ReportCallbacks    gHID_Mouse_ReportCBs;
+extern tHID_ReportCallbacks    gHID_Kb_ReportCBs;
 
 // === PROTOTYPES ===
  int   HID_Initialise(char **Arguments);
+void   HID_InterruptCallback(tUSBInterface *Dev, int EndPt, int Length, void *Data);
 void   HID_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t DescriptorsLen);
 tHID_ReportCallbacks   *HID_RootCollection(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
 void   HID_int_ParseReport(tUSBInterface *Dev, Uint8 *Data, size_t Length, tHID_ReportCallbacks *StartCBs);
@@ -24,11 +40,16 @@ static void _AddItems(struct sHID_IntList *List, Uint32 First, Uint32 Last);
 static void    _FreeList(struct sHID_IntList *List);
 
 // === GLOBALS ===
-MODULE_DEFINE(0, VERSION, USB_HID, HID_Initialise, NULL, "USB_Core", NULL);
+MODULE_DEFINE(0, VERSION, USB_HID, HID_Initialise, NULL, "USB_Core", "Keyboard", "Mouse", NULL);
 tUSBDriver     gHID_USBDriver = {
        .Name = "HID",
        .Match = {.Class = {0x030000, 0xFF0000}},
        .Connected = HID_DeviceConnected,
+       .MaxEndpoints = 2,
+       .Endpoints = {
+               {0x80, HID_InterruptCallback},
+               {0, NULL}
+       }
 };
 tHID_ReportCallbacks   gHID_RootCallbacks = {
        .Collection = HID_RootCollection
@@ -38,9 +59,32 @@ tHID_ReportCallbacks gHID_RootCallbacks = {
 int HID_Initialise(char **Arguments)
 {
        USB_RegisterDriver( &gHID_USBDriver );
+       
        return 0;
 }
 
+/**
+ * \brief Callback for when there's new data from the device
+ * 
+ * Calls the subdriver callback (stored at a fixed offset in the device data structure)
+ */
+void HID_InterruptCallback(tUSBInterface *Dev, int EndPt, int Length, void *Data)
+{
+       tHID_Device     *info;
+       
+       info = USB_GetDeviceDataPtr(Dev);
+       if(!info) {
+               Log_Error("USB HID", "Device %p doesn't have a data pointer.", Dev);
+               return ;
+       }
+
+       LOG("Data for %p", info->DataAvail);    
+       info->DataAvail(Dev, EndPt, Length, Data);
+}
+
+/**
+ * \brief Handle a device connection
+ */
 void HID_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t DescriptorsLen)
 {
        struct sDescriptor_HID  *hid_desc;
@@ -49,7 +93,7 @@ void HID_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t Descripto
        
        ENTER("pDev pDescriptors iDescriptorsLen", Dev, Descriptors, DescriptorsLen);
 
-       // Locate HID descriptor
+       // --- Locate HID descriptor ---
        hid_desc = NULL;
        while(ofs + 2 <= DescriptorsLen)
        {
@@ -70,16 +114,7 @@ void HID_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t Descripto
                LEAVE('-');
                return ;
        }
-       
-
-       // Dump descriptor header
-       LOG("hid_desc = {");
-       LOG("  .Length  = %i", hid_desc->Length);
-       LOG("  .Type    = 0x%x", hid_desc->Type);
-       LOG("  .Version = 0x%x", hid_desc->Version);
-       LOG("  .NumDescriptors = %i", hid_desc->NumDescriptors);
-       LOG("}");
-
+       // - Sanity check length
        if( hid_desc->Length < sizeof(*hid_desc) + hid_desc->NumDescriptors * sizeof(hid_desc->Descriptors[0]) )
        {
                // Too small!
@@ -90,7 +125,15 @@ void HID_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t Descripto
                return ;
        }
 
-       // Locate report descriptor
+       // --- Dump descriptor header ---
+       LOG("hid_desc = {");
+       LOG("  .Length  = %i", hid_desc->Length);
+       LOG("  .Type    = 0x%x", hid_desc->Type);
+       LOG("  .Version = 0x%x", hid_desc->Version);
+       LOG("  .NumDescriptors = %i", hid_desc->NumDescriptors);
+       LOG("}");
+
+       // --- Locate report descriptor length ---
        for( int i = 0; i < hid_desc->NumDescriptors; i ++ )
        {
                if( hid_desc->Descriptors[i].DescType == 0x22 ) {
@@ -104,11 +147,25 @@ void HID_DeviceConnected(tUSBInterface *Dev, void *Descriptors, size_t Descripto
                return ;
        }
        
-       // Read and parse report descriptor
-       Uint8   *report_data = alloca(report_len);
+       // --- Read and parse report descriptor ---
+       // NOTE: Also does sub-driver selection and initialisation
+       Uint8   report_data[report_len];
        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('-');
 }
 
@@ -141,19 +198,19 @@ 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");
                        break;
                case 0x0006:    // Keyboard
                        LOG("Desktop->Keyboard");
-                       break;
+                       return &gHID_Kb_ReportCBs;
                }
                break;
        case 0x0007:    // Keyboard / Keypad
                LOG("Keyboard");
-               break;
+               return &gHID_Kb_ReportCBs;
        }
        return NULL;
 }
@@ -169,19 +226,22 @@ void HID_int_ParseReport(tUSBInterface *Dev, Uint8 *Data, size_t Length, tHID_Re
        
        ENTER("pData iLength pStartCBs", Data, Length, StartCBs);
 
+       // Initialise callback stack
        cb_stack[0] = StartCBs;
        cur_cbs = StartCBs;
 
+       // Clear state
        memset(&global_state, 0, sizeof(global_state));
        memset(&local_state, 0, sizeof(local_state));
 
+       // Iterate though the report data
        for( int ofs = 0; ofs < Length; )
        {
                Uint8   byte;
                Uint32  val;
                
+               // --- Get value and length ---
                byte = Data[ofs];
-               // Get value (and increase offset)
                switch(byte & 3)
                {
                case 0:
@@ -189,19 +249,23 @@ void HID_int_ParseReport(tUSBInterface *Dev, Uint8 *Data, size_t Length, tHID_Re
                        ofs += 1;
                        break;
                case 1:
+                       if( ofs + 2 > Length ) { LEAVE('-'); return; }
                        val = Data[ofs+1];
                        ofs += 2;
                        break;
                case 2:
+                       if( ofs + 3 > Length ) { LEAVE('-'); return; }
                        val = Data[ofs + 1] | (Data[ofs + 1]<<8);
                        ofs += 3;
                        break;
                case 3:
+                       if( ofs + 5 > Length ) { LEAVE('-'); return; }
                        val = Data[ofs + 1] | (Data[ofs + 2] << 8) | (Data[ofs + 3] << 16) | (Data[ofs + 4] << 24);
                        ofs += 5;
                        break;
                }
        
+               // --- Process the item ---
                LOG("Type = 0x%x, len = %i, val = 0x%x", byte & 0xFC, byte & 3, val);
                switch(byte & 0xFC)
                {
@@ -231,7 +295,7 @@ void HID_int_ParseReport(tUSBInterface *Dev, Uint8 *Data, size_t Length, tHID_Re
                        else
                                next_cbs = NULL;
                        cur_cbs = next_cbs;
-                       break;
+                       goto _clear_local;
                // - Feature
                case 0xB0:
                        LOG("Feature 0x%x", val);
@@ -277,14 +341,17 @@ void HID_int_ParseReport(tUSBInterface *Dev, Uint8 *Data, size_t Length, tHID_Re
                // - Usages
                case 0x08:      // Single
                        if( (byte & 3) != 3 )   val |= global_state.UsagePage;
+                       LOG("Usage %x", val);
                        _AddItem(&local_state.Usages, val);
                        break;
                case 0x18:      // Range start
                        if( (byte & 3) != 3 )   val |= global_state.UsagePage;
+                       LOG("Usage start %x", val);
                        local_state.UsageMin = val;
                        break;
                case 0x28:      // Range end (apply)
                        if( (byte & 3) != 3 )   val |= global_state.UsagePage;
+                       LOG("Usage end %x (from %x)", val, local_state.UsageMin);
                        _AddItems(&local_state.Usages, local_state.UsageMin, val);
                        break;
                // - Designators (Index into Physical report)
@@ -329,6 +396,9 @@ void HID_int_ParseReport(tUSBInterface *Dev, Uint8 *Data, size_t Length, tHID_Re
        LEAVE('-');
 }
 
+// --------------------------------------------------------------------
+// List helpers
+// --------------------------------------------------------------------
 static void _AddItem(struct sHID_IntList *List, Uint32 Value)
 {
        if( List->Space == List->nItems )
@@ -337,6 +407,7 @@ static void _AddItem(struct sHID_IntList *List, Uint32 Value)
                List->Items = realloc( List->Items, List->Space * sizeof(List->Items[0]) );
        }
        
+//     LOG("Added %x to %p", Value, List);
        List->Items[ List->nItems ] = Value;
        List->nItems ++;
 }
@@ -352,6 +423,7 @@ static void _AddItems(struct sHID_IntList *List, Uint32 First, Uint32 Last)
 
 static void _FreeList(struct sHID_IntList *List)
 {
-       free(List->Items);
+       if( List->Items )
+               free(List->Items);
 }
 

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