2 * Acess2 Mouse Driver
\r
8 #include <fs_devfs.h>
\r
9 #include <api_drv_common.h>
\r
10 #include <api_drv_joystick.h>
\r
13 static inline int MIN(int a, int b) { return (a < b) ? a : b; }
\r
14 static inline int MAX(int a, int b) { return (a > b) ? a : b; }
\r
17 #define NUM_AXIES 2 // X+Y
\r
18 #define NUM_BUTTONS 5 // Left, Right, Scroll Click, Scroll Up, Scroll Down
\r
22 int PS2Mouse_Install(char **Arguments);
\r
23 void PS2Mouse_HandleInterrupt(Uint8 InputByte);
\r
25 Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
\r
26 int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data);
\r
29 void (*gpMouse_EnableFcn)(void);
\r
31 int giMouse_Sensitivity = 1;
\r
32 int giMouse_MaxX = 640, giMouse_MaxY = 480;
\r
34 Uint8 gMouse_FileData[sizeof(tJoystick_FileHeader) + NUM_AXIES*sizeof(tJoystick_Axis) + NUM_BUTTONS];
\r
35 tJoystick_FileHeader *gMouse_FileHeader = (void *)gMouse_FileData;
\r
36 tJoystick_Axis *gMouse_Axies;
\r
37 Uint8 *gMouse_Buttons;
\r
38 tJoystick_Callback gMouse_Callback;
\r
39 int gMouse_CallbackArg;
\r
40 int giMouse_AxisLimits[2];
\r
42 int giMouse_Cycle = 0; // IRQ Position
\r
43 Uint8 gaMouse_Bytes[4] = {0,0,0,0};
\r
44 // - Driver definition
\r
45 tDevFS_Driver gMouse_DriverStruct = {
\r
48 .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,
\r
49 .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl
\r
54 int PS2Mouse_Install(char **Arguments)
\r
59 gMouse_Axies = (void*)&gMouse_FileData[4];
\r
60 gMouse_Buttons = (void*)&gMouse_Axies[NUM_AXIES];
\r
62 gMouse_FileHeader->NAxies = 2; gMouse_FileHeader->NButtons = 3;
\r
63 gMouse_Axies[0].MinValue = -10; gMouse_Axies[0].MaxValue = 10;
\r
64 gMouse_Axies[1].MinValue = -10; gMouse_Axies[1].MaxValue = 10;
\r
66 // Initialise Mouse Controller
\r
67 giMouse_Cycle = 0; // Set Current Cycle position
\r
68 gpMouse_EnableFcn();
\r
70 DevFS_AddDevice(&gMouse_DriverStruct);
\r
72 return MODULE_ERR_OK;
\r
75 /* Handle Mouse Interrupt
\r
77 void PS2Mouse_HandleInterrupt(Uint8 InputByte)
\r
80 int d[2], d_accel[2];
\r
83 // Gather mouse data
\r
84 gaMouse_Bytes[giMouse_Cycle] = InputByte;
\r
85 LOG("gaMouse_Bytes[%i] = 0x%02x", gMouse_Axies[0].MaxValue);
\r
86 // - If bit 3 of the first byte is not set, it's not a valid packet?
\r
87 if(giMouse_Cycle == 0 && !(gaMouse_Bytes[0] & 0x08) )
\r
90 if(giMouse_Cycle < 3)
\r
95 // Actual Processing (once we have all bytes)
\r
96 flags = gaMouse_Bytes[0];
\r
98 LOG("flags = 0x%x", flags);
\r
100 // Check for X/Y Overflow
\r
101 if(flags & 0xC0) return;
\r
103 // Calculate dX and dY
\r
104 d[0] = gaMouse_Bytes[1]; if(flags & 0x10) d[0] = -(256-d[0]); // x
\r
105 d[1] = gaMouse_Bytes[2]; if(flags & 0x20) d[1] = -(256-d[1]); // y
\r
106 d[1] = -d[1]; // Y is negated
\r
107 LOG("RAW dx=%i, dy=%i\n", d[0], d[1]);
\r
109 // TODO: Apply a form of curve to the mouse movement (dx*log(dx), dx^k?)
\r
110 // TODO: Independent sensitivities?
\r
111 // TODO: Disable acceleration via a flag?
\r
112 d_accel[0] = d[0]*giMouse_Sensitivity;
\r
113 d_accel[1] = d[1]*giMouse_Sensitivity;
\r
115 // Set Buttons (Primary)
\r
116 for( i = 0; i < 3; i ++ )
\r
118 Uint8 newVal = (flags & (1 << i)) ? 0xFF : 0;
\r
119 if(newVal != gMouse_Buttons[i]) {
\r
120 if( gMouse_Callback )
\r
121 gMouse_Callback(gMouse_CallbackArg, 0, i, newVal - gMouse_Buttons[i]);
\r
122 gMouse_Buttons[i] = newVal;
\r
126 // Update X and Y Positions
\r
127 for( i = 0; i < 2; i ++ )
\r
129 Sint16 newCursor = 0;
\r
130 if( giMouse_AxisLimits[i] )
\r
131 newCursor = MIN( MAX(0, gMouse_Axies[i].CursorPos + d_accel[i]), giMouse_AxisLimits[i] );;
\r
133 if( gMouse_Callback )
\r
135 if(giMouse_AxisLimits[i] && gMouse_Axies[i].CursorPos != newCursor)
\r
136 gMouse_Callback(gMouse_CallbackArg, 1, i, newCursor - gMouse_Axies[i].CursorPos);
\r
137 if(!giMouse_AxisLimits[i] && gMouse_Axies[i].CurValue != d_accel[i])
\r
138 gMouse_Callback(gMouse_CallbackArg, 1, i, d_accel[i] - gMouse_Axies[i].CurValue);
\r
141 gMouse_Axies[i].CurValue = d_accel[i];
\r
142 gMouse_Axies[i].CursorPos = newCursor;
\r
145 // Log("Mouse at %ix%i", gMouse_Axies[0].CursorPos, gMouse_Axies[1].CursorPos);
\r
147 VFS_MarkAvaliable(&gMouse_DriverStruct.RootNode, 1);
\r
150 /* Read mouse state (coordinates)
\r
152 Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
\r
154 if(Offset > sizeof(gMouse_FileData)) return 0;
\r
155 if(Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData);
\r
156 if(Offset + Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData) - Offset;
\r
158 memcpy(Buffer, &gMouse_FileData[Offset], Length);
\r
160 VFS_MarkAvaliable(Node, 0);
\r
164 static const char *csaIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
\r
165 /* Handle messages to the device
\r
167 int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)
\r
169 tJoystick_NumValue *info = Data;
\r
173 BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);
\r
175 case JOY_IOCTL_SETCALLBACK: // TODO: Implement
\r
178 case JOY_IOCTL_SETCALLBACKARG: // TODO: Implement
\r
181 case JOY_IOCTL_GETSETAXISLIMIT:
\r
182 if(!info) return 0;
\r
183 if(info->Num < 0 || info->Num >= 2) return 0;
\r
184 if(info->Value != -1)
\r
185 giMouse_AxisLimits[info->Num] = info->Value;
\r
186 return giMouse_AxisLimits[info->Num];
\r
188 case JOY_IOCTL_GETSETAXISPOSITION:
\r
189 if(!info) return 0;
\r
190 if(info->Num < 0 || info->Num >= 2) return 0;
\r
191 if(info->Value != -1)
\r
192 gMouse_Axies[info->Num].CursorPos = info->Value;
\r
193 return gMouse_Axies[info->Num].CursorPos;
\r
195 case JOY_IOCTL_GETSETAXISFLAGS:
\r
198 case JOY_IOCTL_GETSETBUTTONFLAGS:
\r