2 * Acess2 USB Stack HID Driver
3 * - By John Hodge (thePowersGang)
10 #include "hid_reports.h"
11 #include <Input/Mouse/include/mouse.h>
14 #define MAX_AXIES 3 // X, Y, Scroll
15 #define MAX_BUTTONS 5 // Left, Right, Middle, ...
18 typedef struct sHID_Mouse tHID_Mouse;
23 tUSB_DataCallback DataAvail;
30 Uint8 Dest; // 0x00-0x7F = Buttons, 0x80-0xFE = Axies, 0xFF = Ignore
34 // - Initialisation only data
39 Sint32 _ReadBits(void *Data, int Offset, int Length);
40 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data);
42 tHID_ReportCallbacks *HID_Mouse_Report_Collection(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
43 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev);
44 void HID_Mouse_Report_Input(tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, Uint32 Value);
47 tHID_ReportCallbacks gHID_Mouse_ReportCBs = {
48 .Collection = HID_Mouse_Report_Collection,
49 .EndCollection = HID_Mouse_Report_EndCollection,
50 .Input = HID_Mouse_Report_Input,
52 tMutex glHID_MouseListLock;
53 tHID_Mouse *gpHID_FirstMouse;
54 tHID_Mouse *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse;
57 // ----------------------------------------------------------------------------
58 // Data input / Update
59 // ----------------------------------------------------------------------------
61 * \brief Read a set amounts of bits from a stream
62 * \param Data Base of data
63 * \param Offset Bit offset
64 * \param Length Number of bits to read
65 * \return Sign-extended value
67 Sint32 _ReadBits(void *Data, int Offset, int Length)
72 Uint8 *bytes = (Uint8*)Data + Offset / 8;
75 if( Length > 32 ) return 0;
80 if( Length < 8 - (Offset & 7) )
82 rv = (*bytes >> Offset) & ((1 << Length)-1);
86 rv = (*bytes >> Offset);
88 dest_ofs = Offset & 7;
89 rem = Length - (Offset & 7);
96 rv |= *bytes << dest_ofs;
104 rv |= (*bytes & ((1 << rem)-1)) << dest_ofs;
109 if( rv & (1 << (Length-1)) )
110 rv |= 0xFFFFFFFF << Length;
115 * \brief Handle an update from the device
117 void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data)
121 Uint32 button_value = 0;
122 int axis_values[MAX_AXIES] = {0};
124 info = USB_GetDeviceDataPtr(Dev);
128 for( int i = 0; i < info->nMappings; i ++ )
131 Uint8 dest = info->Mappings[i].Dest;
133 if( ofs + info->Mappings[i].BitSize > Length * 8 )
136 value = _ReadBits(Data, ofs, info->Mappings[i].BitSize);
137 LOG("%i+%i: value = %i", ofs, info->Mappings[i].BitSize, value);
138 ofs += info->Mappings[i].BitSize;
140 if( dest == 0xFF ) continue ;
145 axis_values[ dest & 0x7F ] = value;
146 LOG("Axis %i = %i", dest & 0x7F, value);
154 button_value |= 1 << (dest & 0x7F);
158 Mouse_HandleEvent(info->Handle, button_value, axis_values);
161 // ----------------------------------------------------------------------------
162 // Device initialisation
163 // ----------------------------------------------------------------------------
165 * \brief Handle the opening of a collection
167 tHID_ReportCallbacks *HID_Mouse_Report_Collection(
169 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
175 info = USB_GetDeviceDataPtr(Dev);
179 info = calloc( sizeof(tHID_Mouse), 1 );
180 info->DataAvail = HID_Mouse_DataAvail;
182 info->Handle = Mouse_Register("USBMouse", MAX_BUTTONS, MAX_AXIES);
184 LOG("Initialised new mouse at %p", info);
186 USB_SetDeviceDataPtr(Dev, info);
190 info->CollectionDepth ++;
193 return &gHID_Mouse_ReportCBs;
197 * \brief Handle the end of a collection
199 void HID_Mouse_Report_EndCollection(tUSBInterface *Dev)
203 info = USB_GetDeviceDataPtr(Dev);
205 Log_Error("HID", "HID is not initialised when _AddInput is called");
209 if( info->CollectionDepth == 0 )
211 // Perform final initialisation steps
212 Mutex_Acquire(&glHID_MouseListLock);
213 gpHID_LastMouse->Next = info;
214 gpHID_LastMouse = info;
215 Mutex_Release(&glHID_MouseListLock);
219 info->CollectionDepth --;
224 * \brief Add a new input mapping
226 void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, Uint32 Max)
231 info = USB_GetDeviceDataPtr(Dev);
233 Log_Error("HID", "HID is not initialised when _AddInput is called");
237 // --- Get the destination for the field ---
240 case 0x00010030: tag = 0x80; break; // Generic Desktop - X
241 case 0x00010031: tag = 0x81; break; // Generic Desktop - Y
242 case 0x00010038: tag = 0x82; break; // Generic Desktop - Wheel
243 case 0x00090001: tag = 0x00; break; // Button 1
244 case 0x00090002: tag = 0x01; break; // Button 2
245 case 0x00090003: tag = 0x02; break; // Button 3
246 case 0x00090004: tag = 0x03; break; // Button 4
247 case 0x00090005: tag = 0x04; break; // Button 5
248 default: tag = 0xFF; break;
251 LOG("Usage = 0x%08x, tag = 0x%2x", Usage, tag);
253 // --- Add to list of mappings ---
255 info->Mappings = realloc(info->Mappings, info->nMappings * sizeof(info->Mappings[0]));
257 info->Mappings[ info->nMappings - 1].Dest = tag;
258 info->Mappings[ info->nMappings - 1].BitSize = Size;
260 // --- Update Min/Max for Axies ---
262 // TODO: Pass to mouse multiplexer
263 // if( tag != 0xFF && (tag & 0x80) )
265 // info->Axies[ tag & 0x7F ].MinValue = Min;
266 // info->Axies[ tag & 0x7F ].MaxValue = Max;
271 * \brief Handle an input item in a report
273 void HID_Mouse_Report_Input(
275 tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local,
280 LOG("Local->Usages.nItems = %i", Local->Usages.nItems);
281 for( int i = 0; i < Global->ReportCount; i ++ )
284 if( i < Local->Usages.nItems )
285 usage = Local->Usages.Items[i];
286 LOG("%i: usage = %x", i, usage);
288 HID_int_AddInput(Dev, usage, Global->ReportSize, Global->LogMin, Global->LogMax);