X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FUSB%2FHID%2Fmouse.c;h=6ca88a5dff7e41843633f3ef3729a19d15573e53;hb=b21ce7f2b5fda2b8eb6156b3073753296ee7296c;hp=be015adda3991b65cae870b9694597f5927ad7c5;hpb=4eca73b17dde3a39b8b918d92ebe45261929615e;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/USB/HID/mouse.c b/KernelLand/Modules/USB/HID/mouse.c index be015add..6ca88a5d 100644 --- a/KernelLand/Modules/USB/HID/mouse.c +++ b/KernelLand/Modules/USB/HID/mouse.c @@ -14,6 +14,7 @@ // === CONSTANTS === #define MAX_AXIES 3 // X, Y, Scroll #define MAX_BUTTONS 5 // Left, Right, Middle, ... +#define FILE_SIZE (sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS) // === TYPES === typedef struct sHID_Mouse tHID_Mouse; @@ -23,45 +24,69 @@ struct sHID_Mouse tHID_Mouse *Next; tUSB_DataCallback DataAvail; + // VFS Node tVFS_Node Node; - int CollectionDepth; - - Uint8 FileData[ sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS ]; + + // Joystick Spec data + Uint8 FileData[ FILE_SIZE ]; tJoystick_FileHeader *FileHeader; tJoystick_Axis *Axies; Uint8 *Buttons; + // Limits for axis positions Uint16 AxisLimits[MAX_AXIES]; + // - Report parsing int nMappings; struct { Uint8 Dest; // 0x00-0x7F = Buttons, 0x80-0xFE = Axies, 0xFF = Ignore Uint8 BitSize; } *Mappings; + + // - Initialisation only data + int CollectionDepth; }; // === PROTOTYES === +char *HID_Mouse_Root_ReadDir(tVFS_Node *Node, int Pos); +tVFS_Node *HID_Mouse_Root_FindDir(tVFS_Node *Node, const char *Name); +size_t HID_Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer); + int HID_Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data); +void HID_Mouse_Dev_Reference(tVFS_Node *Node); +void HID_Mouse_Dev_Close(tVFS_Node *Node); + 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); // === GLOBALS === tVFS_NodeType gHID_Mouse_RootNodeType = { - .TypeName = "HID Mouse Root" + .TypeName = "HID Mouse Root", + .ReadDir = HID_Mouse_Root_ReadDir, + .FindDir = HID_Mouse_Root_FindDir }; tVFS_NodeType gHID_Mouse_DevNodeType = { - .TypeName = "HID Mouse Dev" + .TypeName = "HID Mouse Dev", + .Read = HID_Mouse_Dev_Read, + .IOCtl = HID_Mouse_Dev_IOCtl, + .Reference = HID_Mouse_Dev_Reference, + .Close = HID_Mouse_Dev_Close, }; tDevFS_Driver gHID_Mouse_DevFS = { .Name = "USBMouse", - .RootNode = {.Type = &gHID_Mouse_RootNodeType} + .RootNode = { + .Type = &gHID_Mouse_RootNodeType, + .Flags = VFS_FFLAG_DIRECTORY + } }; tHID_ReportCallbacks gHID_Mouse_ReportCBs = { .Collection = HID_Mouse_Report_Collection, .EndCollection = HID_Mouse_Report_EndCollection, .Input = HID_Mouse_Report_Input, }; +tMutex glHID_MouseListLock; tHID_Mouse *gpHID_FirstMouse; tHID_Mouse *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse; @@ -69,16 +94,115 @@ tHID_Mouse *gpHID_LastMouse = (tHID_Mouse*)&gpHID_FirstMouse; // ---------------------------------------------------------------------------- // VFS Interface // ---------------------------------------------------------------------------- +char *HID_Mouse_Root_ReadDir(tVFS_Node *Node, int Pos) +{ + char data[3]; + if(Pos < 0 || Pos >= Node->Size) return NULL; + + snprintf(data, 3, "%i", Pos); + return strdup(data); +} + +tVFS_Node *HID_Mouse_Root_FindDir(tVFS_Node *Node, const char *Name) +{ + int ID; + int ofs; + tHID_Mouse *mouse; + + if( Name[0] == '\0' ) + return NULL; + + ofs = ParseInt(Name, &ID); + if( ofs == 0 || Name[ofs] != '\0' ) + return NULL; + + // Scan list, locate item + Mutex_Acquire(&glHID_MouseListLock); + for( mouse = gpHID_FirstMouse; mouse && ID --; mouse = mouse->Next ) ; + if( mouse ) + mouse->Node.ReferenceCount ++; + Mutex_Release(&glHID_MouseListLock); + + if( mouse ) + return &mouse->Node; + else + return NULL; +} + +size_t HID_Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer) +{ + tHID_Mouse *info = Node->ImplPtr; + + if( Offset > FILE_SIZE ) return 0; + + if( Length > FILE_SIZE ) Length = FILE_SIZE; + if( Offset + Length > FILE_SIZE ) Length = FILE_SIZE - Offset; + + memcpy( Buffer, info->FileData + Offset, Length ); + + VFS_MarkAvaliable( &info->Node, 0 ); + + return Length; +} + +static const char *csaDevIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL}; +int HID_Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data) +{ + tJoystick_NumValue *numval = Data; + tHID_Mouse *info = Node->ImplPtr; + switch(ID) + { + BASE_IOCTLS(DRV_TYPE_JOYSTICK, "USBMouse", 0x050, csaDevIOCtls); + + case JOY_IOCTL_GETSETAXISLIMIT: + if( !numval || !CheckMem(numval, sizeof(*numval)) ) + return -1; + if(numval->Num < 0 || numval->Num >= MAX_AXIES) + return 0; + if(numval->Value != -1) + info->AxisLimits[numval->Num] = numval->Value; + return info->AxisLimits[numval->Num]; + + case JOY_IOCTL_GETSETAXISPOSITION: + if( !numval || !CheckMem(numval, sizeof(*numval)) ) + return -1; + if(numval->Num < 0 || numval->Num >= MAX_AXIES) + return 0; + if(numval->Value != -1) + info->Axies[numval->Num].CursorPos = numval->Value; + return info->Axies[numval->Num].CursorPos; + } + return -1; +} +void HID_Mouse_Dev_Reference(tVFS_Node *Node) +{ + Node->ReferenceCount ++; +} +void HID_Mouse_Dev_Close(tVFS_Node *Node) +{ + Node->ReferenceCount --; +} // ---------------------------------------------------------------------------- // 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 ) { @@ -91,23 +215,22 @@ Sint32 _ReadBits(void *Data, int Offset, int Length) rv = (*bytes >> Offset); dest_ofs = Offset & 7; - Length -= Offset & 7; + rem = Length - (Offset & 7); bytes ++; } // Body bytes - while( Length >= 8 ) + while( rem >= 8 ) { rv |= *bytes << dest_ofs; dest_ofs += 8; - Length -= 8; + rem -= 8; bytes ++; } - if( Length ) + if( rem ) { - rv |= (*bytes & ((1 << Length)-1)) << dest_ofs; - + rv |= (*bytes & ((1 << rem)-1)) << dest_ofs; } // Do sign extension @@ -117,6 +240,9 @@ _ext: return rv; } +/** + * \brief Handle an update from the device + */ void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data) { tHID_Mouse *info; @@ -124,8 +250,7 @@ void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data) info = USB_GetDeviceDataPtr(Dev); if( !info ) return ; - - + ofs = 0; for( int i = 0; i < info->nMappings; i ++ ) { @@ -136,6 +261,7 @@ void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data) 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 ; @@ -144,11 +270,13 @@ void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data) { // Axis info->Axies[ dest & 0x7F ].CurValue = value; + LOG("Axis %i = %i", dest & 0x7F, info->Axies[dest & 0x7F].CurValue); } else { // Button info->Buttons[ dest & 0x7F ] = (value == 0) ? 0 : 0xFF; + LOG("Button %i = %x", dest & 0x7F, info->Buttons[dest & 0x7F]); } } @@ -165,15 +293,17 @@ void HID_Mouse_DataAvail(tUSBInterface *Dev, int EndPt, int Length, void *Data) info->Axies[i].CursorPos = newpos; } - Log_Debug("USBMouse", "New Pos (%i,%i,%i)", - info->Axies[0].CursorPos, info->Axies[1].CursorPos, info->Axies[2].CursorPos - ); +// Log_Debug("USBMouse", "New Pos (%i,%i,%i)", +// info->Axies[0].CursorPos, info->Axies[1].CursorPos, info->Axies[2].CursorPos +// ); + VFS_MarkAvaliable( &info->Node, 1 ); } // ---------------------------------------------------------------------------- // Device initialisation // ---------------------------------------------------------------------------- /** + * \brief Handle the opening of a collection */ tHID_ReportCallbacks *HID_Mouse_Report_Collection( tUSBInterface *Dev, @@ -189,11 +319,22 @@ tHID_ReportCallbacks *HID_Mouse_Report_Collection( // New device! info = calloc( sizeof(tHID_Mouse), 1 ); info->DataAvail = HID_Mouse_DataAvail; + info->Node.ImplPtr = info; info->Node.Type = &gHID_Mouse_DevNodeType; info->FileHeader = (void*)info->FileData; info->Axies = (void*)(info->FileHeader + 1); info->Buttons = (void*)(info->Axies + MAX_AXIES); + info->FileHeader->NAxies = MAX_AXIES; + info->FileHeader->NButtons = MAX_BUTTONS; + + for( int i = 0; i < MAX_AXIES; i ++ ) { + info->Axies[i].MinValue = -10; + info->Axies[i].MaxValue = 10; + } + + + LOG("Initialised new mouse at %p", info); USB_SetDeviceDataPtr(Dev, info); } @@ -205,6 +346,9 @@ tHID_ReportCallbacks *HID_Mouse_Report_Collection( return &gHID_Mouse_ReportCBs; } +/** + * \brief Handle the end of a collection + */ void HID_Mouse_Report_EndCollection(tUSBInterface *Dev) { tHID_Mouse *info; @@ -217,9 +361,12 @@ void HID_Mouse_Report_EndCollection(tUSBInterface *Dev) if( info->CollectionDepth == 0 ) { - // TODO: Do final cleanup on device + // Perform final initialisation steps + Mutex_Acquire(&glHID_MouseListLock); gpHID_LastMouse->Next = info; gpHID_LastMouse = info; + gHID_Mouse_DevFS.RootNode.Size ++; + Mutex_Release(&glHID_MouseListLock); } else { @@ -227,6 +374,9 @@ void HID_Mouse_Report_EndCollection(tUSBInterface *Dev) } } +/** + * \brief Add a new input mapping + */ void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, Uint32 Max) { Uint8 tag; @@ -238,6 +388,7 @@ void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, return ; } + // --- Get the destination for the field --- switch(Usage) { case 0x00010030: tag = 0x80; break; // Generic Desktop - X @@ -251,13 +402,17 @@ void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, 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 if( tag != 0xFF && (tag & 0x80) ) { info->Axies[ tag & 0x7F ].MinValue = Min; @@ -265,6 +420,9 @@ void HID_int_AddInput(tUSBInterface *Dev, Uint32 Usage, Uint8 Size, Uint32 Min, } } +/** + * \brief Handle an input item in a report + */ void HID_Mouse_Report_Input( tUSBInterface *Dev, tHID_ReportGlobalState *Global, tHID_ReportLocalState *Local, @@ -272,10 +430,14 @@ void HID_Mouse_Report_Input( ) { 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); } }