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, ...
17 #define FILE_SIZE (sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS)
20 typedef struct sHID_Mouse tHID_Mouse;
25 tUSB_DataCallback DataAvail;
30 Uint8 FileData[ FILE_SIZE ];
31 tJoystick_FileHeader *FileHeader;
32 tJoystick_Axis *Axies;
35 Uint16 AxisLimits[MAX_AXIES];
39 Uint8 Dest; // 0x00-0x7F = Buttons, 0x80-0xFE = Axies, 0xFF = Ignore
45 char *HID_Mouse_Root_ReadDir(tVFS_Node *Node, int Pos);
46 tVFS_Node *HID_Mouse_Root_FindDir(tVFS_Node *Node, const char *Name);
47 Uint64 HID_Mouse_Dev_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
48 int HID_Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data);
49 void HID_Mouse_Dev_Reference(tVFS_Node *Node);
50 void HID_Mouse_Dev_Close(tVFS_Node *Node);
52 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data);
54 tHID_ReportCallbacks *HID_Mouse_Report_Collection(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
55 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev);
56 void HID_Mouse_Report_Input(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
59 tVFS_NodeType gHID_Mouse_RootNodeType = {
60 .TypeName = "HID Mouse Root",
61 .ReadDir = HID_Mouse_Root_ReadDir,
62 .FindDir = HID_Mouse_Root_FindDir
64 tVFS_NodeType gHID_Mouse_DevNodeType = {
65 .TypeName = "HID Mouse Dev",
66 .Read = HID_Mouse_Dev_Read,
67 .IOCtl = HID_Mouse_Dev_IOCtl,
68 .Reference = HID_Mouse_Dev_Reference,
69 .Close = HID_Mouse_Dev_Close,
71 tDevFS_Driver gHID_Mouse_DevFS = {
73 .RootNode = {.Type = &gHID_Mouse_RootNodeType}
75 tHID_ReportCallbacks gHID_Mouse_ReportCBs = {
76 .Collection = HID_Mouse_Report_Collection,
77 .EndCollection = HID_Mouse_Report_EndCollection,
78 .Input = HID_Mouse_Report_Input,
80 tMutex glHID_MouseListLock;
81 tHID_Mouse *gpHID_FirstMouse;
82 tHID_Mouse *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse;
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
88 char *HID_Mouse_Root_ReadDir(tVFS_Node *Node, int Pos)
91 if(Pos < 0 || Pos >= Node->Size) return NULL;
93 snprintf(data, 3, "%i", Pos);
97 tVFS_Node *HID_Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
103 if( Name[0] == '\0' )
106 ofs = ParseInt(Name, &ID);
107 if( ofs == 0 || Name[ofs] != '\0' )
110 // Scan list, locate item
111 Mutex_Acquire(&glHID_MouseListLock);
112 for( mouse = gpHID_FirstMouse; mouse && ID --; mouse = mouse->Next ) ;
113 mouse->Node.ReferenceCount ++;
114 Mutex_Release(&glHID_MouseListLock);
119 Uint64 HID_Mouse_Dev_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
121 tHID_Mouse *info = Node->ImplPtr;
123 if( Offset > FILE_SIZE ) return 0;
125 if( Length > FILE_SIZE ) Length = FILE_SIZE;
126 if( Offset + Length > FILE_SIZE ) Length = FILE_SIZE - Offset;
128 memcpy( Buffer, info->FileData + Offset, Length );
133 static const char *csaDevIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
134 int HID_Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data)
138 BASE_IOCTLS(DRV_TYPE_JOYSTICK, "USBMouse", 0x050, csaDevIOCtls);
142 void HID_Mouse_Dev_Reference(tVFS_Node *Node)
144 Node->ReferenceCount ++;
146 void HID_Mouse_Dev_Close(tVFS_Node *Node)
148 Node->ReferenceCount --;
151 // ----------------------------------------------------------------------------
152 // Data input / Update
153 // ----------------------------------------------------------------------------
154 Sint32 _ReadBits(void *Data, int Offset, int Length)
158 Uint8 *bytes = (Uint8*)Data + Offset / 8;
163 if( Length < 8 - (Offset & 7) )
165 rv = (*bytes >> Offset) & ((1 << Length)-1);
169 rv = (*bytes >> Offset);
171 dest_ofs = Offset & 7;
172 Length -= Offset & 7;
179 rv |= *bytes << dest_ofs;
187 rv |= (*bytes & ((1 << Length)-1)) << dest_ofs;
193 if( rv & (1 << (Length-1)) )
194 rv |= 0xFFFFFFFF << Length;
198 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data)
203 info = USB_GetDeviceDataPtr(Dev);
206 Log_Debug("USBMouse", "info = %p", info);
209 for( int i = 0; i < info->nMappings; i ++ )
212 Uint8 dest = info->Mappings[i].Dest;
214 if( ofs + info->Mappings[i].BitSize > Length * 8 )
217 value = _ReadBits(Data, ofs, info->Mappings[i].BitSize);
218 ofs += info->Mappings[i].BitSize;
220 if( dest == 0xFF ) continue ;
225 info->Axies[ dest & 0x7F ].CurValue = value;
230 info->Buttons[ dest & 0x7F ] = (value == 0) ? 0 : 0xFF;
234 // Update axis positions
235 for( int i = 0; i < MAX_AXIES; i ++ )
240 newpos = info->Axies[i].CursorPos + info->Axies[i].CurValue;
242 if(newpos < 0) newpos = 0;
243 if(newpos > info->AxisLimits[i]) newpos = info->AxisLimits[i];
245 info->Axies[i].CursorPos = newpos;
247 Log_Debug("USBMouse", "New Pos (%i,%i,%i)",
248 info->Axies[0].CursorPos, info->Axies[1].CursorPos, info->Axies[2].CursorPos
252 // ----------------------------------------------------------------------------
253 // Device initialisation
254 // ----------------------------------------------------------------------------
257 tHID_ReportCallbacks *HID_Mouse_Report_Collection(
259 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
265 info = USB_GetDeviceDataPtr(Dev);
269 info = calloc( sizeof(tHID_Mouse), 1 );
270 info->DataAvail = HID_Mouse_DataAvail;
271 info->Node.ImplPtr = info;
272 info->Node.Type = &gHID_Mouse_DevNodeType;
274 info->FileHeader = (void*)info->FileData;
275 info->Axies = (void*)(info->FileHeader + 1);
276 info->Buttons = (void*)(info->Axies + MAX_AXIES);
278 LOG("Initialised new mouse at %p", info);
280 USB_SetDeviceDataPtr(Dev, info);
284 info->CollectionDepth ++;
287 return &gHID_Mouse_ReportCBs;
290 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev)
294 info = USB_GetDeviceDataPtr(Dev);
296 Log_Error("HID", "HID is not initialised when _AddInput is called");
300 if( info->CollectionDepth == 0 )
302 // Perform final initialisation steps
303 Mutex_Acquire(&glHID_MouseListLock);
304 gpHID_LastMouse->Next = info;
305 gpHID_LastMouse = info;
306 gHID_Mouse_DevFS.RootNode.Size ++;
307 Mutex_Release(&glHID_MouseListLock);
311 info->CollectionDepth --;
315 void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, Uint32 Max)
320 info = USB_GetDeviceDataPtr(Dev);
322 Log_Error("HID", "HID is not initialised when _AddInput is called");
328 case 0x00010030: tag = 0x80; break; // Generic Desktop - X
329 case 0x00010031: tag = 0x81; break; // Generic Desktop - Y
330 case 0x00010038: tag = 0x82; break; // Generic Desktop - Wheel
331 case 0x00090001: tag = 0x00; break; // Button 1
332 case 0x00090002: tag = 0x01; break; // Button 2
333 case 0x00090003: tag = 0x02; break; // Button 3
334 case 0x00090004: tag = 0x03; break; // Button 4
335 case 0x00090005: tag = 0x04; break; // Button 5
336 default: tag = 0xFF; break;
340 info->Mappings = realloc(info->Mappings, info->nMappings * sizeof(info->Mappings[0]));
343 info->Mappings[ info->nMappings - 1].Dest = tag;
344 info->Mappings[ info->nMappings - 1].BitSize = Size;
346 if( tag != 0xFF && (tag & 0x80) )
348 info->Axies[ tag & 0x7F ].MinValue = Min;
349 info->Axies[ tag & 0x7F ].MaxValue = Max;
353 void HID_Mouse_Report_Input(
355 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
360 for( int i = 0; i < Global->ReportCount; i ++ )
362 if( i < Local->Usages.nItems )
363 usage = Local->Usages.Items[i];
364 HID_int_AddInput(Dev, usage, Global->ReportSize, Global->LogMin, Global->LogMax);