2 * Acess2 USB Stack HID Driver
3 * - By John Hodge (thePowersGang)
10 #include "hid_reports.h"
12 #include <api_drv_joystick.h>
15 #define MAX_AXIES 3 // X, Y, Scroll
16 #define MAX_BUTTONS 5 // Left, Right, Middle, ...
19 typedef struct sHID_Mouse tHID_Mouse;
24 tUSB_DataCallback DataAvail;
29 Uint8 FileData[ sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS ];
30 tJoystick_FileHeader *FileHeader;
31 tJoystick_Axis *Axies;
34 Uint16 AxisLimits[MAX_AXIES];
38 Uint8 Dest; // 0x00-0x7F = Buttons, 0x80-0xFE = Axies, 0xFF = Ignore
44 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data);
45 tHID_ReportCallbacks *HID_Mouse_Report_Collection(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
46 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev);
47 void HID_Mouse_Report_Input(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
50 tVFS_NodeType gHID_Mouse_RootNodeType = {
51 .TypeName = "HID Mouse Root"
53 tVFS_NodeType gHID_Mouse_DevNodeType = {
54 .TypeName = "HID Mouse Dev"
56 tDevFS_Driver gHID_Mouse_DevFS = {
58 .RootNode = {.Type = &gHID_Mouse_RootNodeType}
60 tHID_ReportCallbacks gHID_Mouse_ReportCBs = {
61 .Collection = HID_Mouse_Report_Collection,
62 .EndCollection = HID_Mouse_Report_EndCollection,
63 .Input = HID_Mouse_Report_Input,
65 tHID_Mouse *gpHID_FirstMouse;
66 tHID_Mouse *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse;
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 // ----------------------------------------------------------------------------
74 // Data input / Update
75 // ----------------------------------------------------------------------------
76 Sint32 _ReadBits(void *Data, int Offset, int Length)
80 Uint8 *bytes = (Uint8*)Data + Offset / 8;
85 if( Length < 8 - (Offset & 7) )
87 rv = (*bytes >> Offset) & ((1 << Length)-1);
91 rv = (*bytes >> Offset);
93 dest_ofs = Offset & 7;
101 rv |= *bytes << dest_ofs;
109 rv |= (*bytes & ((1 << Length)-1)) << dest_ofs;
115 if( rv & (1 << (Length-1)) )
116 rv |= 0xFFFFFFFF << Length;
120 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data)
125 info = USB_GetDeviceDataPtr(Dev);
130 for( int i = 0; i < info->nMappings; i ++ )
133 Uint8 dest = info->Mappings[i].Dest;
135 if( ofs + info->Mappings[i].BitSize > Length * 8 )
138 value = _ReadBits(Data, ofs, info->Mappings[i].BitSize);
139 ofs += info->Mappings[i].BitSize;
141 if( dest == 0xFF ) continue ;
146 info->Axies[ dest & 0x7F ].CurValue = value;
151 info->Buttons[ dest & 0x7F ] = (value == 0) ? 0 : 0xFF;
155 // Update axis positions
156 for( int i = 0; i < MAX_AXIES; i ++ )
161 newpos = info->Axies[i].CursorPos + info->Axies[i].CurValue;
163 if(newpos < 0) newpos = 0;
164 if(newpos > info->AxisLimits[i]) newpos = info->AxisLimits[i];
166 info->Axies[i].CursorPos = newpos;
168 Log_Debug("USBMouse", "New Pos (%i,%i,%i)",
169 info->Axies[0].CursorPos, info->Axies[1].CursorPos, info->Axies[2].CursorPos
173 // ----------------------------------------------------------------------------
174 // Device initialisation
175 // ----------------------------------------------------------------------------
178 tHID_ReportCallbacks *HID_Mouse_Report_Collection(
180 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
186 info = USB_GetDeviceDataPtr(Dev);
190 info = calloc( sizeof(tHID_Mouse), 1 );
191 info->DataAvail = HID_Mouse_DataAvail;
192 info->Node.Type = &gHID_Mouse_DevNodeType;
194 info->FileHeader = (void*)info->FileData;
195 info->Axies = (void*)(info->FileHeader + 1);
196 info->Buttons = (void*)(info->Axies + MAX_AXIES);
198 USB_SetDeviceDataPtr(Dev, info);
202 info->CollectionDepth ++;
205 return &gHID_Mouse_ReportCBs;
208 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev)
212 info = USB_GetDeviceDataPtr(Dev);
214 Log_Error("HID", "HID is not initialised when _AddInput is called");
218 if( info->CollectionDepth == 0 )
220 // TODO: Do final cleanup on device
221 gpHID_LastMouse->Next = info;
222 gpHID_LastMouse = info;
226 info->CollectionDepth --;
230 void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, Uint32 Max)
235 info = USB_GetDeviceDataPtr(Dev);
237 Log_Error("HID", "HID is not initialised when _AddInput is called");
243 case 0x00010030: tag = 0x80; break; // Generic Desktop - X
244 case 0x00010031: tag = 0x81; break; // Generic Desktop - Y
245 case 0x00010038: tag = 0x82; break; // Generic Desktop - Wheel
246 case 0x00090001: tag = 0x00; break; // Button 1
247 case 0x00090002: tag = 0x01; break; // Button 2
248 case 0x00090003: tag = 0x02; break; // Button 3
249 case 0x00090004: tag = 0x03; break; // Button 4
250 case 0x00090005: tag = 0x04; break; // Button 5
251 default: tag = 0xFF; break;
255 info->Mappings = realloc(info->Mappings, info->nMappings * sizeof(info->Mappings[0]));
258 info->Mappings[ info->nMappings - 1].Dest = tag;
259 info->Mappings[ info->nMappings - 1].BitSize = Size;
261 if( tag != 0xFF && (tag & 0x80) )
263 info->Axies[ tag & 0x7F ].MinValue = Min;
264 info->Axies[ tag & 0x7F ].MaxValue = Max;
268 void HID_Mouse_Report_Input(
270 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
275 for( int i = 0; i < Global->ReportCount; i ++ )
277 if( i < Local->Usages.nItems )
278 usage = Local->Usages.Items[i];
279 HID_int_AddInput(Dev, usage, Global->ReportSize, Global->LogMin, Global->LogMax);