]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/omap/mouse.c
apply ps2mouse corruption fix to omap
[plan9front.git] / sys / src / 9 / omap / mouse.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 #include "io.h"
8
9 #define Image   IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14
15 /*
16  *  mouse types
17  */
18 enum
19 {
20         Mouseother=     0,
21         Mouseserial=    1,
22         MousePS2=       2,
23 };
24
25 extern int mouseshifted;
26
27 static QLock mousectlqlock;
28 static int mousetype;
29 static int intellimouse;
30 static int packetsize;
31 static int resolution;
32 static int accelerated;
33 static int mousehwaccel;
34 static char mouseport[5];
35
36 enum
37 {
38         CMaccelerated,
39         CMhwaccel,
40         CMintellimouse,
41         CMlinear,
42         CMps2,
43         CMps2intellimouse,
44         CMres,
45         CMreset,
46         CMserial,
47 };
48
49 static Cmdtab mousectlmsg[] =
50 {
51         CMaccelerated,          "accelerated",          0,
52         CMhwaccel,              "hwaccel",              2,
53         CMintellimouse,         "intellimouse",         1,
54         CMlinear,               "linear",               1,
55         CMps2,                  "ps2",                  1,
56         CMps2intellimouse,      "ps2intellimouse",      1,
57         CMres,                  "res",                  0,
58         CMreset,                "reset",                1,
59         CMserial,               "serial",               0,
60 };
61
62 /*
63  *  ps/2 mouse message is three bytes
64  *
65  *      byte 0 -        0 0 SDY SDX 1 M R L
66  *      byte 1 -        DX
67  *      byte 2 -        DY
68  *
69  *  shift & right button is the same as middle button
70  *
71  * Intellimouse and AccuPoint with extra buttons deliver
72  *      byte 3 -        00 or 01 or FF according to extra button state.
73  * extra buttons are mapped in this code to buttons 4 and 5.
74  * AccuPoint generates repeated events for these buttons;
75 *  it and Intellimouse generate 'down' events only, so
76  * user-level code is required to generate button 'up' events
77  * if they are needed by the application.
78  * Also on laptops with AccuPoint AND external mouse, the
79  * controller may deliver 3 or 4 bytes according to the type
80  * of the external mouse; code must adapt.
81  *
82  * On the NEC Versa series (and perhaps others?) we seem to
83  * lose a byte from the packet every once in a while, which
84  * means we lose where we are in the instruction stream.
85  * To resynchronize, if we get a byte more than two seconds
86  * after the previous byte, we assume it's the first in a packet.
87  */
88 static void
89 ps2mouseputc(int c, int shift)
90 {
91         static short msg[4];
92         static int nb;
93         static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 };
94         static ulong lasttick;
95         ulong m;
96         int buttons, dx, dy;
97
98         shift |= mouseshifted;
99         m = MACHP(0)->ticks;
100         if(TK2SEC(m - lasttick) > 2)
101                 nb = 0;
102         lasttick = m;
103         if(nb==0 && (c&0xc8)!=0x08)
104                 if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){
105                         packetsize = 4;
106                         return;
107                 }
108
109         msg[nb] = c;
110         if(++nb >= packetsize){
111                 nb = 0;
112                 if(msg[0] & 0x10)
113                         msg[1] |= 0xFF00;
114                 if(msg[0] & 0x20)
115                         msg[2] |= 0xFF00;
116
117                 buttons = b[(msg[0]&7) | (shift ? 8 : 0)];
118                 if(intellimouse && packetsize==4){
119                         if((msg[3]&0xc8) == 0x08){
120                                 packetsize = 3;
121                                 msg[0] = msg[3];
122                                 nb = 1;
123                         }else{
124                                 if((msg[3] >> 3) & 1)
125                                         buttons |= 1<<3;
126                                 else if(msg[3] & 0x7)
127                                         buttons |= 1<<4;
128                         }
129                 }
130                 dx = msg[1];
131                 dy = -msg[2];
132                 mousetrack(dx, dy, buttons, TK2MS(MACHP(0)->ticks));
133         }
134 }
135
136 /*
137  *  set up a ps2 mouse
138  */
139 static void
140 ps2mouse(void)
141 {
142         if(mousetype == MousePS2)
143                 return;
144
145         mousetype = MousePS2;
146         packetsize = 3;
147         mousehwaccel = 1;
148
149 //      i8042auxenable(ps2mouseputc);
150 //      i8042auxcmd(0xEA);      // TODO
151 //      i8042auxcmd(0xF4);
152 }
153
154 /*
155  * The PS/2 Trackpoint multiplexor on the IBM Thinkpad T23 ignores
156  * acceleration commands.  It is supposed to pass them on
157  * to the attached device, but my Logitech mouse is simply
158  * not behaving any differently.  For such devices, we allow
159  * the user to use "hwaccel off" to tell us to back off to
160  * software acceleration even if we're using the PS/2 port.
161  * (Serial mice are always software accelerated.)
162  * For more information on the Thinkpad multiplexor, see
163  * http://wwwcssrv.almaden.ibm.com/trackpoint/
164  */
165 static void
166 setaccelerated(int x)
167 {
168         accelerated = x;
169         mouseaccelerate(x);
170 }
171
172 static void
173 setlinear(void)
174 {
175         accelerated = 0;
176         mouseaccelerate(0);
177 }
178
179 static void
180 setres(int n)
181 {
182         resolution = n;
183 }
184
185 static void
186 setintellimouse(void)
187 {
188         intellimouse = 1;
189         packetsize = 4;
190 }
191
192 static void
193 resetmouse(void)
194 {
195         packetsize = 3;
196 }
197
198 void
199 mousectl(Cmdbuf *cb)
200 {
201         Cmdtab *ct;
202
203         qlock(&mousectlqlock);
204         if(waserror()){
205                 qunlock(&mousectlqlock);
206                 nexterror();
207         }
208
209         ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
210         switch(ct->index){
211         case CMaccelerated:
212                 setaccelerated(cb->nf == 1? 1: atoi(cb->f[1]));
213                 break;
214         case CMintellimouse:
215                 setintellimouse();
216                 break;
217         case CMlinear:
218                 setlinear();
219                 break;
220         case CMps2:
221                 intellimouse = 0;
222                 break;
223         case CMps2intellimouse:
224                 setintellimouse();
225                 break;
226         case CMres:
227                 if(cb->nf >= 2)
228                         setres(atoi(cb->f[1]));
229                 else
230                         setres(1);
231                 break;
232         case CMreset:
233                 resetmouse();
234                 if(accelerated)
235                         setaccelerated(accelerated);
236                 if(resolution)
237                         setres(resolution);
238                 if(intellimouse)
239                         setintellimouse();
240                 break;
241         case CMserial:
242                 error("serial mice not supported");
243                 break;
244         case CMhwaccel:
245                 if(strcmp(cb->f[1], "on")==0)
246                         mousehwaccel = 1;
247                 else if(strcmp(cb->f[1], "off")==0)
248                         mousehwaccel = 0;
249                 else
250                         cmderror(cb, "bad mouse control message");
251         }
252
253         qunlock(&mousectlqlock);
254         poperror();
255 }