From 889b379627388811c630aad3214efcaee1ac9885 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 28 May 2011 21:10:31 +0800 Subject: [PATCH] Mouse driver and AxWin - Mouse driver implemented, only had very basic testing - Decided to use select() and sockets for the AxWin IPC framework > Allows the use of select() on the keyboard and mouse for input --- Kernel/include/tpl_drv_joystick.h | 45 ++++- Modules/Input/PS2KbMouse/main.c | 5 +- Modules/Input/PS2KbMouse/ps2mouse.c | 180 ++++++++++-------- Usermode/Applications/axwin2_src/WM/main.c | 24 ++- .../Applications/axwin2_src/WM/messages.c | 9 + 5 files changed, 168 insertions(+), 95 deletions(-) diff --git a/Kernel/include/tpl_drv_joystick.h b/Kernel/include/tpl_drv_joystick.h index dd220011..3ba441ac 100644 --- a/Kernel/include/tpl_drv_joystick.h +++ b/Kernel/include/tpl_drv_joystick.h @@ -28,7 +28,7 @@ */ enum eTplJoystick_IOCtl { /** - * ioctl(..., struct{int Ident;tJoystickCallback *Callback}) + * ioctl(..., tJoystickCallback *Callback) * \brief Sets the callback * \note Can be called from kernel mode only * @@ -39,33 +39,64 @@ enum eTplJoystick_IOCtl { JOY_IOCTL_SETCALLBACK = 4, /** - * ioctl(..., struct{int AxisNum;int Value}) + * ioctl(..., int *Argument) + * \brief Set the argument passed as the first parameter to the callback + * \note Kernel mode only + */ + JOY_IOCTL_SETCALLBACKARG, + + /** + * ioctl(..., tJoystickNumValue *) * \brief Set maximum value for sJoystick_Axis.CurState * \note If \a Value is equal to -1 (all bits set), the value is not changed */ JOY_IOCTL_GETSETAXISLIMIT, + + /** + * ioctl(..., tJoystickNumValue *) + * \brief Set the value of sJoystick_Axis.CurState + * \note If \a Value is equal to -1 (all bits set), the value is not changed + */ + JOY_IOCTL_GETSETAXISPOSITION, /** - * ioctl(..., struct{int AxisNum;int Value}) + * ioctl(..., tJoystickNumValue *) * \brief Set axis flags * \note If \a Value is equal to -1 (all bits set), the value is not changed */ JOY_IOCTL_GETSETAXISFLAGS, /** - * ioctl(..., struct{int ButtonNum;int Value}) + * ioctl(..., tJoystickNumValue *) * \brief Set Button Flags * \note If \a Value is equal to -1 (all bits set), the value is not changed */ JOY_IOCTL_GETSETBUTTONFLAGS, }; +#define DRV_JOY_IOCTLNAMES "set_callback", "set_callback_arg", "getset_axis_limit", "getset_axis_position", \ + "getset_axis_flags", "getset_button_flags" + +// === TYPES === +typedef struct sJoystick_NumValue tJoystick_NumValue; +typedef struct sJoystick_FileHeader tJoystick_FileHeader; +typedef struct sJoystick_Axis tJoystick_Axis; + +/** + * \brief Number/Value pair for joystick IOCtls + */ +struct sJoystick_NumValue +{ + int Num; //!< Axis/Button number + int Value; //!< Value (see IOCtl defs for meaning) +}; + /** * \brief Callback type for JOY_IOCTL_SETCALLBACK * \param Ident Ident value passed to JOY_IOCTL_SETCALLBACK * */ -typedef void (*tJoystickCallback)(int Ident, int bIsAxis, int Num, int Delta); +typedef void (*tJoystick_Callback)(int Ident, int bIsAxis, int Num, int Delta); /** * \struct sJoystick_FileHeader @@ -77,7 +108,7 @@ struct sJoystick_FileHeader }; /** - * \brief Axis Definition + * \brief Axis Definition in file data * * Describes the current state of an axis on the joystick. * \a MinValue and \a MaxValue describe the valid range for \a CurValue @@ -87,7 +118,7 @@ struct sJoystick_FileHeader struct sJoystick_Axis { Sint16 MinValue; //!< Minumum value for \a CurValue - Sint16 MaxValue; //!< Maximum value for \a MaxValue + Sint16 MaxValue; //!< Maximum value for \a CurValue Sint16 CurValue; //!< Current value (joystick position) Uint16 CurState; //!< Current state (cursor position) }; diff --git a/Modules/Input/PS2KbMouse/main.c b/Modules/Input/PS2KbMouse/main.c index 353befb5..344c59ea 100644 --- a/Modules/Input/PS2KbMouse/main.c +++ b/Modules/Input/PS2KbMouse/main.c @@ -8,14 +8,15 @@ // === IMPORTS === extern int KB_Install(char **Arguments); -extern int Mouse_Install(char **Arguments); +extern int PS2Mouse_Install(char **Arguments); // === PROTOTYPES === int PS2_Install(char **Arguments); // === GLOBALS === -MODULE_DEFINE(0, 0x0100, Input_PS2KbMouse, PS2_Install, NULL, NULL); +MODULE_DEFINE(0, 0x0100, Input_PS2KbMouse, PS2_Install, NULL, NULL); // Shuts the makefile up MODULE_DEFINE(0, 0x0100, PS2Keyboard, KB_Install, NULL, NULL); +MODULE_DEFINE(0, 0x0100, PS2Mouse, PS2Mouse_Install, NULL, NULL); // === CODE === int PS2_Install(char **Arguments) diff --git a/Modules/Input/PS2KbMouse/ps2mouse.c b/Modules/Input/PS2KbMouse/ps2mouse.c index e87292ad..7ccf461d 100644 --- a/Modules/Input/PS2KbMouse/ps2mouse.c +++ b/Modules/Input/PS2KbMouse/ps2mouse.c @@ -9,33 +9,39 @@ #include #include +static inline int MIN(int a, int b) { return (a < b) ? a : b; } +static inline int MAX(int a, int b) { return (a > b) ? a : b; } + // == CONSTANTS == +#define NUM_AXIES 2 // X+Y +#define NUM_BUTTONS 5 // Left, Right, Scroll Click, Scroll Up, Scroll Down #define PS2_IO_PORT 0x60 -#define MOUSE_BUFFER_SIZE (sizeof(t_mouse_fsdata)) -#define MOUSE_SENS_BASE 5 // == PROTOTYPES == // - Internal - int PS2Mouse_Install(char **Arguments); void PS2Mouse_IRQ(int Num); static void mouseSendCommand(Uint8 cmd); -static void enableMouse(); +void PS2Mouse_Enable(); // - Filesystem - -static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); -static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data); - -typedef struct { - int x, y, buttons, unk; -} t_mouse_fsdata; +Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data); // == GLOBALS == +// - Settings int giMouse_Sensitivity = 1; -t_mouse_fsdata gMouse_Data = {0, 0, 0, 0}; - int giMouse_MaxX = 640, giMouse_MaxY = 480; + int giMouse_MaxX = 640, giMouse_MaxY = 480; +// - File Data +Uint8 gMouse_FileData[sizeof(tJoystick_FileHeader) + NUM_AXIES*sizeof(tJoystick_Axis) + NUM_BUTTONS]; +tJoystick_FileHeader *gMouse_FileHeader = (void *)gMouse_FileData; +tJoystick_Axis *gMouse_Axies; +Uint8 *gMouse_Buttons; +// - Internal State int giMouse_Cycle = 0; // IRQ Position Uint8 gaMouse_Bytes[4] = {0,0,0,0}; +// - Driver definition tDevFS_Driver gMouse_DriverStruct = { - NULL, "ps2mouse", + NULL, "PS2Mouse", { .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX, .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl @@ -43,12 +49,16 @@ tDevFS_Driver gMouse_DriverStruct = { }; // == CODE == -int Mouse_Install(char **Arguments) +int PS2Mouse_Install(char **Arguments) { + // Set up variables + gMouse_Axies = (void*)&gMouse_FileData[1]; + gMouse_Buttons = (void*)&gMouse_Axies[NUM_AXIES]; + // Initialise Mouse Controller IRQ_AddHandler(12, PS2Mouse_IRQ); // Set IRQ giMouse_Cycle = 0; // Set Current Cycle position - enableMouse(); // Enable the mouse + PS2Mouse_Enable(); // Enable the mouse DevFS_AddDevice(&gMouse_DriverStruct); @@ -60,99 +70,102 @@ int Mouse_Install(char **Arguments) void PS2Mouse_IRQ(int Num) { Uint8 flags; - int dx, dy; - //int log2x, log2y; + int dx, dy; + int dx_accel, dy_accel; + + // Gather mouse data gaMouse_Bytes[giMouse_Cycle] = inb(0x60); - if(giMouse_Cycle == 0 && !(gaMouse_Bytes[giMouse_Cycle] & 0x8)) - return; + LOG("gaMouse_Bytes[%i] = 0x%02x", gMouse_Axies[0].MaxValue); + // - If bit 3 of the first byte is not set, it's not a valid packet? + if(giMouse_Cycle == 0 && !(gaMouse_Bytes[0] & 0x08) ) + return ; giMouse_Cycle++; - if(giMouse_Cycle == 3) - giMouse_Cycle = 0; - else - return; - - if(giMouse_Cycle > 0) - return; - - // Read Flags + if(giMouse_Cycle < 3) + return ; + + giMouse_Cycle = 0; + + // Actual Processing (once we have all bytes) flags = gaMouse_Bytes[0]; - if(flags & 0xC0) // X/Y Overflow - return; - - #if DEBUG - //LogF(" PS2Mouse_Irq: flags = 0x%x\n", flags); - #endif + + LOG("flags = 0x%x", flags); + // Check for X/Y Overflow + if(flags & 0xC0) return; + // Calculate dX and dY - dx = (int) ( gaMouse_Bytes[1] | (flags & 0x10 ? ~0x00FF : 0) ); - dy = (int) ( gaMouse_Bytes[2] | (flags & 0x20 ? ~0x00FF : 0) ); + dx = gaMouse_Bytes[1]; if(flags & 0x10) dx = -(256-dx); + dy = gaMouse_Bytes[2]; if(flags & 0x20) dy = -(256-dy); dy = -dy; // Y is negated LOG("RAW dx=%i, dy=%i\n", dx, dy); - dx = dx*MOUSE_SENS_BASE/giMouse_Sensitivity; - dy = dy*MOUSE_SENS_BASE/giMouse_Sensitivity; + // Apply scaling + // TODO: Apply a form of curve to the mouse movement (dx*log(dx), dx^k?) + // TODO: Independent sensitivities? + // TODO: Disable acceleration via a flag? + dx_accel = dx*giMouse_Sensitivity; + dy_accel = dy*giMouse_Sensitivity; - //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2x) : "a" ((Uint)gaMouse_Bytes[1])); - //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2y) : "a" ((Uint)gaMouse_Bytes[2])); - //LogF(" PS2Mouse_Irq: dx=%i, log2x = %i\n", dx, log2x); - //LogF(" PS2Mouse_Irq: dy=%i, log2y = %i\n", dy, log2y); - //dx *= log2x; - //dy *= log2y; - - // Set Buttons - gMouse_Data.buttons = flags & 0x7; //Buttons (3 only) + // Set Buttons (Primary) + gMouse_Buttons[0] = (flags & 1) ? 0xFF : 0; + gMouse_Buttons[1] = (flags & 2) ? 0xFF : 0; + gMouse_Buttons[2] = (flags & 4) ? 0xFF : 0; // Update X and Y Positions - gMouse_Data.x += (int)dx; - gMouse_Data.y += (int)dy; - - // Constrain Positions - if(gMouse_Data.x < 0) gMouse_Data.x = 0; - if(gMouse_Data.y < 0) gMouse_Data.y = 0; - if(gMouse_Data.x >= giMouse_MaxX) gMouse_Data.x = giMouse_MaxX-1; - if(gMouse_Data.y >= giMouse_MaxY) gMouse_Data.y = giMouse_MaxY-1; + gMouse_Axies[0].CurValue = MIN( MAX(gMouse_Axies[0].MinValue, gMouse_Axies[0].CurValue + dx_accel), gMouse_Axies[0].MaxValue ); + gMouse_Axies[1].CurValue = MIN( MAX(gMouse_Axies[1].MinValue, gMouse_Axies[1].CurValue + dy_accel), gMouse_Axies[1].MaxValue ); } /* Read mouse state (coordinates) */ -static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) { - if(Length < MOUSE_BUFFER_SIZE) - return -1; + if(Offset > sizeof(gMouse_FileData)) return 0; + if(Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData); + if(Offset + Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData) - Offset; - memcpy(Buffer, &gMouse_Data, MOUSE_BUFFER_SIZE); + memcpy(Buffer, &gMouse_FileData[Offset], Length); - return MOUSE_BUFFER_SIZE; + return Length; } -static const char *csaIOCtls[] = {DRV_IOCTLNAMES, NULL}; +static const char *csaIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL}; /* Handle messages to the device */ -static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data) +int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data) { - struct { - int Num; - int Value; - } *info = Data; + tJoystick_NumValue *info = Data; + switch(ID) { BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls); + + case JOY_IOCTL_SETCALLBACK: // TODO: Implement + return -1; + + case JOY_IOCTL_SETCALLBACKARG: // TODO: Implement + return -1; case JOY_IOCTL_GETSETAXISLIMIT: if(!info) return 0; - switch(info->Num) - { - case 0: // X - if(info->Value != -1) - giMouse_MaxX = info->Value; - return giMouse_MaxX; - case 1: // Y - if(info->Value != -1) - giMouse_MaxY = info->Value; - return giMouse_MaxY; - } - return 0; - + if(info->Num < 0 || info->Num >= 2) return 0; + if(info->Value != -1) + gMouse_Axies[info->Num].MaxValue = info->Value; + return gMouse_Axies[info->Num].MaxValue; + + case JOY_IOCTL_GETSETAXISPOSITION: + if(!info) return 0; + if(info->Num < 0 || info->Num >= 2) return 0; + if(info->Value != -1) + gMouse_Axies[info->Num].CurValue = info->Value; + return gMouse_Axies[info->Num].CurValue; + + case JOY_IOCTL_GETSETAXISFLAGS: + return -1; + + case JOY_IOCTL_GETSETBUTTONFLAGS: + return -1; + default: return 0; } @@ -171,22 +184,22 @@ static inline void mouseOut60(Uint8 data) while( timeout-- && inb(0x64) & 2 ); // Wait for Flag to clear outb(0x60, data); // Send Command } -static inline Uint8 mouseIn60() +static inline Uint8 mouseIn60(void) { int timeout=100000; while( timeout-- && (inb(0x64) & 1) == 0); // Wait for Flag to set return inb(0x60); } -static void mouseSendCommand(Uint8 cmd) +static inline void mouseSendCommand(Uint8 cmd) { mouseOut64(0xD4); mouseOut60(cmd); } -static void enableMouse() +void PS2Mouse_Enable(void) { Uint8 status; - Log_Log("PS2 Mouse", "Enabling Mouse..."); + Log_Log("PS2Mouse", "Enabling Mouse..."); // Enable AUX PS/2 mouseOut64(0xA8); @@ -194,7 +207,8 @@ static void enableMouse() // Enable AUX PS/2 (Compaq Status Byte) mouseOut64(0x20); // Send Command status = mouseIn60(); // Get Status - status &= 0xDF; status |= 0x02; // Alter Flags (Set IRQ12 (2) and Clear Disable Mouse Clock (20)) + status &= ~0x20; // Clear "Disable Mouse Clock" + status |= 0x02; // Set IRQ12 Enable mouseOut64(0x60); // Send Command mouseOut60(status); // Set Status diff --git a/Usermode/Applications/axwin2_src/WM/main.c b/Usermode/Applications/axwin2_src/WM/main.c index 7b42562d..67ceb637 100644 --- a/Usermode/Applications/axwin2_src/WM/main.c +++ b/Usermode/Applications/axwin2_src/WM/main.c @@ -9,8 +9,12 @@ extern void ParseCommandline(int argc, char *argv[]); extern void Video_Setup(void); extern void WM_Update(void); -extern void Messages_PollIPC(void); extern void Interface_Init(void); +extern void IPC_Init(void); +extern void IPC_FillSelect(int *nfds, fd_set *set); +extern void IPC_HandleSelect(fd_set *set); +extern void Input_FillSelect(int *nfds, fd_set *set); +extern void Input_HandleSelect(fd_set *set); // === GLOBALS === char *gsTerminalDevice = NULL; @@ -35,17 +39,31 @@ int main(int argc, char *argv[]) if( gsTerminalDevice == NULL ) { gsTerminalDevice = "/Devices/VTerm/6"; } + if( gsMouseDevice == NULL ) { + gsMouseDevice = "/Devices/PS2Mouse"; + } Video_Setup(); Interface_Init(); + IPC_Init(); WM_Update(); // Main Loop for(;;) { - Messages_PollIPC(); - //yield(); + fd_set fds; + int nfds = 0; + FD_ZERO(&fds); + + Input_FillSelect(&nfds, &fds); + IPC_FillSelect(&nfds, &fds); + + select(nfds, &fds, NULL, NULL, NULL); + + Input_HandleSelect(&fds); + IPC_HandleSelect(&fds); } return 0; } + diff --git a/Usermode/Applications/axwin2_src/WM/messages.c b/Usermode/Applications/axwin2_src/WM/messages.c index 92137f07..c4bed7ad 100644 --- a/Usermode/Applications/axwin2_src/WM/messages.c +++ b/Usermode/Applications/axwin2_src/WM/messages.c @@ -4,6 +4,7 @@ */ #include "common.h" #include +#include #include #define STATICBUF_SIZE 64 @@ -17,8 +18,16 @@ void Messages_RespondIPC(int ID, size_t Length, void *Data); void Messages_Handle(tAxWin_Message *Msg, tMessages_Handle_Callback *Respond, int ID); // === GLOBALS === + int giIPCFileHandle; // === CODE === +void IPC_Init(void) +{ + // TODO: Check this + giIPCFileHandle = open("/Devices/ip/loop/udpc", OPENFLAG_READ|OPENFLAG_EXEC); +// ioctl(giIPCFileHandle, ); +} + void Messages_PollIPC() { int len; -- 2.20.1