Modules/PS2KbMouse - Broke 8042 specific code out
[tpg/acess2.git] / Modules / Input / PS2KbMouse / ps2mouse.c
1 /*\r
2  * Acess2 Mouse Driver\r
3  */\r
4 #define DEBUG   0\r
5 #include <acess.h>\r
6 #include <modules.h>\r
7 #include <vfs.h>\r
8 #include <fs_devfs.h>\r
9 #include <api_drv_common.h>\r
10 #include <api_drv_joystick.h>\r
11 #include "common.h"\r
12 \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
15 \r
16 // == CONSTANTS ==\r
17 #define NUM_AXIES       2       // X+Y\r
18 #define NUM_BUTTONS     5       // Left, Right, Scroll Click, Scroll Up, Scroll Down\r
19 \r
20 // == PROTOTYPES ==\r
21 // - Internal -\r
22  int    PS2Mouse_Install(char **Arguments);\r
23 void    PS2Mouse_HandleInterrupt(Uint8 InputByte);\r
24 // - Filesystem -\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
27 \r
28 // == GLOBALS ==\r
29 // - Settings\r
30  int    giMouse_Sensitivity = 1;\r
31  int    giMouse_MaxX = 640, giMouse_MaxY = 480;\r
32 // - File Data\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
40 // - Internal State\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
45         NULL, "PS2Mouse",\r
46         {\r
47         .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,\r
48         .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl\r
49         }\r
50 };\r
51 \r
52 // == CODE ==\r
53 int PS2Mouse_Install(char **Arguments)\r
54 {\r
55         // Set up variables\r
56         gMouse_Axies = (void*)&gMouse_FileData[1];\r
57         gMouse_Buttons = (void*)&gMouse_Axies[NUM_AXIES];\r
58         \r
59         // Initialise Mouse Controller\r
60         giMouse_Cycle = 0;      // Set Current Cycle position\r
61         KBC8042_EnableMouse();\r
62         \r
63         DevFS_AddDevice(&gMouse_DriverStruct);\r
64         \r
65         return MODULE_ERR_OK;\r
66 }\r
67 \r
68 /* Handle Mouse Interrupt\r
69  */\r
70 void PS2Mouse_HandleInterrupt(Uint8 InputByte)\r
71 {\r
72         Uint8   flags;\r
73          int    d[2], d_accel[2];\r
74          int    i;\r
75         \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
81                 return ;\r
82         giMouse_Cycle++;\r
83         if(giMouse_Cycle < 3)\r
84                 return ;\r
85 \r
86         giMouse_Cycle = 0;\r
87 \r
88         // Actual Processing (once we have all bytes)   \r
89         flags = gaMouse_Bytes[0];\r
90 \r
91         LOG("flags = 0x%x", flags);\r
92         \r
93         // Check for X/Y Overflow\r
94         if(flags & 0xC0)        return;\r
95                 \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
101         // Apply scaling\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
107         \r
108         // Set Buttons (Primary)\r
109         for( i = 0; i < 3; i ++ )\r
110         {\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
116                 }\r
117         }\r
118         \r
119         // Update X and Y Positions\r
120         for( i = 0; i < 2; i ++ )\r
121         {\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
125                 \r
126                 if( gMouse_Callback )\r
127                 {\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
132                 }\r
133                 \r
134                 gMouse_Axies[i].CurValue = d_accel[i];\r
135                 gMouse_Axies[i].CursorPos = newCursor;\r
136         }\r
137 \r
138                 \r
139         VFS_MarkAvaliable(&gMouse_DriverStruct.RootNode, 1);\r
140 }\r
141 \r
142 /* Read mouse state (coordinates)\r
143  */\r
144 Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
145 {\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
149 \r
150         memcpy(Buffer, &gMouse_FileData[Offset], Length);\r
151         \r
152         VFS_MarkAvaliable(Node, 0);\r
153         return Length;\r
154 }\r
155 \r
156 static const char *csaIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};\r
157 /* Handle messages to the device\r
158  */\r
159 int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
160 {\r
161         tJoystick_NumValue      *info = Data;\r
162 \r
163         switch(ID)\r
164         {\r
165         BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);\r
166 \r
167         case JOY_IOCTL_SETCALLBACK:     // TODO: Implement\r
168                 return -1;\r
169         \r
170         case JOY_IOCTL_SETCALLBACKARG:  // TODO: Implement\r
171                 return -1;\r
172         \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
179         \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
186 \r
187         case JOY_IOCTL_GETSETAXISFLAGS:\r
188                 return -1;\r
189         \r
190         case JOY_IOCTL_GETSETBUTTONFLAGS:\r
191                 return -1;\r
192 \r
193         default:\r
194                 return 0;\r
195         }\r
196 }\r
197 \r

UCC git Repository :: git.ucc.asn.au