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

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