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
57 gMouse_Axies = (void*)&gMouse_FileData[1];
\r
58 gMouse_Buttons = (void*)&gMouse_Axies[NUM_AXIES];
\r
60 // Initialise Mouse Controller
\r
61 giMouse_Cycle = 0; // Set Current Cycle position
\r
62 gpMouse_EnableFcn();
\r
64 DevFS_AddDevice(&gMouse_DriverStruct);
\r
66 return MODULE_ERR_OK;
\r
69 /* Handle Mouse Interrupt
\r
71 void PS2Mouse_HandleInterrupt(Uint8 InputByte)
\r
74 int d[2], d_accel[2];
\r
77 // Gather mouse data
\r
78 gaMouse_Bytes[giMouse_Cycle] = InputByte;
\r
79 LOG("gaMouse_Bytes[%i] = 0x%02x", gMouse_Axies[0].MaxValue);
\r
80 // - If bit 3 of the first byte is not set, it's not a valid packet?
\r
81 if(giMouse_Cycle == 0 && !(gaMouse_Bytes[0] & 0x08) )
\r
84 if(giMouse_Cycle < 3)
\r
89 // Actual Processing (once we have all bytes)
\r
90 flags = gaMouse_Bytes[0];
\r
92 LOG("flags = 0x%x", flags);
\r
94 // Check for X/Y Overflow
\r
95 if(flags & 0xC0) return;
\r
97 // Calculate dX and dY
\r
98 d[0] = gaMouse_Bytes[1]; if(flags & 0x10) d[0] = -(256-d[0]); // x
\r
99 d[1] = gaMouse_Bytes[2]; if(flags & 0x20) d[1] = -(256-d[1]); // y
\r
100 d[1] = -d[1]; // Y is negated
\r
101 LOG("RAW dx=%i, dy=%i\n", d[0], d[1]);
\r
103 // TODO: Apply a form of curve to the mouse movement (dx*log(dx), dx^k?)
\r
104 // TODO: Independent sensitivities?
\r
105 // TODO: Disable acceleration via a flag?
\r
106 d_accel[0] = d[0]*giMouse_Sensitivity;
\r
107 d_accel[1] = d[1]*giMouse_Sensitivity;
\r
109 // Set Buttons (Primary)
\r
110 for( i = 0; i < 3; i ++ )
\r
112 Uint8 newVal = (flags & (1 << i)) ? 0xFF : 0;
\r
113 if(newVal != gMouse_Buttons[i]) {
\r
114 if( gMouse_Callback )
\r
115 gMouse_Callback(gMouse_CallbackArg, 0, i, newVal - gMouse_Buttons[i]);
\r
116 gMouse_Buttons[i] = newVal;
\r
120 // Update X and Y Positions
\r
121 for( i = 0; i < 2; i ++ )
\r
123 Sint16 newCursor = 0;
\r
124 if( giMouse_AxisLimits[i] )
\r
125 newCursor = MIN( MAX(0, gMouse_Axies[i].CursorPos + d_accel[i]), giMouse_AxisLimits[i] );;
\r
127 if( gMouse_Callback )
\r
129 if(giMouse_AxisLimits[i] && gMouse_Axies[i].CursorPos != newCursor)
\r
130 gMouse_Callback(gMouse_CallbackArg, 1, i, newCursor - gMouse_Axies[i].CursorPos);
\r
131 if(!giMouse_AxisLimits[i] && gMouse_Axies[i].CurValue != d_accel[i])
\r
132 gMouse_Callback(gMouse_CallbackArg, 1, i, d_accel[i] - gMouse_Axies[i].CurValue);
\r
135 gMouse_Axies[i].CurValue = d_accel[i];
\r
136 gMouse_Axies[i].CursorPos = newCursor;
\r
140 VFS_MarkAvaliable(&gMouse_DriverStruct.RootNode, 1);
\r
143 /* Read mouse state (coordinates)
\r
145 Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
\r
147 if(Offset > sizeof(gMouse_FileData)) return 0;
\r
148 if(Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData);
\r
149 if(Offset + Length > sizeof(gMouse_FileData)) Length = sizeof(gMouse_FileData) - Offset;
\r
151 memcpy(Buffer, &gMouse_FileData[Offset], Length);
\r
153 VFS_MarkAvaliable(Node, 0);
\r
157 static const char *csaIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
\r
158 /* Handle messages to the device
\r
160 int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)
\r
162 tJoystick_NumValue *info = Data;
\r
166 BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);
\r
168 case JOY_IOCTL_SETCALLBACK: // TODO: Implement
\r
171 case JOY_IOCTL_SETCALLBACKARG: // TODO: Implement
\r
174 case JOY_IOCTL_GETSETAXISLIMIT:
\r
175 if(!info) return 0;
\r
176 if(info->Num < 0 || info->Num >= 2) return 0;
\r
177 if(info->Value != -1)
\r
178 giMouse_AxisLimits[info->Num] = info->Value;
\r
179 return giMouse_AxisLimits[info->Num];
\r
181 case JOY_IOCTL_GETSETAXISPOSITION:
\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 gMouse_Axies[info->Num].CursorPos = info->Value;
\r
186 return gMouse_Axies[info->Num].CursorPos;
\r
188 case JOY_IOCTL_GETSETAXISFLAGS:
\r
191 case JOY_IOCTL_GETSETBUTTONFLAGS:
\r