1ad771aa1SSøren Schmidt /** 21de7b4b8SPedro F. Giffuni ** SPDX-License-Identifier: BSD-4-Clause 31de7b4b8SPedro F. Giffuni ** 4ad771aa1SSøren Schmidt ** Copyright (c) 1995 Michael Smith, All rights reserved. 5ad771aa1SSøren Schmidt ** 6ad771aa1SSøren Schmidt ** Redistribution and use in source and binary forms, with or without 7ad771aa1SSøren Schmidt ** modification, are permitted provided that the following conditions 8ad771aa1SSøren Schmidt ** are met: 9ad771aa1SSøren Schmidt ** 1. Redistributions of source code must retain the above copyright 10ad771aa1SSøren Schmidt ** notice, this list of conditions and the following disclaimer as 11ad771aa1SSøren Schmidt ** the first lines of this file unmodified. 12ad771aa1SSøren Schmidt ** 2. Redistributions in binary form must reproduce the above copyright 13ad771aa1SSøren Schmidt ** notice, this list of conditions and the following disclaimer in the 14ad771aa1SSøren Schmidt ** documentation and/or other materials provided with the distribution. 15ad771aa1SSøren Schmidt ** 3. All advertising materials mentioning features or use of this software 16ad771aa1SSøren Schmidt ** must display the following acknowledgment: 17ad771aa1SSøren Schmidt ** This product includes software developed by Michael Smith. 18ad771aa1SSøren Schmidt ** 4. The name of the author may not be used to endorse or promote products 19ad771aa1SSøren Schmidt ** derived from this software without specific prior written permission. 20ad771aa1SSøren Schmidt ** 21ad771aa1SSøren Schmidt ** 22ad771aa1SSøren Schmidt ** THIS SOFTWARE IS PROVIDED BY Michael Smith ``AS IS'' AND ANY 23ad771aa1SSøren Schmidt ** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24ad771aa1SSøren Schmidt ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25ad771aa1SSøren Schmidt ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Michael Smith BE LIABLE FOR 26ad771aa1SSøren Schmidt ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27ad771aa1SSøren Schmidt ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28ad771aa1SSøren Schmidt ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29ad771aa1SSøren Schmidt ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30ad771aa1SSøren Schmidt ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 31ad771aa1SSøren Schmidt ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32ad771aa1SSøren Schmidt ** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33ad771aa1SSøren Schmidt ** 34ad771aa1SSøren Schmidt **/ 35ad771aa1SSøren Schmidt 36ad771aa1SSøren Schmidt /** 37ad771aa1SSøren Schmidt ** MOUSED.C 38ad771aa1SSøren Schmidt ** 395f436cfbSKazutaka YOKOTA ** Mouse daemon : listens to a serial port, the bus mouse interface, or 405f436cfbSKazutaka YOKOTA ** the PS/2 mouse port for mouse data stream, interprets data and passes 415f436cfbSKazutaka YOKOTA ** ioctls off to the console driver. 42ad771aa1SSøren Schmidt ** 43ad771aa1SSøren Schmidt ** The mouse interface functions are derived closely from the mouse 44ad771aa1SSøren Schmidt ** handler in the XFree86 X server. Many thanks to the XFree86 people 45ad771aa1SSøren Schmidt ** for their great work! 46ad771aa1SSøren Schmidt ** 47ad771aa1SSøren Schmidt **/ 48ad771aa1SSøren Schmidt 49038ec830SDag-Erling Smørgrav #include <sys/param.h> 50038ec830SDag-Erling Smørgrav #include <sys/consio.h> 51038ec830SDag-Erling Smørgrav #include <sys/mouse.h> 52038ec830SDag-Erling Smørgrav #include <sys/socket.h> 53038ec830SDag-Erling Smørgrav #include <sys/stat.h> 54038ec830SDag-Erling Smørgrav #include <sys/time.h> 55038ec830SDag-Erling Smørgrav #include <sys/un.h> 56038ec830SDag-Erling Smørgrav 57038ec830SDag-Erling Smørgrav #include <ctype.h> 5807e1d533SPhilippe Charnier #include <err.h> 5907e1d533SPhilippe Charnier #include <errno.h> 6007e1d533SPhilippe Charnier #include <fcntl.h> 61a80d5fc2SPawel Jakub Dawidek #include <libutil.h> 6207e1d533SPhilippe Charnier #include <limits.h> 63038ec830SDag-Erling Smørgrav #include <setjmp.h> 64038ec830SDag-Erling Smørgrav #include <signal.h> 65038ec830SDag-Erling Smørgrav #include <stdarg.h> 66f2559616SJung-uk Kim #include <stdint.h> 67ad771aa1SSøren Schmidt #include <stdio.h> 68ad771aa1SSøren Schmidt #include <stdlib.h> 69ad771aa1SSøren Schmidt #include <string.h> 705f436cfbSKazutaka YOKOTA #include <syslog.h> 71038ec830SDag-Erling Smørgrav #include <termios.h> 7220a2630bSSøren Schmidt #include <unistd.h> 7386b3ea36SPhilip Paeps #include <math.h> 74ad771aa1SSøren Schmidt 755f436cfbSKazutaka YOKOTA #define MAX_CLICKTHRESHOLD 2000 /* 2 seconds */ 7644bdcfa6SKazutaka YOKOTA #define MAX_BUTTON2TIMEOUT 2000 /* 2 seconds */ 7744bdcfa6SKazutaka YOKOTA #define DFLT_CLICKTHRESHOLD 500 /* 0.5 second */ 789c9d9993SKazutaka YOKOTA #define DFLT_BUTTON2TIMEOUT 100 /* 0.1 second */ 792a669c47SPhilip Paeps #define DFLT_SCROLLTHRESHOLD 3 /* 3 pixels */ 803e95467cSPhilip Paeps #define DFLT_SCROLLSPEED 2 /* 2 pixels */ 815f436cfbSKazutaka YOKOTA 8270ccc8d8SIan Dowse /* Abort 3-button emulation delay after this many movement events. */ 8370ccc8d8SIan Dowse #define BUTTON2_MAXMOVE 3 8470ccc8d8SIan Dowse 855f436cfbSKazutaka YOKOTA #define TRUE 1 865f436cfbSKazutaka YOKOTA #define FALSE 0 875f436cfbSKazutaka YOKOTA 885f436cfbSKazutaka YOKOTA #define MOUSE_XAXIS (-1) 895f436cfbSKazutaka YOKOTA #define MOUSE_YAXIS (-2) 905f436cfbSKazutaka YOKOTA 9101533d85SKazutaka YOKOTA /* Logitech PS2++ protocol */ 9201533d85SKazutaka YOKOTA #define MOUSE_PS2PLUS_CHECKBITS(b) \ 9301533d85SKazutaka YOKOTA ((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f)) 9401533d85SKazutaka YOKOTA #define MOUSE_PS2PLUS_PACKET_TYPE(b) \ 9501533d85SKazutaka YOKOTA (((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4)) 9601533d85SKazutaka YOKOTA 975f436cfbSKazutaka YOKOTA #define ChordMiddle 0x0001 985f436cfbSKazutaka YOKOTA #define Emulate3Button 0x0002 995f436cfbSKazutaka YOKOTA #define ClearDTR 0x0004 1005f436cfbSKazutaka YOKOTA #define ClearRTS 0x0008 1015f436cfbSKazutaka YOKOTA #define NoPnP 0x0010 1022a669c47SPhilip Paeps #define VirtualScroll 0x0020 1032c9b9132SPhilip Paeps #define HVirtualScroll 0x0040 10486b3ea36SPhilip Paeps #define ExponentialAcc 0x0080 1055f436cfbSKazutaka YOKOTA 1065f436cfbSKazutaka YOKOTA #define ID_NONE 0 1075f436cfbSKazutaka YOKOTA #define ID_PORT 1 1085f436cfbSKazutaka YOKOTA #define ID_IF 2 1095f436cfbSKazutaka YOKOTA #define ID_TYPE 4 1105f436cfbSKazutaka YOKOTA #define ID_MODEL 8 1115f436cfbSKazutaka YOKOTA #define ID_ALL (ID_PORT | ID_IF | ID_TYPE | ID_MODEL) 1125f436cfbSKazutaka YOKOTA 11313f1c59bSJung-uk Kim /* Operations on timespecs */ 11413f1c59bSJung-uk Kim #define tsclr(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0) 11513f1c59bSJung-uk Kim #define tscmp(tvp, uvp, cmp) \ 11613f1c59bSJung-uk Kim (((tvp)->tv_sec == (uvp)->tv_sec) ? \ 11713f1c59bSJung-uk Kim ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \ 11813f1c59bSJung-uk Kim ((tvp)->tv_sec cmp (uvp)->tv_sec)) 11913f1c59bSJung-uk Kim #define tssub(tvp, uvp, vvp) \ 12013f1c59bSJung-uk Kim do { \ 12113f1c59bSJung-uk Kim (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ 12213f1c59bSJung-uk Kim (vvp)->tv_nsec = (tvp)->tv_nsec - (uvp)->tv_nsec; \ 12313f1c59bSJung-uk Kim if ((vvp)->tv_nsec < 0) { \ 12413f1c59bSJung-uk Kim (vvp)->tv_sec--; \ 12513f1c59bSJung-uk Kim (vvp)->tv_nsec += 1000000000; \ 12613f1c59bSJung-uk Kim } \ 12713f1c59bSJung-uk Kim } while (0) 12813f1c59bSJung-uk Kim 129a68654e6SStefan Farfeleder #define debug(...) do { \ 13062e621e8SIan Dowse if (debug && nodaemon) \ 131a68654e6SStefan Farfeleder warnx(__VA_ARGS__); \ 13262e621e8SIan Dowse } while (0) 13362e621e8SIan Dowse 134a68654e6SStefan Farfeleder #define logerr(e, ...) do { \ 135a68654e6SStefan Farfeleder log_or_warn(LOG_DAEMON | LOG_ERR, errno, __VA_ARGS__); \ 13662e621e8SIan Dowse exit(e); \ 13762e621e8SIan Dowse } while (0) 13862e621e8SIan Dowse 139a68654e6SStefan Farfeleder #define logerrx(e, ...) do { \ 140a68654e6SStefan Farfeleder log_or_warn(LOG_DAEMON | LOG_ERR, 0, __VA_ARGS__); \ 14162e621e8SIan Dowse exit(e); \ 14262e621e8SIan Dowse } while (0) 14362e621e8SIan Dowse 144a68654e6SStefan Farfeleder #define logwarn(...) \ 145a68654e6SStefan Farfeleder log_or_warn(LOG_DAEMON | LOG_WARNING, errno, __VA_ARGS__) 14662e621e8SIan Dowse 147a68654e6SStefan Farfeleder #define logwarnx(...) \ 148a68654e6SStefan Farfeleder log_or_warn(LOG_DAEMON | LOG_WARNING, 0, __VA_ARGS__) 1495f436cfbSKazutaka YOKOTA 1505f436cfbSKazutaka YOKOTA /* structures */ 1515f436cfbSKazutaka YOKOTA 1525f436cfbSKazutaka YOKOTA /* symbol table entry */ 1535f436cfbSKazutaka YOKOTA typedef struct { 1542657f6e9SJung-uk Kim const char *name; 1555f436cfbSKazutaka YOKOTA int val; 1565f436cfbSKazutaka YOKOTA int val2; 1575f436cfbSKazutaka YOKOTA } symtab_t; 1585f436cfbSKazutaka YOKOTA 1595f436cfbSKazutaka YOKOTA /* serial PnP ID string */ 1605f436cfbSKazutaka YOKOTA typedef struct { 1615f436cfbSKazutaka YOKOTA int revision; /* PnP revision, 100 for 1.00 */ 1622657f6e9SJung-uk Kim const char *eisaid; /* EISA ID including mfr ID and product ID */ 1635f436cfbSKazutaka YOKOTA char *serial; /* serial No, optional */ 1642657f6e9SJung-uk Kim const char *class; /* device class, optional */ 1655f436cfbSKazutaka YOKOTA char *compat; /* list of compatible drivers, optional */ 1665f436cfbSKazutaka YOKOTA char *description; /* product description, optional */ 1675f436cfbSKazutaka YOKOTA int neisaid; /* length of the above fields... */ 1685f436cfbSKazutaka YOKOTA int nserial; 1695f436cfbSKazutaka YOKOTA int nclass; 1705f436cfbSKazutaka YOKOTA int ncompat; 1715f436cfbSKazutaka YOKOTA int ndescription; 1725f436cfbSKazutaka YOKOTA } pnpid_t; 1735f436cfbSKazutaka YOKOTA 1745f436cfbSKazutaka YOKOTA /* global variables */ 1755f436cfbSKazutaka YOKOTA 1767a106fe4SEd Schouten static int debug = 0; 1777a106fe4SEd Schouten static int nodaemon = FALSE; 1787a106fe4SEd Schouten static int background = FALSE; 1797a106fe4SEd Schouten static int paused = FALSE; 1807a106fe4SEd Schouten static int identify = ID_NONE; 1817a106fe4SEd Schouten static int extioctl = FALSE; 1827a106fe4SEd Schouten static const char *pidfile = "/var/run/moused.pid"; 1837a106fe4SEd Schouten static struct pidfh *pfh; 184ad771aa1SSøren Schmidt 1852a669c47SPhilip Paeps #define SCROLL_NOTSCROLLING 0 1862a669c47SPhilip Paeps #define SCROLL_PREPARE 1 1872a669c47SPhilip Paeps #define SCROLL_SCROLLING 2 1882a669c47SPhilip Paeps 1892a669c47SPhilip Paeps static int scroll_state; 1902a669c47SPhilip Paeps static int scroll_movement; 1912c9b9132SPhilip Paeps static int hscroll_movement; 1922a669c47SPhilip Paeps 1935f436cfbSKazutaka YOKOTA /* local variables */ 194ad771aa1SSøren Schmidt 1955f436cfbSKazutaka YOKOTA /* interface (the table must be ordered by MOUSE_IF_XXX in mouse.h) */ 1965f436cfbSKazutaka YOKOTA static symtab_t rifs[] = { 1972657f6e9SJung-uk Kim { "serial", MOUSE_IF_SERIAL, 0 }, 1982657f6e9SJung-uk Kim { "ps/2", MOUSE_IF_PS2, 0 }, 1992657f6e9SJung-uk Kim { "sysmouse", MOUSE_IF_SYSMOUSE, 0 }, 2002657f6e9SJung-uk Kim { "usb", MOUSE_IF_USB, 0 }, 2012657f6e9SJung-uk Kim { NULL, MOUSE_IF_UNKNOWN, 0 }, 2025f436cfbSKazutaka YOKOTA }; 203ad771aa1SSøren Schmidt 2045f436cfbSKazutaka YOKOTA /* types (the table must be ordered by MOUSE_PROTO_XXX in mouse.h) */ 2052657f6e9SJung-uk Kim static const char *rnames[] = { 206ad771aa1SSøren Schmidt "microsoft", 207ad771aa1SSøren Schmidt "mousesystems", 208ad771aa1SSøren Schmidt "logitech", 2095f436cfbSKazutaka YOKOTA "mmseries", 210ad771aa1SSøren Schmidt "mouseman", 211c1cdf6a4SWarner Losh "wasbusmouse", 212c1cdf6a4SWarner Losh "wasinportmouse", 213ad771aa1SSøren Schmidt "ps/2", 21413379e47SPeter Wemm "mmhitab", 2155f436cfbSKazutaka YOKOTA "glidepoint", 2165f436cfbSKazutaka YOKOTA "intellimouse", 2175f436cfbSKazutaka YOKOTA "thinkingmouse", 2185f436cfbSKazutaka YOKOTA "sysmouse", 21967978692SAmancio Hasty "x10mouseremote", 2201b11ca6cSKazutaka YOKOTA "kidspad", 22105f92020SWill Andrews "versapad", 22205f92020SWill Andrews "jogdial", 2235f436cfbSKazutaka YOKOTA #if notyet 2245f436cfbSKazutaka YOKOTA "mariqua", 2255f436cfbSKazutaka YOKOTA #endif 226ce99e877SMatthew N. Dodd "gtco_digipad", 227ad771aa1SSøren Schmidt NULL 228ad771aa1SSøren Schmidt }; 229ad771aa1SSøren Schmidt 2305f436cfbSKazutaka YOKOTA /* models */ 2315f436cfbSKazutaka YOKOTA static symtab_t rmodels[] = { 2322657f6e9SJung-uk Kim { "NetScroll", MOUSE_MODEL_NETSCROLL, 0 }, 2332657f6e9SJung-uk Kim { "NetMouse/NetScroll Optical", MOUSE_MODEL_NET, 0 }, 2342657f6e9SJung-uk Kim { "GlidePoint", MOUSE_MODEL_GLIDEPOINT, 0 }, 2352657f6e9SJung-uk Kim { "ThinkingMouse", MOUSE_MODEL_THINK, 0 }, 2362657f6e9SJung-uk Kim { "IntelliMouse", MOUSE_MODEL_INTELLI, 0 }, 2372657f6e9SJung-uk Kim { "EasyScroll/SmartScroll", MOUSE_MODEL_EASYSCROLL, 0 }, 2382657f6e9SJung-uk Kim { "MouseMan+", MOUSE_MODEL_MOUSEMANPLUS, 0 }, 2392657f6e9SJung-uk Kim { "Kidspad", MOUSE_MODEL_KIDSPAD, 0 }, 2402657f6e9SJung-uk Kim { "VersaPad", MOUSE_MODEL_VERSAPAD, 0 }, 2412657f6e9SJung-uk Kim { "IntelliMouse Explorer", MOUSE_MODEL_EXPLORER, 0 }, 2422657f6e9SJung-uk Kim { "4D Mouse", MOUSE_MODEL_4D, 0 }, 2432657f6e9SJung-uk Kim { "4D+ Mouse", MOUSE_MODEL_4DPLUS, 0 }, 2442657f6e9SJung-uk Kim { "Synaptics Touchpad", MOUSE_MODEL_SYNAPTICS, 0 }, 245569d8f7eSJung-uk Kim { "TrackPoint", MOUSE_MODEL_TRACKPOINT, 0 }, 2464f57f07eSOleksandr Tymoshenko { "Elantech Touchpad", MOUSE_MODEL_ELANTECH, 0 }, 2472657f6e9SJung-uk Kim { "generic", MOUSE_MODEL_GENERIC, 0 }, 2482657f6e9SJung-uk Kim { NULL, MOUSE_MODEL_UNKNOWN, 0 }, 249ad771aa1SSøren Schmidt }; 250ad771aa1SSøren Schmidt 2515f436cfbSKazutaka YOKOTA /* PnP EISA/product IDs */ 2525f436cfbSKazutaka YOKOTA static symtab_t pnpprod[] = { 2535f436cfbSKazutaka YOKOTA /* Kensignton ThinkingMouse */ 2545f436cfbSKazutaka YOKOTA { "KML0001", MOUSE_PROTO_THINK, MOUSE_MODEL_THINK }, 2555f436cfbSKazutaka YOKOTA /* MS IntelliMouse */ 2565f436cfbSKazutaka YOKOTA { "MSH0001", MOUSE_PROTO_INTELLI, MOUSE_MODEL_INTELLI }, 2575f436cfbSKazutaka YOKOTA /* MS IntelliMouse TrackBall */ 2585f436cfbSKazutaka YOKOTA { "MSH0004", MOUSE_PROTO_INTELLI, MOUSE_MODEL_INTELLI }, 2596555de48SAndrey A. Chernov /* Tremon Wheel Mouse MUSD */ 2606555de48SAndrey A. Chernov { "HTK0001", MOUSE_PROTO_INTELLI, MOUSE_MODEL_INTELLI }, 2614b6860cfSAndrey A. Chernov /* Genius PnP Mouse */ 2624b6860cfSAndrey A. Chernov { "KYE0001", MOUSE_PROTO_MS, MOUSE_MODEL_GENERIC }, 26317441011SKazutaka YOKOTA /* MouseSystems SmartScroll Mouse (OEM from Genius?) */ 26417441011SKazutaka YOKOTA { "KYE0002", MOUSE_PROTO_MS, MOUSE_MODEL_EASYSCROLL }, 2655f436cfbSKazutaka YOKOTA /* Genius NetMouse */ 2665f436cfbSKazutaka YOKOTA { "KYE0003", MOUSE_PROTO_INTELLI, MOUSE_MODEL_NET }, 2671b11ca6cSKazutaka YOKOTA /* Genius Kidspad, Easypad and other tablets */ 2681b11ca6cSKazutaka YOKOTA { "KYE0005", MOUSE_PROTO_KIDSPAD, MOUSE_MODEL_KIDSPAD }, 2694b6860cfSAndrey A. Chernov /* Genius EZScroll */ 2704b6860cfSAndrey A. Chernov { "KYEEZ00", MOUSE_PROTO_MS, MOUSE_MODEL_EASYSCROLL }, 27127d63c19SKazutaka YOKOTA /* Logitech Cordless MouseMan Wheel */ 27227d63c19SKazutaka YOKOTA { "LGI8033", MOUSE_PROTO_INTELLI, MOUSE_MODEL_MOUSEMANPLUS }, 27330ee7535SKazutaka YOKOTA /* Logitech MouseMan (new 4 button model) */ 27430ee7535SKazutaka YOKOTA { "LGI800C", MOUSE_PROTO_INTELLI, MOUSE_MODEL_MOUSEMANPLUS }, 2755f436cfbSKazutaka YOKOTA /* Logitech MouseMan+ */ 2765f436cfbSKazutaka YOKOTA { "LGI8050", MOUSE_PROTO_INTELLI, MOUSE_MODEL_MOUSEMANPLUS }, 2775f436cfbSKazutaka YOKOTA /* Logitech FirstMouse+ */ 2785f436cfbSKazutaka YOKOTA { "LGI8051", MOUSE_PROTO_INTELLI, MOUSE_MODEL_MOUSEMANPLUS }, 279f17c0039SKazutaka YOKOTA /* Logitech serial */ 280f17c0039SKazutaka YOKOTA { "LGI8001", MOUSE_PROTO_LOGIMOUSEMAN, MOUSE_MODEL_GENERIC }, 281fb966343SKazutaka YOKOTA /* A4 Tech 4D/4D+ Mouse */ 282fb966343SKazutaka YOKOTA { "A4W0005", MOUSE_PROTO_INTELLI, MOUSE_MODEL_4D }, 283fb966343SKazutaka YOKOTA /* 8D Scroll Mouse */ 284fb966343SKazutaka YOKOTA { "PEC9802", MOUSE_PROTO_INTELLI, MOUSE_MODEL_INTELLI }, 285d65ffe4aSKazutaka YOKOTA /* Mitsumi Wireless Scroll Mouse */ 286d65ffe4aSKazutaka YOKOTA { "MTM6401", MOUSE_PROTO_INTELLI, MOUSE_MODEL_INTELLI }, 287ad771aa1SSøren Schmidt 2885f436cfbSKazutaka YOKOTA /* MS serial */ 2895f436cfbSKazutaka YOKOTA { "PNP0F01", MOUSE_PROTO_MS, MOUSE_MODEL_GENERIC }, 2905f436cfbSKazutaka YOKOTA /* MS PS/2 */ 2915f436cfbSKazutaka YOKOTA { "PNP0F03", MOUSE_PROTO_PS2, MOUSE_MODEL_GENERIC }, 2925f436cfbSKazutaka YOKOTA /* 2935f436cfbSKazutaka YOKOTA * EzScroll returns PNP0F04 in the compatible device field; but it 2945f436cfbSKazutaka YOKOTA * doesn't look compatible... XXX 2955f436cfbSKazutaka YOKOTA */ 2965f436cfbSKazutaka YOKOTA /* MouseSystems */ 2975f436cfbSKazutaka YOKOTA { "PNP0F04", MOUSE_PROTO_MSC, MOUSE_MODEL_GENERIC }, 2985f436cfbSKazutaka YOKOTA /* MouseSystems */ 2995f436cfbSKazutaka YOKOTA { "PNP0F05", MOUSE_PROTO_MSC, MOUSE_MODEL_GENERIC }, 3005f436cfbSKazutaka YOKOTA #if notyet 3015f436cfbSKazutaka YOKOTA /* Genius Mouse */ 302b2183f97SDag-Erling Smørgrav { "PNP0F06", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3035f436cfbSKazutaka YOKOTA /* Genius Mouse */ 304b2183f97SDag-Erling Smørgrav { "PNP0F07", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3055f436cfbSKazutaka YOKOTA #endif 3065f436cfbSKazutaka YOKOTA /* Logitech serial */ 3075f436cfbSKazutaka YOKOTA { "PNP0F08", MOUSE_PROTO_LOGIMOUSEMAN, MOUSE_MODEL_GENERIC }, 3085f436cfbSKazutaka YOKOTA /* MS BallPoint serial */ 3095f436cfbSKazutaka YOKOTA { "PNP0F09", MOUSE_PROTO_MS, MOUSE_MODEL_GENERIC }, 3105f436cfbSKazutaka YOKOTA /* MS PnP serial */ 3115f436cfbSKazutaka YOKOTA { "PNP0F0A", MOUSE_PROTO_MS, MOUSE_MODEL_GENERIC }, 3125f436cfbSKazutaka YOKOTA /* MS PnP BallPoint serial */ 3135f436cfbSKazutaka YOKOTA { "PNP0F0B", MOUSE_PROTO_MS, MOUSE_MODEL_GENERIC }, 31464b3bcc6SGordon Bergling /* MS serial compatible */ 3155f436cfbSKazutaka YOKOTA { "PNP0F0C", MOUSE_PROTO_MS, MOUSE_MODEL_GENERIC }, 31664b3bcc6SGordon Bergling /* MS PS/2 compatible */ 3175f436cfbSKazutaka YOKOTA { "PNP0F0E", MOUSE_PROTO_PS2, MOUSE_MODEL_GENERIC }, 31864b3bcc6SGordon Bergling /* MS BallPoint compatible */ 3195f436cfbSKazutaka YOKOTA { "PNP0F0F", MOUSE_PROTO_MS, MOUSE_MODEL_GENERIC }, 3205f436cfbSKazutaka YOKOTA #if notyet 3215f436cfbSKazutaka YOKOTA /* TI QuickPort */ 322b2183f97SDag-Erling Smørgrav { "PNP0F10", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3235f436cfbSKazutaka YOKOTA #endif 3245f436cfbSKazutaka YOKOTA /* Logitech PS/2 */ 3255f436cfbSKazutaka YOKOTA { "PNP0F12", MOUSE_PROTO_PS2, MOUSE_MODEL_GENERIC }, 3265f436cfbSKazutaka YOKOTA /* PS/2 */ 3275f436cfbSKazutaka YOKOTA { "PNP0F13", MOUSE_PROTO_PS2, MOUSE_MODEL_GENERIC }, 3285f436cfbSKazutaka YOKOTA #if notyet 3295f436cfbSKazutaka YOKOTA /* MS Kids Mouse */ 330b2183f97SDag-Erling Smørgrav { "PNP0F14", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3315f436cfbSKazutaka YOKOTA #endif 3325f436cfbSKazutaka YOKOTA #if notyet 3335f436cfbSKazutaka YOKOTA /* Logitech SWIFT */ 334b2183f97SDag-Erling Smørgrav { "PNP0F16", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3355f436cfbSKazutaka YOKOTA #endif 3365f436cfbSKazutaka YOKOTA /* Logitech serial compat */ 3375f436cfbSKazutaka YOKOTA { "PNP0F17", MOUSE_PROTO_LOGIMOUSEMAN, MOUSE_MODEL_GENERIC }, 3385f436cfbSKazutaka YOKOTA /* Logitech PS/2 compatible */ 3395f436cfbSKazutaka YOKOTA { "PNP0F19", MOUSE_PROTO_PS2, MOUSE_MODEL_GENERIC }, 3405f436cfbSKazutaka YOKOTA #if notyet 3415f436cfbSKazutaka YOKOTA /* Logitech SWIFT compatible */ 342b2183f97SDag-Erling Smørgrav { "PNP0F1A", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3435f436cfbSKazutaka YOKOTA /* HP Omnibook */ 344b2183f97SDag-Erling Smørgrav { "PNP0F1B", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3455f436cfbSKazutaka YOKOTA /* Compaq LTE TrackBall PS/2 */ 346b2183f97SDag-Erling Smørgrav { "PNP0F1C", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3475f436cfbSKazutaka YOKOTA /* Compaq LTE TrackBall serial */ 348b2183f97SDag-Erling Smørgrav { "PNP0F1D", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3495f436cfbSKazutaka YOKOTA /* MS Kidts Trackball */ 350b2183f97SDag-Erling Smørgrav { "PNP0F1E", MOUSE_PROTO_XXX, MOUSE_MODEL_GENERIC }, 3515f436cfbSKazutaka YOKOTA #endif 3522e09fb67SKazutaka YOKOTA /* Interlink VersaPad */ 3532e09fb67SKazutaka YOKOTA { "LNK0001", MOUSE_PROTO_VERSAPAD, MOUSE_MODEL_VERSAPAD }, 3545f436cfbSKazutaka YOKOTA 3555f436cfbSKazutaka YOKOTA { NULL, MOUSE_PROTO_UNKNOWN, MOUSE_MODEL_GENERIC }, 3565f436cfbSKazutaka YOKOTA }; 3575f436cfbSKazutaka YOKOTA 3585f436cfbSKazutaka YOKOTA /* the table must be ordered by MOUSE_PROTO_XXX in mouse.h */ 3595f436cfbSKazutaka YOKOTA static unsigned short rodentcflags[] = 360ad771aa1SSøren Schmidt { 3615f436cfbSKazutaka YOKOTA (CS7 | CREAD | CLOCAL | HUPCL), /* MicroSoft */ 3625f436cfbSKazutaka YOKOTA (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL), /* MouseSystems */ 3635f436cfbSKazutaka YOKOTA (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL), /* Logitech */ 3645f436cfbSKazutaka YOKOTA (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL), /* MMSeries */ 3655f436cfbSKazutaka YOKOTA (CS7 | CREAD | CLOCAL | HUPCL), /* MouseMan */ 3665f436cfbSKazutaka YOKOTA 0, /* Bus */ 3675f436cfbSKazutaka YOKOTA 0, /* InPort */ 3685f436cfbSKazutaka YOKOTA 0, /* PS/2 */ 3695f436cfbSKazutaka YOKOTA (CS8 | CREAD | CLOCAL | HUPCL), /* MM HitTablet */ 3705f436cfbSKazutaka YOKOTA (CS7 | CREAD | CLOCAL | HUPCL), /* GlidePoint */ 3715f436cfbSKazutaka YOKOTA (CS7 | CREAD | CLOCAL | HUPCL), /* IntelliMouse */ 3725f436cfbSKazutaka YOKOTA (CS7 | CREAD | CLOCAL | HUPCL), /* Thinking Mouse */ 3735d6618faSKazutaka YOKOTA (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL), /* sysmouse */ 37467978692SAmancio Hasty (CS7 | CREAD | CLOCAL | HUPCL), /* X10 MouseRemote */ 3751b11ca6cSKazutaka YOKOTA (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL), /* kidspad etc. */ 3762e09fb67SKazutaka YOKOTA (CS8 | CREAD | CLOCAL | HUPCL), /* VersaPad */ 37705f92020SWill Andrews 0, /* JogDial */ 3785f436cfbSKazutaka YOKOTA #if notyet 3795f436cfbSKazutaka YOKOTA (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL), /* Mariqua */ 3805f436cfbSKazutaka YOKOTA #endif 381ce99e877SMatthew N. Dodd (CS8 | CREAD | HUPCL ), /* GTCO Digi-Pad */ 3825f436cfbSKazutaka YOKOTA }; 383ad771aa1SSøren Schmidt 3845f436cfbSKazutaka YOKOTA static struct rodentparam { 3855f436cfbSKazutaka YOKOTA int flags; 3862657f6e9SJung-uk Kim const char *portname; /* /dev/XXX */ 3875f436cfbSKazutaka YOKOTA int rtype; /* MOUSE_PROTO_XXX */ 3885f436cfbSKazutaka YOKOTA int level; /* operation level: 0 or greater */ 3895f436cfbSKazutaka YOKOTA int baudrate; 3905f436cfbSKazutaka YOKOTA int rate; /* report rate */ 3915f436cfbSKazutaka YOKOTA int resolution; /* MOUSE_RES_XXX or a positive number */ 392fb966343SKazutaka YOKOTA int zmap[4]; /* MOUSE_{X|Y}AXIS or a button number */ 3939fb1d70cSKazutaka YOKOTA int wmode; /* wheel mode button number */ 3945f436cfbSKazutaka YOKOTA int mfd; /* mouse file descriptor */ 3955f436cfbSKazutaka YOKOTA int cfd; /* /dev/consolectl file descriptor */ 39667978692SAmancio Hasty int mremsfd; /* mouse remote server file descriptor */ 39767978692SAmancio Hasty int mremcfd; /* mouse remote client file descriptor */ 39808f950a3SHans Petter Selasky int is_removable; /* set if device is removable, like USB */ 3995f436cfbSKazutaka YOKOTA long clickthreshold; /* double click speed in msec */ 40044bdcfa6SKazutaka YOKOTA long button2timeout; /* 3 button emulation timeout */ 4015f436cfbSKazutaka YOKOTA mousehw_t hw; /* mouse device hardware information */ 4025f436cfbSKazutaka YOKOTA mousemode_t mode; /* protocol information */ 403efe4cd6aSGeorge C A Reid float accelx; /* Acceleration in the X axis */ 404efe4cd6aSGeorge C A Reid float accely; /* Acceleration in the Y axis */ 40586b3ea36SPhilip Paeps float expoaccel; /* Exponential acceleration */ 40686b3ea36SPhilip Paeps float expoffset; /* Movement offset for exponential accel. */ 407d9338247SPhilip Paeps float remainx; /* Remainder on X and Y axis, respectively... */ 408d9338247SPhilip Paeps float remainy; /* ... to compensate for rounding errors. */ 4092a669c47SPhilip Paeps int scrollthreshold; /* Movement distance before virtual scrolling */ 4103e95467cSPhilip Paeps int scrollspeed; /* Movement distance to rate of scrolling */ 4115f436cfbSKazutaka YOKOTA } rodent = { 412358f61ceSStefan Farfeleder .flags = 0, 413358f61ceSStefan Farfeleder .portname = NULL, 414358f61ceSStefan Farfeleder .rtype = MOUSE_PROTO_UNKNOWN, 415358f61ceSStefan Farfeleder .level = -1, 416358f61ceSStefan Farfeleder .baudrate = 1200, 417358f61ceSStefan Farfeleder .rate = 0, 418358f61ceSStefan Farfeleder .resolution = MOUSE_RES_UNKNOWN, 419358f61ceSStefan Farfeleder .zmap = { 0, 0, 0, 0 }, 420358f61ceSStefan Farfeleder .wmode = 0, 421358f61ceSStefan Farfeleder .mfd = -1, 422358f61ceSStefan Farfeleder .cfd = -1, 423358f61ceSStefan Farfeleder .mremsfd = -1, 424358f61ceSStefan Farfeleder .mremcfd = -1, 42508f950a3SHans Petter Selasky .is_removable = 0, 426358f61ceSStefan Farfeleder .clickthreshold = DFLT_CLICKTHRESHOLD, 427358f61ceSStefan Farfeleder .button2timeout = DFLT_BUTTON2TIMEOUT, 428358f61ceSStefan Farfeleder .accelx = 1.0, 429358f61ceSStefan Farfeleder .accely = 1.0, 43086b3ea36SPhilip Paeps .expoaccel = 1.0, 43186b3ea36SPhilip Paeps .expoffset = 1.0, 432d9338247SPhilip Paeps .remainx = 0.0, 433d9338247SPhilip Paeps .remainy = 0.0, 4342a669c47SPhilip Paeps .scrollthreshold = DFLT_SCROLLTHRESHOLD, 4353e95467cSPhilip Paeps .scrollspeed = DFLT_SCROLLSPEED, 4365f436cfbSKazutaka YOKOTA }; 437ad771aa1SSøren Schmidt 4385f436cfbSKazutaka YOKOTA /* button status */ 43944bdcfa6SKazutaka YOKOTA struct button_state { 4405f436cfbSKazutaka YOKOTA int count; /* 0: up, 1: single click, 2: double click,... */ 44113f1c59bSJung-uk Kim struct timespec ts; /* timestamp on the last button event */ 44244bdcfa6SKazutaka YOKOTA }; 44344bdcfa6SKazutaka YOKOTA static struct button_state bstate[MOUSE_MAXBUTTON]; /* button state */ 44444bdcfa6SKazutaka YOKOTA static struct button_state *mstate[MOUSE_MAXBUTTON];/* mapped button st.*/ 44544bdcfa6SKazutaka YOKOTA static struct button_state zstate[4]; /* Z/W axis state */ 44644bdcfa6SKazutaka YOKOTA 44744bdcfa6SKazutaka YOKOTA /* state machine for 3 button emulation */ 44844bdcfa6SKazutaka YOKOTA 44944bdcfa6SKazutaka YOKOTA #define S0 0 /* start */ 45044bdcfa6SKazutaka YOKOTA #define S1 1 /* button 1 delayed down */ 45144bdcfa6SKazutaka YOKOTA #define S2 2 /* button 3 delayed down */ 45244bdcfa6SKazutaka YOKOTA #define S3 3 /* both buttons down -> button 2 down */ 45344bdcfa6SKazutaka YOKOTA #define S4 4 /* button 1 delayed up */ 45444bdcfa6SKazutaka YOKOTA #define S5 5 /* button 1 down */ 45544bdcfa6SKazutaka YOKOTA #define S6 6 /* button 3 down */ 45644bdcfa6SKazutaka YOKOTA #define S7 7 /* both buttons down */ 45744bdcfa6SKazutaka YOKOTA #define S8 8 /* button 3 delayed up */ 45844bdcfa6SKazutaka YOKOTA #define S9 9 /* button 1 or 3 up after S3 */ 45944bdcfa6SKazutaka YOKOTA 46044bdcfa6SKazutaka YOKOTA #define A(b1, b3) (((b1) ? 2 : 0) | ((b3) ? 1 : 0)) 46144bdcfa6SKazutaka YOKOTA #define A_TIMEOUT 4 46270ccc8d8SIan Dowse #define S_DELAYED(st) (states[st].s[A_TIMEOUT] != (st)) 46344bdcfa6SKazutaka YOKOTA 46444bdcfa6SKazutaka YOKOTA static struct { 46544bdcfa6SKazutaka YOKOTA int s[A_TIMEOUT + 1]; 46644bdcfa6SKazutaka YOKOTA int buttons; 46744bdcfa6SKazutaka YOKOTA int mask; 468127d54baSKazutaka YOKOTA int timeout; 46944bdcfa6SKazutaka YOKOTA } states[10] = { 47044bdcfa6SKazutaka YOKOTA /* S0 */ 471127d54baSKazutaka YOKOTA { { S0, S2, S1, S3, S0 }, 0, ~(MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN), FALSE }, 47244bdcfa6SKazutaka YOKOTA /* S1 */ 473127d54baSKazutaka YOKOTA { { S4, S2, S1, S3, S5 }, 0, ~MOUSE_BUTTON1DOWN, FALSE }, 47444bdcfa6SKazutaka YOKOTA /* S2 */ 475127d54baSKazutaka YOKOTA { { S8, S2, S1, S3, S6 }, 0, ~MOUSE_BUTTON3DOWN, FALSE }, 47644bdcfa6SKazutaka YOKOTA /* S3 */ 477127d54baSKazutaka YOKOTA { { S0, S9, S9, S3, S3 }, MOUSE_BUTTON2DOWN, ~0, FALSE }, 47844bdcfa6SKazutaka YOKOTA /* S4 */ 479127d54baSKazutaka YOKOTA { { S0, S2, S1, S3, S0 }, MOUSE_BUTTON1DOWN, ~0, TRUE }, 48044bdcfa6SKazutaka YOKOTA /* S5 */ 481127d54baSKazutaka YOKOTA { { S0, S2, S5, S7, S5 }, MOUSE_BUTTON1DOWN, ~0, FALSE }, 48244bdcfa6SKazutaka YOKOTA /* S6 */ 483127d54baSKazutaka YOKOTA { { S0, S6, S1, S7, S6 }, MOUSE_BUTTON3DOWN, ~0, FALSE }, 48444bdcfa6SKazutaka YOKOTA /* S7 */ 485127d54baSKazutaka YOKOTA { { S0, S6, S5, S7, S7 }, MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, ~0, FALSE }, 48644bdcfa6SKazutaka YOKOTA /* S8 */ 487127d54baSKazutaka YOKOTA { { S0, S2, S1, S3, S0 }, MOUSE_BUTTON3DOWN, ~0, TRUE }, 48844bdcfa6SKazutaka YOKOTA /* S9 */ 489127d54baSKazutaka YOKOTA { { S0, S9, S9, S3, S9 }, 0, ~(MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN), FALSE }, 49044bdcfa6SKazutaka YOKOTA }; 49144bdcfa6SKazutaka YOKOTA static int mouse_button_state; 49213f1c59bSJung-uk Kim static struct timespec mouse_button_state_ts; 49370ccc8d8SIan Dowse static int mouse_move_delayed; 494ad771aa1SSøren Schmidt 4955f436cfbSKazutaka YOKOTA static jmp_buf env; 4965f436cfbSKazutaka YOKOTA 49713f1c59bSJung-uk Kim struct drift_xy { 49813f1c59bSJung-uk Kim int x; 49913f1c59bSJung-uk Kim int y; 50013f1c59bSJung-uk Kim }; 501d5f2946aSPhilip Paeps static int drift_distance = 4; /* max steps X+Y */ 502d5f2946aSPhilip Paeps static int drift_time = 500; /* in 0.5 sec */ 50313f1c59bSJung-uk Kim static struct timespec drift_time_ts; 50413f1c59bSJung-uk Kim static struct timespec drift_2time_ts; /* 2*drift_time */ 505d5f2946aSPhilip Paeps static int drift_after = 4000; /* 4 sec */ 50613f1c59bSJung-uk Kim static struct timespec drift_after_ts; 507d5f2946aSPhilip Paeps static int drift_terminate = FALSE; 50813f1c59bSJung-uk Kim static struct timespec drift_current_ts; 50913f1c59bSJung-uk Kim static struct timespec drift_tmp; 51013f1c59bSJung-uk Kim static struct timespec drift_last_activity = {0, 0}; 51113f1c59bSJung-uk Kim static struct timespec drift_since = {0, 0}; 51213f1c59bSJung-uk Kim static struct drift_xy drift_last = {0, 0}; /* steps in last drift_time */ 51313f1c59bSJung-uk Kim static struct drift_xy drift_previous = {0, 0}; /* steps in prev. drift_time */ 514d5f2946aSPhilip Paeps 5155f436cfbSKazutaka YOKOTA /* function prototypes */ 5165f436cfbSKazutaka YOKOTA 517d9338247SPhilip Paeps static void linacc(int, int, int*, int*); 51886b3ea36SPhilip Paeps static void expoacc(int, int, int*, int*); 5195f436cfbSKazutaka YOKOTA static void moused(void); 5205f436cfbSKazutaka YOKOTA static void hup(int sig); 52167978692SAmancio Hasty static void cleanup(int sig); 5229eac5bb9SPhilip Paeps static void pause_mouse(int sig); 5235f436cfbSKazutaka YOKOTA static void usage(void); 52462e621e8SIan Dowse static void log_or_warn(int log_pri, int errnum, const char *fmt, ...) 52562e621e8SIan Dowse __printflike(3, 4); 5265f436cfbSKazutaka YOKOTA 5275f436cfbSKazutaka YOKOTA static int r_identify(void); 5282657f6e9SJung-uk Kim static const char *r_if(int type); 5292657f6e9SJung-uk Kim static const char *r_name(int type); 5302657f6e9SJung-uk Kim static const char *r_model(int model); 5315f436cfbSKazutaka YOKOTA static void r_init(void); 5325f436cfbSKazutaka YOKOTA static int r_protocol(u_char b, mousestatus_t *act); 53344bdcfa6SKazutaka YOKOTA static int r_statetrans(mousestatus_t *a1, mousestatus_t *a2, int trans); 5345f436cfbSKazutaka YOKOTA static int r_installmap(char *arg); 5355f436cfbSKazutaka YOKOTA static void r_map(mousestatus_t *act1, mousestatus_t *act2); 53644bdcfa6SKazutaka YOKOTA static void r_timestamp(mousestatus_t *act); 53744bdcfa6SKazutaka YOKOTA static int r_timeout(void); 5385f436cfbSKazutaka YOKOTA static void r_click(mousestatus_t *act); 5395f436cfbSKazutaka YOKOTA static void setmousespeed(int old, int new, unsigned cflag); 5405f436cfbSKazutaka YOKOTA 541f41621f9SKazutaka YOKOTA static int pnpwakeup1(void); 542f41621f9SKazutaka YOKOTA static int pnpwakeup2(void); 5435f436cfbSKazutaka YOKOTA static int pnpgets(char *buf); 5445f436cfbSKazutaka YOKOTA static int pnpparse(pnpid_t *id, char *buf, int len); 5455f436cfbSKazutaka YOKOTA static symtab_t *pnpproto(pnpid_t *id); 5465f436cfbSKazutaka YOKOTA 5472657f6e9SJung-uk Kim static symtab_t *gettoken(symtab_t *tab, const char *s, int len); 5482657f6e9SJung-uk Kim static const char *gettokenname(symtab_t *tab, int val); 549ad771aa1SSøren Schmidt 5502657f6e9SJung-uk Kim static void mremote_serversetup(void); 55167978692SAmancio Hasty static void mremote_clientchg(int add); 55267978692SAmancio Hasty 5531b11ca6cSKazutaka YOKOTA static int kidspad(u_char rxc, mousestatus_t *act); 554ce99e877SMatthew N. Dodd static int gtco_digipad(u_char, mousestatus_t *); 5551b11ca6cSKazutaka YOKOTA 556e46b89dcSPeter Wemm int 557ad771aa1SSøren Schmidt main(int argc, char *argv[]) 558ad771aa1SSøren Schmidt { 5595f436cfbSKazutaka YOKOTA int c; 5605f436cfbSKazutaka YOKOTA int i; 561fb966343SKazutaka YOKOTA int j; 562ad771aa1SSøren Schmidt 56344bdcfa6SKazutaka YOKOTA for (i = 0; i < MOUSE_MAXBUTTON; ++i) 56444bdcfa6SKazutaka YOKOTA mstate[i] = &bstate[i]; 56544bdcfa6SKazutaka YOKOTA 5663e95467cSPhilip Paeps while ((c = getopt(argc, argv, "3A:C:DE:F:HI:L:PRS:T:VU:a:cdfhi:l:m:p:r:st:w:z:")) != -1) 5675f436cfbSKazutaka YOKOTA switch(c) { 5685f436cfbSKazutaka YOKOTA 5695f436cfbSKazutaka YOKOTA case '3': 5705f436cfbSKazutaka YOKOTA rodent.flags |= Emulate3Button; 5715f436cfbSKazutaka YOKOTA break; 5725f436cfbSKazutaka YOKOTA 57344bdcfa6SKazutaka YOKOTA case 'E': 57444bdcfa6SKazutaka YOKOTA rodent.button2timeout = atoi(optarg); 57544bdcfa6SKazutaka YOKOTA if ((rodent.button2timeout < 0) || 57644bdcfa6SKazutaka YOKOTA (rodent.button2timeout > MAX_BUTTON2TIMEOUT)) { 57744bdcfa6SKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 57844bdcfa6SKazutaka YOKOTA usage(); 57944bdcfa6SKazutaka YOKOTA } 58044bdcfa6SKazutaka YOKOTA break; 58144bdcfa6SKazutaka YOKOTA 582efe4cd6aSGeorge C A Reid case 'a': 583efe4cd6aSGeorge C A Reid i = sscanf(optarg, "%f,%f", &rodent.accelx, &rodent.accely); 584efe4cd6aSGeorge C A Reid if (i == 0) { 58586b3ea36SPhilip Paeps warnx("invalid linear acceleration argument '%s'", optarg); 586efe4cd6aSGeorge C A Reid usage(); 587efe4cd6aSGeorge C A Reid } 588efe4cd6aSGeorge C A Reid 589efe4cd6aSGeorge C A Reid if (i == 1) 590efe4cd6aSGeorge C A Reid rodent.accely = rodent.accelx; 591efe4cd6aSGeorge C A Reid 592efe4cd6aSGeorge C A Reid break; 593efe4cd6aSGeorge C A Reid 59486b3ea36SPhilip Paeps case 'A': 59586b3ea36SPhilip Paeps rodent.flags |= ExponentialAcc; 59686b3ea36SPhilip Paeps i = sscanf(optarg, "%f,%f", &rodent.expoaccel, &rodent.expoffset); 59786b3ea36SPhilip Paeps if (i == 0) { 59886b3ea36SPhilip Paeps warnx("invalid exponential acceleration argument '%s'", optarg); 59986b3ea36SPhilip Paeps usage(); 60086b3ea36SPhilip Paeps } 60186b3ea36SPhilip Paeps 60286b3ea36SPhilip Paeps if (i == 1) 60386b3ea36SPhilip Paeps rodent.expoffset = 1.0; 60486b3ea36SPhilip Paeps 60586b3ea36SPhilip Paeps break; 60686b3ea36SPhilip Paeps 607ad771aa1SSøren Schmidt case 'c': 608ad771aa1SSøren Schmidt rodent.flags |= ChordMiddle; 609ad771aa1SSøren Schmidt break; 610ad771aa1SSøren Schmidt 611ad771aa1SSøren Schmidt case 'd': 6125f436cfbSKazutaka YOKOTA ++debug; 613ad771aa1SSøren Schmidt break; 614ad771aa1SSøren Schmidt 615ad771aa1SSøren Schmidt case 'f': 6165f436cfbSKazutaka YOKOTA nodaemon = TRUE; 6175f436cfbSKazutaka YOKOTA break; 6185f436cfbSKazutaka YOKOTA 6195f436cfbSKazutaka YOKOTA case 'i': 6205f436cfbSKazutaka YOKOTA if (strcmp(optarg, "all") == 0) 6215f436cfbSKazutaka YOKOTA identify = ID_ALL; 6225f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "port") == 0) 6235f436cfbSKazutaka YOKOTA identify = ID_PORT; 6245f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "if") == 0) 6255f436cfbSKazutaka YOKOTA identify = ID_IF; 6265f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "type") == 0) 6275f436cfbSKazutaka YOKOTA identify = ID_TYPE; 6285f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "model") == 0) 6295f436cfbSKazutaka YOKOTA identify = ID_MODEL; 6305f436cfbSKazutaka YOKOTA else { 6315f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 6325f436cfbSKazutaka YOKOTA usage(); 6335f436cfbSKazutaka YOKOTA } 6345f436cfbSKazutaka YOKOTA nodaemon = TRUE; 6355f436cfbSKazutaka YOKOTA break; 6365f436cfbSKazutaka YOKOTA 6375f436cfbSKazutaka YOKOTA case 'l': 6385f436cfbSKazutaka YOKOTA rodent.level = atoi(optarg); 6395f436cfbSKazutaka YOKOTA if ((rodent.level < 0) || (rodent.level > 4)) { 6405f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 6415f436cfbSKazutaka YOKOTA usage(); 6425f436cfbSKazutaka YOKOTA } 6435f436cfbSKazutaka YOKOTA break; 6445f436cfbSKazutaka YOKOTA 6455f436cfbSKazutaka YOKOTA case 'm': 6465f436cfbSKazutaka YOKOTA if (!r_installmap(optarg)) { 6475f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 6485f436cfbSKazutaka YOKOTA usage(); 6495f436cfbSKazutaka YOKOTA } 650ad771aa1SSøren Schmidt break; 651ad771aa1SSøren Schmidt 652ad771aa1SSøren Schmidt case 'p': 653ad771aa1SSøren Schmidt rodent.portname = optarg; 654ad771aa1SSøren Schmidt break; 655ad771aa1SSøren Schmidt 65663599332SPeter Wemm case 'r': 6575f436cfbSKazutaka YOKOTA if (strcmp(optarg, "high") == 0) 6585f436cfbSKazutaka YOKOTA rodent.resolution = MOUSE_RES_HIGH; 6595f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "medium-high") == 0) 6605f436cfbSKazutaka YOKOTA rodent.resolution = MOUSE_RES_HIGH; 6615f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "medium-low") == 0) 6625f436cfbSKazutaka YOKOTA rodent.resolution = MOUSE_RES_MEDIUMLOW; 6635f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "low") == 0) 6645f436cfbSKazutaka YOKOTA rodent.resolution = MOUSE_RES_LOW; 6655f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "default") == 0) 6665f436cfbSKazutaka YOKOTA rodent.resolution = MOUSE_RES_DEFAULT; 6675f436cfbSKazutaka YOKOTA else { 6685f436cfbSKazutaka YOKOTA rodent.resolution = atoi(optarg); 6695f436cfbSKazutaka YOKOTA if (rodent.resolution <= 0) { 6705f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 6715f436cfbSKazutaka YOKOTA usage(); 6725f436cfbSKazutaka YOKOTA } 6735f436cfbSKazutaka YOKOTA } 67463599332SPeter Wemm break; 67563599332SPeter Wemm 676ad771aa1SSøren Schmidt case 's': 677ad771aa1SSøren Schmidt rodent.baudrate = 9600; 67813379e47SPeter Wemm break; 67913379e47SPeter Wemm 6809fb1d70cSKazutaka YOKOTA case 'w': 6819fb1d70cSKazutaka YOKOTA i = atoi(optarg); 6829fb1d70cSKazutaka YOKOTA if ((i <= 0) || (i > MOUSE_MAXBUTTON)) { 6839fb1d70cSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 6849fb1d70cSKazutaka YOKOTA usage(); 6859fb1d70cSKazutaka YOKOTA } 6869fb1d70cSKazutaka YOKOTA rodent.wmode = 1 << (i - 1); 6879fb1d70cSKazutaka YOKOTA break; 6889fb1d70cSKazutaka YOKOTA 6895f436cfbSKazutaka YOKOTA case 'z': 6905f436cfbSKazutaka YOKOTA if (strcmp(optarg, "x") == 0) 691fb966343SKazutaka YOKOTA rodent.zmap[0] = MOUSE_XAXIS; 6925f436cfbSKazutaka YOKOTA else if (strcmp(optarg, "y") == 0) 693fb966343SKazutaka YOKOTA rodent.zmap[0] = MOUSE_YAXIS; 6945f436cfbSKazutaka YOKOTA else { 6955f436cfbSKazutaka YOKOTA i = atoi(optarg); 6965f436cfbSKazutaka YOKOTA /* 6975f436cfbSKazutaka YOKOTA * Use button i for negative Z axis movement and 6985f436cfbSKazutaka YOKOTA * button (i + 1) for positive Z axis movement. 6995f436cfbSKazutaka YOKOTA */ 7005f436cfbSKazutaka YOKOTA if ((i <= 0) || (i > MOUSE_MAXBUTTON - 1)) { 7015f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 7025f436cfbSKazutaka YOKOTA usage(); 7035f436cfbSKazutaka YOKOTA } 70444bdcfa6SKazutaka YOKOTA rodent.zmap[0] = i; 70544bdcfa6SKazutaka YOKOTA rodent.zmap[1] = i + 1; 7064e008b7fSKazutaka YOKOTA debug("optind: %d, optarg: '%s'", optind, optarg); 707fb966343SKazutaka YOKOTA for (j = 1; j < 4; ++j) { 708fb966343SKazutaka YOKOTA if ((optind >= argc) || !isdigit(*argv[optind])) 709fb966343SKazutaka YOKOTA break; 710fb966343SKazutaka YOKOTA i = atoi(argv[optind]); 711fb966343SKazutaka YOKOTA if ((i <= 0) || (i > MOUSE_MAXBUTTON - 1)) { 712fb966343SKazutaka YOKOTA warnx("invalid argument `%s'", argv[optind]); 713fb966343SKazutaka YOKOTA usage(); 714fb966343SKazutaka YOKOTA } 71544bdcfa6SKazutaka YOKOTA rodent.zmap[j] = i; 716fb966343SKazutaka YOKOTA ++optind; 717fb966343SKazutaka YOKOTA } 718127d54baSKazutaka YOKOTA if ((rodent.zmap[2] != 0) && (rodent.zmap[3] == 0)) 71944bdcfa6SKazutaka YOKOTA rodent.zmap[3] = rodent.zmap[2] + 1; 7205f436cfbSKazutaka YOKOTA } 7215f436cfbSKazutaka YOKOTA break; 7225f436cfbSKazutaka YOKOTA 7235f436cfbSKazutaka YOKOTA case 'C': 7245f436cfbSKazutaka YOKOTA rodent.clickthreshold = atoi(optarg); 7255f436cfbSKazutaka YOKOTA if ((rodent.clickthreshold < 0) || 7265f436cfbSKazutaka YOKOTA (rodent.clickthreshold > MAX_CLICKTHRESHOLD)) { 7275f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 7285f436cfbSKazutaka YOKOTA usage(); 7295f436cfbSKazutaka YOKOTA } 73013379e47SPeter Wemm break; 73113379e47SPeter Wemm 73213379e47SPeter Wemm case 'D': 7335f436cfbSKazutaka YOKOTA rodent.flags |= ClearDTR; 7345f436cfbSKazutaka YOKOTA break; 7355f436cfbSKazutaka YOKOTA 7365f436cfbSKazutaka YOKOTA case 'F': 7375f436cfbSKazutaka YOKOTA rodent.rate = atoi(optarg); 7385f436cfbSKazutaka YOKOTA if (rodent.rate <= 0) { 7395f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 7405f436cfbSKazutaka YOKOTA usage(); 7415f436cfbSKazutaka YOKOTA } 7425f436cfbSKazutaka YOKOTA break; 7435f436cfbSKazutaka YOKOTA 7442c9b9132SPhilip Paeps case 'H': 7452c9b9132SPhilip Paeps rodent.flags |= HVirtualScroll; 7462c9b9132SPhilip Paeps break; 7472c9b9132SPhilip Paeps 7487b60e552SJordan K. Hubbard case 'I': 7497b60e552SJordan K. Hubbard pidfile = optarg; 7507b60e552SJordan K. Hubbard break; 7517b60e552SJordan K. Hubbard 7523e95467cSPhilip Paeps case 'L': 7533e95467cSPhilip Paeps rodent.scrollspeed = atoi(optarg); 7543e95467cSPhilip Paeps if (rodent.scrollspeed < 0) { 7553e95467cSPhilip Paeps warnx("invalid argument `%s'", optarg); 7563e95467cSPhilip Paeps usage(); 7573e95467cSPhilip Paeps } 7583e95467cSPhilip Paeps break; 7593e95467cSPhilip Paeps 7605f436cfbSKazutaka YOKOTA case 'P': 7615f436cfbSKazutaka YOKOTA rodent.flags |= NoPnP; 7625f436cfbSKazutaka YOKOTA break; 7635f436cfbSKazutaka YOKOTA 7645f436cfbSKazutaka YOKOTA case 'R': 7655f436cfbSKazutaka YOKOTA rodent.flags |= ClearRTS; 76613379e47SPeter Wemm break; 76713379e47SPeter Wemm 76813379e47SPeter Wemm case 'S': 76913379e47SPeter Wemm rodent.baudrate = atoi(optarg); 7705f436cfbSKazutaka YOKOTA if (rodent.baudrate <= 0) { 7715f436cfbSKazutaka YOKOTA warnx("invalid argument `%s'", optarg); 7725f436cfbSKazutaka YOKOTA usage(); 7735f436cfbSKazutaka YOKOTA } 77413379e47SPeter Wemm debug("rodent baudrate %d", rodent.baudrate); 77513379e47SPeter Wemm break; 776ad771aa1SSøren Schmidt 777d5f2946aSPhilip Paeps case 'T': 778d5f2946aSPhilip Paeps drift_terminate = TRUE; 779d5f2946aSPhilip Paeps sscanf(optarg, "%d,%d,%d", &drift_distance, &drift_time, 780d5f2946aSPhilip Paeps &drift_after); 781d5f2946aSPhilip Paeps if (drift_distance <= 0 || drift_time <= 0 || drift_after <= 0) { 782d5f2946aSPhilip Paeps warnx("invalid argument `%s'", optarg); 783d5f2946aSPhilip Paeps usage(); 784d5f2946aSPhilip Paeps } 785d5f2946aSPhilip Paeps debug("terminate drift: distance %d, time %d, after %d", 786d5f2946aSPhilip Paeps drift_distance, drift_time, drift_after); 78713f1c59bSJung-uk Kim drift_time_ts.tv_sec = drift_time / 1000; 78813f1c59bSJung-uk Kim drift_time_ts.tv_nsec = (drift_time % 1000) * 1000000; 78913f1c59bSJung-uk Kim drift_2time_ts.tv_sec = (drift_time *= 2) / 1000; 79013f1c59bSJung-uk Kim drift_2time_ts.tv_nsec = (drift_time % 1000) * 1000000; 79113f1c59bSJung-uk Kim drift_after_ts.tv_sec = drift_after / 1000; 79213f1c59bSJung-uk Kim drift_after_ts.tv_nsec = (drift_after % 1000) * 1000000; 793d5f2946aSPhilip Paeps break; 794d5f2946aSPhilip Paeps 795ad771aa1SSøren Schmidt case 't': 79630ee7535SKazutaka YOKOTA if (strcmp(optarg, "auto") == 0) { 79730ee7535SKazutaka YOKOTA rodent.rtype = MOUSE_PROTO_UNKNOWN; 79830ee7535SKazutaka YOKOTA rodent.flags &= ~NoPnP; 79930ee7535SKazutaka YOKOTA rodent.level = -1; 80030ee7535SKazutaka YOKOTA break; 80130ee7535SKazutaka YOKOTA } 8022657f6e9SJung-uk Kim for (i = 0; rnames[i] != NULL; i++) 80330ee7535SKazutaka YOKOTA if (strcmp(optarg, rnames[i]) == 0) { 804ad771aa1SSøren Schmidt rodent.rtype = i; 80530ee7535SKazutaka YOKOTA rodent.flags |= NoPnP; 80630ee7535SKazutaka YOKOTA rodent.level = (i == MOUSE_PROTO_SYSMOUSE) ? 1 : 0; 807ad771aa1SSøren Schmidt break; 808ad771aa1SSøren Schmidt } 8092657f6e9SJung-uk Kim if (rnames[i] == NULL) { 81013379e47SPeter Wemm warnx("no such mouse type `%s'", optarg); 811ad771aa1SSøren Schmidt usage(); 8122657f6e9SJung-uk Kim } 8132657f6e9SJung-uk Kim break; 814ad771aa1SSøren Schmidt 8152a669c47SPhilip Paeps case 'V': 8162a669c47SPhilip Paeps rodent.flags |= VirtualScroll; 8172a669c47SPhilip Paeps break; 8182a669c47SPhilip Paeps case 'U': 8192a669c47SPhilip Paeps rodent.scrollthreshold = atoi(optarg); 8202a669c47SPhilip Paeps if (rodent.scrollthreshold < 0) { 8212a669c47SPhilip Paeps warnx("invalid argument `%s'", optarg); 8222a669c47SPhilip Paeps usage(); 8232a669c47SPhilip Paeps } 8242a669c47SPhilip Paeps break; 8252a669c47SPhilip Paeps 826ad771aa1SSøren Schmidt case 'h': 827ad771aa1SSøren Schmidt case '?': 828ad771aa1SSøren Schmidt default: 829ad771aa1SSøren Schmidt usage(); 830ad771aa1SSøren Schmidt } 831ad771aa1SSøren Schmidt 832127d54baSKazutaka YOKOTA /* fix Z axis mapping */ 833127d54baSKazutaka YOKOTA for (i = 0; i < 4; ++i) { 834127d54baSKazutaka YOKOTA if (rodent.zmap[i] > 0) { 835127d54baSKazutaka YOKOTA for (j = 0; j < MOUSE_MAXBUTTON; ++j) { 836127d54baSKazutaka YOKOTA if (mstate[j] == &bstate[rodent.zmap[i] - 1]) 837127d54baSKazutaka YOKOTA mstate[j] = &zstate[i]; 838127d54baSKazutaka YOKOTA } 839127d54baSKazutaka YOKOTA rodent.zmap[i] = 1 << (rodent.zmap[i] - 1); 840127d54baSKazutaka YOKOTA } 841127d54baSKazutaka YOKOTA } 842127d54baSKazutaka YOKOTA 8435f436cfbSKazutaka YOKOTA /* the default port name */ 8445f436cfbSKazutaka YOKOTA switch(rodent.rtype) { 8455f436cfbSKazutaka YOKOTA 8465f436cfbSKazutaka YOKOTA case MOUSE_PROTO_PS2: 847ad771aa1SSøren Schmidt if (!rodent.portname) 848ad771aa1SSøren Schmidt rodent.portname = "/dev/psm0"; 849ad771aa1SSøren Schmidt break; 8505f436cfbSKazutaka YOKOTA 851ad771aa1SSøren Schmidt default: 852ad771aa1SSøren Schmidt if (rodent.portname) 853ad771aa1SSøren Schmidt break; 85407e1d533SPhilippe Charnier warnx("no port name specified"); 855ad771aa1SSøren Schmidt usage(); 856ad771aa1SSøren Schmidt } 857ad771aa1SSøren Schmidt 85808f950a3SHans Petter Selasky if (strncmp(rodent.portname, "/dev/ums", 8) == 0) 85908f950a3SHans Petter Selasky rodent.is_removable = 1; 86049271db4SDag-Erling Smørgrav 8615f436cfbSKazutaka YOKOTA for (;;) { 8625f436cfbSKazutaka YOKOTA if (setjmp(env) == 0) { 8635f436cfbSKazutaka YOKOTA signal(SIGHUP, hup); 86467978692SAmancio Hasty signal(SIGINT , cleanup); 86567978692SAmancio Hasty signal(SIGQUIT, cleanup); 86667978692SAmancio Hasty signal(SIGTERM, cleanup); 8679eac5bb9SPhilip Paeps signal(SIGUSR1, pause_mouse); 86808f950a3SHans Petter Selasky 86949271db4SDag-Erling Smørgrav rodent.mfd = open(rodent.portname, O_RDWR | O_NONBLOCK); 87049271db4SDag-Erling Smørgrav if (rodent.mfd == -1) 8715f436cfbSKazutaka YOKOTA logerr(1, "unable to open %s", rodent.portname); 8725f436cfbSKazutaka YOKOTA if (r_identify() == MOUSE_PROTO_UNKNOWN) { 8735f436cfbSKazutaka YOKOTA logwarnx("cannot determine mouse type on %s", rodent.portname); 8745f436cfbSKazutaka YOKOTA close(rodent.mfd); 8755f436cfbSKazutaka YOKOTA rodent.mfd = -1; 876ad771aa1SSøren Schmidt } 8775f436cfbSKazutaka YOKOTA 8785f436cfbSKazutaka YOKOTA /* print some information */ 8795f436cfbSKazutaka YOKOTA if (identify != ID_NONE) { 8805f436cfbSKazutaka YOKOTA if (identify == ID_ALL) 8815f436cfbSKazutaka YOKOTA printf("%s %s %s %s\n", 8825f436cfbSKazutaka YOKOTA rodent.portname, r_if(rodent.hw.iftype), 8835f436cfbSKazutaka YOKOTA r_name(rodent.rtype), r_model(rodent.hw.model)); 8845f436cfbSKazutaka YOKOTA else if (identify & ID_PORT) 8855f436cfbSKazutaka YOKOTA printf("%s\n", rodent.portname); 8865f436cfbSKazutaka YOKOTA else if (identify & ID_IF) 8875f436cfbSKazutaka YOKOTA printf("%s\n", r_if(rodent.hw.iftype)); 8885f436cfbSKazutaka YOKOTA else if (identify & ID_TYPE) 8895f436cfbSKazutaka YOKOTA printf("%s\n", r_name(rodent.rtype)); 8905f436cfbSKazutaka YOKOTA else if (identify & ID_MODEL) 8915f436cfbSKazutaka YOKOTA printf("%s\n", r_model(rodent.hw.model)); 8925f436cfbSKazutaka YOKOTA exit(0); 8935f436cfbSKazutaka YOKOTA } else { 8945f436cfbSKazutaka YOKOTA debug("port: %s interface: %s type: %s model: %s", 8955f436cfbSKazutaka YOKOTA rodent.portname, r_if(rodent.hw.iftype), 8965f436cfbSKazutaka YOKOTA r_name(rodent.rtype), r_model(rodent.hw.model)); 8975f436cfbSKazutaka YOKOTA } 8985f436cfbSKazutaka YOKOTA 8995f436cfbSKazutaka YOKOTA if (rodent.mfd == -1) { 9005f436cfbSKazutaka YOKOTA /* 9015f436cfbSKazutaka YOKOTA * We cannot continue because of error. Exit if the 9025f436cfbSKazutaka YOKOTA * program has not become a daemon. Otherwise, block 9036bccea7cSRebecca Cran * until the user corrects the problem and issues SIGHUP. 9045f436cfbSKazutaka YOKOTA */ 9055f436cfbSKazutaka YOKOTA if (!background) 9065f436cfbSKazutaka YOKOTA exit(1); 9075f436cfbSKazutaka YOKOTA sigpause(0); 9085f436cfbSKazutaka YOKOTA } 9095f436cfbSKazutaka YOKOTA 910ad771aa1SSøren Schmidt r_init(); /* call init function */ 9115f436cfbSKazutaka YOKOTA moused(); 912ad771aa1SSøren Schmidt } 913ad771aa1SSøren Schmidt 9145f436cfbSKazutaka YOKOTA if (rodent.mfd != -1) 9155f436cfbSKazutaka YOKOTA close(rodent.mfd); 9165f436cfbSKazutaka YOKOTA if (rodent.cfd != -1) 9175f436cfbSKazutaka YOKOTA close(rodent.cfd); 9185f436cfbSKazutaka YOKOTA rodent.mfd = rodent.cfd = -1; 91908f950a3SHans Petter Selasky if (rodent.is_removable) 92008f950a3SHans Petter Selasky exit(0); 9215f436cfbSKazutaka YOKOTA } 9225f436cfbSKazutaka YOKOTA /* NOT REACHED */ 9235f436cfbSKazutaka YOKOTA 9245f436cfbSKazutaka YOKOTA exit(0); 9255f436cfbSKazutaka YOKOTA } 9265f436cfbSKazutaka YOKOTA 92786b3ea36SPhilip Paeps /* 928d9338247SPhilip Paeps * Function to calculate linear acceleration. 929d9338247SPhilip Paeps * 930d9338247SPhilip Paeps * If there are any rounding errors, the remainder 931d9338247SPhilip Paeps * is stored in the remainx and remainy variables 932d9338247SPhilip Paeps * and taken into account upon the next movement. 933d9338247SPhilip Paeps */ 934d9338247SPhilip Paeps 935d9338247SPhilip Paeps static void 936d9338247SPhilip Paeps linacc(int dx, int dy, int *movex, int *movey) 937d9338247SPhilip Paeps { 938d9338247SPhilip Paeps float fdx, fdy; 939d9338247SPhilip Paeps 940d9338247SPhilip Paeps if (dx == 0 && dy == 0) { 941d9338247SPhilip Paeps *movex = *movey = 0; 942d9338247SPhilip Paeps return; 943d9338247SPhilip Paeps } 944d9338247SPhilip Paeps fdx = dx * rodent.accelx + rodent.remainx; 945d9338247SPhilip Paeps fdy = dy * rodent.accely + rodent.remainy; 946d9338247SPhilip Paeps *movex = lround(fdx); 947d9338247SPhilip Paeps *movey = lround(fdy); 948d9338247SPhilip Paeps rodent.remainx = fdx - *movex; 949d9338247SPhilip Paeps rodent.remainy = fdy - *movey; 950d9338247SPhilip Paeps } 951d9338247SPhilip Paeps 952d9338247SPhilip Paeps /* 95386b3ea36SPhilip Paeps * Function to calculate exponential acceleration. 954d9338247SPhilip Paeps * (Also includes linear acceleration if enabled.) 95586b3ea36SPhilip Paeps * 95686b3ea36SPhilip Paeps * In order to give a smoother behaviour, we record the four 95786b3ea36SPhilip Paeps * most recent non-zero movements and use their average value 95886b3ea36SPhilip Paeps * to calculate the acceleration. 95986b3ea36SPhilip Paeps */ 96086b3ea36SPhilip Paeps 96186b3ea36SPhilip Paeps static void 96286b3ea36SPhilip Paeps expoacc(int dx, int dy, int *movex, int *movey) 96386b3ea36SPhilip Paeps { 96486b3ea36SPhilip Paeps static float lastlength[3] = {0.0, 0.0, 0.0}; 96586b3ea36SPhilip Paeps float fdx, fdy, length, lbase, accel; 96686b3ea36SPhilip Paeps 96786b3ea36SPhilip Paeps if (dx == 0 && dy == 0) { 96886b3ea36SPhilip Paeps *movex = *movey = 0; 96986b3ea36SPhilip Paeps return; 97086b3ea36SPhilip Paeps } 97186b3ea36SPhilip Paeps fdx = dx * rodent.accelx; 97286b3ea36SPhilip Paeps fdy = dy * rodent.accely; 97386b3ea36SPhilip Paeps length = sqrtf((fdx * fdx) + (fdy * fdy)); /* Pythagoras */ 97486b3ea36SPhilip Paeps length = (length + lastlength[0] + lastlength[1] + lastlength[2]) / 4; 97586b3ea36SPhilip Paeps lbase = length / rodent.expoffset; 97686b3ea36SPhilip Paeps accel = powf(lbase, rodent.expoaccel) / lbase; 977d9338247SPhilip Paeps fdx = fdx * accel + rodent.remainx; 978d9338247SPhilip Paeps fdy = fdy * accel + rodent.remainy; 979d9338247SPhilip Paeps *movex = lroundf(fdx); 980d9338247SPhilip Paeps *movey = lroundf(fdy); 981d9338247SPhilip Paeps rodent.remainx = fdx - *movex; 982d9338247SPhilip Paeps rodent.remainy = fdy - *movey; 98386b3ea36SPhilip Paeps lastlength[2] = lastlength[1]; 98486b3ea36SPhilip Paeps lastlength[1] = lastlength[0]; 98586b3ea36SPhilip Paeps lastlength[0] = length; /* Insert new average, not original length! */ 98686b3ea36SPhilip Paeps } 98786b3ea36SPhilip Paeps 9885f436cfbSKazutaka YOKOTA static void 9895f436cfbSKazutaka YOKOTA moused(void) 990ad771aa1SSøren Schmidt { 9915f436cfbSKazutaka YOKOTA struct mouse_info mouse; 99244bdcfa6SKazutaka YOKOTA mousestatus_t action0; /* original mouse action */ 9933df5ecacSUlrich Spörlein mousestatus_t action; /* interim buffer */ 9945f436cfbSKazutaka YOKOTA mousestatus_t action2; /* mapped action */ 99544bdcfa6SKazutaka YOKOTA struct timeval timeout; 9965f436cfbSKazutaka YOKOTA fd_set fds; 9975f436cfbSKazutaka YOKOTA u_char b; 998a80d5fc2SPawel Jakub Dawidek pid_t mpid; 99944bdcfa6SKazutaka YOKOTA int flags; 100044bdcfa6SKazutaka YOKOTA int c; 100144bdcfa6SKazutaka YOKOTA int i; 10025f436cfbSKazutaka YOKOTA 10035f436cfbSKazutaka YOKOTA if ((rodent.cfd = open("/dev/consolectl", O_RDWR, 0)) == -1) 100462e621e8SIan Dowse logerr(1, "cannot open /dev/consolectl"); 10055f436cfbSKazutaka YOKOTA 100662e621e8SIan Dowse if (!nodaemon && !background) { 10078b28aef2SPawel Jakub Dawidek pfh = pidfile_open(pidfile, 0600, &mpid); 1008a80d5fc2SPawel Jakub Dawidek if (pfh == NULL) { 1009a80d5fc2SPawel Jakub Dawidek if (errno == EEXIST) 1010a80d5fc2SPawel Jakub Dawidek logerrx(1, "moused already running, pid: %d", mpid); 1011a80d5fc2SPawel Jakub Dawidek logwarn("cannot open pid file"); 1012a80d5fc2SPawel Jakub Dawidek } 10135f436cfbSKazutaka YOKOTA if (daemon(0, 0)) { 1014a80d5fc2SPawel Jakub Dawidek int saved_errno = errno; 1015a80d5fc2SPawel Jakub Dawidek pidfile_remove(pfh); 1016a80d5fc2SPawel Jakub Dawidek errno = saved_errno; 101762e621e8SIan Dowse logerr(1, "failed to become a daemon"); 10185f436cfbSKazutaka YOKOTA } else { 10195f436cfbSKazutaka YOKOTA background = TRUE; 1020a80d5fc2SPawel Jakub Dawidek pidfile_write(pfh); 10215f436cfbSKazutaka YOKOTA } 102262e621e8SIan Dowse } 10235f436cfbSKazutaka YOKOTA 10245f436cfbSKazutaka YOKOTA /* clear mouse data */ 102544bdcfa6SKazutaka YOKOTA bzero(&action0, sizeof(action0)); 10265f436cfbSKazutaka YOKOTA bzero(&action, sizeof(action)); 10275f436cfbSKazutaka YOKOTA bzero(&action2, sizeof(action2)); 10285f436cfbSKazutaka YOKOTA bzero(&mouse, sizeof(mouse)); 102944bdcfa6SKazutaka YOKOTA mouse_button_state = S0; 103013f1c59bSJung-uk Kim clock_gettime(CLOCK_MONOTONIC_FAST, &mouse_button_state_ts); 103170ccc8d8SIan Dowse mouse_move_delayed = 0; 103244bdcfa6SKazutaka YOKOTA for (i = 0; i < MOUSE_MAXBUTTON; ++i) { 103344bdcfa6SKazutaka YOKOTA bstate[i].count = 0; 103413f1c59bSJung-uk Kim bstate[i].ts = mouse_button_state_ts; 103544bdcfa6SKazutaka YOKOTA } 1036*83409a93SElyes Haouas for (i = 0; i < (int)nitems(zstate); ++i) { 103744bdcfa6SKazutaka YOKOTA zstate[i].count = 0; 103813f1c59bSJung-uk Kim zstate[i].ts = mouse_button_state_ts; 103944bdcfa6SKazutaka YOKOTA } 10405f436cfbSKazutaka YOKOTA 10415f436cfbSKazutaka YOKOTA /* choose which ioctl command to use */ 10425f436cfbSKazutaka YOKOTA mouse.operation = MOUSE_MOTION_EVENT; 10435f436cfbSKazutaka YOKOTA extioctl = (ioctl(rodent.cfd, CONS_MOUSECTL, &mouse) == 0); 10445f436cfbSKazutaka YOKOTA 10455f436cfbSKazutaka YOKOTA /* process mouse data */ 104644bdcfa6SKazutaka YOKOTA timeout.tv_sec = 0; 104744bdcfa6SKazutaka YOKOTA timeout.tv_usec = 20000; /* 20 msec */ 10485f436cfbSKazutaka YOKOTA for (;;) { 10495f436cfbSKazutaka YOKOTA 105020a2630bSSøren Schmidt FD_ZERO(&fds); 105120a2630bSSøren Schmidt FD_SET(rodent.mfd, &fds); 105244bdcfa6SKazutaka YOKOTA if (rodent.mremsfd >= 0) 105344bdcfa6SKazutaka YOKOTA FD_SET(rodent.mremsfd, &fds); 105444bdcfa6SKazutaka YOKOTA if (rodent.mremcfd >= 0) 105544bdcfa6SKazutaka YOKOTA FD_SET(rodent.mremcfd, &fds); 105667978692SAmancio Hasty 105744bdcfa6SKazutaka YOKOTA c = select(FD_SETSIZE, &fds, NULL, NULL, 1058ce304e08SAlexander Motin ((rodent.flags & Emulate3Button) && 1059ce304e08SAlexander Motin S_DELAYED(mouse_button_state)) ? &timeout : NULL); 106044bdcfa6SKazutaka YOKOTA if (c < 0) { /* error */ 106162e621e8SIan Dowse logwarn("failed to read from mouse"); 106244bdcfa6SKazutaka YOKOTA continue; 106344bdcfa6SKazutaka YOKOTA } else if (c == 0) { /* timeout */ 106444bdcfa6SKazutaka YOKOTA /* assert(rodent.flags & Emulate3Button) */ 106544bdcfa6SKazutaka YOKOTA action0.button = action0.obutton; 106644bdcfa6SKazutaka YOKOTA action0.dx = action0.dy = action0.dz = 0; 106744bdcfa6SKazutaka YOKOTA action0.flags = flags = 0; 106844bdcfa6SKazutaka YOKOTA if (r_timeout() && r_statetrans(&action0, &action, A_TIMEOUT)) { 106944bdcfa6SKazutaka YOKOTA if (debug > 2) 107044bdcfa6SKazutaka YOKOTA debug("flags:%08x buttons:%08x obuttons:%08x", 107144bdcfa6SKazutaka YOKOTA action.flags, action.button, action.obutton); 107244bdcfa6SKazutaka YOKOTA } else { 107344bdcfa6SKazutaka YOKOTA action0.obutton = action0.button; 107444bdcfa6SKazutaka YOKOTA continue; 107544bdcfa6SKazutaka YOKOTA } 107644bdcfa6SKazutaka YOKOTA } else { 107767978692SAmancio Hasty /* MouseRemote client connect/disconnect */ 107867978692SAmancio Hasty if ((rodent.mremsfd >= 0) && FD_ISSET(rodent.mremsfd, &fds)) { 107967978692SAmancio Hasty mremote_clientchg(TRUE); 108067978692SAmancio Hasty continue; 108167978692SAmancio Hasty } 108267978692SAmancio Hasty if ((rodent.mremcfd >= 0) && FD_ISSET(rodent.mremcfd, &fds)) { 108367978692SAmancio Hasty mremote_clientchg(FALSE); 108467978692SAmancio Hasty continue; 108567978692SAmancio Hasty } 108644bdcfa6SKazutaka YOKOTA /* mouse movement */ 108744bdcfa6SKazutaka YOKOTA if (read(rodent.mfd, &b, 1) == -1) { 108844bdcfa6SKazutaka YOKOTA if (errno == EWOULDBLOCK) 108944bdcfa6SKazutaka YOKOTA continue; 109044bdcfa6SKazutaka YOKOTA else 109144bdcfa6SKazutaka YOKOTA return; 109244bdcfa6SKazutaka YOKOTA } 109344bdcfa6SKazutaka YOKOTA if ((flags = r_protocol(b, &action0)) == 0) 109444bdcfa6SKazutaka YOKOTA continue; 10952a669c47SPhilip Paeps 10962c9b9132SPhilip Paeps if ((rodent.flags & VirtualScroll) || (rodent.flags & HVirtualScroll)) { 10972a669c47SPhilip Paeps /* Allow middle button drags to scroll up and down */ 10982a669c47SPhilip Paeps if (action0.button == MOUSE_BUTTON2DOWN) { 10992a669c47SPhilip Paeps if (scroll_state == SCROLL_NOTSCROLLING) { 11002a669c47SPhilip Paeps scroll_state = SCROLL_PREPARE; 11013e95467cSPhilip Paeps scroll_movement = hscroll_movement = 0; 11022a669c47SPhilip Paeps debug("PREPARING TO SCROLL"); 11032a669c47SPhilip Paeps } 11042a669c47SPhilip Paeps debug("[BUTTON2] flags:%08x buttons:%08x obuttons:%08x", 11052a669c47SPhilip Paeps action.flags, action.button, action.obutton); 11062a669c47SPhilip Paeps } else { 11072a669c47SPhilip Paeps debug("[NOTBUTTON2] flags:%08x buttons:%08x obuttons:%08x", 11082a669c47SPhilip Paeps action.flags, action.button, action.obutton); 11092a669c47SPhilip Paeps 11102a669c47SPhilip Paeps /* This isn't a middle button down... move along... */ 11112a669c47SPhilip Paeps if (scroll_state == SCROLL_SCROLLING) { 11122a669c47SPhilip Paeps /* 11132a669c47SPhilip Paeps * We were scrolling, someone let go of button 2. 11142a669c47SPhilip Paeps * Now turn autoscroll off. 11152a669c47SPhilip Paeps */ 11162a669c47SPhilip Paeps scroll_state = SCROLL_NOTSCROLLING; 11172a669c47SPhilip Paeps debug("DONE WITH SCROLLING / %d", scroll_state); 11182a669c47SPhilip Paeps } else if (scroll_state == SCROLL_PREPARE) { 11192a669c47SPhilip Paeps mousestatus_t newaction = action0; 11202a669c47SPhilip Paeps 11212a669c47SPhilip Paeps /* We were preparing to scroll, but we never moved... */ 11222a669c47SPhilip Paeps r_timestamp(&action0); 11232a669c47SPhilip Paeps r_statetrans(&action0, &newaction, 11242a669c47SPhilip Paeps A(newaction.button & MOUSE_BUTTON1DOWN, 11252a669c47SPhilip Paeps action0.button & MOUSE_BUTTON3DOWN)); 11262a669c47SPhilip Paeps 11272a669c47SPhilip Paeps /* Send middle down */ 11282a669c47SPhilip Paeps newaction.button = MOUSE_BUTTON2DOWN; 11292a669c47SPhilip Paeps r_click(&newaction); 11302a669c47SPhilip Paeps 11312a669c47SPhilip Paeps /* Send middle up */ 11322a669c47SPhilip Paeps r_timestamp(&newaction); 11332a669c47SPhilip Paeps newaction.obutton = newaction.button; 11342a669c47SPhilip Paeps newaction.button = action0.button; 11352a669c47SPhilip Paeps r_click(&newaction); 11362a669c47SPhilip Paeps } 11372a669c47SPhilip Paeps } 11382a669c47SPhilip Paeps } 11392a669c47SPhilip Paeps 114044bdcfa6SKazutaka YOKOTA r_timestamp(&action0); 114144bdcfa6SKazutaka YOKOTA r_statetrans(&action0, &action, 114244bdcfa6SKazutaka YOKOTA A(action0.button & MOUSE_BUTTON1DOWN, 114344bdcfa6SKazutaka YOKOTA action0.button & MOUSE_BUTTON3DOWN)); 114444bdcfa6SKazutaka YOKOTA debug("flags:%08x buttons:%08x obuttons:%08x", action.flags, 114544bdcfa6SKazutaka YOKOTA action.button, action.obutton); 114644bdcfa6SKazutaka YOKOTA } 114744bdcfa6SKazutaka YOKOTA action0.obutton = action0.button; 114844bdcfa6SKazutaka YOKOTA flags &= MOUSE_POSCHANGED; 114944bdcfa6SKazutaka YOKOTA flags |= action.obutton ^ action.button; 115044bdcfa6SKazutaka YOKOTA action.flags = flags; 115167978692SAmancio Hasty 115244bdcfa6SKazutaka YOKOTA if (flags) { /* handler detected action */ 11535f436cfbSKazutaka YOKOTA r_map(&action, &action2); 11545f436cfbSKazutaka YOKOTA debug("activity : buttons 0x%08x dx %d dy %d dz %d", 11555f436cfbSKazutaka YOKOTA action2.button, action2.dx, action2.dy, action2.dz); 11565f436cfbSKazutaka YOKOTA 11572c9b9132SPhilip Paeps if ((rodent.flags & VirtualScroll) || (rodent.flags & HVirtualScroll)) { 11582a669c47SPhilip Paeps /* 11592a669c47SPhilip Paeps * If *only* the middle button is pressed AND we are moving 11602a669c47SPhilip Paeps * the stick/trackpoint/nipple, scroll! 11612a669c47SPhilip Paeps */ 11622a669c47SPhilip Paeps if (scroll_state == SCROLL_PREPARE) { 11633e95467cSPhilip Paeps /* Middle button down, waiting for movement threshold */ 11643e95467cSPhilip Paeps if (action2.dy || action2.dx) { 11653e95467cSPhilip Paeps if (rodent.flags & VirtualScroll) { 11663e95467cSPhilip Paeps scroll_movement += action2.dy; 11673e95467cSPhilip Paeps if (scroll_movement < -rodent.scrollthreshold) { 11683e95467cSPhilip Paeps scroll_state = SCROLL_SCROLLING; 11693e95467cSPhilip Paeps } else if (scroll_movement > rodent.scrollthreshold) { 11702a669c47SPhilip Paeps scroll_state = SCROLL_SCROLLING; 11712a669c47SPhilip Paeps } 11723e95467cSPhilip Paeps } 11733e95467cSPhilip Paeps if (rodent.flags & HVirtualScroll) { 11743e95467cSPhilip Paeps hscroll_movement += action2.dx; 11753e95467cSPhilip Paeps if (hscroll_movement < -rodent.scrollthreshold) { 11763e95467cSPhilip Paeps scroll_state = SCROLL_SCROLLING; 11773e95467cSPhilip Paeps } else if (hscroll_movement > rodent.scrollthreshold) { 11783e95467cSPhilip Paeps scroll_state = SCROLL_SCROLLING; 11793e95467cSPhilip Paeps } 11803e95467cSPhilip Paeps } 11813e95467cSPhilip Paeps if (scroll_state == SCROLL_SCROLLING) scroll_movement = hscroll_movement = 0; 11823e95467cSPhilip Paeps } 11833e95467cSPhilip Paeps } else if (scroll_state == SCROLL_SCROLLING) { 11842c9b9132SPhilip Paeps if (rodent.flags & VirtualScroll) { 11852a669c47SPhilip Paeps scroll_movement += action2.dy; 11862a669c47SPhilip Paeps debug("SCROLL: %d", scroll_movement); 11873e95467cSPhilip Paeps if (scroll_movement < -rodent.scrollspeed) { 11882a669c47SPhilip Paeps /* Scroll down */ 11892a669c47SPhilip Paeps action2.dz = -1; 11902a669c47SPhilip Paeps scroll_movement = 0; 11912a669c47SPhilip Paeps } 11923e95467cSPhilip Paeps else if (scroll_movement > rodent.scrollspeed) { 11932a669c47SPhilip Paeps /* Scroll up */ 11942a669c47SPhilip Paeps action2.dz = 1; 11952a669c47SPhilip Paeps scroll_movement = 0; 11962a669c47SPhilip Paeps } 11972c9b9132SPhilip Paeps } 11982c9b9132SPhilip Paeps if (rodent.flags & HVirtualScroll) { 11992c9b9132SPhilip Paeps hscroll_movement += action2.dx; 12002c9b9132SPhilip Paeps debug("HORIZONTAL SCROLL: %d", hscroll_movement); 12012c9b9132SPhilip Paeps 12023e95467cSPhilip Paeps if (hscroll_movement < -rodent.scrollspeed) { 12032c9b9132SPhilip Paeps action2.dz = -2; 12042c9b9132SPhilip Paeps hscroll_movement = 0; 12052c9b9132SPhilip Paeps } 12063e95467cSPhilip Paeps else if (hscroll_movement > rodent.scrollspeed) { 12072c9b9132SPhilip Paeps action2.dz = 2; 12082c9b9132SPhilip Paeps hscroll_movement = 0; 12092c9b9132SPhilip Paeps } 12102c9b9132SPhilip Paeps } 12112a669c47SPhilip Paeps 12122a669c47SPhilip Paeps /* Don't move while scrolling */ 12132a669c47SPhilip Paeps action2.dx = action2.dy = 0; 12142a669c47SPhilip Paeps } 12152a669c47SPhilip Paeps } 12162a669c47SPhilip Paeps 1217d5f2946aSPhilip Paeps if (drift_terminate) { 12182657f6e9SJung-uk Kim if ((flags & MOUSE_POSCHANGED) == 0 || action.dz || action2.dz) 121913f1c59bSJung-uk Kim drift_last_activity = drift_current_ts; 1220d5f2946aSPhilip Paeps else { 1221d5f2946aSPhilip Paeps /* X or/and Y movement only - possibly drift */ 122213f1c59bSJung-uk Kim tssub(&drift_current_ts, &drift_last_activity, &drift_tmp); 122313f1c59bSJung-uk Kim if (tscmp(&drift_tmp, &drift_after_ts, >)) { 122413f1c59bSJung-uk Kim tssub(&drift_current_ts, &drift_since, &drift_tmp); 122513f1c59bSJung-uk Kim if (tscmp(&drift_tmp, &drift_time_ts, <)) { 1226d5f2946aSPhilip Paeps drift_last.x += action2.dx; 1227d5f2946aSPhilip Paeps drift_last.y += action2.dy; 1228d5f2946aSPhilip Paeps } else { 1229d5f2946aSPhilip Paeps /* discard old accumulated steps (drift) */ 123013f1c59bSJung-uk Kim if (tscmp(&drift_tmp, &drift_2time_ts, >)) 1231d5f2946aSPhilip Paeps drift_previous.x = drift_previous.y = 0; 1232d5f2946aSPhilip Paeps else 1233d5f2946aSPhilip Paeps drift_previous = drift_last; 1234d5f2946aSPhilip Paeps drift_last.x = action2.dx; 1235d5f2946aSPhilip Paeps drift_last.y = action2.dy; 123613f1c59bSJung-uk Kim drift_since = drift_current_ts; 1237d5f2946aSPhilip Paeps } 1238d5f2946aSPhilip Paeps if (abs(drift_last.x) + abs(drift_last.y) 1239d5f2946aSPhilip Paeps > drift_distance) { 1240d5f2946aSPhilip Paeps /* real movement, pass all accumulated steps */ 1241d5f2946aSPhilip Paeps action2.dx = drift_previous.x + drift_last.x; 1242d5f2946aSPhilip Paeps action2.dy = drift_previous.y + drift_last.y; 1243d5f2946aSPhilip Paeps /* and reset accumulators */ 124413f1c59bSJung-uk Kim tsclr(&drift_since); 1245d5f2946aSPhilip Paeps drift_last.x = drift_last.y = 0; 1246d5f2946aSPhilip Paeps /* drift_previous will be cleared at next movement*/ 124713f1c59bSJung-uk Kim drift_last_activity = drift_current_ts; 1248d5f2946aSPhilip Paeps } else { 1249d5f2946aSPhilip Paeps continue; /* don't pass current movement to 1250d5f2946aSPhilip Paeps * console driver */ 1251d5f2946aSPhilip Paeps } 1252d5f2946aSPhilip Paeps } 1253d5f2946aSPhilip Paeps } 1254d5f2946aSPhilip Paeps } 1255d5f2946aSPhilip Paeps 12565f436cfbSKazutaka YOKOTA if (extioctl) { 12572a669c47SPhilip Paeps /* Defer clicks until we aren't VirtualScroll'ing. */ 12582a669c47SPhilip Paeps if (scroll_state == SCROLL_NOTSCROLLING) 12595f436cfbSKazutaka YOKOTA r_click(&action2); 12602a669c47SPhilip Paeps 12615f436cfbSKazutaka YOKOTA if (action2.flags & MOUSE_POSCHANGED) { 12625f436cfbSKazutaka YOKOTA mouse.operation = MOUSE_MOTION_EVENT; 12635f436cfbSKazutaka YOKOTA mouse.u.data.buttons = action2.button; 126486b3ea36SPhilip Paeps if (rodent.flags & ExponentialAcc) { 126586b3ea36SPhilip Paeps expoacc(action2.dx, action2.dy, 126686b3ea36SPhilip Paeps &mouse.u.data.x, &mouse.u.data.y); 126786b3ea36SPhilip Paeps } 126886b3ea36SPhilip Paeps else { 1269d9338247SPhilip Paeps linacc(action2.dx, action2.dy, 1270d9338247SPhilip Paeps &mouse.u.data.x, &mouse.u.data.y); 127186b3ea36SPhilip Paeps } 12725f436cfbSKazutaka YOKOTA mouse.u.data.z = action2.dz; 12735f436cfbSKazutaka YOKOTA if (debug < 2) 12749eac5bb9SPhilip Paeps if (!paused) 12755f436cfbSKazutaka YOKOTA ioctl(rodent.cfd, CONS_MOUSECTL, &mouse); 1276ad771aa1SSøren Schmidt } 12775f436cfbSKazutaka YOKOTA } else { 1278ad0c0c78SSøren Schmidt mouse.operation = MOUSE_ACTION; 12795f436cfbSKazutaka YOKOTA mouse.u.data.buttons = action2.button; 128086b3ea36SPhilip Paeps if (rodent.flags & ExponentialAcc) { 128186b3ea36SPhilip Paeps expoacc(action2.dx, action2.dy, 128286b3ea36SPhilip Paeps &mouse.u.data.x, &mouse.u.data.y); 128386b3ea36SPhilip Paeps } 128486b3ea36SPhilip Paeps else { 1285d9338247SPhilip Paeps linacc(action2.dx, action2.dy, 1286d9338247SPhilip Paeps &mouse.u.data.x, &mouse.u.data.y); 128786b3ea36SPhilip Paeps } 12885f436cfbSKazutaka YOKOTA mouse.u.data.z = action2.dz; 12895f436cfbSKazutaka YOKOTA if (debug < 2) 12909eac5bb9SPhilip Paeps if (!paused) 12915f436cfbSKazutaka YOKOTA ioctl(rodent.cfd, CONS_MOUSECTL, &mouse); 1292ad771aa1SSøren Schmidt } 1293ad771aa1SSøren Schmidt 12945f436cfbSKazutaka YOKOTA /* 12959d5abbddSJens Schweikhardt * If the Z axis movement is mapped to an imaginary physical 12965f436cfbSKazutaka YOKOTA * button, we need to cook up a corresponding button `up' event 12975f436cfbSKazutaka YOKOTA * after sending a button `down' event. 12985f436cfbSKazutaka YOKOTA */ 1299fb966343SKazutaka YOKOTA if ((rodent.zmap[0] > 0) && (action.dz != 0)) { 13005f436cfbSKazutaka YOKOTA action.obutton = action.button; 13015f436cfbSKazutaka YOKOTA action.dx = action.dy = action.dz = 0; 13025f436cfbSKazutaka YOKOTA r_map(&action, &action2); 13035f436cfbSKazutaka YOKOTA debug("activity : buttons 0x%08x dx %d dy %d dz %d", 13045f436cfbSKazutaka YOKOTA action2.button, action2.dx, action2.dy, action2.dz); 13055f436cfbSKazutaka YOKOTA 13065f436cfbSKazutaka YOKOTA if (extioctl) { 13075f436cfbSKazutaka YOKOTA r_click(&action2); 13085f436cfbSKazutaka YOKOTA } else { 13095f436cfbSKazutaka YOKOTA mouse.operation = MOUSE_ACTION; 13105f436cfbSKazutaka YOKOTA mouse.u.data.buttons = action2.button; 13115f436cfbSKazutaka YOKOTA mouse.u.data.x = mouse.u.data.y = mouse.u.data.z = 0; 13125f436cfbSKazutaka YOKOTA if (debug < 2) 13139eac5bb9SPhilip Paeps if (!paused) 13145f436cfbSKazutaka YOKOTA ioctl(rodent.cfd, CONS_MOUSECTL, &mouse); 13155f436cfbSKazutaka YOKOTA } 13165f436cfbSKazutaka YOKOTA } 13175f436cfbSKazutaka YOKOTA } 13185f436cfbSKazutaka YOKOTA } 13195f436cfbSKazutaka YOKOTA /* NOT REACHED */ 13205f436cfbSKazutaka YOKOTA } 13215f436cfbSKazutaka YOKOTA 13225f436cfbSKazutaka YOKOTA static void 13232657f6e9SJung-uk Kim hup(__unused int sig) 13245f436cfbSKazutaka YOKOTA { 13255f436cfbSKazutaka YOKOTA longjmp(env, 1); 13265f436cfbSKazutaka YOKOTA } 1327ad771aa1SSøren Schmidt 132867978692SAmancio Hasty static void 13292657f6e9SJung-uk Kim cleanup(__unused int sig) 133067978692SAmancio Hasty { 133167978692SAmancio Hasty if (rodent.rtype == MOUSE_PROTO_X10MOUSEREM) 133267978692SAmancio Hasty unlink(_PATH_MOUSEREMOTE); 133367978692SAmancio Hasty exit(0); 133467978692SAmancio Hasty } 133567978692SAmancio Hasty 13369eac5bb9SPhilip Paeps static void 13372657f6e9SJung-uk Kim pause_mouse(__unused int sig) 13389eac5bb9SPhilip Paeps { 13399eac5bb9SPhilip Paeps paused = !paused; 13409eac5bb9SPhilip Paeps } 13419eac5bb9SPhilip Paeps 1342ad771aa1SSøren Schmidt /** 1343ad771aa1SSøren Schmidt ** usage 1344ad771aa1SSøren Schmidt ** 1345ad771aa1SSøren Schmidt ** Complain, and free the CPU for more worthy tasks 1346ad771aa1SSøren Schmidt **/ 13475f436cfbSKazutaka YOKOTA static void 1348ad771aa1SSøren Schmidt usage(void) 1349ad771aa1SSøren Schmidt { 1350d5f2946aSPhilip Paeps fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 135144bdcfa6SKazutaka YOKOTA "usage: moused [-DRcdfs] [-I file] [-F rate] [-r resolution] [-S baudrate]", 13522c9b9132SPhilip Paeps " [-VH [-U threshold]] [-a X[,Y]] [-C threshold] [-m N=M] [-w N]", 1353d5f2946aSPhilip Paeps " [-z N] [-t <mousetype>] [-l level] [-3 [-E timeout]]", 1354d5f2946aSPhilip Paeps " [-T distance[,time[,after]]] -p <port>", 1355040eea4cSDoug Barton " moused [-d] -i <port|if|type|model|all> -p <port>"); 1356ad771aa1SSøren Schmidt exit(1); 1357ad771aa1SSøren Schmidt } 1358ad771aa1SSøren Schmidt 135962e621e8SIan Dowse /* 136062e621e8SIan Dowse * Output an error message to syslog or stderr as appropriate. If 136162e621e8SIan Dowse * `errnum' is non-zero, append its string form to the message. 136262e621e8SIan Dowse */ 136362e621e8SIan Dowse static void 136462e621e8SIan Dowse log_or_warn(int log_pri, int errnum, const char *fmt, ...) 136562e621e8SIan Dowse { 136662e621e8SIan Dowse va_list ap; 136762e621e8SIan Dowse char buf[256]; 136862e621e8SIan Dowse 136962e621e8SIan Dowse va_start(ap, fmt); 137062e621e8SIan Dowse vsnprintf(buf, sizeof(buf), fmt, ap); 137162e621e8SIan Dowse va_end(ap); 137262e621e8SIan Dowse if (errnum) { 137362e621e8SIan Dowse strlcat(buf, ": ", sizeof(buf)); 137462e621e8SIan Dowse strlcat(buf, strerror(errnum), sizeof(buf)); 137562e621e8SIan Dowse } 137662e621e8SIan Dowse 137762e621e8SIan Dowse if (background) 137862e621e8SIan Dowse syslog(log_pri, "%s", buf); 137962e621e8SIan Dowse else 138062e621e8SIan Dowse warnx("%s", buf); 138162e621e8SIan Dowse } 138262e621e8SIan Dowse 1383ad771aa1SSøren Schmidt /** 1384ad771aa1SSøren Schmidt ** Mouse interface code, courtesy of XFree86 3.1.2. 1385ad771aa1SSøren Schmidt ** 1386ad771aa1SSøren Schmidt ** Note: Various bits have been trimmed, and in my shortsighted enthusiasm 1387ad771aa1SSøren Schmidt ** to clean, reformat and rationalise naming, it's quite possible that 1388ad771aa1SSøren Schmidt ** some things in here have been broken. 1389ad771aa1SSøren Schmidt ** 1390ad771aa1SSøren Schmidt ** I hope not 8) 1391ad771aa1SSøren Schmidt ** 1392ad771aa1SSøren Schmidt ** The following code is derived from a module marked : 1393ad771aa1SSøren Schmidt **/ 1394ad771aa1SSøren Schmidt 1395ad771aa1SSøren Schmidt /* $XConsortium: xf86_Mouse.c,v 1.2 94/10/12 20:33:21 kaleb Exp $ */ 1396ad771aa1SSøren Schmidt /* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86_Mouse.c,v 3.2 1995/01/28 1397ad771aa1SSøren Schmidt 17:03:40 dawes Exp $ */ 1398ad771aa1SSøren Schmidt /* 1399ad771aa1SSøren Schmidt * 1400ad771aa1SSøren Schmidt * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 1401ad771aa1SSøren Schmidt * Copyright 1993 by David Dawes <dawes@physics.su.oz.au> 1402ad771aa1SSøren Schmidt * 1403ad771aa1SSøren Schmidt * Permission to use, copy, modify, distribute, and sell this software and its 1404ad771aa1SSøren Schmidt * documentation for any purpose is hereby granted without fee, provided that 1405ad771aa1SSøren Schmidt * the above copyright notice appear in all copies and that both that 1406ad771aa1SSøren Schmidt * copyright notice and this permission notice appear in supporting 1407ad771aa1SSøren Schmidt * documentation, and that the names of Thomas Roell and David Dawes not be 1408ad771aa1SSøren Schmidt * used in advertising or publicity pertaining to distribution of the 1409ad771aa1SSøren Schmidt * software without specific, written prior permission. Thomas Roell 1410ad771aa1SSøren Schmidt * and David Dawes makes no representations about the suitability of this 1411ad771aa1SSøren Schmidt * software for any purpose. It is provided "as is" without express or 1412ad771aa1SSøren Schmidt * implied warranty. 1413ad771aa1SSøren Schmidt * 1414ad771aa1SSøren Schmidt * THOMAS ROELL AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 1415ad771aa1SSøren Schmidt * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 1416ad771aa1SSøren Schmidt * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES BE LIABLE FOR ANY 1417ad771aa1SSøren Schmidt * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 1418ad771aa1SSøren Schmidt * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 1419ad771aa1SSøren Schmidt * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 1420ad771aa1SSøren Schmidt * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1421ad771aa1SSøren Schmidt * 1422ad771aa1SSøren Schmidt */ 1423ad771aa1SSøren Schmidt 14245f436cfbSKazutaka YOKOTA /** 14255f436cfbSKazutaka YOKOTA ** GlidePoint support from XFree86 3.2. 14265f436cfbSKazutaka YOKOTA ** Derived from the module: 14275f436cfbSKazutaka YOKOTA **/ 1428ad771aa1SSøren Schmidt 14295f436cfbSKazutaka YOKOTA /* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86_Mouse.c,v 3.19 1996/10/16 14:40:51 dawes Exp $ */ 14305f436cfbSKazutaka YOKOTA /* $XConsortium: xf86_Mouse.c /main/10 1996/01/30 15:16:12 kaleb $ */ 14315f436cfbSKazutaka YOKOTA 14325f436cfbSKazutaka YOKOTA /* the following table must be ordered by MOUSE_PROTO_XXX in mouse.h */ 14335f436cfbSKazutaka YOKOTA static unsigned char proto[][7] = { 14345f436cfbSKazutaka YOKOTA /* hd_mask hd_id dp_mask dp_id bytes b4_mask b4_id */ 14355f436cfbSKazutaka YOKOTA { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00 }, /* MicroSoft */ 14365f436cfbSKazutaka YOKOTA { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff }, /* MouseSystems */ 14375f436cfbSKazutaka YOKOTA { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff }, /* Logitech */ 14385f436cfbSKazutaka YOKOTA { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff }, /* MMSeries */ 143936b1e17dSKazutaka YOKOTA { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00 }, /* MouseMan */ 14405f436cfbSKazutaka YOKOTA { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff }, /* Bus */ 14415f436cfbSKazutaka YOKOTA { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff }, /* InPort */ 14425f436cfbSKazutaka YOKOTA { 0xc0, 0x00, 0x00, 0x00, 3, 0x00, 0xff }, /* PS/2 mouse */ 14435f436cfbSKazutaka YOKOTA { 0xe0, 0x80, 0x80, 0x00, 3, 0x00, 0xff }, /* MM HitTablet */ 14445f436cfbSKazutaka YOKOTA { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00 }, /* GlidePoint */ 14455f436cfbSKazutaka YOKOTA { 0x40, 0x40, 0x40, 0x00, 3, ~0x3f, 0x00 }, /* IntelliMouse */ 14465f436cfbSKazutaka YOKOTA { 0x40, 0x40, 0x40, 0x00, 3, ~0x33, 0x00 }, /* ThinkingMouse */ 14475f436cfbSKazutaka YOKOTA { 0xf8, 0x80, 0x00, 0x00, 5, 0x00, 0xff }, /* sysmouse */ 144867978692SAmancio Hasty { 0x40, 0x40, 0x40, 0x00, 3, ~0x23, 0x00 }, /* X10 MouseRem */ 14491b11ca6cSKazutaka YOKOTA { 0x80, 0x80, 0x00, 0x00, 5, 0x00, 0xff }, /* KIDSPAD */ 14502e09fb67SKazutaka YOKOTA { 0xc3, 0xc0, 0x00, 0x00, 6, 0x00, 0xff }, /* VersaPad */ 145105f92020SWill Andrews { 0x00, 0x00, 0x00, 0x00, 1, 0x00, 0xff }, /* JogDial */ 14525f436cfbSKazutaka YOKOTA #if notyet 14535f436cfbSKazutaka YOKOTA { 0xf8, 0x80, 0x00, 0x00, 5, ~0x2f, 0x10 }, /* Mariqua */ 14545f436cfbSKazutaka YOKOTA #endif 14555f436cfbSKazutaka YOKOTA }; 14565f436cfbSKazutaka YOKOTA static unsigned char cur_proto[7]; 14575f436cfbSKazutaka YOKOTA 14585f436cfbSKazutaka YOKOTA static int 14595f436cfbSKazutaka YOKOTA r_identify(void) 14605f436cfbSKazutaka YOKOTA { 14615f436cfbSKazutaka YOKOTA char pnpbuf[256]; /* PnP identifier string may be up to 256 bytes long */ 14625f436cfbSKazutaka YOKOTA pnpid_t pnpid; 14635f436cfbSKazutaka YOKOTA symtab_t *t; 14645f436cfbSKazutaka YOKOTA int level; 14655f436cfbSKazutaka YOKOTA int len; 14665f436cfbSKazutaka YOKOTA 14675f436cfbSKazutaka YOKOTA /* set the driver operation level, if applicable */ 14685f436cfbSKazutaka YOKOTA if (rodent.level < 0) 14695f436cfbSKazutaka YOKOTA rodent.level = 1; 14705f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, MOUSE_SETLEVEL, &rodent.level); 14715f436cfbSKazutaka YOKOTA rodent.level = (ioctl(rodent.mfd, MOUSE_GETLEVEL, &level) == 0) ? level : 0; 14725f436cfbSKazutaka YOKOTA 14735f436cfbSKazutaka YOKOTA /* 14745f436cfbSKazutaka YOKOTA * Interrogate the driver and get some intelligence on the device... 14755f436cfbSKazutaka YOKOTA * The following ioctl functions are not always supported by device 14765f436cfbSKazutaka YOKOTA * drivers. When the driver doesn't support them, we just trust the 14775f436cfbSKazutaka YOKOTA * user to supply valid information. 14785f436cfbSKazutaka YOKOTA */ 14795f436cfbSKazutaka YOKOTA rodent.hw.iftype = MOUSE_IF_UNKNOWN; 14805f436cfbSKazutaka YOKOTA rodent.hw.model = MOUSE_MODEL_GENERIC; 14815f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, MOUSE_GETHWINFO, &rodent.hw); 14825f436cfbSKazutaka YOKOTA 14835f436cfbSKazutaka YOKOTA if (rodent.rtype != MOUSE_PROTO_UNKNOWN) 14845f436cfbSKazutaka YOKOTA bcopy(proto[rodent.rtype], cur_proto, sizeof(cur_proto)); 14855f436cfbSKazutaka YOKOTA rodent.mode.protocol = MOUSE_PROTO_UNKNOWN; 14865f436cfbSKazutaka YOKOTA rodent.mode.rate = -1; 14875f436cfbSKazutaka YOKOTA rodent.mode.resolution = MOUSE_RES_UNKNOWN; 14885f436cfbSKazutaka YOKOTA rodent.mode.accelfactor = 0; 14895f436cfbSKazutaka YOKOTA rodent.mode.level = 0; 14905f436cfbSKazutaka YOKOTA if (ioctl(rodent.mfd, MOUSE_GETMODE, &rodent.mode) == 0) { 14912657f6e9SJung-uk Kim if (rodent.mode.protocol == MOUSE_PROTO_UNKNOWN || 1492*83409a93SElyes Haouas rodent.mode.protocol >= (int)nitems(proto)) { 14935f436cfbSKazutaka YOKOTA logwarnx("unknown mouse protocol (%d)", rodent.mode.protocol); 14942657f6e9SJung-uk Kim return (MOUSE_PROTO_UNKNOWN); 14955f436cfbSKazutaka YOKOTA } else { 14965f436cfbSKazutaka YOKOTA if (rodent.mode.protocol != rodent.rtype) { 14975f436cfbSKazutaka YOKOTA /* Hmm, the driver doesn't agree with the user... */ 14985f436cfbSKazutaka YOKOTA if (rodent.rtype != MOUSE_PROTO_UNKNOWN) 14995f436cfbSKazutaka YOKOTA logwarnx("mouse type mismatch (%s != %s), %s is assumed", 15005f436cfbSKazutaka YOKOTA r_name(rodent.mode.protocol), r_name(rodent.rtype), 15015f436cfbSKazutaka YOKOTA r_name(rodent.mode.protocol)); 15025f436cfbSKazutaka YOKOTA rodent.rtype = rodent.mode.protocol; 15035f436cfbSKazutaka YOKOTA bcopy(proto[rodent.rtype], cur_proto, sizeof(cur_proto)); 15045f436cfbSKazutaka YOKOTA } 15055f436cfbSKazutaka YOKOTA } 15065f436cfbSKazutaka YOKOTA cur_proto[4] = rodent.mode.packetsize; 15075f436cfbSKazutaka YOKOTA cur_proto[0] = rodent.mode.syncmask[0]; /* header byte bit mask */ 15085f436cfbSKazutaka YOKOTA cur_proto[1] = rodent.mode.syncmask[1]; /* header bit pattern */ 15095f436cfbSKazutaka YOKOTA } 15105f436cfbSKazutaka YOKOTA 1511d64ada50SJens Schweikhardt /* maybe this is a PnP mouse... */ 15125f436cfbSKazutaka YOKOTA if (rodent.mode.protocol == MOUSE_PROTO_UNKNOWN) { 15135f436cfbSKazutaka YOKOTA 15145f436cfbSKazutaka YOKOTA if (rodent.flags & NoPnP) 15152657f6e9SJung-uk Kim return (rodent.rtype); 15165f436cfbSKazutaka YOKOTA if (((len = pnpgets(pnpbuf)) <= 0) || !pnpparse(&pnpid, pnpbuf, len)) 15172657f6e9SJung-uk Kim return (rodent.rtype); 15185f436cfbSKazutaka YOKOTA 15195f436cfbSKazutaka YOKOTA debug("PnP serial mouse: '%*.*s' '%*.*s' '%*.*s'", 15205f436cfbSKazutaka YOKOTA pnpid.neisaid, pnpid.neisaid, pnpid.eisaid, 15215f436cfbSKazutaka YOKOTA pnpid.ncompat, pnpid.ncompat, pnpid.compat, 15225f436cfbSKazutaka YOKOTA pnpid.ndescription, pnpid.ndescription, pnpid.description); 15235f436cfbSKazutaka YOKOTA 15245f436cfbSKazutaka YOKOTA /* we have a valid PnP serial device ID */ 15255f436cfbSKazutaka YOKOTA rodent.hw.iftype = MOUSE_IF_SERIAL; 15265f436cfbSKazutaka YOKOTA t = pnpproto(&pnpid); 15275f436cfbSKazutaka YOKOTA if (t != NULL) { 15285f436cfbSKazutaka YOKOTA rodent.mode.protocol = t->val; 15295f436cfbSKazutaka YOKOTA rodent.hw.model = t->val2; 15305f436cfbSKazutaka YOKOTA } else { 15315f436cfbSKazutaka YOKOTA rodent.mode.protocol = MOUSE_PROTO_UNKNOWN; 15325f436cfbSKazutaka YOKOTA } 15335f436cfbSKazutaka YOKOTA 15345f436cfbSKazutaka YOKOTA /* make final adjustment */ 15355f436cfbSKazutaka YOKOTA if (rodent.mode.protocol != MOUSE_PROTO_UNKNOWN) { 15365f436cfbSKazutaka YOKOTA if (rodent.mode.protocol != rodent.rtype) { 15375f436cfbSKazutaka YOKOTA /* Hmm, the device doesn't agree with the user... */ 15385f436cfbSKazutaka YOKOTA if (rodent.rtype != MOUSE_PROTO_UNKNOWN) 15395f436cfbSKazutaka YOKOTA logwarnx("mouse type mismatch (%s != %s), %s is assumed", 15405f436cfbSKazutaka YOKOTA r_name(rodent.mode.protocol), r_name(rodent.rtype), 15415f436cfbSKazutaka YOKOTA r_name(rodent.mode.protocol)); 15425f436cfbSKazutaka YOKOTA rodent.rtype = rodent.mode.protocol; 15435f436cfbSKazutaka YOKOTA bcopy(proto[rodent.rtype], cur_proto, sizeof(cur_proto)); 15445f436cfbSKazutaka YOKOTA } 15455f436cfbSKazutaka YOKOTA } 15465f436cfbSKazutaka YOKOTA } 15475f436cfbSKazutaka YOKOTA 15485f436cfbSKazutaka YOKOTA debug("proto params: %02x %02x %02x %02x %d %02x %02x", 15495f436cfbSKazutaka YOKOTA cur_proto[0], cur_proto[1], cur_proto[2], cur_proto[3], 15505f436cfbSKazutaka YOKOTA cur_proto[4], cur_proto[5], cur_proto[6]); 15515f436cfbSKazutaka YOKOTA 15522657f6e9SJung-uk Kim return (rodent.rtype); 15535f436cfbSKazutaka YOKOTA } 15545f436cfbSKazutaka YOKOTA 15552657f6e9SJung-uk Kim static const char * 15565f436cfbSKazutaka YOKOTA r_if(int iftype) 15575f436cfbSKazutaka YOKOTA { 15585f436cfbSKazutaka YOKOTA 15592657f6e9SJung-uk Kim return (gettokenname(rifs, iftype)); 15605f436cfbSKazutaka YOKOTA } 15615f436cfbSKazutaka YOKOTA 15622657f6e9SJung-uk Kim static const char * 15635f436cfbSKazutaka YOKOTA r_name(int type) 15645f436cfbSKazutaka YOKOTA { 15652657f6e9SJung-uk Kim const char *unknown = "unknown"; 15662657f6e9SJung-uk Kim 1567*83409a93SElyes Haouas return (type == MOUSE_PROTO_UNKNOWN || type >= (int)nitems(rnames) ? 15682657f6e9SJung-uk Kim unknown : rnames[type]); 15695f436cfbSKazutaka YOKOTA } 15705f436cfbSKazutaka YOKOTA 15712657f6e9SJung-uk Kim static const char * 15725f436cfbSKazutaka YOKOTA r_model(int model) 15735f436cfbSKazutaka YOKOTA { 15745f436cfbSKazutaka YOKOTA 15752657f6e9SJung-uk Kim return (gettokenname(rmodels, model)); 15765f436cfbSKazutaka YOKOTA } 15775f436cfbSKazutaka YOKOTA 15785f436cfbSKazutaka YOKOTA static void 1579ad771aa1SSøren Schmidt r_init(void) 1580ad771aa1SSøren Schmidt { 15812e09fb67SKazutaka YOKOTA unsigned char buf[16]; /* scrach buffer */ 15825f436cfbSKazutaka YOKOTA fd_set fds; 15832657f6e9SJung-uk Kim const char *s; 15845f436cfbSKazutaka YOKOTA char c; 15855f436cfbSKazutaka YOKOTA int i; 15865f436cfbSKazutaka YOKOTA 1587ad771aa1SSøren Schmidt /** 1588ad771aa1SSøren Schmidt ** This comment is a little out of context here, but it contains 1589ad771aa1SSøren Schmidt ** some useful information... 1590ad771aa1SSøren Schmidt ******************************************************************** 1591ad771aa1SSøren Schmidt ** 1592ad771aa1SSøren Schmidt ** The following lines take care of the Logitech MouseMan protocols. 1593ad771aa1SSøren Schmidt ** 1594ad771aa1SSøren Schmidt ** NOTE: There are different versions of both MouseMan and TrackMan! 1595ad771aa1SSøren Schmidt ** Hence I add another protocol P_LOGIMAN, which the user can 1596ad771aa1SSøren Schmidt ** specify as MouseMan in his XF86Config file. This entry was 1597ad771aa1SSøren Schmidt ** formerly handled as a special case of P_MS. However, people 1598ad771aa1SSøren Schmidt ** who don't have the middle button problem, can still specify 1599ad771aa1SSøren Schmidt ** Microsoft and use P_MS. 1600ad771aa1SSøren Schmidt ** 1601ad771aa1SSøren Schmidt ** By default, these mice should use a 3 byte Microsoft protocol 1602ad771aa1SSøren Schmidt ** plus a 4th byte for the middle button. However, the mouse might 1603ad771aa1SSøren Schmidt ** have switched to a different protocol before we use it, so I send 1604ad771aa1SSøren Schmidt ** the proper sequence just in case. 1605ad771aa1SSøren Schmidt ** 1606ad771aa1SSøren Schmidt ** NOTE: - all commands to (at least the European) MouseMan have to 1607ad771aa1SSøren Schmidt ** be sent at 1200 Baud. 1608ad771aa1SSøren Schmidt ** - each command starts with a '*'. 1609ad771aa1SSøren Schmidt ** - whenever the MouseMan receives a '*', it will switch back 1610ad771aa1SSøren Schmidt ** to 1200 Baud. Hence I have to select the desired protocol 1611ad771aa1SSøren Schmidt ** first, then select the baud rate. 1612ad771aa1SSøren Schmidt ** 1613ad771aa1SSøren Schmidt ** The protocols supported by the (European) MouseMan are: 1614ad771aa1SSøren Schmidt ** - 5 byte packed binary protocol, as with the Mouse Systems 1615ad771aa1SSøren Schmidt ** mouse. Selected by sequence "*U". 1616ad771aa1SSøren Schmidt ** - 2 button 3 byte MicroSoft compatible protocol. Selected 1617ad771aa1SSøren Schmidt ** by sequence "*V". 1618ad771aa1SSøren Schmidt ** - 3 button 3+1 byte MicroSoft compatible protocol (default). 1619ad771aa1SSøren Schmidt ** Selected by sequence "*X". 1620ad771aa1SSøren Schmidt ** 1621ad771aa1SSøren Schmidt ** The following baud rates are supported: 1622ad771aa1SSøren Schmidt ** - 1200 Baud (default). Selected by sequence "*n". 1623ad771aa1SSøren Schmidt ** - 9600 Baud. Selected by sequence "*q". 1624ad771aa1SSøren Schmidt ** 1625ad771aa1SSøren Schmidt ** Selecting a sample rate is no longer supported with the MouseMan! 1626ad771aa1SSøren Schmidt ** Some additional lines in xf86Config.c take care of ill configured 1627ad771aa1SSøren Schmidt ** baud rates and sample rates. (The user will get an error.) 1628ad771aa1SSøren Schmidt */ 1629ad771aa1SSøren Schmidt 16305f436cfbSKazutaka YOKOTA switch (rodent.rtype) { 1631ad771aa1SSøren Schmidt 16325f436cfbSKazutaka YOKOTA case MOUSE_PROTO_LOGI: 16335f436cfbSKazutaka YOKOTA /* 16345f436cfbSKazutaka YOKOTA * The baud rate selection command must be sent at the current 16355f436cfbSKazutaka YOKOTA * baud rate; try all likely settings 16365f436cfbSKazutaka YOKOTA */ 163713379e47SPeter Wemm setmousespeed(9600, rodent.baudrate, rodentcflags[rodent.rtype]); 163813379e47SPeter Wemm setmousespeed(4800, rodent.baudrate, rodentcflags[rodent.rtype]); 163913379e47SPeter Wemm setmousespeed(2400, rodent.baudrate, rodentcflags[rodent.rtype]); 164013379e47SPeter Wemm setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 16415f436cfbSKazutaka YOKOTA /* select MM series data format */ 1642ad771aa1SSøren Schmidt write(rodent.mfd, "S", 1); 164313379e47SPeter Wemm setmousespeed(rodent.baudrate, rodent.baudrate, 16445f436cfbSKazutaka YOKOTA rodentcflags[MOUSE_PROTO_MM]); 16455f436cfbSKazutaka YOKOTA /* select report rate/frequency */ 16465f436cfbSKazutaka YOKOTA if (rodent.rate <= 0) write(rodent.mfd, "O", 1); 16475f436cfbSKazutaka YOKOTA else if (rodent.rate <= 15) write(rodent.mfd, "J", 1); 16485f436cfbSKazutaka YOKOTA else if (rodent.rate <= 27) write(rodent.mfd, "K", 1); 16495f436cfbSKazutaka YOKOTA else if (rodent.rate <= 42) write(rodent.mfd, "L", 1); 16505f436cfbSKazutaka YOKOTA else if (rodent.rate <= 60) write(rodent.mfd, "R", 1); 16515f436cfbSKazutaka YOKOTA else if (rodent.rate <= 85) write(rodent.mfd, "M", 1); 16525f436cfbSKazutaka YOKOTA else if (rodent.rate <= 125) write(rodent.mfd, "Q", 1); 16535f436cfbSKazutaka YOKOTA else write(rodent.mfd, "N", 1); 16545f436cfbSKazutaka YOKOTA break; 165513379e47SPeter Wemm 16565f436cfbSKazutaka YOKOTA case MOUSE_PROTO_LOGIMOUSEMAN: 16575f436cfbSKazutaka YOKOTA /* The command must always be sent at 1200 baud */ 16585f436cfbSKazutaka YOKOTA setmousespeed(1200, 1200, rodentcflags[rodent.rtype]); 16595f436cfbSKazutaka YOKOTA write(rodent.mfd, "*X", 2); 16605f436cfbSKazutaka YOKOTA setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 16615f436cfbSKazutaka YOKOTA break; 16625f436cfbSKazutaka YOKOTA 16635f436cfbSKazutaka YOKOTA case MOUSE_PROTO_HITTAB: 16645f436cfbSKazutaka YOKOTA setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 16655f436cfbSKazutaka YOKOTA 166613379e47SPeter Wemm /* 166713379e47SPeter Wemm * Initialize Hitachi PUMA Plus - Model 1212E to desired settings. 166813379e47SPeter Wemm * The tablet must be configured to be in MM mode, NO parity, 166913379e47SPeter Wemm * Binary Format. xf86Info.sampleRate controls the sensativity 167013379e47SPeter Wemm * of the tablet. We only use this tablet for it's 4-button puck 167113379e47SPeter Wemm * so we don't run in "Absolute Mode" 167213379e47SPeter Wemm */ 167313379e47SPeter Wemm write(rodent.mfd, "z8", 2); /* Set Parity = "NONE" */ 167413379e47SPeter Wemm usleep(50000); 167513379e47SPeter Wemm write(rodent.mfd, "zb", 2); /* Set Format = "Binary" */ 167613379e47SPeter Wemm usleep(50000); 167713379e47SPeter Wemm write(rodent.mfd, "@", 1); /* Set Report Mode = "Stream" */ 167813379e47SPeter Wemm usleep(50000); 167913379e47SPeter Wemm write(rodent.mfd, "R", 1); /* Set Output Rate = "45 rps" */ 168013379e47SPeter Wemm usleep(50000); 168113379e47SPeter Wemm write(rodent.mfd, "I\x20", 2); /* Set Incrememtal Mode "20" */ 168213379e47SPeter Wemm usleep(50000); 168313379e47SPeter Wemm write(rodent.mfd, "E", 1); /* Set Data Type = "Relative */ 168413379e47SPeter Wemm usleep(50000); 168513379e47SPeter Wemm 16865f436cfbSKazutaka YOKOTA /* Resolution is in 'lines per inch' on the Hitachi tablet */ 16875f436cfbSKazutaka YOKOTA if (rodent.resolution == MOUSE_RES_LOW) c = 'g'; 16885f436cfbSKazutaka YOKOTA else if (rodent.resolution == MOUSE_RES_MEDIUMLOW) c = 'e'; 16895f436cfbSKazutaka YOKOTA else if (rodent.resolution == MOUSE_RES_MEDIUMHIGH) c = 'h'; 16905f436cfbSKazutaka YOKOTA else if (rodent.resolution == MOUSE_RES_HIGH) c = 'd'; 16915f436cfbSKazutaka YOKOTA else if (rodent.resolution <= 40) c = 'g'; 16925f436cfbSKazutaka YOKOTA else if (rodent.resolution <= 100) c = 'd'; 16935f436cfbSKazutaka YOKOTA else if (rodent.resolution <= 200) c = 'e'; 16945f436cfbSKazutaka YOKOTA else if (rodent.resolution <= 500) c = 'h'; 16955f436cfbSKazutaka YOKOTA else if (rodent.resolution <= 1000) c = 'j'; 16965f436cfbSKazutaka YOKOTA else c = 'd'; 16975f436cfbSKazutaka YOKOTA write(rodent.mfd, &c, 1); 169813379e47SPeter Wemm usleep(50000); 169913379e47SPeter Wemm 170013379e47SPeter Wemm write(rodent.mfd, "\021", 1); /* Resume DATA output */ 17015f436cfbSKazutaka YOKOTA break; 17025f436cfbSKazutaka YOKOTA 17035f436cfbSKazutaka YOKOTA case MOUSE_PROTO_THINK: 17045f436cfbSKazutaka YOKOTA setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 17055f436cfbSKazutaka YOKOTA /* the PnP ID string may be sent again, discard it */ 17065f436cfbSKazutaka YOKOTA usleep(200000); 17075f436cfbSKazutaka YOKOTA i = FREAD; 17085f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCFLUSH, &i); 17095f436cfbSKazutaka YOKOTA /* send the command to initialize the beast */ 17105f436cfbSKazutaka YOKOTA for (s = "E5E5"; *s; ++s) { 17115f436cfbSKazutaka YOKOTA write(rodent.mfd, s, 1); 17125f436cfbSKazutaka YOKOTA FD_ZERO(&fds); 17135f436cfbSKazutaka YOKOTA FD_SET(rodent.mfd, &fds); 17145f436cfbSKazutaka YOKOTA if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) <= 0) 17155f436cfbSKazutaka YOKOTA break; 17165f436cfbSKazutaka YOKOTA read(rodent.mfd, &c, 1); 17175f436cfbSKazutaka YOKOTA debug("%c", c); 17185f436cfbSKazutaka YOKOTA if (c != *s) 17195f436cfbSKazutaka YOKOTA break; 1720ad771aa1SSøren Schmidt } 17215f436cfbSKazutaka YOKOTA break; 17225f436cfbSKazutaka YOKOTA 172305f92020SWill Andrews case MOUSE_PROTO_JOGDIAL: 172405f92020SWill Andrews break; 17255f436cfbSKazutaka YOKOTA case MOUSE_PROTO_MSC: 17265f436cfbSKazutaka YOKOTA setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 17275f436cfbSKazutaka YOKOTA if (rodent.flags & ClearDTR) { 17285f436cfbSKazutaka YOKOTA i = TIOCM_DTR; 17295f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIC, &i); 173013379e47SPeter Wemm } 17315f436cfbSKazutaka YOKOTA if (rodent.flags & ClearRTS) { 17325f436cfbSKazutaka YOKOTA i = TIOCM_RTS; 17335f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIC, &i); 173413379e47SPeter Wemm } 17355f436cfbSKazutaka YOKOTA break; 17365f436cfbSKazutaka YOKOTA 17375d6618faSKazutaka YOKOTA case MOUSE_PROTO_SYSMOUSE: 17385d6618faSKazutaka YOKOTA if (rodent.hw.iftype == MOUSE_IF_SYSMOUSE) 17395d6618faSKazutaka YOKOTA setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 1740f0067240SPhilippe Charnier /* FALLTHROUGH */ 17415d6618faSKazutaka YOKOTA 17425f436cfbSKazutaka YOKOTA case MOUSE_PROTO_PS2: 17435f436cfbSKazutaka YOKOTA if (rodent.rate >= 0) 17445f436cfbSKazutaka YOKOTA rodent.mode.rate = rodent.rate; 17455f436cfbSKazutaka YOKOTA if (rodent.resolution != MOUSE_RES_UNKNOWN) 17465f436cfbSKazutaka YOKOTA rodent.mode.resolution = rodent.resolution; 17475f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, MOUSE_SETMODE, &rodent.mode); 17485f436cfbSKazutaka YOKOTA break; 17495f436cfbSKazutaka YOKOTA 175067978692SAmancio Hasty case MOUSE_PROTO_X10MOUSEREM: 175167978692SAmancio Hasty mremote_serversetup(); 175267978692SAmancio Hasty setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 175367978692SAmancio Hasty break; 175467978692SAmancio Hasty 175567978692SAmancio Hasty 17562e09fb67SKazutaka YOKOTA case MOUSE_PROTO_VERSAPAD: 17572e09fb67SKazutaka YOKOTA tcsendbreak(rodent.mfd, 0); /* send break for 400 msec */ 17582e09fb67SKazutaka YOKOTA i = FREAD; 17592e09fb67SKazutaka YOKOTA ioctl(rodent.mfd, TIOCFLUSH, &i); 17602e09fb67SKazutaka YOKOTA for (i = 0; i < 7; ++i) { 17612e09fb67SKazutaka YOKOTA FD_ZERO(&fds); 17622e09fb67SKazutaka YOKOTA FD_SET(rodent.mfd, &fds); 17632e09fb67SKazutaka YOKOTA if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) <= 0) 17642e09fb67SKazutaka YOKOTA break; 17652e09fb67SKazutaka YOKOTA read(rodent.mfd, &c, 1); 17662e09fb67SKazutaka YOKOTA buf[i] = c; 17672e09fb67SKazutaka YOKOTA } 17682e09fb67SKazutaka YOKOTA debug("%s\n", buf); 17692e09fb67SKazutaka YOKOTA if ((buf[0] != 'V') || (buf[1] != 'P')|| (buf[7] != '\r')) 17702e09fb67SKazutaka YOKOTA break; 17712e09fb67SKazutaka YOKOTA setmousespeed(9600, rodent.baudrate, rodentcflags[rodent.rtype]); 17722e09fb67SKazutaka YOKOTA tcsendbreak(rodent.mfd, 0); /* send break for 400 msec again */ 17732e09fb67SKazutaka YOKOTA for (i = 0; i < 7; ++i) { 17742e09fb67SKazutaka YOKOTA FD_ZERO(&fds); 17752e09fb67SKazutaka YOKOTA FD_SET(rodent.mfd, &fds); 17762e09fb67SKazutaka YOKOTA if (select(FD_SETSIZE, &fds, NULL, NULL, NULL) <= 0) 17772e09fb67SKazutaka YOKOTA break; 17782e09fb67SKazutaka YOKOTA read(rodent.mfd, &c, 1); 17792e09fb67SKazutaka YOKOTA debug("%c", c); 17802e09fb67SKazutaka YOKOTA if (c != buf[i]) 17812e09fb67SKazutaka YOKOTA break; 17822e09fb67SKazutaka YOKOTA } 17832e09fb67SKazutaka YOKOTA i = FREAD; 17842e09fb67SKazutaka YOKOTA ioctl(rodent.mfd, TIOCFLUSH, &i); 17852e09fb67SKazutaka YOKOTA break; 17862e09fb67SKazutaka YOKOTA 17875f436cfbSKazutaka YOKOTA default: 17885f436cfbSKazutaka YOKOTA setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 17895f436cfbSKazutaka YOKOTA break; 1790ad771aa1SSøren Schmidt } 1791ad771aa1SSøren Schmidt } 1792ad771aa1SSøren Schmidt 17935f436cfbSKazutaka YOKOTA static int 17945f436cfbSKazutaka YOKOTA r_protocol(u_char rBuf, mousestatus_t *act) 1795ad771aa1SSøren Schmidt { 17965f436cfbSKazutaka YOKOTA /* MOUSE_MSS_BUTTON?DOWN -> MOUSE_BUTTON?DOWN */ 17975f436cfbSKazutaka YOKOTA static int butmapmss[4] = { /* Microsoft, MouseMan, GlidePoint, 17985f436cfbSKazutaka YOKOTA IntelliMouse, Thinking Mouse */ 17995f436cfbSKazutaka YOKOTA 0, 18005f436cfbSKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18015f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18025f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 18035f436cfbSKazutaka YOKOTA }; 18045f436cfbSKazutaka YOKOTA static int butmapmss2[4] = { /* Microsoft, MouseMan, GlidePoint, 18055f436cfbSKazutaka YOKOTA Thinking Mouse */ 18065f436cfbSKazutaka YOKOTA 0, 18075f436cfbSKazutaka YOKOTA MOUSE_BUTTON4DOWN, 18085f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN, 18095f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN | MOUSE_BUTTON4DOWN, 18105f436cfbSKazutaka YOKOTA }; 18115f436cfbSKazutaka YOKOTA /* MOUSE_INTELLI_BUTTON?DOWN -> MOUSE_BUTTON?DOWN */ 18125f436cfbSKazutaka YOKOTA static int butmapintelli[4] = { /* IntelliMouse, NetMouse, Mie Mouse, 18135f436cfbSKazutaka YOKOTA MouseMan+ */ 18145f436cfbSKazutaka YOKOTA 0, 18155f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN, 18165f436cfbSKazutaka YOKOTA MOUSE_BUTTON4DOWN, 18175f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN | MOUSE_BUTTON4DOWN, 18185f436cfbSKazutaka YOKOTA }; 18195f436cfbSKazutaka YOKOTA /* MOUSE_MSC_BUTTON?UP -> MOUSE_BUTTON?DOWN */ 18205f436cfbSKazutaka YOKOTA static int butmapmsc[8] = { /* MouseSystems, MMSeries, Logitech, 18215f436cfbSKazutaka YOKOTA Bus, sysmouse */ 18225f436cfbSKazutaka YOKOTA 0, 18235f436cfbSKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18245f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN, 18255f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 18265f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18275f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 18285f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 18295f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 18305f436cfbSKazutaka YOKOTA }; 18315f436cfbSKazutaka YOKOTA /* MOUSE_PS2_BUTTON?DOWN -> MOUSE_BUTTON?DOWN */ 18325f436cfbSKazutaka YOKOTA static int butmapps2[8] = { /* PS/2 */ 18335f436cfbSKazutaka YOKOTA 0, 18345f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18355f436cfbSKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18365f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 18375f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN, 18385f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 18395f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 18405f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN 18415f436cfbSKazutaka YOKOTA }; 18425f436cfbSKazutaka YOKOTA /* for Hitachi tablet */ 18435f436cfbSKazutaka YOKOTA static int butmaphit[8] = { /* MM HitTablet */ 18445f436cfbSKazutaka YOKOTA 0, 18455f436cfbSKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18465f436cfbSKazutaka YOKOTA MOUSE_BUTTON2DOWN, 18475f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18485f436cfbSKazutaka YOKOTA MOUSE_BUTTON4DOWN, 18495f436cfbSKazutaka YOKOTA MOUSE_BUTTON5DOWN, 18505f436cfbSKazutaka YOKOTA MOUSE_BUTTON6DOWN, 18515f436cfbSKazutaka YOKOTA MOUSE_BUTTON7DOWN, 18525f436cfbSKazutaka YOKOTA }; 18532e09fb67SKazutaka YOKOTA /* for serial VersaPad */ 18542e09fb67SKazutaka YOKOTA static int butmapversa[8] = { /* VersaPad */ 18552e09fb67SKazutaka YOKOTA 0, 18562e09fb67SKazutaka YOKOTA 0, 18572e09fb67SKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18582e09fb67SKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18592e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18602e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18612e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 18622e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 18632e09fb67SKazutaka YOKOTA }; 18642e09fb67SKazutaka YOKOTA /* for PS/2 VersaPad */ 18652e09fb67SKazutaka YOKOTA static int butmapversaps2[8] = { /* VersaPad */ 18662e09fb67SKazutaka YOKOTA 0, 18672e09fb67SKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18682e09fb67SKazutaka YOKOTA 0, 18692e09fb67SKazutaka YOKOTA MOUSE_BUTTON3DOWN, 18702e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18712e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 18722e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN, 18732e09fb67SKazutaka YOKOTA MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 18742e09fb67SKazutaka YOKOTA }; 1875ad771aa1SSøren Schmidt static int pBufP = 0; 1876ad771aa1SSøren Schmidt static unsigned char pBuf[8]; 18772e09fb67SKazutaka YOKOTA static int prev_x, prev_y; 18782e09fb67SKazutaka YOKOTA static int on = FALSE; 18792e09fb67SKazutaka YOKOTA int x, y; 1880ad771aa1SSøren Schmidt 1881ad771aa1SSøren Schmidt debug("received char 0x%x",(int)rBuf); 18821b11ca6cSKazutaka YOKOTA if (rodent.rtype == MOUSE_PROTO_KIDSPAD) 18832657f6e9SJung-uk Kim return (kidspad(rBuf, act)); 1884ce99e877SMatthew N. Dodd if (rodent.rtype == MOUSE_PROTO_GTCO_DIGIPAD) 18852657f6e9SJung-uk Kim return (gtco_digipad(rBuf, act)); 1886ad771aa1SSøren Schmidt 1887ad771aa1SSøren Schmidt /* 1888ad771aa1SSøren Schmidt * Hack for resyncing: We check here for a package that is: 1889ad771aa1SSøren Schmidt * a) illegal (detected by wrong data-package header) 1890ad771aa1SSøren Schmidt * b) invalid (0x80 == -128 and that might be wrong for MouseSystems) 1891ad771aa1SSøren Schmidt * c) bad header-package 1892ad771aa1SSøren Schmidt * 1893ad771aa1SSøren Schmidt * NOTE: b) is a voilation of the MouseSystems-Protocol, since values of 1894ad771aa1SSøren Schmidt * -128 are allowed, but since they are very seldom we can easily 1895ad771aa1SSøren Schmidt * use them as package-header with no button pressed. 1896ad771aa1SSøren Schmidt * NOTE/2: On a PS/2 mouse any byte is valid as a data byte. Furthermore, 1897ad771aa1SSøren Schmidt * 0x80 is not valid as a header byte. For a PS/2 mouse we skip 1898ad771aa1SSøren Schmidt * checking data bytes. 1899ad771aa1SSøren Schmidt * For resyncing a PS/2 mouse we require the two most significant 1900ad771aa1SSøren Schmidt * bits in the header byte to be 0. These are the overflow bits, 1901ad771aa1SSøren Schmidt * and in case of an overflow we actually lose sync. Overflows 1902ad771aa1SSøren Schmidt * are very rare, however, and we quickly gain sync again after 1903ad771aa1SSøren Schmidt * an overflow condition. This is the best we can do. (Actually, 1904ad771aa1SSøren Schmidt * we could use bit 0x08 in the header byte for resyncing, since 1905ad771aa1SSøren Schmidt * that bit is supposed to be always on, but nobody told 1906ad771aa1SSøren Schmidt * Microsoft...) 1907ad771aa1SSøren Schmidt */ 1908ad771aa1SSøren Schmidt 19095f436cfbSKazutaka YOKOTA if (pBufP != 0 && rodent.rtype != MOUSE_PROTO_PS2 && 19105f436cfbSKazutaka YOKOTA ((rBuf & cur_proto[2]) != cur_proto[3] || rBuf == 0x80)) 1911ad771aa1SSøren Schmidt { 1912ad771aa1SSøren Schmidt pBufP = 0; /* skip package */ 1913ad771aa1SSøren Schmidt } 1914ad771aa1SSøren Schmidt 19155f436cfbSKazutaka YOKOTA if (pBufP == 0 && (rBuf & cur_proto[0]) != cur_proto[1]) 19162657f6e9SJung-uk Kim return (0); 19175f436cfbSKazutaka YOKOTA 19185f436cfbSKazutaka YOKOTA /* is there an extra data byte? */ 19195f436cfbSKazutaka YOKOTA if (pBufP >= cur_proto[4] && (rBuf & cur_proto[0]) != cur_proto[1]) 1920ad771aa1SSøren Schmidt { 1921ad771aa1SSøren Schmidt /* 1922ad771aa1SSøren Schmidt * Hack for Logitech MouseMan Mouse - Middle button 1923ad771aa1SSøren Schmidt * 1924ad771aa1SSøren Schmidt * Unfortunately this mouse has variable length packets: the standard 1925ad771aa1SSøren Schmidt * Microsoft 3 byte packet plus an optional 4th byte whenever the 1926ad771aa1SSøren Schmidt * middle button status changes. 1927ad771aa1SSøren Schmidt * 1928ad771aa1SSøren Schmidt * We have already processed the standard packet with the movement 1929ad771aa1SSøren Schmidt * and button info. Now post an event message with the old status 1930ad771aa1SSøren Schmidt * of the left and right buttons and the updated middle button. 1931ad771aa1SSøren Schmidt */ 1932ad771aa1SSøren Schmidt 1933ad771aa1SSøren Schmidt /* 1934ad771aa1SSøren Schmidt * Even worse, different MouseMen and TrackMen differ in the 4th 1935ad771aa1SSøren Schmidt * byte: some will send 0x00/0x20, others 0x01/0x21, or even 1936ad771aa1SSøren Schmidt * 0x02/0x22, so I have to strip off the lower bits. 19375f436cfbSKazutaka YOKOTA * 19385f436cfbSKazutaka YOKOTA * [JCH-96/01/21] 19395f436cfbSKazutaka YOKOTA * HACK for ALPS "fourth button". (It's bit 0x10 of the "fourth byte" 19405f436cfbSKazutaka YOKOTA * and it is activated by tapping the glidepad with the finger! 8^) 19415f436cfbSKazutaka YOKOTA * We map it to bit bit3, and the reverse map in xf86Events just has 19425f436cfbSKazutaka YOKOTA * to be extended so that it is identified as Button 4. The lower 19435f436cfbSKazutaka YOKOTA * half of the reverse-map may remain unchanged. 1944ad771aa1SSøren Schmidt */ 19455f436cfbSKazutaka YOKOTA 19465f436cfbSKazutaka YOKOTA /* 19475f436cfbSKazutaka YOKOTA * [KY-97/08/03] 1948d7d97eb0SJeroen Ruigrok van der Werven * Receive the fourth byte only when preceding three bytes have 19495f436cfbSKazutaka YOKOTA * been detected (pBufP >= cur_proto[4]). In the previous 19505f436cfbSKazutaka YOKOTA * versions, the test was pBufP == 0; thus, we may have mistakingly 1951d7d97eb0SJeroen Ruigrok van der Werven * received a byte even if we didn't see anything preceding 19525f436cfbSKazutaka YOKOTA * the byte. 19535f436cfbSKazutaka YOKOTA */ 19545f436cfbSKazutaka YOKOTA 19555f436cfbSKazutaka YOKOTA if ((rBuf & cur_proto[5]) != cur_proto[6]) { 19565f436cfbSKazutaka YOKOTA pBufP = 0; 19572657f6e9SJung-uk Kim return (0); 1958ad771aa1SSøren Schmidt } 1959ad771aa1SSøren Schmidt 19605f436cfbSKazutaka YOKOTA switch (rodent.rtype) { 19615f436cfbSKazutaka YOKOTA #if notyet 19625f436cfbSKazutaka YOKOTA case MOUSE_PROTO_MARIQUA: 19635f436cfbSKazutaka YOKOTA /* 19645f436cfbSKazutaka YOKOTA * This mouse has 16! buttons in addition to the standard 19655f436cfbSKazutaka YOKOTA * three of them. They return 0x10 though 0x1f in the 19665f436cfbSKazutaka YOKOTA * so-called `ten key' mode and 0x30 though 0x3f in the 19675f436cfbSKazutaka YOKOTA * `function key' mode. As there are only 31 bits for 19685f436cfbSKazutaka YOKOTA * button state (including the standard three), we ignore 19695f436cfbSKazutaka YOKOTA * the bit 0x20 and don't distinguish the two modes. 19705f436cfbSKazutaka YOKOTA */ 19715f436cfbSKazutaka YOKOTA act->dx = act->dy = act->dz = 0; 19725f436cfbSKazutaka YOKOTA act->obutton = act->button; 19735f436cfbSKazutaka YOKOTA rBuf &= 0x1f; 19745f436cfbSKazutaka YOKOTA act->button = (1 << (rBuf - 13)) 19755f436cfbSKazutaka YOKOTA | (act->obutton & (MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN)); 19765f436cfbSKazutaka YOKOTA /* 19775f436cfbSKazutaka YOKOTA * FIXME: this is a button "down" event. There needs to be 19785f436cfbSKazutaka YOKOTA * a corresponding button "up" event... XXX 19795f436cfbSKazutaka YOKOTA */ 19805f436cfbSKazutaka YOKOTA break; 19815f436cfbSKazutaka YOKOTA #endif /* notyet */ 198205f92020SWill Andrews case MOUSE_PROTO_JOGDIAL: 198305f92020SWill Andrews break; 19845f436cfbSKazutaka YOKOTA 19855f436cfbSKazutaka YOKOTA /* 19865f436cfbSKazutaka YOKOTA * IntelliMouse, NetMouse (including NetMouse Pro) and Mie Mouse 19875f436cfbSKazutaka YOKOTA * always send the fourth byte, whereas the fourth byte is 19885f436cfbSKazutaka YOKOTA * optional for GlidePoint and ThinkingMouse. The fourth byte 19895f436cfbSKazutaka YOKOTA * is also optional for MouseMan+ and FirstMouse+ in their 19905f436cfbSKazutaka YOKOTA * native mode. It is always sent if they are in the IntelliMouse 19915f436cfbSKazutaka YOKOTA * compatible mode. 19925f436cfbSKazutaka YOKOTA */ 19935f436cfbSKazutaka YOKOTA case MOUSE_PROTO_INTELLI: /* IntelliMouse, NetMouse, Mie Mouse, 19945f436cfbSKazutaka YOKOTA MouseMan+ */ 19955f436cfbSKazutaka YOKOTA act->dx = act->dy = 0; 19965f436cfbSKazutaka YOKOTA act->dz = (rBuf & 0x08) ? (rBuf & 0x0f) - 16 : (rBuf & 0x0f); 1997fb966343SKazutaka YOKOTA if ((act->dz >= 7) || (act->dz <= -7)) 1998fb966343SKazutaka YOKOTA act->dz = 0; 19995f436cfbSKazutaka YOKOTA act->obutton = act->button; 20005f436cfbSKazutaka YOKOTA act->button = butmapintelli[(rBuf & MOUSE_MSS_BUTTONS) >> 4] 20015f436cfbSKazutaka YOKOTA | (act->obutton & (MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN)); 20025f436cfbSKazutaka YOKOTA break; 20035f436cfbSKazutaka YOKOTA 20045f436cfbSKazutaka YOKOTA default: 20055f436cfbSKazutaka YOKOTA act->dx = act->dy = act->dz = 0; 20065f436cfbSKazutaka YOKOTA act->obutton = act->button; 20075f436cfbSKazutaka YOKOTA act->button = butmapmss2[(rBuf & MOUSE_MSS_BUTTONS) >> 4] 20085f436cfbSKazutaka YOKOTA | (act->obutton & (MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN)); 20095f436cfbSKazutaka YOKOTA break; 2010ad771aa1SSøren Schmidt } 2011ad771aa1SSøren Schmidt 20125f436cfbSKazutaka YOKOTA act->flags = ((act->dx || act->dy || act->dz) ? MOUSE_POSCHANGED : 0) 20135f436cfbSKazutaka YOKOTA | (act->obutton ^ act->button); 20145f436cfbSKazutaka YOKOTA pBufP = 0; 20152657f6e9SJung-uk Kim return (act->flags); 20165f436cfbSKazutaka YOKOTA } 20175f436cfbSKazutaka YOKOTA 20185f436cfbSKazutaka YOKOTA if (pBufP >= cur_proto[4]) 20195f436cfbSKazutaka YOKOTA pBufP = 0; 2020ad771aa1SSøren Schmidt pBuf[pBufP++] = rBuf; 20215f436cfbSKazutaka YOKOTA if (pBufP != cur_proto[4]) 20222657f6e9SJung-uk Kim return (0); 2023ad771aa1SSøren Schmidt 2024ad771aa1SSøren Schmidt /* 2025ad771aa1SSøren Schmidt * assembly full package 2026ad771aa1SSøren Schmidt */ 2027ad771aa1SSøren Schmidt 20285f436cfbSKazutaka YOKOTA debug("assembled full packet (len %d) %x,%x,%x,%x,%x,%x,%x,%x", 20295f436cfbSKazutaka YOKOTA cur_proto[4], 20305f436cfbSKazutaka YOKOTA pBuf[0], pBuf[1], pBuf[2], pBuf[3], 20315f436cfbSKazutaka YOKOTA pBuf[4], pBuf[5], pBuf[6], pBuf[7]); 2032ad771aa1SSøren Schmidt 20335f436cfbSKazutaka YOKOTA act->dz = 0; 20345f436cfbSKazutaka YOKOTA act->obutton = act->button; 2035ad771aa1SSøren Schmidt switch (rodent.rtype) 2036ad771aa1SSøren Schmidt { 20375f436cfbSKazutaka YOKOTA case MOUSE_PROTO_MS: /* Microsoft */ 20385f436cfbSKazutaka YOKOTA case MOUSE_PROTO_LOGIMOUSEMAN: /* MouseMan/TrackMan */ 203967978692SAmancio Hasty case MOUSE_PROTO_X10MOUSEREM: /* X10 MouseRemote */ 204036b1e17dSKazutaka YOKOTA act->button = act->obutton & MOUSE_BUTTON4DOWN; 2041ad771aa1SSøren Schmidt if (rodent.flags & ChordMiddle) 204236b1e17dSKazutaka YOKOTA act->button |= ((pBuf[0] & MOUSE_MSS_BUTTONS) == MOUSE_MSS_BUTTONS) 20435f436cfbSKazutaka YOKOTA ? MOUSE_BUTTON2DOWN 20445f436cfbSKazutaka YOKOTA : butmapmss[(pBuf[0] & MOUSE_MSS_BUTTONS) >> 4]; 2045ad771aa1SSøren Schmidt else 204636b1e17dSKazutaka YOKOTA act->button |= (act->obutton & MOUSE_BUTTON2DOWN) 20475f436cfbSKazutaka YOKOTA | butmapmss[(pBuf[0] & MOUSE_MSS_BUTTONS) >> 4]; 204867978692SAmancio Hasty 204967978692SAmancio Hasty /* Send X10 btn events to remote client (ensure -128-+127 range) */ 205067978692SAmancio Hasty if ((rodent.rtype == MOUSE_PROTO_X10MOUSEREM) && 205167978692SAmancio Hasty ((pBuf[0] & 0xFC) == 0x44) && (pBuf[2] == 0x3F)) { 205267978692SAmancio Hasty if (rodent.mremcfd >= 0) { 205367978692SAmancio Hasty unsigned char key = (signed char)(((pBuf[0] & 0x03) << 6) | 205467978692SAmancio Hasty (pBuf[1] & 0x3F)); 205567978692SAmancio Hasty write(rodent.mremcfd, &key, 1); 205667978692SAmancio Hasty } 20572657f6e9SJung-uk Kim return (0); 205867978692SAmancio Hasty } 205967978692SAmancio Hasty 20608f810e50SAkinori MUSHA act->dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 20618f810e50SAkinori MUSHA act->dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 2062ad771aa1SSøren Schmidt break; 2063ad771aa1SSøren Schmidt 20645f436cfbSKazutaka YOKOTA case MOUSE_PROTO_GLIDEPOINT: /* GlidePoint */ 20655f436cfbSKazutaka YOKOTA case MOUSE_PROTO_THINK: /* ThinkingMouse */ 20665f436cfbSKazutaka YOKOTA case MOUSE_PROTO_INTELLI: /* IntelliMouse, NetMouse, Mie Mouse, 20675f436cfbSKazutaka YOKOTA MouseMan+ */ 20685f436cfbSKazutaka YOKOTA act->button = (act->obutton & (MOUSE_BUTTON2DOWN | MOUSE_BUTTON4DOWN)) 20695f436cfbSKazutaka YOKOTA | butmapmss[(pBuf[0] & MOUSE_MSS_BUTTONS) >> 4]; 20708f810e50SAkinori MUSHA act->dx = (signed char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 20718f810e50SAkinori MUSHA act->dy = (signed char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 2072ad771aa1SSøren Schmidt break; 2073ad771aa1SSøren Schmidt 20745f436cfbSKazutaka YOKOTA case MOUSE_PROTO_MSC: /* MouseSystems Corp */ 20755f436cfbSKazutaka YOKOTA #if notyet 20765f436cfbSKazutaka YOKOTA case MOUSE_PROTO_MARIQUA: /* Mariqua */ 20775f436cfbSKazutaka YOKOTA #endif 20785f436cfbSKazutaka YOKOTA act->button = butmapmsc[(~pBuf[0]) & MOUSE_MSC_BUTTONS]; 20798f810e50SAkinori MUSHA act->dx = (signed char)(pBuf[1]) + (signed char)(pBuf[3]); 20808f810e50SAkinori MUSHA act->dy = - ((signed char)(pBuf[2]) + (signed char)(pBuf[4])); 208113379e47SPeter Wemm break; 208213379e47SPeter Wemm 208305f92020SWill Andrews case MOUSE_PROTO_JOGDIAL: /* JogDial */ 208405f92020SWill Andrews if (rBuf == 0x6c) 208505f92020SWill Andrews act->dz = -1; 208605f92020SWill Andrews if (rBuf == 0x72) 208705f92020SWill Andrews act->dz = 1; 208805f92020SWill Andrews if (rBuf == 0x64) 208905f92020SWill Andrews act->button = MOUSE_BUTTON1DOWN; 209005f92020SWill Andrews if (rBuf == 0x75) 209105f92020SWill Andrews act->button = 0; 209205f92020SWill Andrews break; 209305f92020SWill Andrews 20945f436cfbSKazutaka YOKOTA case MOUSE_PROTO_HITTAB: /* MM HitTablet */ 20955f436cfbSKazutaka YOKOTA act->button = butmaphit[pBuf[0] & 0x07]; 20965f436cfbSKazutaka YOKOTA act->dx = (pBuf[0] & MOUSE_MM_XPOSITIVE) ? pBuf[1] : - pBuf[1]; 20975f436cfbSKazutaka YOKOTA act->dy = (pBuf[0] & MOUSE_MM_YPOSITIVE) ? - pBuf[2] : pBuf[2]; 2098ad771aa1SSøren Schmidt break; 2099ad771aa1SSøren Schmidt 21005f436cfbSKazutaka YOKOTA case MOUSE_PROTO_MM: /* MM Series */ 21015f436cfbSKazutaka YOKOTA case MOUSE_PROTO_LOGI: /* Logitech Mice */ 21025f436cfbSKazutaka YOKOTA act->button = butmapmsc[pBuf[0] & MOUSE_MSC_BUTTONS]; 21035f436cfbSKazutaka YOKOTA act->dx = (pBuf[0] & MOUSE_MM_XPOSITIVE) ? pBuf[1] : - pBuf[1]; 21045f436cfbSKazutaka YOKOTA act->dy = (pBuf[0] & MOUSE_MM_YPOSITIVE) ? - pBuf[2] : pBuf[2]; 2105ad771aa1SSøren Schmidt break; 2106ad771aa1SSøren Schmidt 21072e09fb67SKazutaka YOKOTA case MOUSE_PROTO_VERSAPAD: /* VersaPad */ 21082e09fb67SKazutaka YOKOTA act->button = butmapversa[(pBuf[0] & MOUSE_VERSA_BUTTONS) >> 3]; 21092e09fb67SKazutaka YOKOTA act->button |= (pBuf[0] & MOUSE_VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0; 21102e09fb67SKazutaka YOKOTA act->dx = act->dy = 0; 21112e09fb67SKazutaka YOKOTA if (!(pBuf[0] & MOUSE_VERSA_IN_USE)) { 21122e09fb67SKazutaka YOKOTA on = FALSE; 21132e09fb67SKazutaka YOKOTA break; 21142e09fb67SKazutaka YOKOTA } 21152e09fb67SKazutaka YOKOTA x = (pBuf[2] << 6) | pBuf[1]; 21162e09fb67SKazutaka YOKOTA if (x & 0x800) 21172e09fb67SKazutaka YOKOTA x -= 0x1000; 21182e09fb67SKazutaka YOKOTA y = (pBuf[4] << 6) | pBuf[3]; 21192e09fb67SKazutaka YOKOTA if (y & 0x800) 21202e09fb67SKazutaka YOKOTA y -= 0x1000; 21212e09fb67SKazutaka YOKOTA if (on) { 21222e09fb67SKazutaka YOKOTA act->dx = prev_x - x; 21232e09fb67SKazutaka YOKOTA act->dy = prev_y - y; 21242e09fb67SKazutaka YOKOTA } else { 21252e09fb67SKazutaka YOKOTA on = TRUE; 21262e09fb67SKazutaka YOKOTA } 21272e09fb67SKazutaka YOKOTA prev_x = x; 21282e09fb67SKazutaka YOKOTA prev_y = y; 21292e09fb67SKazutaka YOKOTA break; 21302e09fb67SKazutaka YOKOTA 21315f436cfbSKazutaka YOKOTA case MOUSE_PROTO_PS2: /* PS/2 */ 21325f436cfbSKazutaka YOKOTA act->button = butmapps2[pBuf[0] & MOUSE_PS2_BUTTONS]; 21335f436cfbSKazutaka YOKOTA act->dx = (pBuf[0] & MOUSE_PS2_XNEG) ? pBuf[1] - 256 : pBuf[1]; 21345f436cfbSKazutaka YOKOTA act->dy = (pBuf[0] & MOUSE_PS2_YNEG) ? -(pBuf[2] - 256) : -pBuf[2]; 21355f436cfbSKazutaka YOKOTA /* 21365f436cfbSKazutaka YOKOTA * Moused usually operates the psm driver at the operation level 1 21375f436cfbSKazutaka YOKOTA * which sends mouse data in MOUSE_PROTO_SYSMOUSE protocol. 21385f436cfbSKazutaka YOKOTA * The following code takes effect only when the user explicitly 21395f436cfbSKazutaka YOKOTA * requets the level 2 at which wheel movement and additional button 21405f436cfbSKazutaka YOKOTA * actions are encoded in model-dependent formats. At the level 0 21415f436cfbSKazutaka YOKOTA * the following code is no-op because the psm driver says the model 21425f436cfbSKazutaka YOKOTA * is MOUSE_MODEL_GENERIC. 21435f436cfbSKazutaka YOKOTA */ 21445f436cfbSKazutaka YOKOTA switch (rodent.hw.model) { 2145fb966343SKazutaka YOKOTA case MOUSE_MODEL_EXPLORER: 2146fb966343SKazutaka YOKOTA /* wheel and additional button data is in the fourth byte */ 2147fb966343SKazutaka YOKOTA act->dz = (pBuf[3] & MOUSE_EXPLORER_ZNEG) 2148fb966343SKazutaka YOKOTA ? (pBuf[3] & 0x0f) - 16 : (pBuf[3] & 0x0f); 2149fb966343SKazutaka YOKOTA act->button |= (pBuf[3] & MOUSE_EXPLORER_BUTTON4DOWN) 2150fb966343SKazutaka YOKOTA ? MOUSE_BUTTON4DOWN : 0; 2151fb966343SKazutaka YOKOTA act->button |= (pBuf[3] & MOUSE_EXPLORER_BUTTON5DOWN) 2152fb966343SKazutaka YOKOTA ? MOUSE_BUTTON5DOWN : 0; 2153fb966343SKazutaka YOKOTA break; 21545f436cfbSKazutaka YOKOTA case MOUSE_MODEL_INTELLI: 21555f436cfbSKazutaka YOKOTA case MOUSE_MODEL_NET: 21565f436cfbSKazutaka YOKOTA /* wheel data is in the fourth byte */ 21578f810e50SAkinori MUSHA act->dz = (signed char)pBuf[3]; 2158fb966343SKazutaka YOKOTA if ((act->dz >= 7) || (act->dz <= -7)) 2159fb966343SKazutaka YOKOTA act->dz = 0; 2160fb966343SKazutaka YOKOTA /* some compatible mice may have additional buttons */ 2161fb966343SKazutaka YOKOTA act->button |= (pBuf[0] & MOUSE_PS2INTELLI_BUTTON4DOWN) 2162fb966343SKazutaka YOKOTA ? MOUSE_BUTTON4DOWN : 0; 2163fb966343SKazutaka YOKOTA act->button |= (pBuf[0] & MOUSE_PS2INTELLI_BUTTON5DOWN) 2164fb966343SKazutaka YOKOTA ? MOUSE_BUTTON5DOWN : 0; 21655f436cfbSKazutaka YOKOTA break; 21665f436cfbSKazutaka YOKOTA case MOUSE_MODEL_MOUSEMANPLUS: 216701533d85SKazutaka YOKOTA if (((pBuf[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) 216801533d85SKazutaka YOKOTA && (abs(act->dx) > 191) 216901533d85SKazutaka YOKOTA && MOUSE_PS2PLUS_CHECKBITS(pBuf)) { 21705f436cfbSKazutaka YOKOTA /* the extended data packet encodes button and wheel events */ 217101533d85SKazutaka YOKOTA switch (MOUSE_PS2PLUS_PACKET_TYPE(pBuf)) { 217201533d85SKazutaka YOKOTA case 1: 217301533d85SKazutaka YOKOTA /* wheel data packet */ 21745f436cfbSKazutaka YOKOTA act->dx = act->dy = 0; 217501533d85SKazutaka YOKOTA if (pBuf[2] & 0x80) { 217601533d85SKazutaka YOKOTA /* horizontal roller count - ignore it XXX*/ 217701533d85SKazutaka YOKOTA } else { 217801533d85SKazutaka YOKOTA /* vertical roller count */ 21792b9e6c75SKazutaka YOKOTA act->dz = (pBuf[2] & MOUSE_PS2PLUS_ZNEG) 21805f436cfbSKazutaka YOKOTA ? (pBuf[2] & 0x0f) - 16 : (pBuf[2] & 0x0f); 218101533d85SKazutaka YOKOTA } 218201533d85SKazutaka YOKOTA act->button |= (pBuf[2] & MOUSE_PS2PLUS_BUTTON4DOWN) 218301533d85SKazutaka YOKOTA ? MOUSE_BUTTON4DOWN : 0; 218401533d85SKazutaka YOKOTA act->button |= (pBuf[2] & MOUSE_PS2PLUS_BUTTON5DOWN) 218501533d85SKazutaka YOKOTA ? MOUSE_BUTTON5DOWN : 0; 218601533d85SKazutaka YOKOTA break; 218701533d85SKazutaka YOKOTA case 2: 2188fb966343SKazutaka YOKOTA /* this packet type is reserved by Logitech */ 2189fb966343SKazutaka YOKOTA /* 2190fb966343SKazutaka YOKOTA * IBM ScrollPoint Mouse uses this packet type to 2191fb966343SKazutaka YOKOTA * encode both vertical and horizontal scroll movement. 2192fb966343SKazutaka YOKOTA */ 2193fb966343SKazutaka YOKOTA act->dx = act->dy = 0; 2194fb966343SKazutaka YOKOTA /* horizontal roller count */ 2195fb966343SKazutaka YOKOTA if (pBuf[2] & 0x0f) 2196fb966343SKazutaka YOKOTA act->dz = (pBuf[2] & MOUSE_SPOINT_WNEG) ? -2 : 2; 2197fb966343SKazutaka YOKOTA /* vertical roller count */ 2198fb966343SKazutaka YOKOTA if (pBuf[2] & 0xf0) 2199fb966343SKazutaka YOKOTA act->dz = (pBuf[2] & MOUSE_SPOINT_ZNEG) ? -1 : 1; 2200fb966343SKazutaka YOKOTA #if 0 2201fb966343SKazutaka YOKOTA /* vertical roller count */ 2202fb966343SKazutaka YOKOTA act->dz = (pBuf[2] & MOUSE_SPOINT_ZNEG) 2203fb966343SKazutaka YOKOTA ? ((pBuf[2] >> 4) & 0x0f) - 16 2204fb966343SKazutaka YOKOTA : ((pBuf[2] >> 4) & 0x0f); 2205fb966343SKazutaka YOKOTA /* horizontal roller count */ 2206fb966343SKazutaka YOKOTA act->dw = (pBuf[2] & MOUSE_SPOINT_WNEG) 2207fb966343SKazutaka YOKOTA ? (pBuf[2] & 0x0f) - 16 : (pBuf[2] & 0x0f); 2208fb966343SKazutaka YOKOTA #endif 2209fb966343SKazutaka YOKOTA break; 221001533d85SKazutaka YOKOTA case 0: 221101533d85SKazutaka YOKOTA /* device type packet - shouldn't happen */ 221201533d85SKazutaka YOKOTA /* FALLTHROUGH */ 221301533d85SKazutaka YOKOTA default: 221401533d85SKazutaka YOKOTA act->dx = act->dy = 0; 221501533d85SKazutaka YOKOTA act->button = act->obutton; 221601533d85SKazutaka YOKOTA debug("unknown PS2++ packet type %d: 0x%02x 0x%02x 0x%02x\n", 221701533d85SKazutaka YOKOTA MOUSE_PS2PLUS_PACKET_TYPE(pBuf), 221801533d85SKazutaka YOKOTA pBuf[0], pBuf[1], pBuf[2]); 221901533d85SKazutaka YOKOTA break; 222001533d85SKazutaka YOKOTA } 22215f436cfbSKazutaka YOKOTA } else { 22225f436cfbSKazutaka YOKOTA /* preserve button states */ 22235f436cfbSKazutaka YOKOTA act->button |= act->obutton & MOUSE_EXTBUTTONS; 22245f436cfbSKazutaka YOKOTA } 22255f436cfbSKazutaka YOKOTA break; 22265f436cfbSKazutaka YOKOTA case MOUSE_MODEL_GLIDEPOINT: 22275f436cfbSKazutaka YOKOTA /* `tapping' action */ 22285f436cfbSKazutaka YOKOTA act->button |= ((pBuf[0] & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN; 22295f436cfbSKazutaka YOKOTA break; 22305f436cfbSKazutaka YOKOTA case MOUSE_MODEL_NETSCROLL: 22313df5ecacSUlrich Spörlein /* three additional bytes encode buttons and wheel events */ 22325f436cfbSKazutaka YOKOTA act->button |= (pBuf[3] & MOUSE_PS2_BUTTON3DOWN) 22335f436cfbSKazutaka YOKOTA ? MOUSE_BUTTON4DOWN : 0; 2234fb966343SKazutaka YOKOTA act->button |= (pBuf[3] & MOUSE_PS2_BUTTON1DOWN) 2235fb966343SKazutaka YOKOTA ? MOUSE_BUTTON5DOWN : 0; 22365f436cfbSKazutaka YOKOTA act->dz = (pBuf[3] & MOUSE_PS2_XNEG) ? pBuf[4] - 256 : pBuf[4]; 22375f436cfbSKazutaka YOKOTA break; 22385f436cfbSKazutaka YOKOTA case MOUSE_MODEL_THINK: 22395f436cfbSKazutaka YOKOTA /* the fourth button state in the first byte */ 22405f436cfbSKazutaka YOKOTA act->button |= (pBuf[0] & MOUSE_PS2_TAP) ? MOUSE_BUTTON4DOWN : 0; 22415f436cfbSKazutaka YOKOTA break; 22422e09fb67SKazutaka YOKOTA case MOUSE_MODEL_VERSAPAD: 22432e09fb67SKazutaka YOKOTA act->button = butmapversaps2[pBuf[0] & MOUSE_PS2VERSA_BUTTONS]; 22442e09fb67SKazutaka YOKOTA act->button |= 22452e09fb67SKazutaka YOKOTA (pBuf[0] & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0; 22462e09fb67SKazutaka YOKOTA act->dx = act->dy = 0; 22472e09fb67SKazutaka YOKOTA if (!(pBuf[0] & MOUSE_PS2VERSA_IN_USE)) { 22482e09fb67SKazutaka YOKOTA on = FALSE; 22492e09fb67SKazutaka YOKOTA break; 22502e09fb67SKazutaka YOKOTA } 22512e09fb67SKazutaka YOKOTA x = ((pBuf[4] << 8) & 0xf00) | pBuf[1]; 22522e09fb67SKazutaka YOKOTA if (x & 0x800) 22532e09fb67SKazutaka YOKOTA x -= 0x1000; 22542e09fb67SKazutaka YOKOTA y = ((pBuf[4] << 4) & 0xf00) | pBuf[2]; 22552e09fb67SKazutaka YOKOTA if (y & 0x800) 22562e09fb67SKazutaka YOKOTA y -= 0x1000; 22572e09fb67SKazutaka YOKOTA if (on) { 22582e09fb67SKazutaka YOKOTA act->dx = prev_x - x; 22592e09fb67SKazutaka YOKOTA act->dy = prev_y - y; 22602e09fb67SKazutaka YOKOTA } else { 22612e09fb67SKazutaka YOKOTA on = TRUE; 22622e09fb67SKazutaka YOKOTA } 22632e09fb67SKazutaka YOKOTA prev_x = x; 22642e09fb67SKazutaka YOKOTA prev_y = y; 22652e09fb67SKazutaka YOKOTA break; 2266fb966343SKazutaka YOKOTA case MOUSE_MODEL_4D: 2267fb966343SKazutaka YOKOTA act->dx = (pBuf[1] & 0x80) ? pBuf[1] - 256 : pBuf[1]; 2268fb966343SKazutaka YOKOTA act->dy = (pBuf[2] & 0x80) ? -(pBuf[2] - 256) : -pBuf[2]; 2269fb966343SKazutaka YOKOTA switch (pBuf[0] & MOUSE_4D_WHEELBITS) { 2270fb966343SKazutaka YOKOTA case 0x10: 2271fb966343SKazutaka YOKOTA act->dz = 1; 2272fb966343SKazutaka YOKOTA break; 2273fb966343SKazutaka YOKOTA case 0x30: 2274fb966343SKazutaka YOKOTA act->dz = -1; 2275fb966343SKazutaka YOKOTA break; 2276fb966343SKazutaka YOKOTA case 0x40: /* 2nd wheel rolling right XXX */ 2277fb966343SKazutaka YOKOTA act->dz = 2; 2278fb966343SKazutaka YOKOTA break; 2279fb966343SKazutaka YOKOTA case 0xc0: /* 2nd wheel rolling left XXX */ 2280fb966343SKazutaka YOKOTA act->dz = -2; 2281fb966343SKazutaka YOKOTA break; 2282fb966343SKazutaka YOKOTA } 2283fb966343SKazutaka YOKOTA break; 2284fb966343SKazutaka YOKOTA case MOUSE_MODEL_4DPLUS: 2285fb966343SKazutaka YOKOTA if ((act->dx < 16 - 256) && (act->dy > 256 - 16)) { 2286fb966343SKazutaka YOKOTA act->dx = act->dy = 0; 2287fb966343SKazutaka YOKOTA if (pBuf[2] & MOUSE_4DPLUS_BUTTON4DOWN) 2288fb966343SKazutaka YOKOTA act->button |= MOUSE_BUTTON4DOWN; 2289fb966343SKazutaka YOKOTA act->dz = (pBuf[2] & MOUSE_4DPLUS_ZNEG) 2290fb966343SKazutaka YOKOTA ? ((pBuf[2] & 0x07) - 8) : (pBuf[2] & 0x07); 2291fb966343SKazutaka YOKOTA } else { 2292fb966343SKazutaka YOKOTA /* preserve previous button states */ 2293fb966343SKazutaka YOKOTA act->button |= act->obutton & MOUSE_EXTBUTTONS; 2294fb966343SKazutaka YOKOTA } 2295fb966343SKazutaka YOKOTA break; 22965f436cfbSKazutaka YOKOTA case MOUSE_MODEL_GENERIC: 22975f436cfbSKazutaka YOKOTA default: 2298ad771aa1SSøren Schmidt break; 2299ad771aa1SSøren Schmidt } 23005f436cfbSKazutaka YOKOTA break; 23015f436cfbSKazutaka YOKOTA 23025f436cfbSKazutaka YOKOTA case MOUSE_PROTO_SYSMOUSE: /* sysmouse */ 23035f436cfbSKazutaka YOKOTA act->button = butmapmsc[(~pBuf[0]) & MOUSE_SYS_STDBUTTONS]; 23048f810e50SAkinori MUSHA act->dx = (signed char)(pBuf[1]) + (signed char)(pBuf[3]); 23058f810e50SAkinori MUSHA act->dy = - ((signed char)(pBuf[2]) + (signed char)(pBuf[4])); 23065f436cfbSKazutaka YOKOTA if (rodent.level == 1) { 23078f810e50SAkinori MUSHA act->dz = ((signed char)(pBuf[5] << 1) + (signed char)(pBuf[6] << 1)) >> 1; 23085f436cfbSKazutaka YOKOTA act->button |= ((~pBuf[7] & MOUSE_SYS_EXTBUTTONS) << 3); 23095f436cfbSKazutaka YOKOTA } 23105f436cfbSKazutaka YOKOTA break; 23115f436cfbSKazutaka YOKOTA 23125f436cfbSKazutaka YOKOTA default: 23132657f6e9SJung-uk Kim return (0); 23145f436cfbSKazutaka YOKOTA } 23155f436cfbSKazutaka YOKOTA /* 23165f436cfbSKazutaka YOKOTA * We don't reset pBufP here yet, as there may be an additional data 23175f436cfbSKazutaka YOKOTA * byte in some protocols. See above. 23185f436cfbSKazutaka YOKOTA */ 23195f436cfbSKazutaka YOKOTA 23205f436cfbSKazutaka YOKOTA /* has something changed? */ 23215f436cfbSKazutaka YOKOTA act->flags = ((act->dx || act->dy || act->dz) ? MOUSE_POSCHANGED : 0) 23225f436cfbSKazutaka YOKOTA | (act->obutton ^ act->button); 23235f436cfbSKazutaka YOKOTA 23242657f6e9SJung-uk Kim return (act->flags); 2325e3b00983SKazutaka YOKOTA } 2326ab51fa72SSheldon Hearn 232744bdcfa6SKazutaka YOKOTA static int 232844bdcfa6SKazutaka YOKOTA r_statetrans(mousestatus_t *a1, mousestatus_t *a2, int trans) 232944bdcfa6SKazutaka YOKOTA { 233044bdcfa6SKazutaka YOKOTA int changed; 233144bdcfa6SKazutaka YOKOTA int flags; 233244bdcfa6SKazutaka YOKOTA 233344bdcfa6SKazutaka YOKOTA a2->dx = a1->dx; 233444bdcfa6SKazutaka YOKOTA a2->dy = a1->dy; 233544bdcfa6SKazutaka YOKOTA a2->dz = a1->dz; 233644bdcfa6SKazutaka YOKOTA a2->obutton = a2->button; 233744bdcfa6SKazutaka YOKOTA a2->button = a1->button; 233844bdcfa6SKazutaka YOKOTA a2->flags = a1->flags; 233944bdcfa6SKazutaka YOKOTA changed = FALSE; 234044bdcfa6SKazutaka YOKOTA 234144bdcfa6SKazutaka YOKOTA if (rodent.flags & Emulate3Button) { 234244bdcfa6SKazutaka YOKOTA if (debug > 2) 234344bdcfa6SKazutaka YOKOTA debug("state:%d, trans:%d -> state:%d", 234444bdcfa6SKazutaka YOKOTA mouse_button_state, trans, 234544bdcfa6SKazutaka YOKOTA states[mouse_button_state].s[trans]); 234670ccc8d8SIan Dowse /* 234770ccc8d8SIan Dowse * Avoid re-ordering button and movement events. While a button 234870ccc8d8SIan Dowse * event is deferred, throw away up to BUTTON2_MAXMOVE movement 234970ccc8d8SIan Dowse * events to allow for mouse jitter. If more movement events 235070ccc8d8SIan Dowse * occur, then complete the deferred button events immediately. 235170ccc8d8SIan Dowse */ 235270ccc8d8SIan Dowse if ((a2->dx != 0 || a2->dy != 0) && 235370ccc8d8SIan Dowse S_DELAYED(states[mouse_button_state].s[trans])) { 235470ccc8d8SIan Dowse if (++mouse_move_delayed > BUTTON2_MAXMOVE) { 235570ccc8d8SIan Dowse mouse_move_delayed = 0; 235670ccc8d8SIan Dowse mouse_button_state = 235770ccc8d8SIan Dowse states[mouse_button_state].s[A_TIMEOUT]; 235844bdcfa6SKazutaka YOKOTA changed = TRUE; 2359a9b238faSIan Dowse } else 236070ccc8d8SIan Dowse a2->dx = a2->dy = 0; 236170ccc8d8SIan Dowse } else 236270ccc8d8SIan Dowse mouse_move_delayed = 0; 236370ccc8d8SIan Dowse if (mouse_button_state != states[mouse_button_state].s[trans]) 236470ccc8d8SIan Dowse changed = TRUE; 236570ccc8d8SIan Dowse if (changed) 236613f1c59bSJung-uk Kim clock_gettime(CLOCK_MONOTONIC_FAST, &mouse_button_state_ts); 236744bdcfa6SKazutaka YOKOTA mouse_button_state = states[mouse_button_state].s[trans]; 236844bdcfa6SKazutaka YOKOTA a2->button &= 236944bdcfa6SKazutaka YOKOTA ~(MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN); 237044bdcfa6SKazutaka YOKOTA a2->button &= states[mouse_button_state].mask; 237144bdcfa6SKazutaka YOKOTA a2->button |= states[mouse_button_state].buttons; 237244bdcfa6SKazutaka YOKOTA flags = a2->flags & MOUSE_POSCHANGED; 237344bdcfa6SKazutaka YOKOTA flags |= a2->obutton ^ a2->button; 237444bdcfa6SKazutaka YOKOTA if (flags & MOUSE_BUTTON2DOWN) { 237544bdcfa6SKazutaka YOKOTA a2->flags = flags & MOUSE_BUTTON2DOWN; 237644bdcfa6SKazutaka YOKOTA r_timestamp(a2); 237744bdcfa6SKazutaka YOKOTA } 237844bdcfa6SKazutaka YOKOTA a2->flags = flags; 237944bdcfa6SKazutaka YOKOTA } 23802657f6e9SJung-uk Kim return (changed); 23815f436cfbSKazutaka YOKOTA } 23825f436cfbSKazutaka YOKOTA 23835f436cfbSKazutaka YOKOTA /* phisical to logical button mapping */ 23845f436cfbSKazutaka YOKOTA static int p2l[MOUSE_MAXBUTTON] = { 23855f436cfbSKazutaka YOKOTA MOUSE_BUTTON1DOWN, MOUSE_BUTTON2DOWN, MOUSE_BUTTON3DOWN, MOUSE_BUTTON4DOWN, 23865f436cfbSKazutaka YOKOTA MOUSE_BUTTON5DOWN, MOUSE_BUTTON6DOWN, MOUSE_BUTTON7DOWN, MOUSE_BUTTON8DOWN, 23875f436cfbSKazutaka YOKOTA 0x00000100, 0x00000200, 0x00000400, 0x00000800, 23885f436cfbSKazutaka YOKOTA 0x00001000, 0x00002000, 0x00004000, 0x00008000, 23895f436cfbSKazutaka YOKOTA 0x00010000, 0x00020000, 0x00040000, 0x00080000, 23905f436cfbSKazutaka YOKOTA 0x00100000, 0x00200000, 0x00400000, 0x00800000, 23915f436cfbSKazutaka YOKOTA 0x01000000, 0x02000000, 0x04000000, 0x08000000, 23925f436cfbSKazutaka YOKOTA 0x10000000, 0x20000000, 0x40000000, 23935f436cfbSKazutaka YOKOTA }; 23945f436cfbSKazutaka YOKOTA 23955f436cfbSKazutaka YOKOTA static char * 23965f436cfbSKazutaka YOKOTA skipspace(char *s) 23975f436cfbSKazutaka YOKOTA { 23985f436cfbSKazutaka YOKOTA while(isspace(*s)) 23995f436cfbSKazutaka YOKOTA ++s; 24002657f6e9SJung-uk Kim return (s); 24015f436cfbSKazutaka YOKOTA } 24025f436cfbSKazutaka YOKOTA 24035f436cfbSKazutaka YOKOTA static int 24045f436cfbSKazutaka YOKOTA r_installmap(char *arg) 24055f436cfbSKazutaka YOKOTA { 24065f436cfbSKazutaka YOKOTA int pbutton; 24075f436cfbSKazutaka YOKOTA int lbutton; 24085f436cfbSKazutaka YOKOTA char *s; 24095f436cfbSKazutaka YOKOTA 24105f436cfbSKazutaka YOKOTA while (*arg) { 24115f436cfbSKazutaka YOKOTA arg = skipspace(arg); 24125f436cfbSKazutaka YOKOTA s = arg; 24135f436cfbSKazutaka YOKOTA while (isdigit(*arg)) 24145f436cfbSKazutaka YOKOTA ++arg; 24155f436cfbSKazutaka YOKOTA arg = skipspace(arg); 24165f436cfbSKazutaka YOKOTA if ((arg <= s) || (*arg != '=')) 24172657f6e9SJung-uk Kim return (FALSE); 24185f436cfbSKazutaka YOKOTA lbutton = atoi(s); 24195f436cfbSKazutaka YOKOTA 24205f436cfbSKazutaka YOKOTA arg = skipspace(++arg); 24215f436cfbSKazutaka YOKOTA s = arg; 24225f436cfbSKazutaka YOKOTA while (isdigit(*arg)) 24235f436cfbSKazutaka YOKOTA ++arg; 24245f436cfbSKazutaka YOKOTA if ((arg <= s) || (!isspace(*arg) && (*arg != '\0'))) 24252657f6e9SJung-uk Kim return (FALSE); 24265f436cfbSKazutaka YOKOTA pbutton = atoi(s); 24275f436cfbSKazutaka YOKOTA 24285f436cfbSKazutaka YOKOTA if ((lbutton <= 0) || (lbutton > MOUSE_MAXBUTTON)) 24292657f6e9SJung-uk Kim return (FALSE); 24305f436cfbSKazutaka YOKOTA if ((pbutton <= 0) || (pbutton > MOUSE_MAXBUTTON)) 24312657f6e9SJung-uk Kim return (FALSE); 24325f436cfbSKazutaka YOKOTA p2l[pbutton - 1] = 1 << (lbutton - 1); 243344bdcfa6SKazutaka YOKOTA mstate[lbutton - 1] = &bstate[pbutton - 1]; 24345f436cfbSKazutaka YOKOTA } 24355f436cfbSKazutaka YOKOTA 24362657f6e9SJung-uk Kim return (TRUE); 24375f436cfbSKazutaka YOKOTA } 24385f436cfbSKazutaka YOKOTA 24395f436cfbSKazutaka YOKOTA static void 24405f436cfbSKazutaka YOKOTA r_map(mousestatus_t *act1, mousestatus_t *act2) 24415f436cfbSKazutaka YOKOTA { 24425f436cfbSKazutaka YOKOTA register int pb; 24435f436cfbSKazutaka YOKOTA register int pbuttons; 24445f436cfbSKazutaka YOKOTA int lbuttons; 24455f436cfbSKazutaka YOKOTA 24465f436cfbSKazutaka YOKOTA pbuttons = act1->button; 24475f436cfbSKazutaka YOKOTA lbuttons = 0; 24485f436cfbSKazutaka YOKOTA 24495f436cfbSKazutaka YOKOTA act2->obutton = act2->button; 24509fb1d70cSKazutaka YOKOTA if (pbuttons & rodent.wmode) { 24519fb1d70cSKazutaka YOKOTA pbuttons &= ~rodent.wmode; 24529fb1d70cSKazutaka YOKOTA act1->dz = act1->dy; 24539fb1d70cSKazutaka YOKOTA act1->dx = 0; 24549fb1d70cSKazutaka YOKOTA act1->dy = 0; 24559fb1d70cSKazutaka YOKOTA } 24565f436cfbSKazutaka YOKOTA act2->dx = act1->dx; 24575f436cfbSKazutaka YOKOTA act2->dy = act1->dy; 24585f436cfbSKazutaka YOKOTA act2->dz = act1->dz; 24595f436cfbSKazutaka YOKOTA 2460fb966343SKazutaka YOKOTA switch (rodent.zmap[0]) { 24615f436cfbSKazutaka YOKOTA case 0: /* do nothing */ 24625f436cfbSKazutaka YOKOTA break; 24635f436cfbSKazutaka YOKOTA case MOUSE_XAXIS: 24645f436cfbSKazutaka YOKOTA if (act1->dz != 0) { 24655f436cfbSKazutaka YOKOTA act2->dx = act1->dz; 24665f436cfbSKazutaka YOKOTA act2->dz = 0; 24675f436cfbSKazutaka YOKOTA } 24685f436cfbSKazutaka YOKOTA break; 24695f436cfbSKazutaka YOKOTA case MOUSE_YAXIS: 24705f436cfbSKazutaka YOKOTA if (act1->dz != 0) { 24715f436cfbSKazutaka YOKOTA act2->dy = act1->dz; 24725f436cfbSKazutaka YOKOTA act2->dz = 0; 24735f436cfbSKazutaka YOKOTA } 24745f436cfbSKazutaka YOKOTA break; 24755f436cfbSKazutaka YOKOTA default: /* buttons */ 2476fb966343SKazutaka YOKOTA pbuttons &= ~(rodent.zmap[0] | rodent.zmap[1] 2477fb966343SKazutaka YOKOTA | rodent.zmap[2] | rodent.zmap[3]); 247844bdcfa6SKazutaka YOKOTA if ((act1->dz < -1) && rodent.zmap[2]) { 2479fb966343SKazutaka YOKOTA pbuttons |= rodent.zmap[2]; 248044bdcfa6SKazutaka YOKOTA zstate[2].count = 1; 248144bdcfa6SKazutaka YOKOTA } else if (act1->dz < 0) { 2482fb966343SKazutaka YOKOTA pbuttons |= rodent.zmap[0]; 248344bdcfa6SKazutaka YOKOTA zstate[0].count = 1; 248444bdcfa6SKazutaka YOKOTA } else if ((act1->dz > 1) && rodent.zmap[3]) { 2485fb966343SKazutaka YOKOTA pbuttons |= rodent.zmap[3]; 248644bdcfa6SKazutaka YOKOTA zstate[3].count = 1; 248744bdcfa6SKazutaka YOKOTA } else if (act1->dz > 0) { 2488fb966343SKazutaka YOKOTA pbuttons |= rodent.zmap[1]; 248944bdcfa6SKazutaka YOKOTA zstate[1].count = 1; 249044bdcfa6SKazutaka YOKOTA } 24915f436cfbSKazutaka YOKOTA act2->dz = 0; 24925f436cfbSKazutaka YOKOTA break; 24935f436cfbSKazutaka YOKOTA } 24945f436cfbSKazutaka YOKOTA 24955f436cfbSKazutaka YOKOTA for (pb = 0; (pb < MOUSE_MAXBUTTON) && (pbuttons != 0); ++pb) { 24965f436cfbSKazutaka YOKOTA lbuttons |= (pbuttons & 1) ? p2l[pb] : 0; 24975f436cfbSKazutaka YOKOTA pbuttons >>= 1; 24985f436cfbSKazutaka YOKOTA } 24995f436cfbSKazutaka YOKOTA act2->button = lbuttons; 25005f436cfbSKazutaka YOKOTA 25015f436cfbSKazutaka YOKOTA act2->flags = ((act2->dx || act2->dy || act2->dz) ? MOUSE_POSCHANGED : 0) 25025f436cfbSKazutaka YOKOTA | (act2->obutton ^ act2->button); 25035f436cfbSKazutaka YOKOTA } 25045f436cfbSKazutaka YOKOTA 25055f436cfbSKazutaka YOKOTA static void 250644bdcfa6SKazutaka YOKOTA r_timestamp(mousestatus_t *act) 25075f436cfbSKazutaka YOKOTA { 250813f1c59bSJung-uk Kim struct timespec ts; 250913f1c59bSJung-uk Kim struct timespec ts1; 251013f1c59bSJung-uk Kim struct timespec ts2; 251113f1c59bSJung-uk Kim struct timespec ts3; 251244bdcfa6SKazutaka YOKOTA int button; 251344bdcfa6SKazutaka YOKOTA int mask; 251444bdcfa6SKazutaka YOKOTA int i; 251544bdcfa6SKazutaka YOKOTA 251644bdcfa6SKazutaka YOKOTA mask = act->flags & MOUSE_BUTTONS; 251744bdcfa6SKazutaka YOKOTA #if 0 251844bdcfa6SKazutaka YOKOTA if (mask == 0) 251944bdcfa6SKazutaka YOKOTA return; 252044bdcfa6SKazutaka YOKOTA #endif 252144bdcfa6SKazutaka YOKOTA 252213f1c59bSJung-uk Kim clock_gettime(CLOCK_MONOTONIC_FAST, &ts1); 252313f1c59bSJung-uk Kim drift_current_ts = ts1; 252444bdcfa6SKazutaka YOKOTA 252544bdcfa6SKazutaka YOKOTA /* double click threshold */ 252613f1c59bSJung-uk Kim ts2.tv_sec = rodent.clickthreshold / 1000; 252713f1c59bSJung-uk Kim ts2.tv_nsec = (rodent.clickthreshold % 1000) * 1000000; 252813f1c59bSJung-uk Kim tssub(&ts1, &ts2, &ts); 2529f2559616SJung-uk Kim debug("ts: %jd %ld", (intmax_t)ts.tv_sec, ts.tv_nsec); 253044bdcfa6SKazutaka YOKOTA 253144bdcfa6SKazutaka YOKOTA /* 3 button emulation timeout */ 253213f1c59bSJung-uk Kim ts2.tv_sec = rodent.button2timeout / 1000; 253313f1c59bSJung-uk Kim ts2.tv_nsec = (rodent.button2timeout % 1000) * 1000000; 253413f1c59bSJung-uk Kim tssub(&ts1, &ts2, &ts3); 253544bdcfa6SKazutaka YOKOTA 253644bdcfa6SKazutaka YOKOTA button = MOUSE_BUTTON1DOWN; 253744bdcfa6SKazutaka YOKOTA for (i = 0; (i < MOUSE_MAXBUTTON) && (mask != 0); ++i) { 253844bdcfa6SKazutaka YOKOTA if (mask & 1) { 253944bdcfa6SKazutaka YOKOTA if (act->button & button) { 254044bdcfa6SKazutaka YOKOTA /* the button is down */ 2541f2559616SJung-uk Kim debug(" : %jd %ld", 2542f2559616SJung-uk Kim (intmax_t)bstate[i].ts.tv_sec, bstate[i].ts.tv_nsec); 254313f1c59bSJung-uk Kim if (tscmp(&ts, &bstate[i].ts, >)) { 254444bdcfa6SKazutaka YOKOTA bstate[i].count = 1; 254544bdcfa6SKazutaka YOKOTA } else { 254644bdcfa6SKazutaka YOKOTA ++bstate[i].count; 254744bdcfa6SKazutaka YOKOTA } 254813f1c59bSJung-uk Kim bstate[i].ts = ts1; 254944bdcfa6SKazutaka YOKOTA } else { 255044bdcfa6SKazutaka YOKOTA /* the button is up */ 255113f1c59bSJung-uk Kim bstate[i].ts = ts1; 255244bdcfa6SKazutaka YOKOTA } 255344bdcfa6SKazutaka YOKOTA } else { 255444bdcfa6SKazutaka YOKOTA if (act->button & button) { 255544bdcfa6SKazutaka YOKOTA /* the button has been down */ 255613f1c59bSJung-uk Kim if (tscmp(&ts3, &bstate[i].ts, >)) { 255744bdcfa6SKazutaka YOKOTA bstate[i].count = 1; 255813f1c59bSJung-uk Kim bstate[i].ts = ts1; 255944bdcfa6SKazutaka YOKOTA act->flags |= button; 256044bdcfa6SKazutaka YOKOTA debug("button %d timeout", i + 1); 256144bdcfa6SKazutaka YOKOTA } 256244bdcfa6SKazutaka YOKOTA } else { 256344bdcfa6SKazutaka YOKOTA /* the button has been up */ 256444bdcfa6SKazutaka YOKOTA } 256544bdcfa6SKazutaka YOKOTA } 256644bdcfa6SKazutaka YOKOTA button <<= 1; 256744bdcfa6SKazutaka YOKOTA mask >>= 1; 256844bdcfa6SKazutaka YOKOTA } 256944bdcfa6SKazutaka YOKOTA } 257044bdcfa6SKazutaka YOKOTA 257144bdcfa6SKazutaka YOKOTA static int 257244bdcfa6SKazutaka YOKOTA r_timeout(void) 257344bdcfa6SKazutaka YOKOTA { 257413f1c59bSJung-uk Kim struct timespec ts; 257513f1c59bSJung-uk Kim struct timespec ts1; 257613f1c59bSJung-uk Kim struct timespec ts2; 257744bdcfa6SKazutaka YOKOTA 2578127d54baSKazutaka YOKOTA if (states[mouse_button_state].timeout) 25792657f6e9SJung-uk Kim return (TRUE); 258013f1c59bSJung-uk Kim clock_gettime(CLOCK_MONOTONIC_FAST, &ts1); 258113f1c59bSJung-uk Kim ts2.tv_sec = rodent.button2timeout / 1000; 258213f1c59bSJung-uk Kim ts2.tv_nsec = (rodent.button2timeout % 1000) * 1000000; 258313f1c59bSJung-uk Kim tssub(&ts1, &ts2, &ts); 25842657f6e9SJung-uk Kim return (tscmp(&ts, &mouse_button_state_ts, >)); 258544bdcfa6SKazutaka YOKOTA } 258644bdcfa6SKazutaka YOKOTA 258744bdcfa6SKazutaka YOKOTA static void 258844bdcfa6SKazutaka YOKOTA r_click(mousestatus_t *act) 258944bdcfa6SKazutaka YOKOTA { 259044bdcfa6SKazutaka YOKOTA struct mouse_info mouse; 25915f436cfbSKazutaka YOKOTA int button; 25925f436cfbSKazutaka YOKOTA int mask; 25935f436cfbSKazutaka YOKOTA int i; 25945f436cfbSKazutaka YOKOTA 25955f436cfbSKazutaka YOKOTA mask = act->flags & MOUSE_BUTTONS; 25965f436cfbSKazutaka YOKOTA if (mask == 0) 25975f436cfbSKazutaka YOKOTA return; 25985f436cfbSKazutaka YOKOTA 25995f436cfbSKazutaka YOKOTA button = MOUSE_BUTTON1DOWN; 26005f436cfbSKazutaka YOKOTA for (i = 0; (i < MOUSE_MAXBUTTON) && (mask != 0); ++i) { 26015f436cfbSKazutaka YOKOTA if (mask & 1) { 260244bdcfa6SKazutaka YOKOTA debug("mstate[%d]->count:%d", i, mstate[i]->count); 26035f436cfbSKazutaka YOKOTA if (act->button & button) { 26045f436cfbSKazutaka YOKOTA /* the button is down */ 260544bdcfa6SKazutaka YOKOTA mouse.u.event.value = mstate[i]->count; 2606e3b00983SKazutaka YOKOTA } else { 2607e3b00983SKazutaka YOKOTA /* the button is up */ 26085f436cfbSKazutaka YOKOTA mouse.u.event.value = 0; 26095f436cfbSKazutaka YOKOTA } 26105f436cfbSKazutaka YOKOTA mouse.operation = MOUSE_BUTTON_EVENT; 26115f436cfbSKazutaka YOKOTA mouse.u.event.id = button; 26125f436cfbSKazutaka YOKOTA if (debug < 2) 26139eac5bb9SPhilip Paeps if (!paused) 26145f436cfbSKazutaka YOKOTA ioctl(rodent.cfd, CONS_MOUSECTL, &mouse); 26155f436cfbSKazutaka YOKOTA debug("button %d count %d", i + 1, mouse.u.event.value); 26165f436cfbSKazutaka YOKOTA } 26175f436cfbSKazutaka YOKOTA button <<= 1; 26185f436cfbSKazutaka YOKOTA mask >>= 1; 26195f436cfbSKazutaka YOKOTA } 2620ad771aa1SSøren Schmidt } 262113379e47SPeter Wemm 262213379e47SPeter Wemm /* $XConsortium: posix_tty.c,v 1.3 95/01/05 20:42:55 kaleb Exp $ */ 262313379e47SPeter Wemm /* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/posix_tty.c,v 3.4 1995/01/28 17:05:03 dawes Exp $ */ 262413379e47SPeter Wemm /* 262513379e47SPeter Wemm * Copyright 1993 by David Dawes <dawes@physics.su.oz.au> 262613379e47SPeter Wemm * 262713379e47SPeter Wemm * Permission to use, copy, modify, distribute, and sell this software and its 262813379e47SPeter Wemm * documentation for any purpose is hereby granted without fee, provided that 262913379e47SPeter Wemm * the above copyright notice appear in all copies and that both that 263013379e47SPeter Wemm * copyright notice and this permission notice appear in supporting 263113379e47SPeter Wemm * documentation, and that the name of David Dawes 263213379e47SPeter Wemm * not be used in advertising or publicity pertaining to distribution of 263313379e47SPeter Wemm * the software without specific, written prior permission. 263413379e47SPeter Wemm * David Dawes makes no representations about the suitability of this 263513379e47SPeter Wemm * software for any purpose. It is provided "as is" without express or 263613379e47SPeter Wemm * implied warranty. 263713379e47SPeter Wemm * 263813379e47SPeter Wemm * DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO 263913379e47SPeter Wemm * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 264013379e47SPeter Wemm * FITNESS, IN NO EVENT SHALL DAVID DAWES BE LIABLE FOR 264113379e47SPeter Wemm * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 264213379e47SPeter Wemm * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 264313379e47SPeter Wemm * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 264413379e47SPeter Wemm * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 264513379e47SPeter Wemm * 264613379e47SPeter Wemm */ 264713379e47SPeter Wemm 264813379e47SPeter Wemm 26495f436cfbSKazutaka YOKOTA static void 26505f436cfbSKazutaka YOKOTA setmousespeed(int old, int new, unsigned cflag) 265113379e47SPeter Wemm { 265213379e47SPeter Wemm struct termios tty; 26532657f6e9SJung-uk Kim const char *c; 265413379e47SPeter Wemm 265513379e47SPeter Wemm if (tcgetattr(rodent.mfd, &tty) < 0) 265613379e47SPeter Wemm { 265762e621e8SIan Dowse logwarn("unable to get status of mouse fd"); 26585f436cfbSKazutaka YOKOTA return; 265913379e47SPeter Wemm } 266013379e47SPeter Wemm 266113379e47SPeter Wemm tty.c_iflag = IGNBRK | IGNPAR; 266213379e47SPeter Wemm tty.c_oflag = 0; 266313379e47SPeter Wemm tty.c_lflag = 0; 266413379e47SPeter Wemm tty.c_cflag = (tcflag_t)cflag; 266513379e47SPeter Wemm tty.c_cc[VTIME] = 0; 266613379e47SPeter Wemm tty.c_cc[VMIN] = 1; 266713379e47SPeter Wemm 266813379e47SPeter Wemm switch (old) 266913379e47SPeter Wemm { 267013379e47SPeter Wemm case 9600: 267113379e47SPeter Wemm cfsetispeed(&tty, B9600); 267213379e47SPeter Wemm cfsetospeed(&tty, B9600); 267313379e47SPeter Wemm break; 267413379e47SPeter Wemm case 4800: 267513379e47SPeter Wemm cfsetispeed(&tty, B4800); 267613379e47SPeter Wemm cfsetospeed(&tty, B4800); 267713379e47SPeter Wemm break; 267813379e47SPeter Wemm case 2400: 267913379e47SPeter Wemm cfsetispeed(&tty, B2400); 268013379e47SPeter Wemm cfsetospeed(&tty, B2400); 268113379e47SPeter Wemm break; 268213379e47SPeter Wemm case 1200: 268313379e47SPeter Wemm default: 268413379e47SPeter Wemm cfsetispeed(&tty, B1200); 268513379e47SPeter Wemm cfsetospeed(&tty, B1200); 268613379e47SPeter Wemm } 268713379e47SPeter Wemm 268813379e47SPeter Wemm if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0) 268913379e47SPeter Wemm { 269062e621e8SIan Dowse logwarn("unable to set status of mouse fd"); 26915f436cfbSKazutaka YOKOTA return; 269213379e47SPeter Wemm } 269313379e47SPeter Wemm 269413379e47SPeter Wemm switch (new) 269513379e47SPeter Wemm { 269613379e47SPeter Wemm case 9600: 269713379e47SPeter Wemm c = "*q"; 269813379e47SPeter Wemm cfsetispeed(&tty, B9600); 269913379e47SPeter Wemm cfsetospeed(&tty, B9600); 270013379e47SPeter Wemm break; 270113379e47SPeter Wemm case 4800: 270213379e47SPeter Wemm c = "*p"; 270313379e47SPeter Wemm cfsetispeed(&tty, B4800); 270413379e47SPeter Wemm cfsetospeed(&tty, B4800); 270513379e47SPeter Wemm break; 270613379e47SPeter Wemm case 2400: 270713379e47SPeter Wemm c = "*o"; 270813379e47SPeter Wemm cfsetispeed(&tty, B2400); 270913379e47SPeter Wemm cfsetospeed(&tty, B2400); 271013379e47SPeter Wemm break; 271113379e47SPeter Wemm case 1200: 271213379e47SPeter Wemm default: 271313379e47SPeter Wemm c = "*n"; 271413379e47SPeter Wemm cfsetispeed(&tty, B1200); 271513379e47SPeter Wemm cfsetospeed(&tty, B1200); 271613379e47SPeter Wemm } 271713379e47SPeter Wemm 27185f436cfbSKazutaka YOKOTA if (rodent.rtype == MOUSE_PROTO_LOGIMOUSEMAN 27195f436cfbSKazutaka YOKOTA || rodent.rtype == MOUSE_PROTO_LOGI) 272013379e47SPeter Wemm { 272113379e47SPeter Wemm if (write(rodent.mfd, c, 2) != 2) 272213379e47SPeter Wemm { 272362e621e8SIan Dowse logwarn("unable to write to mouse fd"); 27245f436cfbSKazutaka YOKOTA return; 272513379e47SPeter Wemm } 272613379e47SPeter Wemm } 272713379e47SPeter Wemm usleep(100000); 272813379e47SPeter Wemm 272913379e47SPeter Wemm if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0) 273062e621e8SIan Dowse logwarn("unable to set status of mouse fd"); 273113379e47SPeter Wemm } 27325f436cfbSKazutaka YOKOTA 27335f436cfbSKazutaka YOKOTA /* 27345f436cfbSKazutaka YOKOTA * PnP COM device support 27355f436cfbSKazutaka YOKOTA * 27365f436cfbSKazutaka YOKOTA * It's a simplistic implementation, but it works :-) 27375f436cfbSKazutaka YOKOTA * KY, 31/7/97. 27385f436cfbSKazutaka YOKOTA */ 27395f436cfbSKazutaka YOKOTA 27405f436cfbSKazutaka YOKOTA /* 27415f436cfbSKazutaka YOKOTA * Try to elicit a PnP ID as described in 27425f436cfbSKazutaka YOKOTA * Microsoft, Hayes: "Plug and Play External COM Device Specification, 27435f436cfbSKazutaka YOKOTA * rev 1.00", 1995. 27445f436cfbSKazutaka YOKOTA * 27455f436cfbSKazutaka YOKOTA * The routine does not fully implement the COM Enumerator as par Section 27465f436cfbSKazutaka YOKOTA * 2.1 of the document. In particular, we don't have idle state in which 27475f436cfbSKazutaka YOKOTA * the driver software monitors the com port for dynamic connection or 27485f436cfbSKazutaka YOKOTA * removal of a device at the port, because `moused' simply quits if no 27495f436cfbSKazutaka YOKOTA * device is found. 27505f436cfbSKazutaka YOKOTA * 27515f436cfbSKazutaka YOKOTA * In addition, as PnP COM device enumeration procedure slightly has 27525f436cfbSKazutaka YOKOTA * changed since its first publication, devices which follow earlier 27535f436cfbSKazutaka YOKOTA * revisions of the above spec. may fail to respond if the rev 1.0 27545f436cfbSKazutaka YOKOTA * procedure is used. XXX 27555f436cfbSKazutaka YOKOTA */ 27565f436cfbSKazutaka YOKOTA static int 2757f41621f9SKazutaka YOKOTA pnpwakeup1(void) 27585f436cfbSKazutaka YOKOTA { 27595f436cfbSKazutaka YOKOTA struct timeval timeout; 27605f436cfbSKazutaka YOKOTA fd_set fds; 27615f436cfbSKazutaka YOKOTA int i; 27625f436cfbSKazutaka YOKOTA 27635f436cfbSKazutaka YOKOTA /* 27645f436cfbSKazutaka YOKOTA * This is the procedure described in rev 1.0 of PnP COM device spec. 27655f436cfbSKazutaka YOKOTA * Unfortunately, some devices which comform to earlier revisions of 27665f436cfbSKazutaka YOKOTA * the spec gets confused and do not return the ID string... 27675f436cfbSKazutaka YOKOTA */ 2768f41621f9SKazutaka YOKOTA debug("PnP COM device rev 1.0 probe..."); 27695f436cfbSKazutaka YOKOTA 27705f436cfbSKazutaka YOKOTA /* port initialization (2.1.2) */ 27715f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMGET, &i); 27725f436cfbSKazutaka YOKOTA i |= TIOCM_DTR; /* DTR = 1 */ 27735f436cfbSKazutaka YOKOTA i &= ~TIOCM_RTS; /* RTS = 0 */ 27745f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMSET, &i); 2775f41621f9SKazutaka YOKOTA usleep(240000); 2776f41621f9SKazutaka YOKOTA 2777f41621f9SKazutaka YOKOTA /* 2778f41621f9SKazutaka YOKOTA * The PnP COM device spec. dictates that the mouse must set DSR 2779f41621f9SKazutaka YOKOTA * in response to DTR (by hardware or by software) and that if DSR is 2780f41621f9SKazutaka YOKOTA * not asserted, the host computer should think that there is no device 2781c49f79b7SKazutaka YOKOTA * at this serial port. But some mice just don't do that... 2782f41621f9SKazutaka YOKOTA */ 2783f41621f9SKazutaka YOKOTA ioctl(rodent.mfd, TIOCMGET, &i); 2784f41621f9SKazutaka YOKOTA debug("modem status 0%o", i); 2785f41621f9SKazutaka YOKOTA if ((i & TIOCM_DSR) == 0) 27862657f6e9SJung-uk Kim return (FALSE); 27875f436cfbSKazutaka YOKOTA 27885f436cfbSKazutaka YOKOTA /* port setup, 1st phase (2.1.3) */ 27895f436cfbSKazutaka YOKOTA setmousespeed(1200, 1200, (CS7 | CREAD | CLOCAL | HUPCL)); 27905f436cfbSKazutaka YOKOTA i = TIOCM_DTR | TIOCM_RTS; /* DTR = 0, RTS = 0 */ 27915f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIC, &i); 2792f41621f9SKazutaka YOKOTA usleep(240000); 27935f436cfbSKazutaka YOKOTA i = TIOCM_DTR; /* DTR = 1, RTS = 0 */ 27945f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIS, &i); 2795f41621f9SKazutaka YOKOTA usleep(240000); 27965f436cfbSKazutaka YOKOTA 27975f436cfbSKazutaka YOKOTA /* wait for response, 1st phase (2.1.4) */ 27985f436cfbSKazutaka YOKOTA i = FREAD; 27995f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCFLUSH, &i); 28005f436cfbSKazutaka YOKOTA i = TIOCM_RTS; /* DTR = 1, RTS = 1 */ 28015f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIS, &i); 28025f436cfbSKazutaka YOKOTA 28035f436cfbSKazutaka YOKOTA /* try to read something */ 28045f436cfbSKazutaka YOKOTA FD_ZERO(&fds); 28055f436cfbSKazutaka YOKOTA FD_SET(rodent.mfd, &fds); 28065f436cfbSKazutaka YOKOTA timeout.tv_sec = 0; 2807f41621f9SKazutaka YOKOTA timeout.tv_usec = 240000; 2808f41621f9SKazutaka YOKOTA if (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) > 0) { 2809f41621f9SKazutaka YOKOTA debug("pnpwakeup1(): valid response in first phase."); 28102657f6e9SJung-uk Kim return (TRUE); 2811c49f79b7SKazutaka YOKOTA } 28125f436cfbSKazutaka YOKOTA 28135f436cfbSKazutaka YOKOTA /* port setup, 2nd phase (2.1.5) */ 28145f436cfbSKazutaka YOKOTA i = TIOCM_DTR | TIOCM_RTS; /* DTR = 0, RTS = 0 */ 28155f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIC, &i); 2816f41621f9SKazutaka YOKOTA usleep(240000); 28175f436cfbSKazutaka YOKOTA 28185f436cfbSKazutaka YOKOTA /* wait for respose, 2nd phase (2.1.6) */ 28195f436cfbSKazutaka YOKOTA i = FREAD; 28205f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCFLUSH, &i); 28215f436cfbSKazutaka YOKOTA i = TIOCM_DTR | TIOCM_RTS; /* DTR = 1, RTS = 1 */ 28225f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIS, &i); 28235f436cfbSKazutaka YOKOTA 28245f436cfbSKazutaka YOKOTA /* try to read something */ 28255f436cfbSKazutaka YOKOTA FD_ZERO(&fds); 28265f436cfbSKazutaka YOKOTA FD_SET(rodent.mfd, &fds); 28275f436cfbSKazutaka YOKOTA timeout.tv_sec = 0; 2828f41621f9SKazutaka YOKOTA timeout.tv_usec = 240000; 2829f41621f9SKazutaka YOKOTA if (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) > 0) { 2830f41621f9SKazutaka YOKOTA debug("pnpwakeup1(): valid response in second phase."); 28312657f6e9SJung-uk Kim return (TRUE); 28325f436cfbSKazutaka YOKOTA } 2833c49f79b7SKazutaka YOKOTA 28342657f6e9SJung-uk Kim return (FALSE); 2835f41621f9SKazutaka YOKOTA } 2836f41621f9SKazutaka YOKOTA 2837f41621f9SKazutaka YOKOTA static int 2838f41621f9SKazutaka YOKOTA pnpwakeup2(void) 2839f41621f9SKazutaka YOKOTA { 2840f41621f9SKazutaka YOKOTA struct timeval timeout; 2841f41621f9SKazutaka YOKOTA fd_set fds; 2842f41621f9SKazutaka YOKOTA int i; 2843f41621f9SKazutaka YOKOTA 28445f436cfbSKazutaka YOKOTA /* 28455f436cfbSKazutaka YOKOTA * This is a simplified procedure; it simply toggles RTS. 28465f436cfbSKazutaka YOKOTA */ 2847c49f79b7SKazutaka YOKOTA debug("alternate probe..."); 28485f436cfbSKazutaka YOKOTA 28495f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMGET, &i); 28505f436cfbSKazutaka YOKOTA i |= TIOCM_DTR; /* DTR = 1 */ 28515f436cfbSKazutaka YOKOTA i &= ~TIOCM_RTS; /* RTS = 0 */ 28525f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMSET, &i); 2853f41621f9SKazutaka YOKOTA usleep(240000); 28545f436cfbSKazutaka YOKOTA 28555f436cfbSKazutaka YOKOTA setmousespeed(1200, 1200, (CS7 | CREAD | CLOCAL | HUPCL)); 28565f436cfbSKazutaka YOKOTA 28575f436cfbSKazutaka YOKOTA /* wait for respose */ 28585f436cfbSKazutaka YOKOTA i = FREAD; 28595f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCFLUSH, &i); 28605f436cfbSKazutaka YOKOTA i = TIOCM_DTR | TIOCM_RTS; /* DTR = 1, RTS = 1 */ 28615f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIS, &i); 28625f436cfbSKazutaka YOKOTA 28635f436cfbSKazutaka YOKOTA /* try to read something */ 28645f436cfbSKazutaka YOKOTA FD_ZERO(&fds); 28655f436cfbSKazutaka YOKOTA FD_SET(rodent.mfd, &fds); 28665f436cfbSKazutaka YOKOTA timeout.tv_sec = 0; 2867f41621f9SKazutaka YOKOTA timeout.tv_usec = 240000; 2868f41621f9SKazutaka YOKOTA if (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) > 0) { 2869f41621f9SKazutaka YOKOTA debug("pnpwakeup2(): valid response."); 28702657f6e9SJung-uk Kim return (TRUE); 28715f436cfbSKazutaka YOKOTA } 2872c49f79b7SKazutaka YOKOTA 28732657f6e9SJung-uk Kim return (FALSE); 28745f436cfbSKazutaka YOKOTA } 28755f436cfbSKazutaka YOKOTA 2876f41621f9SKazutaka YOKOTA static int 2877f41621f9SKazutaka YOKOTA pnpgets(char *buf) 2878f41621f9SKazutaka YOKOTA { 2879f41621f9SKazutaka YOKOTA struct timeval timeout; 2880f41621f9SKazutaka YOKOTA fd_set fds; 2881f41621f9SKazutaka YOKOTA int begin; 2882f41621f9SKazutaka YOKOTA int i; 2883f41621f9SKazutaka YOKOTA char c; 28845f436cfbSKazutaka YOKOTA 2885f41621f9SKazutaka YOKOTA if (!pnpwakeup1() && !pnpwakeup2()) { 28865f436cfbSKazutaka YOKOTA /* 28875f436cfbSKazutaka YOKOTA * According to PnP spec, we should set DTR = 1 and RTS = 0 while 28885f436cfbSKazutaka YOKOTA * in idle state. But, `moused' shall set DTR = RTS = 1 and proceed, 28895f436cfbSKazutaka YOKOTA * assuming there is something at the port even if it didn't 28905f436cfbSKazutaka YOKOTA * respond to the PnP enumeration procedure. 28915f436cfbSKazutaka YOKOTA */ 28925f436cfbSKazutaka YOKOTA i = TIOCM_DTR | TIOCM_RTS; /* DTR = 1, RTS = 1 */ 28935f436cfbSKazutaka YOKOTA ioctl(rodent.mfd, TIOCMBIS, &i); 28942657f6e9SJung-uk Kim return (0); 28955f436cfbSKazutaka YOKOTA } 28965f436cfbSKazutaka YOKOTA 2897f41621f9SKazutaka YOKOTA /* collect PnP COM device ID (2.1.7) */ 2898f41621f9SKazutaka YOKOTA begin = -1; 2899f41621f9SKazutaka YOKOTA i = 0; 2900f41621f9SKazutaka YOKOTA usleep(240000); /* the mouse must send `Begin ID' within 200msec */ 2901f41621f9SKazutaka YOKOTA while (read(rodent.mfd, &c, 1) == 1) { 2902f41621f9SKazutaka YOKOTA /* we may see "M", or "M3..." before `Begin ID' */ 2903f41621f9SKazutaka YOKOTA buf[i++] = c; 2904f41621f9SKazutaka YOKOTA if ((c == 0x08) || (c == 0x28)) { /* Begin ID */ 2905f41621f9SKazutaka YOKOTA debug("begin-id %02x", c); 2906f41621f9SKazutaka YOKOTA begin = i - 1; 2907f41621f9SKazutaka YOKOTA break; 2908f41621f9SKazutaka YOKOTA } 2909f41621f9SKazutaka YOKOTA debug("%c %02x", c, c); 2910f41621f9SKazutaka YOKOTA if (i >= 256) 2911f41621f9SKazutaka YOKOTA break; 2912f41621f9SKazutaka YOKOTA } 2913f41621f9SKazutaka YOKOTA if (begin < 0) { 2914f41621f9SKazutaka YOKOTA /* we haven't seen `Begin ID' in time... */ 2915f41621f9SKazutaka YOKOTA goto connect_idle; 2916f41621f9SKazutaka YOKOTA } 2917f41621f9SKazutaka YOKOTA 2918f41621f9SKazutaka YOKOTA ++c; /* make it `End ID' */ 2919f41621f9SKazutaka YOKOTA for (;;) { 2920f41621f9SKazutaka YOKOTA FD_ZERO(&fds); 2921f41621f9SKazutaka YOKOTA FD_SET(rodent.mfd, &fds); 2922f41621f9SKazutaka YOKOTA timeout.tv_sec = 0; 2923f41621f9SKazutaka YOKOTA timeout.tv_usec = 240000; 2924f41621f9SKazutaka YOKOTA if (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) <= 0) 2925f41621f9SKazutaka YOKOTA break; 2926f41621f9SKazutaka YOKOTA 2927f41621f9SKazutaka YOKOTA read(rodent.mfd, &buf[i], 1); 2928f41621f9SKazutaka YOKOTA if (buf[i++] == c) /* End ID */ 2929f41621f9SKazutaka YOKOTA break; 2930f41621f9SKazutaka YOKOTA if (i >= 256) 2931f41621f9SKazutaka YOKOTA break; 2932f41621f9SKazutaka YOKOTA } 2933f41621f9SKazutaka YOKOTA if (begin > 0) { 2934f41621f9SKazutaka YOKOTA i -= begin; 2935f41621f9SKazutaka YOKOTA bcopy(&buf[begin], &buf[0], i); 2936f41621f9SKazutaka YOKOTA } 2937f41621f9SKazutaka YOKOTA /* string may not be human readable... */ 2938f41621f9SKazutaka YOKOTA debug("len:%d, '%-*.*s'", i, i, i, buf); 2939f41621f9SKazutaka YOKOTA 2940f41621f9SKazutaka YOKOTA if (buf[i - 1] == c) 29412657f6e9SJung-uk Kim return (i); /* a valid PnP string */ 2942f41621f9SKazutaka YOKOTA 2943f41621f9SKazutaka YOKOTA /* 2944f41621f9SKazutaka YOKOTA * According to PnP spec, we should set DTR = 1 and RTS = 0 while 2945f41621f9SKazutaka YOKOTA * in idle state. But, `moused' shall leave the modem control lines 2946f41621f9SKazutaka YOKOTA * as they are. See above. 2947f41621f9SKazutaka YOKOTA */ 2948f41621f9SKazutaka YOKOTA connect_idle: 2949f41621f9SKazutaka YOKOTA 2950f41621f9SKazutaka YOKOTA /* we may still have something in the buffer */ 29515d6026c2SMarcelo Araujo return (MAX(i, 0)); 2952f41621f9SKazutaka YOKOTA } 2953f41621f9SKazutaka YOKOTA 29545f436cfbSKazutaka YOKOTA static int 29555f436cfbSKazutaka YOKOTA pnpparse(pnpid_t *id, char *buf, int len) 29565f436cfbSKazutaka YOKOTA { 29575f436cfbSKazutaka YOKOTA char s[3]; 29585f436cfbSKazutaka YOKOTA int offset; 29595f436cfbSKazutaka YOKOTA int sum = 0; 29605f436cfbSKazutaka YOKOTA int i, j; 29615f436cfbSKazutaka YOKOTA 29625f436cfbSKazutaka YOKOTA id->revision = 0; 29635f436cfbSKazutaka YOKOTA id->eisaid = NULL; 29645f436cfbSKazutaka YOKOTA id->serial = NULL; 29655f436cfbSKazutaka YOKOTA id->class = NULL; 29665f436cfbSKazutaka YOKOTA id->compat = NULL; 29675f436cfbSKazutaka YOKOTA id->description = NULL; 29685f436cfbSKazutaka YOKOTA id->neisaid = 0; 29695f436cfbSKazutaka YOKOTA id->nserial = 0; 29705f436cfbSKazutaka YOKOTA id->nclass = 0; 29715f436cfbSKazutaka YOKOTA id->ncompat = 0; 29725f436cfbSKazutaka YOKOTA id->ndescription = 0; 29735f436cfbSKazutaka YOKOTA 2974f41621f9SKazutaka YOKOTA if ((buf[0] != 0x28) && (buf[0] != 0x08)) { 2975f41621f9SKazutaka YOKOTA /* non-PnP mice */ 2976f41621f9SKazutaka YOKOTA switch(buf[0]) { 2977f41621f9SKazutaka YOKOTA default: 29782657f6e9SJung-uk Kim return (FALSE); 2979f41621f9SKazutaka YOKOTA case 'M': /* Microsoft */ 2980f41621f9SKazutaka YOKOTA id->eisaid = "PNP0F01"; 2981f41621f9SKazutaka YOKOTA break; 2982f41621f9SKazutaka YOKOTA case 'H': /* MouseSystems */ 2983f41621f9SKazutaka YOKOTA id->eisaid = "PNP0F04"; 2984f41621f9SKazutaka YOKOTA break; 2985f41621f9SKazutaka YOKOTA } 2986f41621f9SKazutaka YOKOTA id->neisaid = strlen(id->eisaid); 2987f41621f9SKazutaka YOKOTA id->class = "MOUSE"; 2988f41621f9SKazutaka YOKOTA id->nclass = strlen(id->class); 2989f41621f9SKazutaka YOKOTA debug("non-PnP mouse '%c'", buf[0]); 29902657f6e9SJung-uk Kim return (TRUE); 2991f41621f9SKazutaka YOKOTA } 2992f41621f9SKazutaka YOKOTA 2993f41621f9SKazutaka YOKOTA /* PnP mice */ 29945f436cfbSKazutaka YOKOTA offset = 0x28 - buf[0]; 29955f436cfbSKazutaka YOKOTA 29965f436cfbSKazutaka YOKOTA /* calculate checksum */ 29975f436cfbSKazutaka YOKOTA for (i = 0; i < len - 3; ++i) { 29985f436cfbSKazutaka YOKOTA sum += buf[i]; 29995f436cfbSKazutaka YOKOTA buf[i] += offset; 30005f436cfbSKazutaka YOKOTA } 30015f436cfbSKazutaka YOKOTA sum += buf[len - 1]; 30025f436cfbSKazutaka YOKOTA for (; i < len; ++i) 30035f436cfbSKazutaka YOKOTA buf[i] += offset; 30045f436cfbSKazutaka YOKOTA debug("PnP ID string: '%*.*s'", len, len, buf); 30055f436cfbSKazutaka YOKOTA 30065f436cfbSKazutaka YOKOTA /* revision */ 30075f436cfbSKazutaka YOKOTA buf[1] -= offset; 30085f436cfbSKazutaka YOKOTA buf[2] -= offset; 30095f436cfbSKazutaka YOKOTA id->revision = ((buf[1] & 0x3f) << 6) | (buf[2] & 0x3f); 30105f436cfbSKazutaka YOKOTA debug("PnP rev %d.%02d", id->revision / 100, id->revision % 100); 30115f436cfbSKazutaka YOKOTA 3012de1a17dbSElyes Haouas /* EISA vendor and product ID */ 30135f436cfbSKazutaka YOKOTA id->eisaid = &buf[3]; 30145f436cfbSKazutaka YOKOTA id->neisaid = 7; 30155f436cfbSKazutaka YOKOTA 30165f436cfbSKazutaka YOKOTA /* option strings */ 30175f436cfbSKazutaka YOKOTA i = 10; 30185f436cfbSKazutaka YOKOTA if (buf[i] == '\\') { 30195f436cfbSKazutaka YOKOTA /* device serial # */ 30205f436cfbSKazutaka YOKOTA for (j = ++i; i < len; ++i) { 30215f436cfbSKazutaka YOKOTA if (buf[i] == '\\') 30225f436cfbSKazutaka YOKOTA break; 30235f436cfbSKazutaka YOKOTA } 30245f436cfbSKazutaka YOKOTA if (i >= len) 30255f436cfbSKazutaka YOKOTA i -= 3; 30265f436cfbSKazutaka YOKOTA if (i - j == 8) { 30275f436cfbSKazutaka YOKOTA id->serial = &buf[j]; 30285f436cfbSKazutaka YOKOTA id->nserial = 8; 30295f436cfbSKazutaka YOKOTA } 30305f436cfbSKazutaka YOKOTA } 30315f436cfbSKazutaka YOKOTA if (buf[i] == '\\') { 30325f436cfbSKazutaka YOKOTA /* PnP class */ 30335f436cfbSKazutaka YOKOTA for (j = ++i; i < len; ++i) { 30345f436cfbSKazutaka YOKOTA if (buf[i] == '\\') 30355f436cfbSKazutaka YOKOTA break; 30365f436cfbSKazutaka YOKOTA } 30375f436cfbSKazutaka YOKOTA if (i >= len) 30385f436cfbSKazutaka YOKOTA i -= 3; 30395f436cfbSKazutaka YOKOTA if (i > j + 1) { 30405f436cfbSKazutaka YOKOTA id->class = &buf[j]; 30415f436cfbSKazutaka YOKOTA id->nclass = i - j; 30425f436cfbSKazutaka YOKOTA } 30435f436cfbSKazutaka YOKOTA } 30445f436cfbSKazutaka YOKOTA if (buf[i] == '\\') { 30455f436cfbSKazutaka YOKOTA /* compatible driver */ 30465f436cfbSKazutaka YOKOTA for (j = ++i; i < len; ++i) { 30475f436cfbSKazutaka YOKOTA if (buf[i] == '\\') 30485f436cfbSKazutaka YOKOTA break; 30495f436cfbSKazutaka YOKOTA } 30505f436cfbSKazutaka YOKOTA /* 30515f436cfbSKazutaka YOKOTA * PnP COM spec prior to v0.96 allowed '*' in this field, 3052de1a17dbSElyes Haouas * it's not allowed now; just ignore it. 30535f436cfbSKazutaka YOKOTA */ 30545f436cfbSKazutaka YOKOTA if (buf[j] == '*') 30555f436cfbSKazutaka YOKOTA ++j; 30565f436cfbSKazutaka YOKOTA if (i >= len) 30575f436cfbSKazutaka YOKOTA i -= 3; 30585f436cfbSKazutaka YOKOTA if (i > j + 1) { 30595f436cfbSKazutaka YOKOTA id->compat = &buf[j]; 30605f436cfbSKazutaka YOKOTA id->ncompat = i - j; 30615f436cfbSKazutaka YOKOTA } 30625f436cfbSKazutaka YOKOTA } 30635f436cfbSKazutaka YOKOTA if (buf[i] == '\\') { 30645f436cfbSKazutaka YOKOTA /* product description */ 30655f436cfbSKazutaka YOKOTA for (j = ++i; i < len; ++i) { 30665f436cfbSKazutaka YOKOTA if (buf[i] == ';') 30675f436cfbSKazutaka YOKOTA break; 30685f436cfbSKazutaka YOKOTA } 30695f436cfbSKazutaka YOKOTA if (i >= len) 30705f436cfbSKazutaka YOKOTA i -= 3; 30715f436cfbSKazutaka YOKOTA if (i > j + 1) { 30725f436cfbSKazutaka YOKOTA id->description = &buf[j]; 30735f436cfbSKazutaka YOKOTA id->ndescription = i - j; 30745f436cfbSKazutaka YOKOTA } 30755f436cfbSKazutaka YOKOTA } 30765f436cfbSKazutaka YOKOTA 30775f436cfbSKazutaka YOKOTA /* checksum exists if there are any optional fields */ 30785f436cfbSKazutaka YOKOTA if ((id->nserial > 0) || (id->nclass > 0) 30795f436cfbSKazutaka YOKOTA || (id->ncompat > 0) || (id->ndescription > 0)) { 30805f436cfbSKazutaka YOKOTA debug("PnP checksum: 0x%X", sum); 30815f436cfbSKazutaka YOKOTA sprintf(s, "%02X", sum & 0x0ff); 30825f436cfbSKazutaka YOKOTA if (strncmp(s, &buf[len - 3], 2) != 0) { 30835f436cfbSKazutaka YOKOTA #if 0 30845f436cfbSKazutaka YOKOTA /* 30855f436cfbSKazutaka YOKOTA * I found some mice do not comply with the PnP COM device 30865f436cfbSKazutaka YOKOTA * spec regarding checksum... XXX 30875f436cfbSKazutaka YOKOTA */ 30885f436cfbSKazutaka YOKOTA logwarnx("PnP checksum error", 0); 30892657f6e9SJung-uk Kim return (FALSE); 30905f436cfbSKazutaka YOKOTA #endif 30915f436cfbSKazutaka YOKOTA } 30925f436cfbSKazutaka YOKOTA } 30935f436cfbSKazutaka YOKOTA 30942657f6e9SJung-uk Kim return (TRUE); 30955f436cfbSKazutaka YOKOTA } 30965f436cfbSKazutaka YOKOTA 30975f436cfbSKazutaka YOKOTA static symtab_t * 30985f436cfbSKazutaka YOKOTA pnpproto(pnpid_t *id) 30995f436cfbSKazutaka YOKOTA { 31005f436cfbSKazutaka YOKOTA symtab_t *t; 31015f436cfbSKazutaka YOKOTA int i, j; 31025f436cfbSKazutaka YOKOTA 31035f436cfbSKazutaka YOKOTA if (id->nclass > 0) 31041b11ca6cSKazutaka YOKOTA if (strncmp(id->class, "MOUSE", id->nclass) != 0 && 31051b11ca6cSKazutaka YOKOTA strncmp(id->class, "TABLET", id->nclass) != 0) 31065f436cfbSKazutaka YOKOTA /* this is not a mouse! */ 31072657f6e9SJung-uk Kim return (NULL); 31085f436cfbSKazutaka YOKOTA 31095f436cfbSKazutaka YOKOTA if (id->neisaid > 0) { 31105f436cfbSKazutaka YOKOTA t = gettoken(pnpprod, id->eisaid, id->neisaid); 31115f436cfbSKazutaka YOKOTA if (t->val != MOUSE_PROTO_UNKNOWN) 31122657f6e9SJung-uk Kim return (t); 31135f436cfbSKazutaka YOKOTA } 31145f436cfbSKazutaka YOKOTA 31155f436cfbSKazutaka YOKOTA /* 31165f436cfbSKazutaka YOKOTA * The 'Compatible drivers' field may contain more than one 31175f436cfbSKazutaka YOKOTA * ID separated by ','. 31185f436cfbSKazutaka YOKOTA */ 31195f436cfbSKazutaka YOKOTA if (id->ncompat <= 0) 31202657f6e9SJung-uk Kim return (NULL); 31215f436cfbSKazutaka YOKOTA for (i = 0; i < id->ncompat; ++i) { 31225f436cfbSKazutaka YOKOTA for (j = i; id->compat[i] != ','; ++i) 31235f436cfbSKazutaka YOKOTA if (i >= id->ncompat) 31245f436cfbSKazutaka YOKOTA break; 31255f436cfbSKazutaka YOKOTA if (i > j) { 31265f436cfbSKazutaka YOKOTA t = gettoken(pnpprod, id->compat + j, i - j); 31275f436cfbSKazutaka YOKOTA if (t->val != MOUSE_PROTO_UNKNOWN) 31282657f6e9SJung-uk Kim return (t); 31295f436cfbSKazutaka YOKOTA } 31305f436cfbSKazutaka YOKOTA } 31315f436cfbSKazutaka YOKOTA 31322657f6e9SJung-uk Kim return (NULL); 31335f436cfbSKazutaka YOKOTA } 31345f436cfbSKazutaka YOKOTA 31355f436cfbSKazutaka YOKOTA /* name/val mapping */ 31365f436cfbSKazutaka YOKOTA 31375f436cfbSKazutaka YOKOTA static symtab_t * 31382657f6e9SJung-uk Kim gettoken(symtab_t *tab, const char *s, int len) 31395f436cfbSKazutaka YOKOTA { 31405f436cfbSKazutaka YOKOTA int i; 31415f436cfbSKazutaka YOKOTA 31425f436cfbSKazutaka YOKOTA for (i = 0; tab[i].name != NULL; ++i) { 31435f436cfbSKazutaka YOKOTA if (strncmp(tab[i].name, s, len) == 0) 31445f436cfbSKazutaka YOKOTA break; 31455f436cfbSKazutaka YOKOTA } 31462657f6e9SJung-uk Kim return (&tab[i]); 31475f436cfbSKazutaka YOKOTA } 31485f436cfbSKazutaka YOKOTA 31492657f6e9SJung-uk Kim static const char * 31505f436cfbSKazutaka YOKOTA gettokenname(symtab_t *tab, int val) 31515f436cfbSKazutaka YOKOTA { 31522657f6e9SJung-uk Kim static const char unknown[] = "unknown"; 31535f436cfbSKazutaka YOKOTA int i; 31545f436cfbSKazutaka YOKOTA 31555f436cfbSKazutaka YOKOTA for (i = 0; tab[i].name != NULL; ++i) { 31565f436cfbSKazutaka YOKOTA if (tab[i].val == val) 31572657f6e9SJung-uk Kim return (tab[i].name); 31585f436cfbSKazutaka YOKOTA } 31592657f6e9SJung-uk Kim return (unknown); 316013379e47SPeter Wemm } 316167978692SAmancio Hasty 31621b11ca6cSKazutaka YOKOTA 31631b11ca6cSKazutaka YOKOTA /* 31641b11ca6cSKazutaka YOKOTA * code to read from the Genius Kidspad tablet. 31651b11ca6cSKazutaka YOKOTA 31661b11ca6cSKazutaka YOKOTA The tablet responds to the COM PnP protocol 1.0 with EISA-ID KYE0005, 31671b11ca6cSKazutaka YOKOTA and to pre-pnp probes (RTS toggle) with 'T' (tablet ?) 31681b11ca6cSKazutaka YOKOTA 9600, 8 bit, parity odd. 31691b11ca6cSKazutaka YOKOTA 31701b11ca6cSKazutaka YOKOTA The tablet puts out 5 bytes. b0 (mask 0xb8, value 0xb8) contains 31711b11ca6cSKazutaka YOKOTA the proximity, tip and button info: 31721b11ca6cSKazutaka YOKOTA (byte0 & 0x1) true = tip pressed 31731b11ca6cSKazutaka YOKOTA (byte0 & 0x2) true = button pressed 31741b11ca6cSKazutaka YOKOTA (byte0 & 0x40) false = pen in proximity of tablet. 31751b11ca6cSKazutaka YOKOTA 31761b11ca6cSKazutaka YOKOTA The next 4 bytes are used for coordinates xl, xh, yl, yh (7 bits valid). 31771b11ca6cSKazutaka YOKOTA 31781b11ca6cSKazutaka YOKOTA Only absolute coordinates are returned, so we use the following approach: 31791b11ca6cSKazutaka YOKOTA we store the last coordinates sent when the pen went out of the tablet, 31801b11ca6cSKazutaka YOKOTA 31811b11ca6cSKazutaka YOKOTA 31821b11ca6cSKazutaka YOKOTA * 31831b11ca6cSKazutaka YOKOTA */ 31841b11ca6cSKazutaka YOKOTA 31851b11ca6cSKazutaka YOKOTA typedef enum { 31861b11ca6cSKazutaka YOKOTA S_IDLE, S_PROXY, S_FIRST, S_DOWN, S_UP 31871b11ca6cSKazutaka YOKOTA } k_status; 31881b11ca6cSKazutaka YOKOTA 31891b11ca6cSKazutaka YOKOTA static int 31901b11ca6cSKazutaka YOKOTA kidspad(u_char rxc, mousestatus_t *act) 31911b11ca6cSKazutaka YOKOTA { 319262e621e8SIan Dowse static int buf[5]; 31931b11ca6cSKazutaka YOKOTA static int buflen = 0, b_prev = 0 , x_prev = -1, y_prev = -1; 31941b11ca6cSKazutaka YOKOTA static k_status status = S_IDLE; 31956240691aSEitan Adler static struct timespec now; 31961b11ca6cSKazutaka YOKOTA 31977309915eSDima Dorfman int x, y; 31981b11ca6cSKazutaka YOKOTA 31991b11ca6cSKazutaka YOKOTA if (buflen > 0 && (rxc & 0x80)) { 32001b11ca6cSKazutaka YOKOTA fprintf(stderr, "invalid code %d 0x%x\n", buflen, rxc); 32011b11ca6cSKazutaka YOKOTA buflen = 0; 32021b11ca6cSKazutaka YOKOTA } 32031b11ca6cSKazutaka YOKOTA if (buflen == 0 && (rxc & 0xb8) != 0xb8) { 32041b11ca6cSKazutaka YOKOTA fprintf(stderr, "invalid code 0 0x%x\n", rxc); 32052657f6e9SJung-uk Kim return (0); /* invalid code, no action */ 32061b11ca6cSKazutaka YOKOTA } 32071b11ca6cSKazutaka YOKOTA buf[buflen++] = rxc; 32081b11ca6cSKazutaka YOKOTA if (buflen < 5) 32092657f6e9SJung-uk Kim return (0); 32101b11ca6cSKazutaka YOKOTA 32111b11ca6cSKazutaka YOKOTA buflen = 0; /* for next time... */ 32121b11ca6cSKazutaka YOKOTA 32131b11ca6cSKazutaka YOKOTA x = buf[1]+128*(buf[2] - 7); 32141b11ca6cSKazutaka YOKOTA if (x < 0) x = 0; 32151b11ca6cSKazutaka YOKOTA y = 28*128 - (buf[3] + 128* (buf[4] - 7)); 32161b11ca6cSKazutaka YOKOTA if (y < 0) y = 0; 32171b11ca6cSKazutaka YOKOTA 32181b11ca6cSKazutaka YOKOTA x /= 8; 32191b11ca6cSKazutaka YOKOTA y /= 8; 32201b11ca6cSKazutaka YOKOTA 32211b11ca6cSKazutaka YOKOTA act->flags = 0; 32221b11ca6cSKazutaka YOKOTA act->obutton = act->button; 32231b11ca6cSKazutaka YOKOTA act->dx = act->dy = act->dz = 0; 322413f1c59bSJung-uk Kim clock_gettime(CLOCK_MONOTONIC_FAST, &now); 32251b11ca6cSKazutaka YOKOTA if (buf[0] & 0x40) /* pen went out of reach */ 32261b11ca6cSKazutaka YOKOTA status = S_IDLE; 32271b11ca6cSKazutaka YOKOTA else if (status == S_IDLE) { /* pen is newly near the tablet */ 32281b11ca6cSKazutaka YOKOTA act->flags |= MOUSE_POSCHANGED; /* force update */ 32291b11ca6cSKazutaka YOKOTA status = S_PROXY; 32301b11ca6cSKazutaka YOKOTA x_prev = x; 32311b11ca6cSKazutaka YOKOTA y_prev = y; 32321b11ca6cSKazutaka YOKOTA } 32331b11ca6cSKazutaka YOKOTA act->dx = x - x_prev; 32341b11ca6cSKazutaka YOKOTA act->dy = y - y_prev; 32351b11ca6cSKazutaka YOKOTA if (act->dx || act->dy) 32361b11ca6cSKazutaka YOKOTA act->flags |= MOUSE_POSCHANGED; 32371b11ca6cSKazutaka YOKOTA x_prev = x; 32381b11ca6cSKazutaka YOKOTA y_prev = y; 32391b11ca6cSKazutaka YOKOTA if (b_prev != 0 && b_prev != buf[0]) { /* possibly record button change */ 32401b11ca6cSKazutaka YOKOTA act->button = 0; 32411b11ca6cSKazutaka YOKOTA if (buf[0] & 0x01) /* tip pressed */ 32421b11ca6cSKazutaka YOKOTA act->button |= MOUSE_BUTTON1DOWN; 32431b11ca6cSKazutaka YOKOTA if (buf[0] & 0x02) /* button pressed */ 32441b11ca6cSKazutaka YOKOTA act->button |= MOUSE_BUTTON2DOWN; 32451b11ca6cSKazutaka YOKOTA act->flags |= MOUSE_BUTTONSCHANGED; 32461b11ca6cSKazutaka YOKOTA } 32471b11ca6cSKazutaka YOKOTA b_prev = buf[0]; 32482657f6e9SJung-uk Kim return (act->flags); 32491b11ca6cSKazutaka YOKOTA } 32501b11ca6cSKazutaka YOKOTA 3251ce99e877SMatthew N. Dodd static int 3252ce99e877SMatthew N. Dodd gtco_digipad (u_char rxc, mousestatus_t *act) 3253ce99e877SMatthew N. Dodd { 3254ce99e877SMatthew N. Dodd static u_char buf[5]; 3255ce99e877SMatthew N. Dodd static int buflen = 0, b_prev = 0 , x_prev = -1, y_prev = -1; 3256ce99e877SMatthew N. Dodd static k_status status = S_IDLE; 3257ce99e877SMatthew N. Dodd int x, y; 3258ce99e877SMatthew N. Dodd 3259ce99e877SMatthew N. Dodd #define GTCO_HEADER 0x80 3260ce99e877SMatthew N. Dodd #define GTCO_PROXIMITY 0x40 3261ce99e877SMatthew N. Dodd #define GTCO_START (GTCO_HEADER|GTCO_PROXIMITY) 3262ce99e877SMatthew N. Dodd #define GTCO_BUTTONMASK 0x3c 3263ce99e877SMatthew N. Dodd 3264ce99e877SMatthew N. Dodd 3265ce99e877SMatthew N. Dodd if (buflen > 0 && ((rxc & GTCO_HEADER) != GTCO_HEADER)) { 3266ce99e877SMatthew N. Dodd fprintf(stderr, "invalid code %d 0x%x\n", buflen, rxc); 3267ce99e877SMatthew N. Dodd buflen = 0; 3268ce99e877SMatthew N. Dodd } 3269ce99e877SMatthew N. Dodd if (buflen == 0 && (rxc & GTCO_START) != GTCO_START) { 3270ce99e877SMatthew N. Dodd fprintf(stderr, "invalid code 0 0x%x\n", rxc); 32712657f6e9SJung-uk Kim return (0); /* invalid code, no action */ 3272ce99e877SMatthew N. Dodd } 3273ce99e877SMatthew N. Dodd 3274ce99e877SMatthew N. Dodd buf[buflen++] = rxc; 3275ce99e877SMatthew N. Dodd if (buflen < 5) 32762657f6e9SJung-uk Kim return (0); 3277ce99e877SMatthew N. Dodd 3278ce99e877SMatthew N. Dodd buflen = 0; /* for next time... */ 3279ce99e877SMatthew N. Dodd 3280ce99e877SMatthew N. Dodd x = ((buf[2] & ~GTCO_START) << 6 | (buf[1] & ~GTCO_START)); 3281ce99e877SMatthew N. Dodd y = 4768 - ((buf[4] & ~GTCO_START) << 6 | (buf[3] & ~GTCO_START)); 3282ce99e877SMatthew N. Dodd 3283ce99e877SMatthew N. Dodd x /= 2.5; 3284ce99e877SMatthew N. Dodd y /= 2.5; 3285ce99e877SMatthew N. Dodd 3286ce99e877SMatthew N. Dodd act->flags = 0; 3287ce99e877SMatthew N. Dodd act->obutton = act->button; 3288ce99e877SMatthew N. Dodd act->dx = act->dy = act->dz = 0; 3289ce99e877SMatthew N. Dodd 3290ce99e877SMatthew N. Dodd if ((buf[0] & 0x40) == 0) /* pen went out of reach */ 3291ce99e877SMatthew N. Dodd status = S_IDLE; 3292ce99e877SMatthew N. Dodd else if (status == S_IDLE) { /* pen is newly near the tablet */ 3293ce99e877SMatthew N. Dodd act->flags |= MOUSE_POSCHANGED; /* force update */ 3294ce99e877SMatthew N. Dodd status = S_PROXY; 3295ce99e877SMatthew N. Dodd x_prev = x; 3296ce99e877SMatthew N. Dodd y_prev = y; 3297ce99e877SMatthew N. Dodd } 3298ce99e877SMatthew N. Dodd 3299ce99e877SMatthew N. Dodd act->dx = x - x_prev; 3300ce99e877SMatthew N. Dodd act->dy = y - y_prev; 3301ce99e877SMatthew N. Dodd if (act->dx || act->dy) 3302ce99e877SMatthew N. Dodd act->flags |= MOUSE_POSCHANGED; 3303ce99e877SMatthew N. Dodd x_prev = x; 3304ce99e877SMatthew N. Dodd y_prev = y; 3305ce99e877SMatthew N. Dodd 3306ce99e877SMatthew N. Dodd /* possibly record button change */ 3307ce99e877SMatthew N. Dodd if (b_prev != 0 && b_prev != buf[0]) { 3308ce99e877SMatthew N. Dodd act->button = 0; 33092657f6e9SJung-uk Kim if (buf[0] & 0x04) { 33102657f6e9SJung-uk Kim /* tip pressed/yellow */ 3311ce99e877SMatthew N. Dodd act->button |= MOUSE_BUTTON1DOWN; 33122657f6e9SJung-uk Kim } 33132657f6e9SJung-uk Kim if (buf[0] & 0x08) { 33142657f6e9SJung-uk Kim /* grey/white */ 3315ce99e877SMatthew N. Dodd act->button |= MOUSE_BUTTON2DOWN; 33162657f6e9SJung-uk Kim } 33172657f6e9SJung-uk Kim if (buf[0] & 0x10) { 33182657f6e9SJung-uk Kim /* black/green */ 3319ce99e877SMatthew N. Dodd act->button |= MOUSE_BUTTON3DOWN; 33202657f6e9SJung-uk Kim } 33212657f6e9SJung-uk Kim if (buf[0] & 0x20) { 33222657f6e9SJung-uk Kim /* tip+grey/blue */ 3323ce99e877SMatthew N. Dodd act->button |= MOUSE_BUTTON4DOWN; 33242657f6e9SJung-uk Kim } 3325ce99e877SMatthew N. Dodd act->flags |= MOUSE_BUTTONSCHANGED; 3326ce99e877SMatthew N. Dodd } 3327ce99e877SMatthew N. Dodd b_prev = buf[0]; 33282657f6e9SJung-uk Kim return (act->flags); 3329ce99e877SMatthew N. Dodd } 3330ce99e877SMatthew N. Dodd 333167978692SAmancio Hasty static void 33322657f6e9SJung-uk Kim mremote_serversetup(void) 333367978692SAmancio Hasty { 333467978692SAmancio Hasty struct sockaddr_un ad; 333567978692SAmancio Hasty 333667978692SAmancio Hasty /* Open a UNIX domain stream socket to listen for mouse remote clients */ 333767978692SAmancio Hasty unlink(_PATH_MOUSEREMOTE); 333867978692SAmancio Hasty 333967978692SAmancio Hasty if ((rodent.mremsfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 334067978692SAmancio Hasty logerrx(1, "unable to create unix domain socket %s",_PATH_MOUSEREMOTE); 334167978692SAmancio Hasty 334267978692SAmancio Hasty umask(0111); 334367978692SAmancio Hasty 334467978692SAmancio Hasty bzero(&ad, sizeof(ad)); 334567978692SAmancio Hasty ad.sun_family = AF_UNIX; 334667978692SAmancio Hasty strcpy(ad.sun_path, _PATH_MOUSEREMOTE); 334767978692SAmancio Hasty #ifndef SUN_LEN 334867978692SAmancio Hasty #define SUN_LEN(unp) (((char *)(unp)->sun_path - (char *)(unp)) + \ 334967978692SAmancio Hasty strlen((unp)->path)) 335067978692SAmancio Hasty #endif 335167978692SAmancio Hasty if (bind(rodent.mremsfd, (struct sockaddr *) &ad, SUN_LEN(&ad)) < 0) 335267978692SAmancio Hasty logerrx(1, "unable to bind unix domain socket %s", _PATH_MOUSEREMOTE); 335367978692SAmancio Hasty 335467978692SAmancio Hasty listen(rodent.mremsfd, 1); 335567978692SAmancio Hasty } 335667978692SAmancio Hasty 335767978692SAmancio Hasty static void 335867978692SAmancio Hasty mremote_clientchg(int add) 335967978692SAmancio Hasty { 336067978692SAmancio Hasty struct sockaddr_un ad; 33612657f6e9SJung-uk Kim socklen_t ad_len; 33622657f6e9SJung-uk Kim int fd; 336367978692SAmancio Hasty 336467978692SAmancio Hasty if (rodent.rtype != MOUSE_PROTO_X10MOUSEREM) 336567978692SAmancio Hasty return; 336667978692SAmancio Hasty 336767978692SAmancio Hasty if (add) { 336867978692SAmancio Hasty /* Accept client connection, if we don't already have one */ 336967978692SAmancio Hasty ad_len = sizeof(ad); 337067978692SAmancio Hasty fd = accept(rodent.mremsfd, (struct sockaddr *) &ad, &ad_len); 337167978692SAmancio Hasty if (fd < 0) 337267978692SAmancio Hasty logwarnx("failed accept on mouse remote socket"); 337367978692SAmancio Hasty 337467978692SAmancio Hasty if (rodent.mremcfd < 0) { 337567978692SAmancio Hasty rodent.mremcfd = fd; 337667978692SAmancio Hasty debug("remote client connect...accepted"); 337767978692SAmancio Hasty } 337867978692SAmancio Hasty else { 337967978692SAmancio Hasty close(fd); 338067978692SAmancio Hasty debug("another remote client connect...disconnected"); 338167978692SAmancio Hasty } 338267978692SAmancio Hasty } 338367978692SAmancio Hasty else { 338467978692SAmancio Hasty /* Client disconnected */ 338567978692SAmancio Hasty debug("remote client disconnected"); 338667978692SAmancio Hasty close(rodent.mremcfd); 338767978692SAmancio Hasty rodent.mremcfd = -1; 338867978692SAmancio Hasty } 338967978692SAmancio Hasty } 3390