44be3b7b79ca648dca71d86593c919e2bb645b96
[tpg/acess2.git] / KernelLand / 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 // == CONSTANTS ==\r
14 #define NUM_AXIES       2       // X+Y\r
15 #define NUM_BUTTONS     5       // Left, Right, Scroll Click, Scroll Up, Scroll Down\r
16 \r
17 // == PROTOTYPES ==\r
18 // - Internal -\r
19  int    PS2Mouse_Install(char **Arguments);\r
20 void    PS2Mouse_HandleInterrupt(Uint8 InputByte);\r
21 // - Filesystem -\r
22 Uint64  PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
23 int     PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
24 \r
25 // == GLOBALS ==\r
26 void    (*gpMouse_EnableFcn)(void);\r
27 // - Settings\r
28  int    giMouse_Sensitivity = 1;\r
29  int    giMouse_MaxX = 640, giMouse_MaxY = 480;\r
30 // - File Data\r
31 Uint8   gMouse_FileData[sizeof(tJoystick_FileHeader) + NUM_AXIES*sizeof(tJoystick_Axis) + NUM_BUTTONS];\r
32 tJoystick_FileHeader    *gMouse_FileHeader = (void *)gMouse_FileData;\r
33 tJoystick_Axis  *gMouse_Axies;\r
34 Uint8   *gMouse_Buttons;\r
35 tJoystick_Callback      gMouse_Callback;\r
36  int    gMouse_CallbackArg;\r
37  int    giMouse_AxisLimits[2];\r
38 // - Internal State\r
39  int    giMouse_Cycle = 0;      // IRQ Position\r
40 Uint8   gaMouse_Bytes[4] = {0,0,0,0};\r
41 // - Driver definition\r
42 tVFS_NodeType   gMouse_NodeType = {\r
43         .Read = PS2Mouse_Read,\r
44         .IOCtl = PS2Mouse_IOCtl\r
45 };\r
46 tDevFS_Driver   gMouse_DriverStruct = {\r
47         NULL, "PS2Mouse",\r
48         {\r
49         .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,\r
50         .Type = &gMouse_NodeType\r
51         }\r
52 };\r
53 \r
54 // == CODE ==\r
55 int PS2Mouse_Install(char **Arguments)\r
56 {\r
57         \r
58 \r
59         // Set up variables\r
60         gMouse_Axies = (void*)&gMouse_FileData[4];\r
61         gMouse_Buttons = (void*)&gMouse_Axies[NUM_AXIES];\r
62 \r
63         gMouse_FileHeader->NAxies = 2;  gMouse_FileHeader->NButtons = 3;\r
64         gMouse_Axies[0].MinValue = -10; gMouse_Axies[0].MaxValue = 10;\r
65         gMouse_Axies[1].MinValue = -10; gMouse_Axies[1].MaxValue = 10;\r
66         \r
67         // Initialise Mouse Controller\r
68         giMouse_Cycle = 0;      // Set Current Cycle position\r
69         gpMouse_EnableFcn();\r
70         \r
71         DevFS_AddDevice(&gMouse_DriverStruct);\r
72         \r
73         return MODULE_ERR_OK;\r
74 }\r
75 \r
76 /* Handle Mouse Interrupt\r
77  */\r
78 void PS2Mouse_HandleInterrupt(Uint8 InputByte)\r
79 {\r
80         Uint8   flags;\r
81          int    d[2], d_accel[2];\r
82          int    i;\r
83         \r
84         // Gather mouse data\r
85         gaMouse_Bytes[giMouse_Cycle] = InputByte;\r
86         LOG("gaMouse_Bytes[%i] = 0x%02x", gMouse_Axies[0].MaxValue);\r
87         // - If bit 3 of the first byte is not set, it's not a valid packet?\r
88         if(giMouse_Cycle == 0 && !(gaMouse_Bytes[0] & 0x08) )\r
89                 return ;\r
90         giMouse_Cycle++;\r
91         if(giMouse_Cycle < 3)\r
92                 return ;\r
93 \r
94         giMouse_Cycle = 0;\r
95 \r
96         // Actual Processing (once we have all bytes)   \r
97         flags = gaMouse_Bytes[0];\r
98 \r
99         LOG("flags = 0x%x", flags);\r
100         \r
101         // Check for X/Y Overflow\r
102         if(flags & 0xC0)        return;\r
103                 \r
104         // Calculate dX and dY\r
105         d[0] = gaMouse_Bytes[1];        if(flags & 0x10) d[0] = -(256-d[0]);    // x\r
106         d[1] = gaMouse_Bytes[2];        if(flags & 0x20) d[1] = -(256-d[1]);    // y\r
107         d[1] = -d[1];   // Y is negated\r
108         LOG("RAW dx=%i, dy=%i\n", d[0], d[1]);\r
109         // Apply scaling\r
110         // TODO: Apply a form of curve to the mouse movement (dx*log(dx), dx^k?)\r
111         // TODO: Independent sensitivities?\r
112         // TODO: Disable acceleration via a flag?\r
113         d_accel[0] = d[0]*giMouse_Sensitivity;\r
114         d_accel[1] = d[1]*giMouse_Sensitivity;\r
115         \r
116         // Set Buttons (Primary)\r
117         for( i = 0; i < 3; i ++ )\r
118         {\r
119                 Uint8   newVal = (flags & (1 << i)) ? 0xFF : 0;\r
120                 if(newVal != gMouse_Buttons[i]) {\r
121                         if( gMouse_Callback )\r
122                                 gMouse_Callback(gMouse_CallbackArg, 0, i, newVal - gMouse_Buttons[i]);\r
123                         gMouse_Buttons[i] = newVal;\r
124                 }\r
125         }\r
126         \r
127         // Update X and Y Positions\r
128         for( i = 0; i < 2; i ++ )\r
129         {\r
130                 Sint16  newCursor = 0;\r
131                 if( giMouse_AxisLimits[i] )\r
132                         newCursor = MIN( MAX(0, gMouse_Axies[i].CursorPos + d_accel[i]), giMouse_AxisLimits[i] );;\r
133                 \r
134                 if( gMouse_Callback )\r
135                 {\r
136                         if(giMouse_AxisLimits[i] && gMouse_Axies[i].CursorPos != newCursor)\r
137                                 gMouse_Callback(gMouse_CallbackArg, 1, i, newCursor - gMouse_Axies[i].CursorPos);\r
138                         if(!giMouse_AxisLimits[i] && gMouse_Axies[i].CurValue != d_accel[i])\r
139                                 gMouse_Callback(gMouse_CallbackArg, 1, i, d_accel[i] - gMouse_Axies[i].CurValue);\r
140                 }\r
141                 \r
142                 gMouse_Axies[i].CurValue = d_accel[i];\r
143                 gMouse_Axies[i].CursorPos = newCursor;\r
144         }\r
145 \r
146 //      Log("Mouse at %ix%i", gMouse_Axies[0].CursorPos, gMouse_Axies[1].CursorPos);\r
147                 \r
148         VFS_MarkAvaliable(&gMouse_DriverStruct.RootNode, 1);\r
149 }\r
150 \r
151 /* Read mouse state (coordinates)\r
152  */\r
153 Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
154 {\r
155         if(Offset > sizeof(gMouse_FileData))    return 0;\r
156         if(Length > sizeof(gMouse_FileData))    Length = sizeof(gMouse_FileData);\r
157         if(Offset + Length > sizeof(gMouse_FileData))   Length = sizeof(gMouse_FileData) - Offset;\r
158 \r
159         memcpy(Buffer, &gMouse_FileData[Offset], Length);\r
160         \r
161         VFS_MarkAvaliable(Node, 0);\r
162         return Length;\r
163 }\r
164 \r
165 static const char *csaIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};\r
166 /* Handle messages to the device\r
167  */\r
168 int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
169 {\r
170         tJoystick_NumValue      *info = Data;\r
171 \r
172         switch(ID)\r
173         {\r
174         BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);\r
175 \r
176         case JOY_IOCTL_SETCALLBACK:     // TODO: Implement\r
177                 return -1;\r
178         \r
179         case JOY_IOCTL_SETCALLBACKARG:  // TODO: Implement\r
180                 return -1;\r
181         \r
182         case JOY_IOCTL_GETSETAXISLIMIT:\r
183                 if(!info)       return 0;\r
184                 if(info->Num < 0 || info->Num >= 2)     return 0;\r
185                 if(info->Value != -1)\r
186                         giMouse_AxisLimits[info->Num] = info->Value;\r
187                 return giMouse_AxisLimits[info->Num];\r
188         \r
189         case JOY_IOCTL_GETSETAXISPOSITION:\r
190                 if(!info)       return 0;\r
191                 if(info->Num < 0 || info->Num >= 2)     return 0;\r
192                 if(info->Value != -1)\r
193                         gMouse_Axies[info->Num].CursorPos = info->Value;\r
194                 return gMouse_Axies[info->Num].CursorPos;\r
195 \r
196         case JOY_IOCTL_GETSETAXISFLAGS:\r
197                 return -1;\r
198         \r
199         case JOY_IOCTL_GETSETBUTTONFLAGS:\r
200                 return -1;\r
201 \r
202         default:\r
203                 return 0;\r
204         }\r
205 }\r
206 \r

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