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
30 int giMouse_Sensitivity = 1;
\r
31 int giMouse_MaxX = 640, giMouse_MaxY = 480;
\r
33 Uint8 gMouse_FileData[sizeof(tJoystick_FileHeader) + NUM_AXIES*sizeof(tJoystick_Axis) + NUM_BUTTONS];
\r
34 tJoystick_FileHeader *gMouse_FileHeader = (void *)gMouse_FileData;
\r
35 tJoystick_Axis *gMouse_Axies;
\r
36 Uint8 *gMouse_Buttons;
\r
37 tJoystick_Callback gMouse_Callback;
\r
38 int gMouse_CallbackArg;
\r
39 int giMouse_AxisLimits[2];
\r
41 int giMouse_Cycle = 0; // IRQ Position
\r
42 Uint8 gaMouse_Bytes[4] = {0,0,0,0};
\r
43 // - Driver definition
\r
44 tDevFS_Driver gMouse_DriverStruct = {
\r
47 .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,
\r
48 .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl
\r
53 int PS2Mouse_Install(char **Arguments)
\r
56 gMouse_Axies = (void*)&gMouse_FileData[1];
\r
57 gMouse_Buttons = (void*)&gMouse_Axies[NUM_AXIES];
\r
59 // Initialise Mouse Controller
\r
60 giMouse_Cycle = 0; // Set Current Cycle position
\r
61 KBC8042_EnableMouse();
\r
63 DevFS_AddDevice(&gMouse_DriverStruct);
\r
65 return MODULE_ERR_OK;
\r
68 /* Handle Mouse Interrupt
\r
70 void PS2Mouse_HandleInterrupt(Uint8 InputByte)
\r
73 int d[2], d_accel[2];
\r
76 // Gather mouse data
\r
77 gaMouse_Bytes[giMouse_Cycle] = InputByte;
\r
78 LOG("gaMouse_Bytes[%i] = 0x%02x", gMouse_Axies[0].MaxValue);
\r
79 // - If bit 3 of the first byte is not set, it's not a valid packet?
\r
80 if(giMouse_Cycle == 0 && !(gaMouse_Bytes[0] & 0x08) )
\r
83 if(giMouse_Cycle < 3)
\r
88 // Actual Processing (once we have all bytes)
\r
89 flags = gaMouse_Bytes[0];
\r
91 LOG("flags = 0x%x", flags);
\r
93 // Check for X/Y Overflow
\r
94 if(flags & 0xC0) return;
\r
96 // Calculate dX and dY
\r
97 d[0] = gaMouse_Bytes[1]; if(flags & 0x10) d[0] = -(256-d[0]); // x
\r
98 d[1] = gaMouse_Bytes[2]; if(flags & 0x20) d[1] = -(256-d[1]); // y
\r
99 d[1] = -d[1]; // Y is negated
\r
100 LOG("RAW dx=%i, dy=%i\n", d[0], d[1]);
\r
102 // TODO: Apply a form of curve to the mouse movement (dx*log(dx), dx^k?)
\r
103 // TODO: Independent sensitivities?
\r
104 // TODO: Disable acceleration via a flag?
\r
105 d_accel[0] = d[0]*giMouse_Sensitivity;
\r
106 d_accel[1] = d[1]*giMouse_Sensitivity;
\r
108 // Set Buttons (Primary)
\r
109 for( i = 0; i < 3; i ++ )
\r
111 Uint8 newVal = (flags & (1 << i)) ? 0xFF : 0;
\r
112 if(newVal != gMouse_Buttons[i]) {
\r
113 if( gMouse_Callback )
\r
114 gMouse_Callback(gMouse_CallbackArg, 0, i, newVal - gMouse_Buttons[i]);
\r
115 gMouse_Buttons[i] = newVal;
\r
119 // Update X and Y Positions
\r
120 for( i = 0; i < 2; i ++ )
\r
122 Sint16 newCursor = 0;
\r
123 if( giMouse_AxisLimits[i] )
\r
124 newCursor = MIN( MAX(0, gMouse_Axies[i].CursorPos + d_accel[i]), giMouse_AxisLimits[i] );;
\r
126 if( gMouse_Callback )
\r
128 if(giMouse_AxisLimits[i] && gMouse_Axies[i].CursorPos != newCursor)
\r
129 gMouse_Callback(gMouse_CallbackArg, 1, i, newCursor - gMouse_Axies[i].CursorPos);
\r
130 if(!giMouse_AxisLimits[i] && gMouse_Axies[i].CurValue != d_accel[i])
\r
131 gMouse_Callback(gMouse_CallbackArg, 1, i, d_accel[i] - gMouse_Axies[i].CurValue);
\r
134 gMouse_Axies[i].CurValue = d_accel[i];
\r
135 gMouse_Axies[i].CursorPos = newCursor;
\r
139 VFS_MarkAvaliable(&gMouse_DriverStruct.RootNode, 1);
\r
142 /* Read mouse state (coordinates)
\r
144 Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
\r
146 if(Offset > sizeof(gMouse_FileData)) return 0;
\r
147 if(Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData);
\r
148 if(Offset + Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData) - Offset;
\r
150 memcpy(Buffer, &gMouse_FileData[Offset], Length);
\r
152 VFS_MarkAvaliable(Node, 0);
\r
156 static const char *csaIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
\r
157 /* Handle messages to the device
\r
159 int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)
\r
161 tJoystick_NumValue *info = Data;
\r
165 BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);
\r
167 case JOY_IOCTL_SETCALLBACK: // TODO: Implement
\r
170 case JOY_IOCTL_SETCALLBACKARG: // TODO: Implement
\r
173 case JOY_IOCTL_GETSETAXISLIMIT:
\r
174 if(!info) return 0;
\r
175 if(info->Num < 0 || info->Num >= 2) return 0;
\r
176 if(info->Value != -1)
\r
177 giMouse_AxisLimits[info->Num] = info->Value;
\r
178 return giMouse_AxisLimits[info->Num];
\r
180 case JOY_IOCTL_GETSETAXISPOSITION:
\r
181 if(!info) return 0;
\r
182 if(info->Num < 0 || info->Num >= 2) return 0;
\r
183 if(info->Value != -1)
\r
184 gMouse_Axies[info->Num].CursorPos = info->Value;
\r
185 return gMouse_Axies[info->Num].CursorPos;
\r
187 case JOY_IOCTL_GETSETAXISFLAGS:
\r
190 case JOY_IOCTL_GETSETBUTTONFLAGS:
\r