Mouse driver and AxWin
[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 <tpl_drv_common.h>\r
10 #include <tpl_drv_joystick.h>\r
11 \r
12 static inline int MIN(int a, int b) { return (a < b) ? a : b; }\r
13 static inline int MAX(int a, int b) { return (a > b) ? a : b; }\r
14 \r
15 // == CONSTANTS ==\r
16 #define NUM_AXIES       2       // X+Y\r
17 #define NUM_BUTTONS     5       // Left, Right, Scroll Click, Scroll Up, Scroll Down\r
18 #define PS2_IO_PORT     0x60\r
19 \r
20 // == PROTOTYPES ==\r
21 // - Internal -\r
22  int    PS2Mouse_Install(char **Arguments);\r
23 void    PS2Mouse_IRQ(int Num);\r
24 static void     mouseSendCommand(Uint8 cmd);\r
25 void    PS2Mouse_Enable();\r
26 // - Filesystem -\r
27 Uint64  PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
28 int     PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
29 \r
30 // == GLOBALS ==\r
31 // - Settings\r
32  int    giMouse_Sensitivity = 1;\r
33  int    giMouse_MaxX = 640, giMouse_MaxY = 480;\r
34 // - File Data\r
35 Uint8   gMouse_FileData[sizeof(tJoystick_FileHeader) + NUM_AXIES*sizeof(tJoystick_Axis) + NUM_BUTTONS];\r
36 tJoystick_FileHeader    *gMouse_FileHeader = (void *)gMouse_FileData;\r
37 tJoystick_Axis  *gMouse_Axies;\r
38 Uint8   *gMouse_Buttons;\r
39 // - Internal State\r
40  int    giMouse_Cycle = 0;      // IRQ Position\r
41 Uint8   gaMouse_Bytes[4] = {0,0,0,0};\r
42 // - Driver definition\r
43 tDevFS_Driver   gMouse_DriverStruct = {\r
44         NULL, "PS2Mouse",\r
45         {\r
46         .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,\r
47         .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl\r
48         }\r
49 };\r
50 \r
51 // == CODE ==\r
52 int PS2Mouse_Install(char **Arguments)\r
53 {\r
54         // Set up variables\r
55         gMouse_Axies = (void*)&gMouse_FileData[1];\r
56         gMouse_Buttons = (void*)&gMouse_Axies[NUM_AXIES];\r
57         \r
58         // Initialise Mouse Controller\r
59         IRQ_AddHandler(12, PS2Mouse_IRQ);       // Set IRQ\r
60         giMouse_Cycle = 0;      // Set Current Cycle position\r
61         PS2Mouse_Enable();              // Enable the mouse\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_IRQ(int Num)\r
71 {\r
72         Uint8   flags;\r
73          int    dx, dy;\r
74          int    dx_accel, dy_accel;\r
75 \r
76         \r
77         // Gather mouse data\r
78         gaMouse_Bytes[giMouse_Cycle] = inb(0x60);\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
82                 return ;\r
83         giMouse_Cycle++;\r
84         if(giMouse_Cycle < 3)\r
85                 return ;\r
86 \r
87         giMouse_Cycle = 0;\r
88 \r
89         // Actual Processing (once we have all bytes)   \r
90         flags = gaMouse_Bytes[0];\r
91 \r
92         LOG("flags = 0x%x", flags);\r
93         \r
94         // Check for X/Y Overflow\r
95         if(flags & 0xC0)        return;\r
96                 \r
97         // Calculate dX and dY\r
98         dx = gaMouse_Bytes[1];  if(flags & 0x10) dx = -(256-dx);\r
99         dy = gaMouse_Bytes[2];  if(flags & 0x20) dy = -(256-dy);\r
100         dy = -dy;       // Y is negated\r
101         LOG("RAW dx=%i, dy=%i\n", dx, dy);\r
102         // Apply scaling\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         dx_accel = dx*giMouse_Sensitivity;\r
107         dy_accel = dy*giMouse_Sensitivity;\r
108         \r
109         // Set Buttons (Primary)\r
110         gMouse_Buttons[0] = (flags & 1) ? 0xFF : 0;\r
111         gMouse_Buttons[1] = (flags & 2) ? 0xFF : 0;\r
112         gMouse_Buttons[2] = (flags & 4) ? 0xFF : 0;\r
113         \r
114         // Update X and Y Positions\r
115         gMouse_Axies[0].CurValue = MIN( MAX(gMouse_Axies[0].MinValue, gMouse_Axies[0].CurValue + dx_accel), gMouse_Axies[0].MaxValue );\r
116         gMouse_Axies[1].CurValue = MIN( MAX(gMouse_Axies[1].MinValue, gMouse_Axies[1].CurValue + dy_accel), gMouse_Axies[1].MaxValue );\r
117 }\r
118 \r
119 /* Read mouse state (coordinates)\r
120  */\r
121 Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
122 {\r
123         if(Offset > sizeof(gMouse_FileData))    return 0;\r
124         if(Length > sizeof(gMouse_FileData))    Length = sizeof(gMouse_FileData);\r
125         if(Offset + Length > sizeof(gMouse_FileData))   Length = sizeof(gMouse_FileData) - Offset;\r
126 \r
127         memcpy(Buffer, &gMouse_FileData[Offset], Length);\r
128                 \r
129         return Length;\r
130 }\r
131 \r
132 static const char *csaIOCtls[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};\r
133 /* Handle messages to the device\r
134  */\r
135 int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
136 {\r
137         tJoystick_NumValue      *info = Data;\r
138 \r
139         switch(ID)\r
140         {\r
141         BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);\r
142 \r
143         case JOY_IOCTL_SETCALLBACK:     // TODO: Implement\r
144                 return -1;\r
145         \r
146         case JOY_IOCTL_SETCALLBACKARG:  // TODO: Implement\r
147                 return -1;\r
148         \r
149         case JOY_IOCTL_GETSETAXISLIMIT:\r
150                 if(!info)       return 0;\r
151                 if(info->Num < 0 || info->Num >= 2)     return 0;\r
152                 if(info->Value != -1)\r
153                         gMouse_Axies[info->Num].MaxValue = info->Value;\r
154                 return gMouse_Axies[info->Num].MaxValue;\r
155         \r
156         case JOY_IOCTL_GETSETAXISPOSITION:\r
157                 if(!info)       return 0;\r
158                 if(info->Num < 0 || info->Num >= 2)     return 0;\r
159                 if(info->Value != -1)\r
160                         gMouse_Axies[info->Num].CurValue = info->Value;\r
161                 return gMouse_Axies[info->Num].CurValue;\r
162 \r
163         case JOY_IOCTL_GETSETAXISFLAGS:\r
164                 return -1;\r
165         \r
166         case JOY_IOCTL_GETSETBUTTONFLAGS:\r
167                 return -1;\r
168 \r
169         default:\r
170                 return 0;\r
171         }\r
172 }\r
173 \r
174 //== Internal Functions ==\r
175 static inline void mouseOut64(Uint8 data)\r
176 {\r
177         int timeout=100000;\r
178         while( timeout-- && inb(0x64) & 2 );    // Wait for Flag to clear\r
179         outb(0x64, data);       // Send Command\r
180 }\r
181 static inline void mouseOut60(Uint8 data)\r
182 {\r
183         int timeout=100000;\r
184         while( timeout-- && inb(0x64) & 2 );    // Wait for Flag to clear\r
185         outb(0x60, data);       // Send Command\r
186 }\r
187 static inline Uint8 mouseIn60(void)\r
188 {\r
189         int timeout=100000;\r
190         while( timeout-- && (inb(0x64) & 1) == 0);      // Wait for Flag to set\r
191         return inb(0x60);\r
192 }\r
193 static inline void mouseSendCommand(Uint8 cmd)\r
194 {\r
195         mouseOut64(0xD4);\r
196         mouseOut60(cmd);\r
197 }\r
198 \r
199 void PS2Mouse_Enable(void)\r
200 {\r
201         Uint8   status;\r
202         Log_Log("PS2Mouse", "Enabling Mouse...");\r
203         \r
204         // Enable AUX PS/2\r
205         mouseOut64(0xA8);\r
206         \r
207         // Enable AUX PS/2 (Compaq Status Byte)\r
208         mouseOut64(0x20);       // Send Command\r
209         status = mouseIn60();   // Get Status\r
210         status &= ~0x20;        // Clear "Disable Mouse Clock"\r
211         status |= 0x02;         // Set IRQ12 Enable\r
212         mouseOut64(0x60);       // Send Command\r
213         mouseOut60(status);     // Set Status\r
214         \r
215         //mouseSendCommand(0xF6);       // Set Default Settings\r
216         mouseSendCommand(0xF4); // Enable Packets\r
217 }\r

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