123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
- MODULE MousePS2; (** AUTHOR "pjm"; PURPOSE "PS/2 mouse driver"; *)
- (*
- Mouse protocol information from XFree in X11R6 distribution (Thomas Roell & David Dawes)
- PS/2 Aux port information from Linux (Johan Myreen et al.)
- *)
- IMPORT SYSTEM, Machine, Modules, Objects, Kernel, Inputs;
- TYPE
- Aux = OBJECT
- VAR
- p, numb: LONGINT;
- buf: ARRAY 4 OF SET;
- active: BOOLEAN;
- timer: Objects.Timer;
- PROCEDURE HandleInterrupt;
- VAR b: SET; m: Inputs.MouseMsg; ch: CHAR;
- BEGIN {EXCLUSIVE}
- Machine.Portin8(64H, ch); (* check for valid data *)
- IF SYSTEM.VAL(SET, ch) * {0} = {} THEN INC(ignored); RETURN END;
- Machine.Portin8(60H, ch); (* read byte *)
- IF active THEN
- b := SYSTEM.VAL(SET, LONG(ORD(ch)));
- IF (p = 0) & (b * {6,7} # {}) THEN (* skip package *)
- INC(errors)
- ELSE
- buf[p] := b; INC(p);
- IF p = numb THEN
- m.keys := {};
- IF 2 IN buf[0] THEN INCL(m.keys, 1) END;
- IF 1 IN buf[0] THEN INCL(m.keys, 2) END;
- IF 0 IN buf[0] THEN INCL(m.keys, 0) END;
- m.dx := SYSTEM.VAL(LONGINT, buf[1]);
- IF 4 IN buf[0] THEN DEC(m.dx, 256) END;
- m.dy := SYSTEM.VAL(LONGINT, buf[2]);
- IF 5 IN buf[0] THEN DEC(m.dy, 256) END;
- m.dz := SYSTEM.VAL(SHORTINT, buf[3]);
- IF 6 IN buf[0] THEN DEC(m.dz, 256) END;
- p := 0; m.dy := -m.dy;
- Inputs.mouse.Handle(m)
- END
- END
- ELSE
- INC(ignored)
- END
- END HandleInterrupt;
- PROCEDURE HandleTimeout;
- BEGIN {EXCLUSIVE}
- active := TRUE
- END HandleTimeout;
- PROCEDURE &Init*(rate: LONGINT);
- PROCEDURE SetRate(r: LONGINT);
- BEGIN WriteAck(0F3X); WriteAck(CHR(r))
- END SetRate;
- BEGIN
- active := FALSE; p := 0;
- PollAux;
- Machine.Portout8(64H, 0A8X); (* enable aux *)
- (* enable MS Intellimouse 3rd button *)
- SetRate(200); SetRate(100); SetRate(80); SetRate(rate);
- WriteAck(0F2X);
- IF InAux() # 0X THEN numb := 4 ELSE numb := 3 END; (* Ident *)
- WriteAck(0E8X); WriteAck(3X); (* 8 counts/mm *)
- WriteAck(0E7X); (* 2:1 scale *)
- PollAux;
- Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+12);
- WriteDev(0F4X); (* enable aux device *)
- WriteCmd(47X); (* controller interrupts on *)
- PollAux;
- NEW(timer); Objects.SetTimeout(timer, SELF.HandleTimeout, 250) (* ignore bytes in first 1/4s *)
- END Init;
- PROCEDURE Remove;
- BEGIN {EXCLUSIVE}
- Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0+12);
- Objects.CancelTimeout(timer)
- END Remove;
- END Aux;
- VAR
- errors*, ignored*: LONGINT; (* diagnostic counters *)
- aux: Aux;
- PROCEDURE PollAux;
- VAR s: SET; i: LONGINT; t: Kernel.MilliTimer;
- BEGIN
- i := 10; (* up to 0.2s! *)
- LOOP
- Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
- IF (s * {0,1} = {}) OR (i = 0) THEN EXIT END;
- Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
- IF s * {0,5} = {0,5} THEN Machine.Portin8(60H, SYSTEM.VAL(CHAR, s)) END; (* byte avail *)
- Kernel.SetTimer(t, 20); (* 20ms *)
- REPEAT UNTIL Kernel.Expired(t);
- DEC(i)
- END
- END PollAux;
- PROCEDURE InAux(): CHAR;
- VAR s: SET; t: Kernel.MilliTimer;ch: CHAR; i: SHORTINT;
- BEGIN
- i := 10; (* up to 0.2s! *)
- REPEAT
- Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
- IF s * {0,5} = {0,5} THEN (* byte avail *)
- Machine.Portin8(60H, ch);
- RETURN ch
- END;
- Kernel.SetTimer(t, 20);
- REPEAT UNTIL Kernel.Expired(t);
- DEC(i);
- UNTIL i = 0;
- RETURN 0X
- END InAux;
- PROCEDURE WriteDev(b: CHAR);
- BEGIN
- PollAux; Machine.Portout8(64H, 0D4X); (* aux data coming *)
- PollAux; Machine.Portout8(60H, b)
- END WriteDev;
- PROCEDURE WriteAck(b: CHAR);
- VAR s: SET; i: LONGINT; t: Kernel.MilliTimer;
- BEGIN
- WriteDev(b); i := 10; (* up to 0.2s! *)
- LOOP
- Machine.Portin8(64H, SYSTEM.VAL(CHAR, s));
- IF (s * {0,5} = {0,5}) OR (i = 0) THEN EXIT END;
- Kernel.SetTimer(t, 20); (* 20ms *)
- REPEAT UNTIL Kernel.Expired(t);
- DEC(i)
- END;
- IF i # 0 THEN Machine.Portin8(60H, SYSTEM.VAL(CHAR, s)) END (* byte avail *)
- END WriteAck;
- PROCEDURE WriteCmd(b: CHAR);
- BEGIN
- PollAux; Machine.Portout8(64H, 60X);
- PollAux; Machine.Portout8(60H, b)
- END WriteCmd;
- PROCEDURE ConfigMouse;
- VAR i, rate: LONGINT; s: ARRAY 16 OF CHAR;
- BEGIN
- errors := 0; ignored := 0;
- Machine.GetConfig("MouseRate", s);
- i := 0; rate := Machine.StrToInt(i, s);
- IF (rate <= 0) OR (rate > 150) THEN rate := 100 END;
- NEW(aux, rate)
- END ConfigMouse;
- PROCEDURE Install*;
- BEGIN
- IF aux = NIL THEN ConfigMouse END
- END Install;
- PROCEDURE Remove*;
- BEGIN
- IF aux # NIL THEN aux.Remove(); aux := NIL END
- END Remove;
- BEGIN
- Modules.InstallTermHandler(Remove);
- aux := NIL; Install
- END MousePS2.
|