X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FUSB%2FHID%2Fmain.c;h=c2802737dabca2747c2a613f5fc53b60f158e58d;hb=36b950d17b828c7cd2e5e9dbe5fb4cbded89889c;hp=336609daf5508ba15c2e0546b867fcacf0817a54;hpb=1ba64c63a4a3a8ce27155f9463f0442ea7f7dc89;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/USB/HID/main.c b/KernelLand/Modules/USB/HID/main.c index 336609da..c2802737 100644 --- a/KernelLand/Modules/USB/HID/main.c +++ b/KernelLand/Modules/USB/HID/main.c @@ -5,16 +5,32 @@ * main.c * - Driver Core */ -#define DEBUG 1 +#define DEBUG 0 #define VERSION VER2(0,1) #include #include #include #include "hid.h" #include "hid_reports.h" +#include + +// === 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); }