Merge branch 'master' of [email protected]:acess2
[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 // == CONSTANTS ==\r
13 #define PS2_IO_PORT     0x60\r
14 #define MOUSE_BUFFER_SIZE       (sizeof(t_mouse_fsdata))\r
15 #define MOUSE_SENS_BASE 5\r
16 \r
17 // == PROTOTYPES ==\r
18 // - Internal -\r
19  int    PS2Mouse_Install(char **Arguments);\r
20 void    PS2Mouse_IRQ(int Num);\r
21 static void     mouseSendCommand(Uint8 cmd);\r
22 static void     enableMouse();\r
23 // - Filesystem -\r
24 static Uint64   PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
25 static int      PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
26 \r
27 typedef struct {\r
28         int x, y, buttons, unk;\r
29 }       t_mouse_fsdata;\r
30 \r
31 // == GLOBALS ==\r
32  int    giMouse_Sensitivity = 1;\r
33 t_mouse_fsdata  gMouse_Data = {0, 0, 0, 0};\r
34  int giMouse_MaxX = 640, giMouse_MaxY = 480;\r
35  int    giMouse_Cycle = 0;      // IRQ Position\r
36 Uint8   gaMouse_Bytes[4] = {0,0,0,0};\r
37 tDevFS_Driver   gMouse_DriverStruct = {\r
38         NULL, "ps2mouse",\r
39         {\r
40         .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,\r
41         .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl\r
42         }\r
43 };\r
44 \r
45 // == CODE ==\r
46 int Mouse_Install(char **Arguments)\r
47 {\r
48         // Initialise Mouse Controller\r
49         IRQ_AddHandler(12, PS2Mouse_IRQ);       // Set IRQ\r
50         giMouse_Cycle = 0;      // Set Current Cycle position\r
51         enableMouse();          // Enable the mouse\r
52         \r
53         DevFS_AddDevice(&gMouse_DriverStruct);\r
54         \r
55         return MODULE_ERR_OK;\r
56 }\r
57 \r
58 /* Handle Mouse Interrupt\r
59  */\r
60 void PS2Mouse_IRQ(int Num)\r
61 {\r
62         Uint8   flags;\r
63         int     dx, dy;\r
64         //int   log2x, log2y;\r
65         \r
66         gaMouse_Bytes[giMouse_Cycle] = inb(0x60);\r
67         if(giMouse_Cycle == 0 && !(gaMouse_Bytes[giMouse_Cycle] & 0x8))\r
68                 return;\r
69         giMouse_Cycle++;\r
70         if(giMouse_Cycle == 3)\r
71                 giMouse_Cycle = 0;\r
72         else\r
73                 return;\r
74         \r
75         if(giMouse_Cycle > 0)\r
76                 return;\r
77         \r
78         // Read Flags\r
79         flags = gaMouse_Bytes[0];\r
80         if(flags & 0xC0)        // X/Y Overflow\r
81                 return;\r
82                 \r
83         #if DEBUG\r
84         //LogF(" PS2Mouse_Irq: flags = 0x%x\n", flags);\r
85         #endif\r
86         \r
87         // Calculate dX and dY\r
88         dx = (int) ( gaMouse_Bytes[1] | (flags & 0x10 ? ~0x00FF : 0) );\r
89         dy = (int) ( gaMouse_Bytes[2] | (flags & 0x20 ? ~0x00FF : 0) );\r
90         dy = -dy;       // Y is negated\r
91         LOG("RAW dx=%i, dy=%i\n", dx, dy);\r
92         dx = dx*MOUSE_SENS_BASE/giMouse_Sensitivity;\r
93         dy = dy*MOUSE_SENS_BASE/giMouse_Sensitivity;\r
94         \r
95         //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2x) : "a" ((Uint)gaMouse_Bytes[1]));\r
96         //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2y) : "a" ((Uint)gaMouse_Bytes[2]));\r
97         //LogF(" PS2Mouse_Irq: dx=%i, log2x = %i\n", dx, log2x);\r
98         //LogF(" PS2Mouse_Irq: dy=%i, log2y = %i\n", dy, log2y);\r
99         //dx *= log2x;\r
100         //dy *= log2y;\r
101         \r
102         // Set Buttons\r
103         gMouse_Data.buttons = flags & 0x7;      //Buttons (3 only)\r
104         \r
105         // Update X and Y Positions\r
106         gMouse_Data.x += (int)dx;\r
107         gMouse_Data.y += (int)dy;\r
108         \r
109         // Constrain Positions\r
110         if(gMouse_Data.x < 0)   gMouse_Data.x = 0;\r
111         if(gMouse_Data.y < 0)   gMouse_Data.y = 0;\r
112         if(gMouse_Data.x >= giMouse_MaxX)       gMouse_Data.x = giMouse_MaxX-1;\r
113         if(gMouse_Data.y >= giMouse_MaxY)       gMouse_Data.y = giMouse_MaxY-1; \r
114 }\r
115 \r
116 /* Read mouse state (coordinates)\r
117  */\r
118 static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
119 {\r
120         if(Length < MOUSE_BUFFER_SIZE)\r
121                 return -1;\r
122 \r
123         memcpy(Buffer, &gMouse_Data, MOUSE_BUFFER_SIZE);\r
124                 \r
125         return MOUSE_BUFFER_SIZE;\r
126 }\r
127 \r
128 static const char *csaIOCtls[] = {DRV_IOCTLNAMES, NULL};\r
129 /* Handle messages to the device\r
130  */\r
131 static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
132 {\r
133         struct {\r
134                  int    Num;\r
135                  int    Value;\r
136         }       *info = Data;\r
137         switch(ID)\r
138         {\r
139         BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);\r
140         \r
141         case JOY_IOCTL_GETSETAXISLIMIT:\r
142                 if(!info)       return 0;\r
143                 switch(info->Num)\r
144                 {\r
145                 case 0: // X\r
146                         if(info->Value != -1)\r
147                                 giMouse_MaxX = info->Value;\r
148                         return giMouse_MaxX;\r
149                 case 1: // Y\r
150                         if(info->Value != -1)\r
151                                 giMouse_MaxY = info->Value;\r
152                         return giMouse_MaxY;\r
153                 }\r
154                 return 0;\r
155                 \r
156         default:\r
157                 return 0;\r
158         }\r
159 }\r
160 \r
161 //== Internal Functions ==\r
162 static inline void mouseOut64(Uint8 data)\r
163 {\r
164         int timeout=100000;\r
165         while( timeout-- && inb(0x64) & 2 );    // Wait for Flag to clear\r
166         outb(0x64, data);       // Send Command\r
167 }\r
168 static inline void mouseOut60(Uint8 data)\r
169 {\r
170         int timeout=100000;\r
171         while( timeout-- && inb(0x64) & 2 );    // Wait for Flag to clear\r
172         outb(0x60, data);       // Send Command\r
173 }\r
174 static inline Uint8 mouseIn60()\r
175 {\r
176         int timeout=100000;\r
177         while( timeout-- && (inb(0x64) & 1) == 0);      // Wait for Flag to set\r
178         return inb(0x60);\r
179 }\r
180 static void mouseSendCommand(Uint8 cmd)\r
181 {\r
182         mouseOut64(0xD4);\r
183         mouseOut60(cmd);\r
184 }\r
185 \r
186 static void enableMouse()\r
187 {\r
188         Uint8   status;\r
189         Log_Log("PS2 Mouse", "Enabling Mouse...");\r
190         \r
191         // Enable AUX PS/2\r
192         mouseOut64(0xA8);\r
193         \r
194         // Enable AUX PS/2 (Compaq Status Byte)\r
195         mouseOut64(0x20);       // Send Command\r
196         status = mouseIn60();   // Get Status\r
197         status &= 0xDF; status |= 0x02; // Alter Flags (Set IRQ12 (2) and Clear Disable Mouse Clock (20))\r
198         mouseOut64(0x60);       // Send Command\r
199         mouseOut60(status);     // Set Status\r
200         \r
201         //mouseSendCommand(0xF6);       // Set Default Settings\r
202         mouseSendCommand(0xF4); // Enable Packets\r
203 }\r

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