#define DEBUG 0
#include <acess.h>
#include "hid_reports.h"
-#include <fs_devfs.h>
+#include <Input/Mouse/include/mouse.h>
+// === CONSTANTS ===
+#define MAX_AXIES 3 // X, Y, Scroll
+#define MAX_BUTTONS 5 // Left, Right, Middle, ...
+
+// === TYPES ===
+typedef struct sHID_Mouse tHID_Mouse;
+
+struct sHID_Mouse
+{
+ tHID_Mouse *Next;
+ tUSB_DataCallback DataAvail;
+
+ tMouse *Handle;
+
+ // - Report parsing
+ int nMappings;
+ struct {
+ Uint8 Dest; // 0x00-0x7F = Buttons, 0x80-0xFE = Axies, 0xFF = Ignore
+ Uint8 BitSize;
+ } *Mappings;
+
+ // - Initialisation only data
+ int CollectionDepth;
+};
// === PROTOTYES ===
+Sint32 _ReadBits(void *Data, int Offset, int Length);
+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);
-void HID_Mouse_Report_Output(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
-void HID_Mouse_Report_Feature(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
// === GLOBALS ===
-tDevFS_Driver gHID_Mouse_DevFS = {
- .Name = "USBKeyboard",
-};
tHID_ReportCallbacks gHID_Mouse_ReportCBs = {
.Collection = HID_Mouse_Report_Collection,
+ .EndCollection = HID_Mouse_Report_EndCollection,
.Input = HID_Mouse_Report_Input,
- .Output = HID_Mouse_Report_Output,
- .Feature = HID_Mouse_Report_Feature
};
+tMutex glHID_MouseListLock;
+tHID_Mouse *gpHID_FirstMouse;
+tHID_Mouse *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse;
// === CODE ===
+// ----------------------------------------------------------------------------
+// Data input / Update
+// ----------------------------------------------------------------------------
+/**
+ * \brief Read a set amounts of bits from a stream
+ * \param Data Base of data
+ * \param Offset Bit offset
+ * \param Length Number of bits to read
+ * \return Sign-extended value
+ */
+Sint32 _ReadBits(void *Data, int Offset, int Length)
+{
+ int dest_ofs = 0;
+ int rem = Length;
+ Uint32 rv = 0;
+ Uint8 *bytes = (Uint8*)Data + Offset / 8;
+
+ // Sanity please
+ if( Length > 32 ) return 0;
+
+ // Leading byte
+ if( Offset & 7 )
+ {
+ if( Length < 8 - (Offset & 7) )
+ {
+ rv = (*bytes >> Offset) & ((1 << Length)-1);
+ goto _ext;
+ }
+
+ rv = (*bytes >> Offset);
+
+ dest_ofs = Offset & 7;
+ rem = Length - (Offset & 7);
+ bytes ++;
+ }
+
+ // Body bytes
+ while( rem >= 8 )
+ {
+ rv |= *bytes << dest_ofs;
+ dest_ofs += 8;
+ rem -= 8;
+ bytes ++;
+ }
+
+ if( rem )
+ {
+ rv |= (*bytes & ((1 << rem)-1)) << dest_ofs;
+ }
+
+ // Do sign extension
+_ext:
+ if( rv & (1 << (Length-1)) )
+ rv |= 0xFFFFFFFF << Length;
+ return rv;
+}
+
+/**
+ * \brief Handle an update from the device
+ */
+void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data)
+{
+ tHID_Mouse *info;
+ int ofs;
+ Uint32 button_value = 0;
+ int axis_values[MAX_AXIES] = {0};
+
+ info = USB_GetDeviceDataPtr(Dev);
+ if( !info ) return ;
+
+ ofs = 0;
+ for( int i = 0; i < info->nMappings; i ++ )
+ {
+ Sint32 value;
+ Uint8 dest = info->Mappings[i].Dest;
+
+ if( ofs + info->Mappings[i].BitSize > Length * 8 )
+ return ;
+
+ value = _ReadBits(Data, ofs, info->Mappings[i].BitSize);
+ LOG("%i+%i: value = %i", ofs, info->Mappings[i].BitSize, value);
+ ofs += info->Mappings[i].BitSize;
+
+ if( dest == 0xFF ) continue ;
+
+ if( dest & 0x80 )
+ {
+ // Axis
+ axis_values[ dest & 0x7F ] = value;
+ LOG("Axis %i = %i", dest & 0x7F, value);
+ }
+ else
+ {
+ // Button
+ if( value == 0 )
+ ;
+ else
+ button_value |= 1 << (dest & 0x7F);
+ }
+ }
+
+ Mouse_HandleEvent(info->Handle, button_value, axis_values);
+}
+
+// ----------------------------------------------------------------------------
+// Device initialisation
+// ----------------------------------------------------------------------------
+/**
+ * \brief Handle the opening of a collection
+ */
tHID_ReportCallbacks *HID_Mouse_Report_Collection(
tUSBInterface *Dev,
tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
Uint32 Value
)
{
+ tHID_Mouse *info;
+
+ info = USB_GetDeviceDataPtr(Dev);
+ if( !info )
+ {
+ // New device!
+ info = calloc( sizeof(tHID_Mouse), 1 );
+ info->DataAvail = HID_Mouse_DataAvail;
+
+ info->Handle = Mouse_Register("USBMouse", MAX_BUTTONS, MAX_AXIES);
+
+ LOG("Initialised new mouse at %p", info);
+
+ USB_SetDeviceDataPtr(Dev, info);
+ }
+ else
+ {
+ info->CollectionDepth ++;
+ }
+
return &gHID_Mouse_ReportCBs;
}
-void HID_Mouse_Report_Input(
- tUSBInterface *Dev,
- tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
- Uint32 Value
- )
+/**
+ * \brief Handle the end of a collection
+ */
+void HID_Mouse_Report_EndCollection(tUSBInterface *Dev)
{
-
+ tHID_Mouse *info;
+
+ info = USB_GetDeviceDataPtr(Dev);
+ if(!info) {
+ Log_Error("HID", "HID is not initialised when _AddInput is called");
+ return ;
+ }
+
+ if( info->CollectionDepth == 0 )
+ {
+ // Perform final initialisation steps
+ Mutex_Acquire(&glHID_MouseListLock);
+ gpHID_LastMouse->Next = info;
+ gpHID_LastMouse = info;
+ Mutex_Release(&glHID_MouseListLock);
+ }
+ else
+ {
+ info->CollectionDepth --;
+ }
}
-void HID_Mouse_Report_Output(
- tUSBInterface *Dev,
- tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
- Uint32 Value
- )
+/**
+ * \brief Add a new input mapping
+ */
+void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, Uint32 Max)
{
+ Uint8 tag;
+ tHID_Mouse *info;
+
+ info = USB_GetDeviceDataPtr(Dev);
+ if(!info) {
+ Log_Error("HID", "HID is not initialised when _AddInput is called");
+ return ;
+ }
+
+ // --- Get the destination for the field ---
+ switch(Usage)
+ {
+ case 0x00010030: tag = 0x80; break; // Generic Desktop - X
+ case 0x00010031: tag = 0x81; break; // Generic Desktop - Y
+ case 0x00010038: tag = 0x82; break; // Generic Desktop - Wheel
+ case 0x00090001: tag = 0x00; break; // Button 1
+ case 0x00090002: tag = 0x01; break; // Button 2
+ case 0x00090003: tag = 0x02; break; // Button 3
+ case 0x00090004: tag = 0x03; break; // Button 4
+ case 0x00090005: tag = 0x04; break; // Button 5
+ default: tag = 0xFF; break;
+ }
+
+ LOG("Usage = 0x%08x, tag = 0x%2x", Usage, tag);
+
+ // --- Add to list of mappings ---
+ info->nMappings ++;
+ info->Mappings = realloc(info->Mappings, info->nMappings * sizeof(info->Mappings[0]));
+ // TODO: NULL check
+ info->Mappings[ info->nMappings - 1].Dest = tag;
+ info->Mappings[ info->nMappings - 1].BitSize = Size;
+ // --- Update Min/Max for Axies ---
+ // TODO: DPI too
+ // TODO: Pass to mouse multiplexer
+// if( tag != 0xFF && (tag & 0x80) )
+// {
+// info->Axies[ tag & 0x7F ].MinValue = Min;
+// info->Axies[ tag & 0x7F ].MaxValue = Max;
+// }
}
-void HID_Mouse_Report_Feature(
+/**
+ * \brief Handle an input item in a report
+ */
+void HID_Mouse_Report_Input(
tUSBInterface *Dev,
tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
Uint32 Value
)
{
-
+ Uint32 usage = 0;
+ LOG("Local->Usages.nItems = %i", Local->Usages.nItems);
+ for( int i = 0; i < Global->ReportCount; i ++ )
+ {
+ // - Update usage
+ if( i < Local->Usages.nItems )
+ usage = Local->Usages.Items[i];
+ LOG("%i: usage = %x", i, usage);
+ // - Add to list
+ HID_int_AddInput(Dev, usage, Global->ReportSize, Global->LogMin, Global->LogMax);
+ }
}