* 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);
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
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;
ENTER("pDev pDescriptors iDescriptorsLen", Dev, Descriptors, DescriptorsLen);
- // Locate HID descriptor
+ // --- Locate HID descriptor ---
hid_desc = NULL;
while(ofs + 2 <= DescriptorsLen)
{
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!
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 ) {
return ;
}
- // Read and parse report descriptor
+ // --- Read and parse report descriptor ---
+ // NOTE: Also does sub-driver selection and initialisation
Uint8 *report_data = alloca(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('-');
}
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;
}
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:
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)
{
else
next_cbs = NULL;
cur_cbs = next_cbs;
- break;
+ goto _clear_local;
// - Feature
case 0xB0:
LOG("Feature 0x%x", val);
// - 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)
LEAVE('-');
}
+// --------------------------------------------------------------------
+// List helpers
+// --------------------------------------------------------------------
static void _AddItem(struct sHID_IntList *List, Uint32 Value)
{
if( List->Space == List->nItems )
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 ++;
}
static void _FreeList(struct sHID_IntList *List)
{
- free(List->Items);
+ if( List->Items )
+ free(List->Items);
}