2 * Acess2 USB Stack HID Driver
3 * - By John Hodge (thePowersGang)
10 #include "hid_reports.h"
12 #include <Input/Mouse/include/mouse.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;
31 Uint8 Dest; // 0x00-0x7F = Buttons, 0x80-0xFE = Axies, 0xFF = Ignore
35 // - Initialisation only data
40 Sint32 _ReadBits(void *Data, int Offset, int Length);
41 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data);
43 tHID_ReportCallbacks *HID_Mouse_Report_Collection(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
44 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev);
45 void HID_Mouse_Report_Input(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
48 tHID_ReportCallbacks gHID_Mouse_ReportCBs = {
49 .Collection = HID_Mouse_Report_Collection,
50 .EndCollection = HID_Mouse_Report_EndCollection,
51 .Input = HID_Mouse_Report_Input,
53 tMutex glHID_MouseListLock;
54 tHID_Mouse *gpHID_FirstMouse;
55 tHID_Mouse *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse;
58 // ----------------------------------------------------------------------------
59 // Data input / Update
60 // ----------------------------------------------------------------------------
62 * \brief Read a set amounts of bits from a stream
63 * \param Data Base of data
64 * \param Offset Bit offset
65 * \param Length Number of bits to read
66 * \return Sign-extended value
68 Sint32 _ReadBits(void *Data, int Offset, int Length)
73 Uint8 *bytes = (Uint8*)Data + Offset / 8;
76 if( Length > 32 ) return 0;
81 if( Length < 8 - (Offset & 7) )
83 rv = (*bytes >> Offset) & ((1 << Length)-1);
87 rv = (*bytes >> Offset);
89 dest_ofs = Offset & 7;
90 rem = Length - (Offset & 7);
97 rv |= *bytes << dest_ofs;
105 rv |= (*bytes & ((1 << rem)-1)) << dest_ofs;
110 if( rv & (1 << (Length-1)) )
111 rv |= 0xFFFFFFFF << Length;
116 * \brief Handle an update from the device
118 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data)
122 Uint32 button_value = 0;
123 int axis_values[MAX_AXIES] = {0};
125 info = USB_GetDeviceDataPtr(Dev);
129 for( int i = 0; i < info->nMappings; i ++ )
132 Uint8 dest = info->Mappings[i].Dest;
134 if( ofs + info->Mappings[i].BitSize > Length * 8 )
137 value = _ReadBits(Data, ofs, info->Mappings[i].BitSize);
138 LOG("%i+%i: value = %i", ofs, info->Mappings[i].BitSize, value);
139 ofs += info->Mappings[i].BitSize;
141 if( dest == 0xFF ) continue ;
146 axis_values[ dest & 0x7F ] = value;
147 LOG("Axis %i = %i", dest & 0x7F, value);
155 button_value |= 1 << (dest & 0x7F);
159 Mouse_HandleEvent(info->Handle, button_value, axis_values);
162 // ----------------------------------------------------------------------------
163 // Device initialisation
164 // ----------------------------------------------------------------------------
166 * \brief Handle the opening of a collection
168 tHID_ReportCallbacks *HID_Mouse_Report_Collection(
170 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
176 info = USB_GetDeviceDataPtr(Dev);
180 info = calloc( sizeof(tHID_Mouse), 1 );
181 info->DataAvail = HID_Mouse_DataAvail;
183 info->Handle = Mouse_Register("USBMouse", MAX_BUTTONS, MAX_AXIES);
185 LOG("Initialised new mouse at %p", info);
187 USB_SetDeviceDataPtr(Dev, info);
191 info->CollectionDepth ++;
194 return &gHID_Mouse_ReportCBs;
198 * \brief Handle the end of a collection
200 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev)
204 info = USB_GetDeviceDataPtr(Dev);
206 Log_Error("HID", "HID is not initialised when _AddInput is called");
210 if( info->CollectionDepth == 0 )
212 // Perform final initialisation steps
213 Mutex_Acquire(&glHID_MouseListLock);
214 gpHID_LastMouse->Next = info;
215 gpHID_LastMouse = info;
216 Mutex_Release(&glHID_MouseListLock);
220 info->CollectionDepth --;
225 * \brief Add a new input mapping
227 void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, Uint32 Max)
232 info = USB_GetDeviceDataPtr(Dev);
234 Log_Error("HID", "HID is not initialised when _AddInput is called");
238 // --- Get the destination for the field ---
241 case 0x00010030: tag = 0x80; break; // Generic Desktop - X
242 case 0x00010031: tag = 0x81; break; // Generic Desktop - Y
243 case 0x00010038: tag = 0x82; break; // Generic Desktop - Wheel
244 case 0x00090001: tag = 0x00; break; // Button 1
245 case 0x00090002: tag = 0x01; break; // Button 2
246 case 0x00090003: tag = 0x02; break; // Button 3
247 case 0x00090004: tag = 0x03; break; // Button 4
248 case 0x00090005: tag = 0x04; break; // Button 5
249 default: tag = 0xFF; break;
252 LOG("Usage = 0x%08x, tag = 0x%2x", Usage, tag);
254 // --- Add to list of mappings ---
256 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 // --- Update Min/Max for Axies ---
263 // TODO: Pass to mouse multiplexer
264 // if( tag != 0xFF && (tag & 0x80) )
266 // info->Axies[ tag & 0x7F ].MinValue = Min;
267 // info->Axies[ tag & 0x7F ].MaxValue = Max;
272 * \brief Handle an input item in a report
274 void HID_Mouse_Report_Input(
276 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
281 LOG("Local->Usages.nItems = %i", Local->Usages.nItems);
282 for( int i = 0; i < Global->ReportCount; i ++ )
285 if( i < Local->Usages.nItems )
286 usage = Local->Usages.Items[i];
287 LOG("%i: usage = %x", i, usage);
289 HID_int_AddInput(Dev, usage, Global->ReportSize, Global->LogMin, Global->LogMax);