diff -urN gpm-1.20.1/configure.in gpm/configure.in --- gpm-1.20.1/configure.in 2002-12-24 17:57:16.000000000 -0500 +++ gpm/configure.in 2003-10-02 01:22:42.000000000 -0500 @@ -61,6 +61,13 @@ AC_CHECK_HEADERS(syslog.h linux/input.h linux/joystick.h ncurses.h ncurses/curses.h curses.h) +EVDEV_SRCS= +if test ${ac_cv_header_linux_input_h} = yes ; then + EVDEV_SRCS=evdev.c ; + AC_CHECK_TYPE(struct input_absinfo,AC_DEFINE_UNQUOTED(HAVE_INPUT_ABSINFO, 1, [define if struct input_absinfo defined in linux/input.h]),,[#include ]) + AC_CHECK_TYPE(struct input_id,AC_DEFINE_UNQUOTED(HAVE_INPUT_ID, 1, [define if struct input_id defined in linux/input.h]),,[#include ]) +fi + AC_ARG_WITH(curses, [ --without-curses disable curses support even if curses found]) @@ -124,6 +131,7 @@ AC_SUBST(PICFLAGS) AC_SUBST(SOLDFLAGS) AC_SUBST(CURSES_OBJS) +AC_SUBST(EVDEV_SRCS) AC_SUBST(SHARED_LIBS) AC_SUBST(lispdir) diff -urN gpm-1.20.1/src/client.c gpm/src/client.c --- gpm-1.20.1/src/client.c 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/client.c 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,319 @@ +/* + * client.c - GPM client handling (server side) + * + * Copyright (C) 1993 Andreq Haylett + * Copyright (C) 1994-1999 Alessandro Rubini + * Copyright (C) 1998 Ian Zimmerman + * Copyright (c) 2001,2002 Nico Schottelius + * Copyright (C) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#include +#include +#include /* strerror(); ?!? */ +#include +#include /* select(); */ +#include /* SIGPIPE */ +#include /* time() */ +#include /* O_RDONLY */ +#include /* mkdir() */ +#include /* timeval */ +#include /* socket() */ +#include /* socket() */ +#include /* struct sockaddr_un */ + +#include "headers/gpmInt.h" +#include "headers/message.h" +#include "headers/console.h" +#include "headers/selection.h" +#include "headers/client.h" + +/* who the f*** runs gpm without glibc? doesn't have dietlibc __socklent_t? */ +#if !defined(__GLIBC__) + typedef unsigned int __socklen_t; +#endif /* __GLIBC__ */ + +#ifndef max +#define max(a,b) ((a)>(b) ? (a) : (b)) +#endif + +extern int errno; + +struct client_info *cinfo[MAX_VC + 1]; + +/*-------------------------------------------------------------------* + * This was inline, and incurred in a compiler bug (2.7.0) + *-------------------------------------------------------------------*/ +static int get_data(int fd, Gpm_Connect *data) +{ + static int len; + +#ifdef GPM_USE_MAGIC + while ((len = read(whence, &check, sizeof(int))) == 4 && + check != GPM_MAGIC) + gpm_report(GPM_PR_INFO, GPM_MESS_NO_MAGIC); + + if (len == 0) return 0; + + if (check != GPM_MAGIC) { + gpm_report(GPM_PR_INFO, GPM_MESS_NOTHING_MORE); + return -1; + } +#endif + + len = read(fd, data, sizeof(Gpm_Connect)); + + return len ? (len == sizeof(Gpm_Connect) ? 1 : -1) : 0; +} + +/*-------------------------------------------------------------------*/ +int listen_for_clients(void) +{ + struct sockaddr_un ctladdr; + int fd, len; + + unlink(GPM_NODE_CTL); + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + gpm_report(GPM_PR_OOPS, GPM_MESS_SOCKET_PROB); + + memset(&ctladdr, 0, sizeof(ctladdr)); + ctladdr.sun_family = AF_UNIX; + strcpy(ctladdr.sun_path, GPM_NODE_CTL); + len = sizeof(ctladdr.sun_family) + strlen(GPM_NODE_CTL); + + if (bind(fd, (struct sockaddr *)&ctladdr, len) == -1) + gpm_report(GPM_PR_OOPS, GPM_MESS_BIND_PROB, ctladdr.sun_path); + + /* needs to be 0777, so all users can _try_ to access gpm */ + chmod(GPM_NODE_CTL, 0777); + listen(fd, 5); /* Queue up calls */ + + return fd; +} + +/*-------------------------------------------------------------------*/ +struct client_info *accept_client_connection(int fd) +{ + struct client_info *info; + Gpm_Connect *request; + int newfd; +#if !defined(__GLIBC__) + int len; +#else /* __GLIBC__ */ + size_t len; /* isn't that generally defined in C ??? -- nico */ +#endif /* __GLIBC__ */ + struct sockaddr_un addr; /* reuse this each time */ +#ifndef SO_PEERCRED + struct stat statbuf; + time_t staletime; +#endif + uid_t uid; + + /*....................................... Accept */ + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + + len = sizeof(addr); + if ((newfd = accept(fd, (struct sockaddr *)&addr, &len)) < 0) { + gpm_report(GPM_PR_ERR, GPM_MESS_ACCEPT_FAILED, strerror(errno)); + return NULL; + } + + gpm_report(GPM_PR_INFO, GPM_MESS_CONECT_AT, newfd); + + if (!(info = malloc(sizeof(struct client_info)))) + gpm_report(GPM_PR_OOPS, GPM_MESS_NO_MEM); + + request = &info->data; + if (get_data(newfd, request) == -1) + goto err; + + if (request->vc > MAX_VC) { + gpm_report(GPM_PR_WARN,GPM_MESS_REQUEST_ON, request->vc, MAX_VC); + goto err; + } + +#ifndef SO_PEERCRED + if (stat(addr.sun_path, &statbuf) == -1 || !S_ISSOCK(statbuf.st_mode)) { + gpm_report(GPM_PR_ERR,GPM_MESS_ADDRES_NSOCKET,addr.sun_path); + goto err; + } + + unlink(addr.sun_path); /* delete socket */ + + staletime = time(0) - 30; + if (statbuf.st_atime < staletime || + statbuf.st_ctime < staletime || + statbuf.st_mtime < staletime) { + gpm_report(GPM_PR_ERR, GPM_MESS_SOCKET_OLD); + goto err; + } + + uid = statbuf.st_uid; /* owner of socket */ +#else + { + struct ucred sucred; + socklen_t credlen = sizeof(struct ucred); + + if (getsockopt(newfd, SOL_SOCKET, SO_PEERCRED, &sucred, &credlen) == -1) { + gpm_report(GPM_PR_ERR,GPM_MESS_GETSOCKOPT, strerror(errno)); + goto err; + } + uid = sucred.uid; + gpm_report(GPM_PR_DEBUG,GPM_MESS_PEER_SCK_UID, uid); + } +#endif + + if (uid != 0 && !is_console_owner(request->vc, uid)) { + gpm_report(GPM_PR_WARN, GPM_MESS_FAILED_CONNECT, uid, request->vc); + goto err; + } + + /* register the connection information in the right place */ + info->next = cinfo[request->vc]; + info->fd = newfd; + cinfo[request->vc] = info; + gpm_report(GPM_PR_DEBUG, GPM_MESS_LONG_STATUS, + request->pid, request->vc, request->eventMask, request->defaultMask, + request->minMod, request->maxMod); + + return info; + +err: + free(info); + close(newfd); + + return NULL; +} + +/*-------------------------------------------------------------------*/ +void remove_client(struct client_info *ci, int vc) +{ + struct client_info *p, *prev = NULL; + + for (p = cinfo[vc]; p; prev = p, p = p->next) { + if (p == ci) { + if (!prev) /* it is on top of the stack */ + cinfo[vc] = p->next; + else + prev->next = p->next; + break; + } + } + if (p) free(p); +} + +/*-------------------------------------------------------------------*/ +void notify_clients_resize(void) +{ + struct client_info *ci; + int i; + + for (i = 0; i < MAX_VC + 1; i++) + for (ci = cinfo[i]; ci; ci = ci->next) + kill(ci->data.pid, SIGWINCH); +} + +/*-------------------------------------------------------------------*/ +/* returns 0 if the event has not been processed, and 1 if it has */ +int do_client(struct client_info *cinfo, Gpm_Event *event) +{ + Gpm_Connect *info = &cinfo->data; + /* value to return if event is not used */ + int res = !(info->defaultMask & event->type); + + /* instead of returning 0, scan the stack of clients */ + if ((info->minMod & event->modifiers) < info->minMod) + goto try_next; + if ((info->maxMod & event->modifiers) < event->modifiers) + goto try_next; + + /* if not managed, use default mask */ + if (!(info->eventMask & GPM_BARE_EVENTS(event->type))) { + if (res) return res; + else goto try_next; + } + + /* WARNING */ /* This can generate a SIGPIPE... I'd better catch it */ + MAGIC_P((write(cinfo->fd, &magic, sizeof(int)))); + write(cinfo->fd, event, sizeof(Gpm_Event)); + + return info->defaultMask & GPM_HARD ? res : 1; /* HARD forces pass-on */ + + try_next: + if (cinfo->next != 0) + return do_client(cinfo->next, event); /* try the next */ + + return 0; /* no next, not used */ +} + +/*-------------------------------------------------------------------*/ +/* returns 0 if client disconnects, -1 - error, 1 -successs */ +int process_client_request(struct client_info *ci, int vc, + int x, int y, int buttons, int clicks, + int three_button_mouse) +{ + int rc; + Gpm_Connect conn; + static Gpm_Event event; + + gpm_report(GPM_PR_INFO, GPM_MESS_CON_REQUEST, ci->fd, vc); + if (vc > MAX_VC) return -1; + + /* itz 10-22-96 this shouldn't happen now */ + if (vc == -1) gpm_report(GPM_PR_OOPS, GPM_MESS_UNKNOWN_FD); + + rc = get_data(ci->fd, &conn); + + if (rc == 0) { /* no data */ + gpm_report(GPM_PR_INFO, GPM_MESS_CLOSE); + close(ci->fd); + return 0; + } + + if (rc == -1) return -1; /* too few bytes */ + + if (conn.pid != 0) { + ci->data = conn; + return 1; + } + + /* Aha, request for information (so-called snapshot) */ + switch (conn.vc) { + case GPM_REQ_SNAPSHOT: + event.vc = get_console_state(&event.modifiers); + event.x = x; event.y = y; + event.buttons = buttons; + event.clicks = clicks; + event.dx = console.max_x; event.dy = console.max_y; + /* fall through */ + + case GPM_REQ_BUTTONS: + event.type = (three_button_mouse == 1 ? 3 : 2); /* buttons */ + write(ci->fd, &event, sizeof(Gpm_Event)); + break; + + case GPM_REQ_NOPASTE: + selection_disable_paste(); + gpm_report(GPM_PR_INFO, GPM_MESS_DISABLE_PASTE, vc); + break; + } + + return 1; +} + diff -urN gpm-1.20.1/src/console.c gpm/src/console.c --- gpm-1.20.1/src/console.c 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/console.c 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,257 @@ +/* + * console.c - GPM console and selection/paste handling + * + * Copyright (C) 1993 Andreq Haylett + * Copyright (C) 1994-1999 Alessandro Rubini + * Copyright (C) 1998 Ian Zimmerman + * Copyright (c) 2001,2002 Nico Schottelius + * Copyright (c) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#include +#include +#include /* strerror(); ?!? */ +#include +#include /* select(); */ +#include /* time() */ +#include /* O_RDONLY */ +#include /* mkdir() */ +#include /* __u32 */ + +#include /* VT_GETSTATE */ +#include /* KDGETMODE */ +#include /* winsize */ + +#include "headers/gpmInt.h" +#include "headers/console.h" +#include "headers/message.h" + +#ifndef HAVE___U32 +# ifndef _I386_TYPES_H /* /usr/include/asm/types.h */ +typedef unsigned int __u32; +# endif +#endif + +struct gpm_console console = { 0, DEF_LUT, 0, 0 }; + +/*-------------------------------------------------------------------*/ +static int count_digits(int num) +{ + int digits = 1; + + while ((num /= 10)) + digits++; + + return digits; +} + +/*-------------------------------------------------------------------*/ +char *compose_vc_name(int vc) +{ + char *tty; + + tty = malloc(strlen(console.device) + count_digits(vc) + sizeof(char)); + if (tty) { + /* console is /dev/vc/0 or /dev/tty0 and we trimming the ending 0 */ + strncpy(tty, console.device, strlen(console.device) - 1); + sprintf(&tty[strlen(console.device) - 1], "%d", vc); + } + + return tty; +} + +/*-------------------------------------------------------------------*/ +int open_console(int mode) +{ + int fd; + + if ((fd = open(console.device, mode)) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN_CON); + + return fd; +} + +/*-------------------------------------------------------------------*/ +int is_text_console(void) +{ + int fd; + int kd_mode; + + fd = open_console(O_RDONLY); + if (ioctl(fd, KDGETMODE, &kd_mode)<0) + gpm_report(GPM_PR_OOPS, GPM_MESS_IOCTL_KDGETMODE); + close(fd); + + return kd_mode == KD_TEXT; +} + +/*-------------------------------------------------------------------*/ +void wait_text_console(void) +{ + do { + sleep(2); + } while (!is_text_console()); +} + +/*-------------------------------------------------------------------*/ +void refresh_console_size(void) +{ + struct winsize win; + int fd = open_console(O_RDONLY); + + ioctl(fd, TIOCGWINSZ, &win); + close(fd); + + if (!win.ws_col || !win.ws_row) { + gpm_report(GPM_PR_DEBUG, GPM_MESS_ZERO_SCREEN_DIM); + console.max_x = 80; console.max_y = 25; + } else { + console.max_x = win.ws_col; console.max_y = win.ws_row; + } + gpm_report(GPM_PR_DEBUG, GPM_MESS_SCREEN_SIZE, console.max_x, console.max_y); +} + +/*-------------------------------------------------------------------*/ +int get_console_state(unsigned char *shift_state) +{ + struct vt_stat stat; + int fd; + + fd = open_console(O_RDONLY); + + *shift_state = 6; /* code for the ioctl */ + if (ioctl(fd, TIOCLINUX, shift_state) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_GET_SHIFT_STATE); + + if (ioctl(fd, VT_GETSTATE, &stat) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_GET_CONSOLE_STAT); + + close(fd); + + return stat.v_active; +} + +/*-------------------------------------------------------------------*/ +int is_console_owner(int vc, uid_t uid) +{ + struct stat statbuf; + char *tty; + int rc; + + if ((tty = compose_vc_name(vc)) == NULL) + gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM); + + if ((rc = stat(tty, &statbuf)) == -1) + gpm_report(GPM_PR_ERR, GPM_MESS_STAT_FAILS, tty); + + free(tty); + + return rc != -1 && uid == statbuf.st_uid; +} + +/*-------------------------------------------------------------------*/ +/* octal digit */ +static int isodigit(const unsigned char c) +{ + return ((c & ~7) == '0'); +} + +/*-------------------------------------------------------------------*/ +/* routine to convert digits from octal notation (Andries Brouwer) */ +static int getsym(const unsigned char *p0, unsigned char *res) +{ + const unsigned char *p = p0; + char c; + + c = *p++; + if (c == '\\' && *p) { + c = *p++; + if (isodigit(c)) { + c -= '0'; + if (isodigit(*p)) c = 8*c + (*p++ - '0'); + if (isodigit(*p)) c = 8*c + (*p++ - '0'); + } + } + *res = c; + return (p - p0); +} + +/*-------------------------------------------------------------------*/ +/* description missing! FIXME */ +void console_load_lut(void) +{ + extern int errno; + int i, c, fd; + unsigned char this, next; + static __u32 long_array[9] = { + 0x05050505, /* ugly, but preserves alignment */ + 0x00000000, /* control chars */ + 0x00000000, /* digits */ + 0x00000000, /* uppercase and '_' */ + 0x00000000, /* lowercase */ + 0x00000000, /* Latin-1 control */ + 0x00000000, /* Latin-1 misc */ + 0x00000000, /* Latin-1 uppercase */ + 0x00000000 /* Latin-1 lowercase */ + }; + +#define inwordLut (long_array+1) + + for (i = 0; console.charset[i]; ) { + i += getsym(console.charset + i, &this); + if (console.charset[i] == '-' && console.charset[i + 1] != '\0') + i += getsym(console.charset + i + 1, &next) + 1; + else + next = this; + for (c = this; c <= next; c++) + inwordLut[c >> 5] |= 1 << (c & 0x1F); + } + + fd = open_console(O_WRONLY); + + if (ioctl(fd, TIOCLINUX, &long_array) < 0) { /* fd <0 is checked */ + if (errno == EPERM && getuid()) + gpm_report(GPM_PR_WARN, GPM_MESS_ROOT); /* why do we still continue?*/ + else if (errno == EINVAL) + gpm_report(GPM_PR_OOPS, GPM_MESS_CSELECT); + } + close(fd); +} + +/*-------------------------------------------------------------------*/ +/* Returns the name of the console (/dev/tty0 or /dev/vc/0) */ +/* Also fills console.device */ +char *get_console_name() +{ + struct stat buf; + + /* first try the devfs device, because in the next time this will be + * the preferred one. If that fails, take the old console */ + + /* Check for open new console */ + if (stat(GPM_DEVFS_CONSOLE, &buf) == 0) + console.device = GPM_DEVFS_CONSOLE; + + /* Failed, try OLD console */ + else if (stat(GPM_OLD_CONSOLE, &buf) == 0) + console.device = GPM_OLD_CONSOLE; + else + gpm_report(GPM_PR_OOPS, "Can't determine console device"); + + return console.device; +} + diff -urN gpm-1.20.1/src/evdev.c gpm/src/evdev.c --- gpm-1.20.1/src/evdev.c 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/evdev.c 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,851 @@ +/* + * evdev.c - support for event input devices in linux 2.4 & 2.6 + * + * Copyright (C) 2003 Dmitry Torokhov + * Based on XFree86 driver by Stefan Gmeiner & Peter Osterlund + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "headers/input-defines.h" /* misisng bits in case is old */ + +#include "headers/gpm.h" +#include "headers/gpmInt.h" +#include "headers/console.h" +#include "headers/message.h" +#include "headers/optparser.h" + +enum evdev_type { + EVDEV_UNKNOWN, + EVDEV_RELATIVE, + EVDEV_ABSOLUTE, + EVDEV_TOUCHPAD, + EVDEV_SYNAPTICS +}; + +enum touch_type { + TOUCH_NONE, + TOUCH_FINGERS, + TOUCH_PALM +}; + +enum gesture_type { + GESTURE_NONE, + GESTURE_TAP_PENDING, + GESTURE_TAP, + GESTURE_DRAG_PENDING, + GESTURE_DRAG, + GESTURE_DOUBLE_TAP +}; + +enum edge_type { + BOTTOM_EDGE = 1, + TOP_EDGE = 2, + LEFT_EDGE = 4, + RIGHT_EDGE = 8, + LEFT_BOTTOM_EDGE = BOTTOM_EDGE | LEFT_EDGE, + RIGHT_BOTTOM_EDGE = BOTTOM_EDGE | RIGHT_EDGE, + RIGHT_TOP_EDGE = TOP_EDGE | RIGHT_EDGE, + LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE +}; + +struct event_data { + int dx, dy; + int wdx, wdy; + int abs_x, abs_y; + int buttons; + int touch; /* dumb touchpad report touch events, smart ones - pressure */ + int pressure; + int w; + int finger_count; + int synced; +}; + +struct touch_data { + int touching; + int x, y; + int finger_count; + int buttons; + int clicks; + struct timeval start; + enum gesture_type gesture; +}; + +struct event_device { + enum evdev_type type; + int dont_sync; + + struct event_data pkt; + int pkt_count; + + int prev_x[4], prev_y[4]; + int prev_pressure, avg_w; + struct touch_data touch; + + int left_edge, right_edge; + int top_edge, bottom_edge; + int touch_high, touch_low; + int tap_time, tap_move; + int y_inverted; + + enum touch_type (*detect_touch)(struct event_device *evdev); + void (*update_finger_count)(struct event_device *evdev); +}; + +struct evdev_capabilities { + unsigned char evbits[EV_MAX/8 + 1]; + unsigned char keybits[KEY_MAX/8 + 1]; + unsigned char absbits[ABS_MAX/8 + 1]; + unsigned char mscbits[MSC_MAX/8 + 1]; +}; + +#ifndef max +#define max(a,b) ((a)>(b) ? (a) : (b)) +#endif + +#define fx(i) (evdev->prev_x[(evdev->pkt_count - (i)) & 03]) +#define fy(i) (evdev->prev_y[(evdev->pkt_count - (i)) & 03]) + +#define toggle_btn(btn, val) do { if (val) data->buttons |= (btn);\ + else data->buttons &= ~(btn);\ + } while (0) +#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL)) +#define DIF_TIME(t1,t2) ((t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000) + +#define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8))) + +/* ------------- evdev protocol handling routines ---------------------*/ + +static void parse_input_event(struct input_event *event, struct event_data *data) +{ + switch (event->type) { + case EV_REL: + switch (event->code) { + case REL_X: + data->dx = (signed char)event->value; + break; + case REL_Y: + data->dy = (signed char)event->value; + break; + case REL_WHEEL: + data->wdy += event->value; + break; + case REL_HWHEEL: + data->wdx += event->value; + break; + } + break; + + case EV_ABS: + switch (event->code) { + case ABS_X: + data->abs_x = event->value; + break; + + case ABS_Y: + data->abs_y = event->value; + break; + + case ABS_PRESSURE: + data->pressure = event->value; + break; + + case ABS_TOOL_WIDTH: + data->w = event->value; + break; + } + break; + + case EV_MSC: + switch (event->code) { + case MSC_GESTURE: + data->w = event->value; + break; + } + break; + + + case EV_KEY: + switch(event->code) { + case BTN_0: + case BTN_LEFT: + toggle_btn(GPM_B_LEFT, event->value); + break; + + case BTN_2: + case BTN_STYLUS2: + case BTN_SIDE: + case BTN_MIDDLE: + toggle_btn(GPM_B_MIDDLE, event->value); + break; + + case BTN_STYLUS: + case BTN_1: + case BTN_RIGHT: + toggle_btn(GPM_B_RIGHT, event->value); + break; + + case BTN_TOUCH: + data->touch = event->value ? 1 : 0; + break; + + case BTN_TOOL_FINGER: + if (event->value) data->finger_count = 1; + break; + + case BTN_TOOL_DOUBLETAP: + if (event->value) data->finger_count = 2; + break; + + case BTN_TOOL_TRIPLETAP: + if (event->value) data->finger_count = 3; + break; + + } + break; + + case EV_SYNC: + switch(event->code) { + case SYN_REPORT: + data->synced = 1; + break; + } + break; + } +} + +static void tp_figure_deltas(struct event_device *evdev, struct Gpm_Event *state) +{ + struct event_data *pkt = &evdev->pkt; + + state->dx = state->dy = 0; + if (evdev->touch.touching) { + fx(0) = pkt->abs_x; + fy(0) = pkt->abs_y; + if (evdev->pkt_count >= 2 && + evdev->touch.gesture != GESTURE_DRAG_PENDING) { + state->dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8; //SYN_REL_DECEL_FACTOR; + state->dy = ((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8; //SYN_REL_DECEL_FACTOR; + } + evdev->pkt_count++; + } else { + evdev->pkt_count = 0; + } +} + +static enum touch_type dumb_tp_detect_touch(struct event_device *evdev) +{ + return evdev->pkt.touch ? TOUCH_FINGERS : TOUCH_NONE; +} + +static enum touch_type smart_tp_detect_touch(struct event_device *evdev) +{ + if (evdev->touch.touching) + return evdev->pkt.pressure > evdev->touch_low ? TOUCH_FINGERS : TOUCH_NONE; + else + return evdev->pkt.pressure > evdev->touch_high ? TOUCH_FINGERS : TOUCH_NONE; +} + +static enum touch_type syn_detect_touch(struct event_device *evdev) +{ + struct event_data *pkt = &evdev->pkt; + enum touch_type type = TOUCH_NONE; + + if (pkt->pressure > 200 || pkt->w > 10) + return TOUCH_PALM; + + if (pkt->abs_x == 0) + evdev->avg_w = 0; + else + evdev->avg_w = (pkt->w - evdev->avg_w + 1) / 2; + + if (evdev->touch.touching) { + type = pkt->pressure > evdev->touch_low ? TOUCH_FINGERS : TOUCH_NONE; + } else if (pkt->pressure > evdev->touch_high) { + int safe_w = max(pkt->w, evdev->avg_w); + + if (pkt->finger_count > 1) + type = TOUCH_FINGERS; + else if (pkt->w < 2) + type = TOUCH_FINGERS; /* more than one finger -> not a palm */ + else if (safe_w < 6 && evdev->prev_pressure < evdev->touch_high) + type = TOUCH_FINGERS; /* thin finger, distinct touch -> not a palm */ + else if (safe_w < 7 && evdev->prev_pressure < evdev->touch_high / 2) + type = TOUCH_FINGERS; /* thin finger, distinct touch -> not a palm */ + else if (pkt->pressure > evdev->prev_pressure + 1) + type = TOUCH_NONE; /* pressure not stable, may be a palm */ + else if (pkt->pressure < evdev->prev_pressure - 5) + type = TOUCH_NONE; /* pressure not stable, may be a palm */ + else + type = TOUCH_FINGERS; + } + + evdev->prev_pressure = pkt->pressure; + return type; +} + +static enum edge_type tp_detect_edges(struct event_device *evdev, int x, int y) +{ + enum edge_type edge = 0; + + if (x > evdev->right_edge) + edge |= RIGHT_EDGE; + else if (x < evdev->left_edge) + edge |= LEFT_EDGE; + + if (y < evdev->top_edge) + edge |= TOP_EDGE; + else if (y > evdev->bottom_edge) + edge |= BOTTOM_EDGE; + + return edge; +} + +static int tp_touch_expired(struct event_device *evdev) +{ + struct timeval now; + + GET_TIME(now); + return DIF_TIME(evdev->touch.start, now) > evdev->tap_time; +} + +static int tp_detect_tap(struct event_device *evdev) +{ + return !tp_touch_expired(evdev) && + (evdev->touch.finger_count > 1 || + (abs(evdev->pkt.abs_x - evdev->touch.x) < evdev->tap_move && + abs(evdev->pkt.abs_y - evdev->touch.y) < evdev->tap_move)); +} + +static int tp_tap_to_buttons(struct event_device *evdev) +{ + enum edge_type edge; + if (evdev->touch.finger_count < 2) { + edge = tp_detect_edges(evdev, evdev->pkt.abs_x, evdev->pkt.abs_y); + switch (edge) { + case RIGHT_TOP_EDGE: + return GPM_B_MIDDLE; + break; + case RIGHT_BOTTOM_EDGE: + return GPM_B_RIGHT; + break; + default: + return GPM_B_LEFT; + break; + } + } else { + switch (evdev->touch.finger_count) { + case 2: + return GPM_B_MIDDLE; + case 3: + return GPM_B_RIGHT; + default: + return GPM_B_LEFT; + } + } +} + +static void tp_detect_gesture(struct event_device *evdev, int timed_out, enum touch_type touch_type) +{ + struct touch_data *touch = &evdev->touch; + int was_touching = touch->touching; + + touch->touching = touch_type == TOUCH_FINGERS; + + if (touch->touching) { + if (!was_touching) { + GET_TIME(touch->start); + touch->finger_count = 0; + if (touch->gesture == GESTURE_TAP_PENDING) { + touch->gesture = GESTURE_DRAG_PENDING; + } else { + touch->x = evdev->pkt.abs_x; + touch->y = evdev->pkt.abs_y; + touch->buttons = 0; + } + } else if (touch->gesture == GESTURE_DRAG_PENDING && tp_touch_expired(evdev)) { + touch->gesture = GESTURE_DRAG; + } + } else { + if (was_touching) { + if (tp_detect_tap(evdev)) { + if (touch->gesture == GESTURE_DRAG_PENDING) { + touch->gesture = GESTURE_DOUBLE_TAP; + touch->clicks = 4; + } else { + if ((touch->buttons = tp_tap_to_buttons(evdev)) == GPM_B_LEFT) { + touch->gesture = GESTURE_TAP_PENDING; + } else { + touch->gesture = GESTURE_TAP; + touch->clicks = 2; + } + } + } else { + touch->gesture = GESTURE_NONE; + } + } else { + if (touch->gesture == GESTURE_TAP_PENDING && tp_touch_expired(evdev)) { + touch->gesture = GESTURE_TAP; + touch->clicks = 2; + } + } + } +} + +static int tp_process_gesture(struct event_device *evdev, struct Gpm_Event *state) +{ + int next_timeout = -1; + + switch(evdev->touch.gesture) { + case GESTURE_DOUBLE_TAP: + case GESTURE_TAP: + if (--evdev->touch.clicks == 0) + evdev->touch.gesture = GESTURE_NONE; + else + next_timeout = 0; + + if (evdev->touch.clicks % 2) + state->buttons |= evdev->touch.buttons; + else + state->buttons &= ~evdev->touch.buttons; + break; + + case GESTURE_DRAG: + state->buttons |= evdev->touch.buttons; + break; + + case GESTURE_DRAG_PENDING: + case GESTURE_TAP_PENDING: + next_timeout = evdev->tap_time; + break; + + default: + break; + } + return next_timeout; +} + +static void tp_update_finger_count(struct event_device *evdev) +{ + evdev->touch.finger_count = max(evdev->pkt.finger_count, evdev->touch.finger_count); +} + +static void syn_update_finger_count(struct event_device *evdev) +{ + if (evdev->pkt.w == 1) + evdev->touch.finger_count = 3; + else if (evdev->pkt.w == 0 && evdev->touch.finger_count != 3) + evdev->touch.finger_count = 2; + else + evdev->touch.finger_count = 1; +} + +static int compose_gpm_event(struct event_device *evdev, int timed_out, Gpm_Event *state) +{ + struct event_data *pkt = &evdev->pkt; + enum touch_type touch_type; + int next_timeout = -1; + + if (!timed_out) { + state->buttons = pkt->buttons; + state->wdx = pkt->wdx; state->wdy = pkt->wdy; + } + + switch (evdev->type) { + case EVDEV_RELATIVE: + if (!timed_out) { + state->dx = pkt->dx; state->dy = pkt->dy; + if (evdev->pkt.touch) + state->buttons |= GPM_B_LEFT; + else + state->buttons &= ~GPM_B_LEFT; + } + break; + + case EVDEV_ABSOLUTE: + if (!timed_out) { + if (pkt->abs_x < evdev->left_edge) + pkt->abs_x = evdev->left_edge; + else if (pkt->abs_x > evdev->right_edge) + pkt->abs_x = evdev->right_edge; + + if (pkt->abs_y > evdev->bottom_edge) + pkt->abs_y = evdev->bottom_edge; + else if (pkt->abs_y < evdev->top_edge) + pkt->abs_y = evdev->top_edge; + + state->x = (pkt->abs_x - evdev->left_edge) * + console.max_x / (evdev->right_edge - evdev->left_edge); + state->y = (pkt->abs_y - evdev->top_edge) * + console.max_y / (evdev->bottom_edge - evdev->top_edge); + + if (evdev->y_inverted) state->y = console.max_y - state->y; + + if (evdev->pkt.touch) + state->buttons |= GPM_B_LEFT; + else + state->buttons &= ~GPM_B_LEFT; + } + break; + + case EVDEV_TOUCHPAD: + case EVDEV_SYNAPTICS: + touch_type = timed_out ? TOUCH_NONE : evdev->detect_touch(evdev); + + if (touch_type != TOUCH_PALM) { + tp_detect_gesture(evdev, timed_out, touch_type); + + if (evdev->touch.touching && !tp_touch_expired(evdev)) + evdev->update_finger_count(evdev); + + if (evdev->touch.finger_count < 2) + tp_figure_deltas(evdev, state); + + next_timeout = tp_process_gesture(evdev, state); + } + break; + + default: + /* should not happen */ + gpm_report(GPM_PR_OOPS, "Bad evdev type %d", evdev->type); + break; + } + + if (evdev->y_inverted) state->dy = -state->dy; + + return next_timeout; +} + +int M_evdev(struct micedev *dev, struct miceopt *opts, + unsigned char *data, struct Gpm_Event *state) +{ + struct event_device *evdev = dev->private; + struct input_event *event = (struct input_event *)data; + int timed_out = data == NULL; + + if (!timed_out) + parse_input_event(event, &evdev->pkt); + + if (timed_out || evdev->pkt.synced || evdev->dont_sync) { + dev->timeout = compose_gpm_event(evdev, timed_out, state); + evdev->pkt.dx = evdev->pkt.dy = 0; + evdev->pkt.wdx = evdev->pkt.wdy = 0; + evdev->pkt.finger_count = 0; + evdev->pkt.synced = 0; + return 0; + } + + dev->timeout = -1; + return -1; +} + +/* ------------- evdev initialization routines ---------------------*/ + +static int evdev_get_id(int fd, struct input_id *id) +{ + if (ioctl(fd, EVIOCGID, id) < 0) { + gpm_report(GPM_PR_ERR, "evdev: cannot query device identification"); + return -1; + } + return 0; +} + +static int evdev_get_capabilities(int fd, struct evdev_capabilities *caps) +{ + memset(caps, 0, sizeof(*caps)); + + if (ioctl(fd, EVIOCGBIT(0, EV_MAX), caps->evbits) < 0) { + gpm_report(GPM_PR_ERR, "evdev: cannot query device capabilities"); + return -1; + } + + if (test_bit(EV_ABS, caps->evbits) && + ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(caps->absbits)), caps->absbits) < 0) { + gpm_report(GPM_PR_ERR, "evdev: cannot query ABS device capabilities"); + return -1; + } + + if (test_bit(EV_KEY, caps->evbits) && + ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(caps->keybits)), caps->keybits) < 0) { + gpm_report(GPM_PR_ERR, "evdev: cannot query KEY device capabilities"); + return -1; + } + + if (test_bit(EV_MSC, caps->evbits) && + ioctl(fd, EVIOCGBIT(EV_MSC, sizeof(caps->mscbits)), caps->mscbits) < 0) { + /* don't complain as 2.4 kernels didnt have it + gpm_report(GPM_PR_ERR, "evdev: cannot query MSC device capabilities"); + return -1; + */ + } + return 0; +} + +static int evdev_query_axis(int fd, int axis, int *axis_min, int *axis_max) +{ + struct input_absinfo axis_info; + + if (ioctl(fd, EVIOCGABS(axis), &axis_info) == -1) { + gpm_report(GPM_PR_ERR, "evdev: could not query axis data"); + return -1; + } + + *axis_min = axis_info.minimum; + *axis_max = axis_info.maximum; + return 0; +} + +static int evdev_get_limits(int fd, struct event_device *evdev, + struct evdev_capabilities *caps) +{ + if (test_bit(ABS_X, caps->absbits) && + evdev_query_axis(fd, ABS_X, &evdev->left_edge, &evdev->right_edge) < 0) + return -1; + + if (test_bit(ABS_Y, caps->absbits) && + evdev_query_axis(fd, ABS_Y, &evdev->top_edge, &evdev->bottom_edge) < 0) + return -1; + + return 0; +} + +static int is_synaptics(struct input_id *id) +{ + return id->bustype == BUS_I8042 && id->vendor == 0x0002 && id->product == PSMOUSE_SYNAPTICS; +} + +static enum evdev_type evdev_guess_type(struct input_id *id, struct evdev_capabilities *caps) +{ + if (test_bit(EV_ABS, caps->evbits)) { + if (is_synaptics(id)) + return EVDEV_SYNAPTICS; + + if (test_bit(BTN_TOUCH, caps->keybits) && caps->keybits[BTN_MOUSE / 8]) + return EVDEV_TOUCHPAD; + + return EVDEV_ABSOLUTE; + } + + if (!test_bit(EV_REL, caps->evbits)) { + gpm_report(GPM_PR_ERR, + "evdev: device does not report neither absolute nor relative coordinates"); + return EVDEV_UNKNOWN; + } + + return EVDEV_RELATIVE; +} + +static enum evdev_type evdev_str_to_type(const char *type) +{ + if (!strcmp(type, "relative")) { + return EVDEV_RELATIVE; + } else if (!strcmp(type, "absolute")) { + return EVDEV_ABSOLUTE; + } else if (!strcmp(type, "touchpad")) { + return EVDEV_TOUCHPAD; + } else if (!strcmp(type, "synaptics")) { + return EVDEV_SYNAPTICS; + } else { + gpm_report(GPM_PR_ERR, "evdev: unknown type '%s'", type); + return EVDEV_UNKNOWN; + } +} + +static void warn_if_present(struct option_helper *optinfo, const char *name, const char *type) +{ + if (is_option_present(optinfo, name)) + gpm_report(GPM_PR_WARN, + "evdev: option '%s' is not valud for type '%s', ignored", + name, type); +} + +// -o type=(auto|synaptics|touchpad|relative|absolute),y_inverse, +// left=1234,right=1234,top=1234,bottom=1234, +// touch_high=30,touch_low=25,tap_time=30,tap_move=100 +static int evdev_apply_options(struct event_device *evdev, char *optstring) +{ + char *type = "auto"; + struct option_helper optinfo[] = { + { "type", OPT_STRING, u: { sptr: &type } }, + { "y_inverted", OPT_BOOL, u: { iptr: &evdev->y_inverted }, value: 1 }, + { "left", OPT_INT, u: { iptr: &evdev->left_edge } }, + { "right", OPT_INT, u: { iptr: &evdev->right_edge } }, + { "top", OPT_INT, u: { iptr: &evdev->top_edge } }, + { "bottom", OPT_INT, u: { iptr: &evdev->bottom_edge } }, + { "touch_high", OPT_INT, u: { iptr: &evdev->touch_high } }, + { "touch_low", OPT_INT, u: { iptr: &evdev->touch_low } }, + { "tap_time", OPT_INT, u: { iptr: &evdev->tap_time } }, + { "tap_move", OPT_INT, u: { iptr: &evdev->tap_move } }, + { "", OPT_END } + }; + + if (parse_options("evdev", optstring, ',', optinfo) < 0) + return -1; + + if (strcmp(type, "auto")) + evdev->type = evdev_str_to_type(type); + + switch (evdev->type) { + case EVDEV_RELATIVE: + warn_if_present(optinfo, "left", type); + warn_if_present(optinfo, "right", type); + warn_if_present(optinfo, "top", type); + warn_if_present(optinfo, "bottom", type); + warn_if_present(optinfo, "tap_move", type); + warn_if_present(optinfo, "tap_time", type); + warn_if_present(optinfo, "touch_high", type); + warn_if_present(optinfo, "touch_low", type); + break; + + case EVDEV_ABSOLUTE: + warn_if_present(optinfo, "tap_move", type); + warn_if_present(optinfo, "tap_time", type); + warn_if_present(optinfo, "touch_high", type); + warn_if_present(optinfo, "touch_low", type); + break; + + case EVDEV_TOUCHPAD: + break; + + case EVDEV_SYNAPTICS: + warn_if_present(optinfo, "y_inverted", type); + break; + + default: + return -1; + } + return 0; +} + +int I_evdev(struct micedev *dev, struct miceopt *opts, Gpm_Type *type) +{ + struct input_id id; + struct evdev_capabilities caps; + struct event_device *evdev; + + if (!dev->private) { /* called first time, not re-init */ + if (!(dev->private = evdev = malloc(sizeof(*evdev)))) + gpm_report(GPM_PR_OOPS, "Can't allocate memory for event device"); + + memset(evdev, 0, sizeof(*evdev)); + + if (evdev_get_id(dev->fd, &id)) + goto init_fail; + + if (evdev_get_capabilities(dev->fd, &caps)) + goto init_fail; + + evdev->type = evdev_guess_type(&id, &caps); + + /* load default values - suitable for my synaptics ;P */ + evdev->left_edge = 1900; + evdev->right_edge = 5300; + evdev->top_edge = 2000; + evdev->bottom_edge = 3900; + evdev->tap_time = 180; + evdev->tap_move = 220; + evdev->touch_high = 30; + evdev->touch_low = 25; + + if (evdev->type == EVDEV_ABSOLUTE && evdev_get_limits(dev->fd, evdev, &caps) < 0) + goto init_fail; + + if (evdev_apply_options(evdev, opts->text) < 0) + goto init_fail; + + if (!test_bit(EV_SYNC, caps.evbits)) { + evdev->dont_sync = 1; + if (evdev->type == EVDEV_TOUCHPAD || evdev->type == EVDEV_SYNAPTICS) { + gpm_report(GPM_PR_ERR, + "evdev: The running kernel lacks EV_SYNC support which is required for touchpad/synaptics mode"); + goto init_fail; + } + } + + switch (evdev->type) { + case EVDEV_RELATIVE: + gpm_report(GPM_PR_INFO, "evdev: selected Relative mode"); + if (!test_bit(EV_REL, caps.evbits)) + gpm_report(GPM_PR_WARN, "evdev: selected relative mode but device does not report any relative events"); + break; + + case EVDEV_ABSOLUTE: + gpm_report(GPM_PR_INFO, "evdev: selected Absolute mode"); + if (evdev->right_edge <= evdev->left_edge) { + gpm_report(GPM_PR_ERR, "evdev: right edge value should be gerater than left"); + goto init_fail; + } + if (evdev->bottom_edge <= evdev->top_edge) { + gpm_report(GPM_PR_ERR, "evdev: bottom edge value should be gerater than top"); + goto init_fail; + } + if (!test_bit(EV_ABS, caps.evbits)) + gpm_report(GPM_PR_WARN, "evdev: selected absolute mode but device does not report any absolute events"); + opts->absolute = 1; + break; + + case EVDEV_TOUCHPAD: + gpm_report(GPM_PR_INFO, "evdev: selected Touchpad mode"); + if (!test_bit(EV_ABS, caps.evbits)) + gpm_report(GPM_PR_WARN, "evdev: selected touchpad mode but device does not report any absolute events"); + if (test_bit(ABS_PRESSURE, caps.absbits)) + evdev->detect_touch = smart_tp_detect_touch; + else if (test_bit(BTN_TOUCH, caps.keybits)) + evdev->detect_touch = dumb_tp_detect_touch; + else + gpm_report(GPM_PR_WARN, "evdev: selected touchpad mode but device does not report pressure not touch events"); + evdev->update_finger_count = tp_update_finger_count; + break; + + case EVDEV_SYNAPTICS: + gpm_report(GPM_PR_INFO, "evdev: selected Synaptics mode"); + if (!is_synaptics(&id)) + gpm_report(GPM_PR_WARN, "evdev: idevice isn't identified as Synaptics"); + if (!test_bit(EV_ABS, caps.evbits)) + gpm_report(GPM_PR_WARN, "evdev: selected synaptics mode but device does not report any absolute events"); + if (!test_bit(ABS_PRESSURE, caps.absbits)) + gpm_report(GPM_PR_WARN, "evdev: selected synaptics mode but device does not report pressure"); + if (test_bit(EV_MSC, caps.evbits) && test_bit(MSC_GESTURE, caps.mscbits)) { + /* this is compatibility mode with pre 2.6-test6 kernels */ + evdev->update_finger_count = syn_update_finger_count; + evdev->y_inverted = 1; + } else { + evdev->update_finger_count = tp_update_finger_count; + } + evdev->detect_touch = syn_detect_touch; + break; + + default: + break; + } + } + + return 0; + +init_fail: + free(dev->private); + return -1; +} + diff -urN gpm-1.20.1/src/gpm.c gpm/src/gpm.c --- gpm-1.20.1/src/gpm.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/gpm.c 2003-10-02 01:22:42.000000000 -0500 @@ -24,1108 +24,607 @@ #include #include #include /* strerror(); ?!? */ +#include #include #include /* select(); */ #include /* SIGPIPE */ #include /* time() */ -#include #include /* O_RDONLY */ #include /* wait() */ -#include /* mkdir() */ #include /* timeval */ -#include /* socket() */ -#include /* socket() */ -#include /* struct sockaddr_un */ - -#include /* VT_GETSTATE */ -#include /* KDGETMODE */ -#include /* winsize */ #include "headers/gpmInt.h" #include "headers/message.h" - -/* who the f*** runs gpm without glibc? doesn't have dietlibc __socklent_t? */ -#if !defined(__GLIBC__) - typedef unsigned int __socklen_t; -#endif /* __GLIBC__ */ +#include "headers/console.h" +#include "headers/selection.h" +#include "headers/client.h" #ifndef max #define max(a,b) ((a)>(b) ? (a) : (b)) #endif -extern int errno; - -static void gpm_killed(int); - -/* - * all the values duplicated for dual-mouse operation are - * now in this structure (see gpmInt.h) - * mouse_table[0] is single mouse, mouse_table[1] and mouse_table[2] - * are copied data from mouse_table[0] for dual mouse operation. - */ - -struct mouse_features mouse_table[3] = { - { - DEF_TYPE, DEF_DEV, DEF_SEQUENCE, - DEF_BAUD, DEF_SAMPLE, DEF_DELTA, DEF_ACCEL, DEF_SCALE, 0 /* scaley */, - DEF_TIME, DEF_CLUSTER, DEF_THREE, DEF_GLIDEPOINT_TAP, - (char *)NULL /* extra */, - (Gpm_Type *)NULL, - -1 - } -}; -struct mouse_features *which_mouse; - -/* These are only the 'global' options */ - -char *opt_lut=DEF_LUT; -int opt_test=DEF_TEST; -int opt_ptrdrag=DEF_PTRDRAG; -int opt_double=0; -int opt_aged = 0; -char *opt_special=NULL; /* special commands, like reboot or such */ -int opt_rawrep=0; -Gpm_Type *repeated_type=0; - -static int opt_resize=0; /* not really an option */ -struct winsize win; -int maxx, maxy; -int fifofd=-1; - -int eventFlag=0; -Gpm_Cinfo *cinfo[MAX_VC+1]; -fd_set selSet, readySet, connSet; - -time_t last_selection_time; -time_t opt_age_limit = 0; - -/* BRAINDEAD..ok not really, but got to leave anyway... FIXME */ -/* argc and argv for mice initialization */ -static int mouse_argc[3]; /* 0 for default (unused) and two mice */ -static char **mouse_argv[3]; /* 0 for default (unused) and two mice */ - -/*===================================================================*/ -/* - * first, all the stuff that used to be in gpn.c (i.e., not main-loop) - */ -/*-------------------------------------------------------------------*/ +#ifndef min +#define min(a,b) ((a)<(b) ? (a) : (b)) +#endif -/* build_argv is used for mouse initialization routines */ -static char **build_argv(char *argv0, char *str, int *argcptr, char sep) -{ - int argc = 1; - char **argv; - char *s; - - /* argv0 is never NULL, but the extra string may well be */ - if (str) - for (s=str; sep && (s = strchr(s, sep)); argc++) s++; - - argv = calloc(argc+2, sizeof(char **)); - if (!argv) gpm_report(GPM_PR_OOPS,GPM_MESS_ALLOC_FAILED); - argv[0] = argv0; - - if (!str) { - *argcptr = argc; /* 1 */ - return argv; - } - /* else, add arguments */ - s = argv[1] = strdup(str); - argc = 2; /* first to fill */ - - /* ok, now split: the first one is in place, and s is the whole string */ - for ( ; sep && (s = strchr(s, sep)) ; argc++) { - *s = '\0'; - s++; - argv[argc] = s; - } - *argcptr = argc; - return argv; -} +#define NULL_SET ((fd_set *)NULL) +#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL)) +#define DIF_TIME(t1,t2) ((t2.tv_sec - t1.tv_sec)*1000 + (t2.tv_usec - t1.tv_usec)/1000) -/*-------------------------------------------------------------------*/ -/* The old console option is removed. We are taking stderr now - * In the next update there should also be support for syslog - ********************************************************************/ -static inline int open_console(const int mode) -{ - int fd; +enum mouse_rslt { MOUSE_NO_DATA, MOUSE_DATA_OK, MOUSE_MORE_DATA }; - if ((fd=open(option.consolename, mode)) < 0) - gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_CON); - return fd; -} +extern int errno; -/*-------------------------------------------------------------------*/ -static inline int wait_text(int *fdptr) -{ - int fd; - int kd_mode; +char *opt_special=NULL; /* special commands, like reboot or such */ +struct repeater repeater; - close(*fdptr); - do - { - sleep(2); - fd = open_console(O_RDONLY); - if (ioctl(fd, KDGETMODE, &kd_mode)<0) - gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_KDGETMODE); - close(fd); - } - while (kd_mode != KD_TEXT) ; - - /* reopen, reinit (the function is only used if we have one mouse device) */ - if ((*fdptr=open(opt_dev,O_RDWR))<0) - gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,opt_dev); - if (m_type->init) - m_type=(m_type->init)(*fdptr, m_type->flags, m_type, mouse_argc[1], - mouse_argv[1]); - return (1); -} +static int console_resized; /* not really an option */ /*-------------------------------------------------------------------*/ -static inline void selection_copy(int x1, int y1, int x2, int y2, int mode) +static void gpm_killed(int signo) { -/* - * The approach in "selection" causes a bus error when run under SunOS 4.1 - * due to alignment problems... - */ - unsigned char buf[6*sizeof(short)]; - unsigned short *arg = (unsigned short *)buf + 1; - int fd; - - buf[sizeof(short)-1] = 2; /* set selection */ - - arg[0]=(unsigned short)x1; - arg[1]=(unsigned short)y1; - arg[2]=(unsigned short)x2; - arg[3]=(unsigned short)y2; - arg[4]=(unsigned short)mode; - - if ((fd=open_console(O_WRONLY))<0) - gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_CON); - /* FIXME: should be replaced with string constant (headers/message.h) */ - gpm_report(GPM_PR_DEBUG,"ctl %i, mode %i",(int)*buf, arg[4]); - if (ioctl(fd, TIOCLINUX, buf+sizeof(short)-1) < 0) - gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_TIOCLINUX); - close(fd); - - if (mode < 3) { - opt_aged = 0; - last_selection_time = time(0); + if (signo == SIGWINCH) { + gpm_report(GPM_PR_WARN, GPM_MESS_RESIZING, option.progname, getpid()); + console_resized = 1; + } else { + if (signo == SIGUSR1) + gpm_report(GPM_PR_WARN, GPM_MESS_KILLED_BY, option.progname, getpid(), option.progname); + exit(0); } } - -/*-------------------------------------------------------------------*/ -/* comment missing; FIXME */ -/*-------------------------------------------------------------------*/ -static inline void selection_paste(void) -{ - char c=3; - int fd; - - if (!opt_aged && (0 != opt_age_limit) && - (last_selection_time + opt_age_limit < time(0))) { - opt_aged = 1; - } - - if (opt_aged) { - gpm_report(GPM_PR_DEBUG,GPM_MESS_SKIP_PASTE); - return; - } - - fd=open_console(O_WRONLY); - if(ioctl(fd, TIOCLINUX, &c) < 0) - gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_TIOCLINUX); - close(fd); -} - -/*-------------------------------------------------------------------*/ -static inline int do_selection(Gpm_Event *event) /* returns 0, always */ -{ - static int x1=1, y1=1, x2, y2; -#define UNPOINTER() 0 - - x2=event->x; y2=event->y; - switch(GPM_BARE_EVENTS(event->type)) { - case GPM_MOVE: - if (x2<1) x2++; else if (x2>maxx) x2--; - if (y2<1) y2++; else if (y2>maxy) y2--; - selection_copy(x2,y2,x2,y2,3); /* just highlight pointer */ - return 0; - - case GPM_DRAG: - if (event->buttons==GPM_B_LEFT) { - if (event->margin) /* fix margins */ - switch(event->margin) { - case GPM_TOP: x2=1; y2++; break; - case GPM_BOT: x2=maxx; y2--; break; - case GPM_RGT: x2--; break; - case GPM_LFT: y2<=y1 ? x2++ : (x2=maxx, y2--); break; - } - selection_copy(x1,y1,x2,y2,event->clicks); - if (event->clicks>=opt_ptrdrag && !event->margin) /* pointer */ - selection_copy(x2,y2,x2,y2,3); - } /* if */ - return 0; - - case GPM_DOWN: - switch (event->buttons) { - case GPM_B_LEFT: - x1=x2; y1=y2; - selection_copy(x1,y1,x2,y2,event->clicks); /* start selection */ - return 0; - - case GPM_B_MIDDLE: - selection_paste(); - return 0; - - case GPM_B_RIGHT: - if (opt_three==1) - selection_copy(x1,y1,x2,y2,event->clicks); - else - selection_paste(); - return 0; - } - } /* switch above */ - return 0; -} - -/*-------------------------------------------------------------------*/ -/* returns 0 if the event has not been processed, and 1 if it has */ -static inline int do_client(Gpm_Cinfo *cinfo, Gpm_Event *event) -{ - Gpm_Connect info=cinfo->data; - int fd=cinfo->fd; - /* value to return if event is not used */ - int res = !(info.defaultMask & event->type); - - /* instead of returning 0, scan the stack of clients */ - if ((info.minMod & event->modifiers) < info.minMod) - goto scan; - if ((info.maxMod & event->modifiers) < event->modifiers) - goto scan; - - /* if not managed, use default mask */ - if (!(info.eventMask & GPM_BARE_EVENTS(event->type))) { - if (res) return res; - else goto scan; - } - - /* WARNING */ /* This can generate a SIGPIPE... I'd better catch it */ - MAGIC_P((write(fd,&magic, sizeof(int)))); - write(fd,event, sizeof(Gpm_Event)); - - return info.defaultMask & GPM_HARD ? res : 1; /* HARD forces pass-on */ - - scan: - if (cinfo->next != 0) - return do_client (cinfo->next, event); /* try the next */ - return 0; /* no next, not used */ -} - /*------------------------------------------------------------------- * fetch the actual device data from the mouse device, dependent on * what Gpm_Type is being passed. *-------------------------------------------------------------------*/ -static inline char *getMouseData(int fd, Gpm_Type *type, int kd_mode) +static char *getMouseData(int fd, Gpm_Type *type, int text_mode) { static unsigned char data[32]; /* quite a big margin :) */ - char *edata=data+type->packetlen; - int howmany=type->howmany; - int i,j; + unsigned char *pdata; + int len, togo; -/*....................................... read and identify one byte */ - - if (read(fd, data, howmany)!=howmany) { - if (opt_test) exit(0); + /*....................................... read and identify one byte */ + if (read(fd, data, type->howmany) != type->howmany) { gpm_report(GPM_PR_ERR,GPM_MESS_READ_FIRST, strerror(errno)); return NULL; } - if (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep) - write(fifofd, data, howmany); + if (!text_mode && repeater.fd != -1 && repeater.raw) + write(repeater.fd, data, type->howmany); - if ((data[0]&(m_type->proto)[0]) != (m_type->proto)[1]) { - if (m_type->getextra == 1) { - data[1]=GPM_EXTRA_MAGIC_1; data[2]=GPM_EXTRA_MAGIC_2; - gpm_report(GPM_PR_DEBUG,GPM_EXTRA_DATA,data[0]); + if ((data[0] & type->proto[0]) != type->proto[1]) { + if (type->getextra == 1) { + data[1] = GPM_EXTRA_MAGIC_1; data[2] = GPM_EXTRA_MAGIC_2; + gpm_report(GPM_PR_DEBUG, GPM_EXTRA_DATA, data[0]); return data; } - gpm_report(GPM_PR_DEBUG,GPM_MESS_PROT_ERR); + gpm_report(GPM_PR_DEBUG, GPM_MESS_PROT_ERR); return NULL; } -/*....................................... read the rest */ + /*....................................... read the rest */ /* * well, this seems to work almost right with ps2 mice. However, I've never * tried ps2 with the original selection package, which called usleep() */ - - if((i=m_type->packetlen-howmany)) /* still to get */ + if ((togo = type->packetlen - type->howmany)) { /* still to get */ + pdata = &data[type->howmany]; do { - j = read(fd,edata-i,i); /* edata is pointer just after data */ - if (kd_mode!=KD_TEXT && fifofd != -1 && opt_rawrep && j > 0) - write(fifofd, edata-i, j); - i -= j; - } while (i && j); - - if (i) { - gpm_report(GPM_PR_ERR,GPM_MESS_READ_REST, strerror(errno)); + if ((len = read(fd, pdata, togo)) == 0) + break; + if (!text_mode && repeater.fd != -1 && repeater.raw && len > 0) + write(repeater.fd, pdata, len); + pdata += len; + togo -= len; + } while (togo); + } + + if (togo) { + gpm_report(GPM_PR_ERR, GPM_MESS_READ_REST, strerror(errno)); return NULL; } - if ((data[1]&(m_type->proto)[2]) != (m_type->proto)[3]) { - gpm_report(GPM_PR_INFO,GPM_MESS_SKIP_DATA); + if ((data[1] & type->proto[2]) != type->proto[3]) { + gpm_report(GPM_PR_INFO, GPM_MESS_SKIP_DATA); return NULL; } - gpm_report(GPM_PR_DEBUG,GPM_MESS_DATA_4,data[0],data[1],data[2],data[3]); + gpm_report(GPM_PR_DEBUG, GPM_MESS_DATA_4, data[0], data[1], data[2], data[3]); return data; } - -static int statusX,statusY,statusB; /* to return info */ -static int statusC=0; /* clicks */ -void get_console_size(Gpm_Event *ePtr); - -/*------------------------------------------------------------------- - * call getMouseData to get hardware device data, call mouse device's fun() - * to retrieve the hardware independent event data, then optionally repeat - * the data via repeat_fun() to the repeater device - *-------------------------------------------------------------------*/ -static inline int processMouse(int fd, Gpm_Event *event, Gpm_Type *type, - int kd_mode) +/*-------------------------------------------------------------------*/ +void handle_console_resize(Gpm_Event *event) { - char *data; - static int fine_dx, fine_dy; - static int i, j, m; - static Gpm_Event nEvent; - static struct vt_stat stat; - static struct timeval tv1={0,0}, tv2; /* tv1==0: first click is single */ - static struct timeval timeout={0,0}; - fd_set fdSet; - static int newB=0, oldB=0, oldT=0; /* old buttons and Type to chain events */ - /* static int buttonlock, buttonlockflag; */ - -#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL)) -#define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \ - (t2.tv_usec-t1.tv_usec)/1000) - - - oldT=event->type; - - if (eventFlag) { - eventFlag=0; - - if (m_type->absolute) { /* a pen or other absolute device */ - event->x=nEvent.x; - event->y=nEvent.y; - } - event->dx=nEvent.dx; - event->dy=nEvent.dy; - event->buttons=nEvent.buttons; - } else { - event->dx=event->dy=0; - event->wdx=event->wdy=0; - nEvent.modifiers = 0; /* some mice set them */ - FD_ZERO(&fdSet); FD_SET(fd,&fdSet); i=0; - - do { /* cluster loop */ - if(((data=getMouseData(fd,m_type,kd_mode))==NULL) - || ((*(m_type->fun))(&nEvent,data)==-1) ) { - if (!i) return 0; - else break; - } - - event->modifiers = nEvent.modifiers; /* propagate modifiers */ - - /* propagate buttons */ - nEvent.buttons = (opt_sequence[nEvent.buttons&7]&7) | - (nEvent.buttons & ~7); /* change the order */ - oldB=newB; newB=nEvent.buttons; - if (!i) event->buttons=nEvent.buttons; - - if (oldB!=newB) { - eventFlag = (i!=0)*(which_mouse-mouse_table); /* 1 or 2 */ - break; - } - - /* propagate movement */ - if (!(m_type->absolute)) { /* mouse */ - if (abs(nEvent.dx)+abs(nEvent.dy) > opt_delta) - nEvent.dx*=opt_accel, nEvent.dy*=opt_accel; - - /* increment the reported dx,dy */ - event->dx+=nEvent.dx; - event->dy+=nEvent.dy; - } else { /* a pen */ - /* get dx,dy to check if there has been movement */ - event->dx = (nEvent.x) - (event->x); - event->dy = (nEvent.y) - (event->y); - } - - /* propagate wheel */ - event->wdx += nEvent.wdx; - event->wdy += nEvent.wdy; - - select(fd+1,&fdSet,(fd_set *)NULL,(fd_set *)NULL,&timeout/* zero */); - - } while (i++ buttons&GPM_B_MIDDLE) && !opt_three) opt_three++; + old_x = console.max_x; old_y = console.max_y; + refresh_console_size(); + if (!old_x) { /* first invocation, place the pointer in the middle */ + event->x = console.max_x / 2; + event->y = console.max_y / 2; + } else { /* keep the pointer in the same position where it was */ + event->x = event->x * console.max_x / old_x; + event->y = event->y * console.max_y / old_y; + } -/*....................................... we're a repeater, aren't we? */ + for (mouse = micelist; mouse; mouse = mouse->next) { + /* + * the following operation is based on the observation that 80x50 + * has square cells. (An author-centric observation ;-) + */ + mouse->options.scaley = mouse->options.scalex * 50 * console.max_x / 80 / console.max_y; + gpm_report(GPM_PR_DEBUG, GPM_MESS_X_Y_VAL, + mouse->options.scalex, mouse->options.scaley); + } +} - if (kd_mode!=KD_TEXT) { - if (fifofd != -1 && ! opt_rawrep) { - if (m_type->absolute) { /* hof Wed Feb 3 21:43:28 MET 1999 */ - /* prepare the values from a absolute device for repeater mode */ - static struct timeval rept1,rept2; - gettimeofday(&rept2, (struct timezone *)NULL); - if (((rept2.tv_sec -rept1.tv_sec) - *1000+(rept2.tv_usec-rept1.tv_usec)/1000)>250) { - event->dx=0; - event->dy=0; - } - rept1=rept2; - - event->dy=event->dy*((win.ws_col/win.ws_row)+1); - event->x=nEvent.x; - event->y=nEvent.y; - } - repeated_type->repeat_fun(event, fifofd); /* itz Jan 11 1999 */ +static void handle_repeater(int absolute_dev, Gpm_Event *new_event, Gpm_Event *event) +{ + static struct timeval last; + struct timeval now; + + if (absolute_dev) { + /* prepare the values from a absolute device for repeater mode */ + GET_TIME(now); + if (((now.tv_sec - last.tv_sec) * 1000 + + (now.tv_usec - last.tv_usec) / 1000) > 250) { + event->dx = 0; + event->dy = 0; } - return 0; /* no events nor information for clients */ - } /* first if of these three */ - -/*....................................... no, we arent a repeater, go on */ + last = now; - /* use fine delta values now, if delta is the information */ - if (!(m_type)->absolute) { - fine_dx+=event->dx; fine_dy+=event->dy; - event->dx=fine_dx/opt_scale; event->dy=fine_dy/opt_scaley; - fine_dx %= opt_scale; fine_dy %= opt_scaley; + event->dy = event->dy * ((console.max_x / console.max_y) + 1); + event->x = new_event->x; + event->y = new_event->y; } + repeater.type->repeat_fun(event, repeater.fd); +} - /* up and down, up and down, ... who does a do..while(0) loop ??? - and then makes a break into it... argh ! */ - - if (!event->dx && !event->dy && (event->buttons==oldB)) - do { /* so to break */ - static long awaketime; - /* - * Ret information also if never happens, but enough time has elapsed. - * Note: return 1 will segfault due to missing event->vc; FIXME! - */ - if (time(NULL)<=awaketime) return 0; - awaketime=time(NULL)+1; - break; - } while (0); - -/*....................................... fill missing fields */ - - event->x+=event->dx, event->y+=event->dy; - statusB=event->buttons; - - i=open_console(O_RDONLY); - /* modifiers */ - j = event->modifiers; /* save them */ - event->modifiers=6; /* code for the ioctl */ - if (ioctl(i,TIOCLINUX,&(event->modifiers))<0) - gpm_report(GPM_PR_OOPS,GPM_MESS_GET_SHIFT_STATE); - event->modifiers |= j; /* add mouse-specific bits */ - - /* status */ - j = stat.v_active; - if (ioctl(i,VT_GETSTATE,&stat)<0) gpm_report(GPM_PR_OOPS,GPM_MESS_GET_CONSOLE_STAT); - - /* - * if we changed console, request the current console size, - * as different consoles can be of different size - */ - if (stat.v_active != j) - get_console_size(event); - close(i); - - event->vc = stat.v_active; - - if (oldB==event->buttons) - event->type = (event->buttons ? GPM_DRAG : GPM_MOVE); - else - event->type = (event->buttons > oldB ? GPM_DOWN : GPM_UP); - +static void calculate_clicks(Gpm_Event *event, int click_tmo) +{ + static struct timeval release; + struct timeval now; + switch(event->type) { /* now provide the cooked bits */ case GPM_DOWN: - GET_TIME(tv2); - if (tv1.tv_sec && (DIF_TIME(tv1,tv2)clicks++, event->clicks %= 3; /* 0, 1 or 2 */ else - statusC=0; - event->type|=(GPM_SINGLE<clicks = 0; + event->type |= GPM_SINGLE << event->clicks; break; case GPM_UP: - GET_TIME(tv1); - event->buttons^=oldB; /* for button-up, tell which one */ - event->type|= (oldT&GPM_MFLAG); - event->type|=(GPM_SINGLE<type |= GPM_SINGLE << event->clicks; break; case GPM_DRAG: - event->type |= GPM_MFLAG; - event->type|=(GPM_SINGLE<type |= GPM_SINGLE << event->clicks; break; case GPM_MOVE: - statusC=0; + event->clicks = 0; + default: break; } - event->clicks=statusC; +} + +static void snap_to_screen_limits(Gpm_Event *event) +{ + int extent; -/* UGLY - FIXME! */ -/* The current policy is to force the following behaviour: - * - At buttons up, must fit inside the screen, though flags are set. - * - At button down, allow going outside by one single step - */ + /* The current policy is to force the following behaviour: + * - At buttons up, must fit inside the screen, though flags are set. + * - At button down, allow going outside by one single step + * DTOR: Midnight Commander seems to want the opposite... + */ + extent = (event->type & (GPM_DRAG|GPM_UP)) ? 1 : 0; /* selection used 1-based coordinates, so do I */ - /* * 1.05: only one margin is current. Y takes priority over X. - * The i variable is how much margin is allowed. "m" is which one is there. */ - m = 0; - i = ((event->type&(GPM_DRAG|GPM_UP))!=0); /* i is boolean */ - - if (event->y>win.ws_row) {event->y=win.ws_row+1-!i; i=0; m = GPM_BOT;} - else if (event->y<=0) {event->y=1-i; i=0; m = GPM_TOP;} - - if (event->x>win.ws_col) {event->x=win.ws_col+1-!i; if (!m) m = GPM_RGT;} - else if (event->x<=0) {event->x=1-i; if (!m) m = GPM_LFT;} + event->margin = 0; - event->margin=m; + if (event->y > console.max_y) { + event->y = console.max_y + extent; + extent = 0; + event->margin = GPM_BOT; + } else if (event->y <= 0) { + event->y = 1 - extent; + extent = 0; + event->margin = GPM_TOP; + } - gpm_report(GPM_PR_DEBUG,"M: %3i %3i (%3i %3i) - butt=%i vc=%i cl=%i", - event->dx,event->dy, - event->x,event->y, - event->buttons, event->vc, - event->clicks); + if (event->x > console.max_x) { + event->x = console.max_x + extent; + if (!event->margin) event->margin = GPM_RGT; + } else if (event->x <= 0) { + event->x = 1 - extent; + if (!event->margin) event->margin = GPM_LFT; + } +} - /* update the global state */ - statusX=event->x; statusY=event->y; +static int more_data_waiting(int fd) +{ + static struct timeval timeout = {0, 0}; + fd_set fdSet; - if (opt_special && event->type & GPM_DOWN) - return processSpecial(event); + FD_ZERO(&fdSet); + FD_SET(fd, &fdSet); + select(fd + 1, &fdSet, NULL_SET, NULL_SET, &timeout/* zero */); - return 1; + return FD_ISSET(fd, &fdSet); } -/*-------------------------------------------------------------------* - * This was inline, and incurred in a compiler bug (2.7.0) - *-------------------------------------------------------------------*/ -static int get_data(Gpm_Connect *where, int whence) +static int multiplex_buttons(struct micetab *mouse, int new_buttons) { - static int i; + static int left_btn_clicks, mid_btn_clicks, right_btn_clicks; + int mask; + int muxed_buttons = 0; + + new_buttons = + (mouse->options.sequence[new_buttons & 7] & 7) | (new_buttons & ~7); + mask = new_buttons ^ mouse->buttons; + mouse->buttons = new_buttons; -#ifdef GPM_USE_MAGIC - while ((i=read(whence,&check,sizeof(int)))==4 && check!=GPM_MAGIC) - gpm_report(GPM_PR_INFO,GPM_MESS_NO_MAGIC); - - if (!i) return 0; - if (check!=GPM_MAGIC) { - gpm_report(GPM_PR_INFO,GPM_MESS_NOTHING_MORE); - return -1; + if (mask & GPM_B_LEFT) { + if (new_buttons & GPM_B_LEFT) left_btn_clicks++; + else left_btn_clicks--; } -#endif + if (left_btn_clicks) muxed_buttons |= GPM_B_LEFT; - if ((i=read(whence, where, sizeof(Gpm_Connect)))!=sizeof(Gpm_Connect)) { - return i ? -1 : 0; + if (mask & GPM_B_MIDDLE) { + if (new_buttons & GPM_B_MIDDLE) mid_btn_clicks++; + else mid_btn_clicks--; } + if (mid_btn_clicks) muxed_buttons |= GPM_B_MIDDLE; - return 1; -} + if (mask & GPM_B_RIGHT) { + if (new_buttons & GPM_B_RIGHT) right_btn_clicks++; + else right_btn_clicks--; + } + if (right_btn_clicks) muxed_buttons |= GPM_B_RIGHT; -static void disable_paste(int vc) -{ - opt_aged++; - gpm_report(GPM_PR_INFO,GPM_MESS_DISABLE_PASTE,vc); + return muxed_buttons; } -/*-------------------------------------------------------------------*/ - /* returns -1 if closing connection */ -static inline int processRequest(Gpm_Cinfo *ci, int vc) +/*------------------------------------------------------------------- + * call getMouseData to get hardware device data, call mouse device's fun() + * to retrieve the hardware independent event data, then optionally repeat + * the data via repeat_fun() to the repeater device + *-------------------------------------------------------------------*/ +static enum mouse_rslt processMouse(struct micetab *mouse, int timeout, int attempt, + Gpm_Event *event, int text_mode) { + static int last_active; + static int fine_dx, fine_dy; + static int oldB; + + static Gpm_Event nEvent; + struct Gpm_Type *type = mouse->type; + struct miceopt *opt = &mouse->options; + enum mouse_rslt rslt = MOUSE_DATA_OK; + unsigned char shift_state; + char *data = NULL; int i; - Gpm_Cinfo *cinfoPtr, *next; - Gpm_Connect conn; - static Gpm_Event event; - static struct vt_stat stat; - - gpm_report(GPM_PR_INFO,GPM_MESS_CON_REQUEST, ci->fd, vc); - if (vc>MAX_VC) return -1; - - /* itz 10-22-96 this shouldn't happen now */ - if (vc==-1) gpm_report(GPM_PR_OOPS,GPM_MESS_UNKNOWN_FD); - - i=get_data(&conn,ci->fd); - - if (!i) { /* no data */ - gpm_report(GPM_PR_INFO,GPM_MESS_CLOSE); - close(ci->fd); - FD_CLR(ci->fd,&connSet); - FD_CLR(ci->fd,&readySet); - if (cinfo[vc]->fd == ci->fd) { /* it was on top of the stack */ - cinfoPtr = cinfo[vc]; - cinfo[vc]=cinfo[vc]->next; /* pop the stack */ - free(cinfoPtr); - return -1; - } - /* somewhere inside the stack, have to walk it */ - cinfoPtr = cinfo[vc]; - while (cinfoPtr && cinfoPtr->next) { - if (cinfoPtr->next->fd == ci->fd) { - next = cinfoPtr->next; - cinfoPtr->next = next->next; - free (next); + + if (attempt > 1) { /* continue interrupted cluster loop */ + if (opt->absolute) { + event->x = nEvent.x; + event->y = nEvent.y; + } + event->dx = nEvent.dx; + event->dy = nEvent.dy; + event->buttons = nEvent.buttons; + } else { + event->dx = event->dy = 0; + event->wdx = event->wdy = 0; + nEvent.modifiers = 0; /* some mice set them */ + i = 0; + + do { /* cluster loop */ + if (!timeout && (data = getMouseData(mouse->dev.fd, type, text_mode)) != NULL) { + GET_TIME(mouse->timestamp); + } + + /* in case of timeout data passed to typr->fun() is NULL */ + if ((!timeout && data == NULL) || + type->fun(&mouse->dev, &mouse->options, data, &nEvent) == -1) { + if (!i) return MOUSE_NO_DATA; + else break; + } + + event->modifiers = nEvent.modifiers; /* propagate modifiers */ + + /* propagate buttons */ + nEvent.buttons = multiplex_buttons(mouse, nEvent.buttons); + + if (!i) event->buttons = nEvent.buttons; + + if (oldB != nEvent.buttons) { + rslt = MOUSE_MORE_DATA; break; } - cinfoPtr = cinfoPtr->next; - } - return -1; - } /* not data */ - - if (i == -1) return -1; /* too few bytes */ - if (conn.pid!=0) { - ci->data = conn; - return 0; - } - - /* Aha, request for information (so-called snapshot) */ - switch(conn.vc) { - case GPM_REQ_SNAPSHOT: - i=open_console(O_RDONLY); - ioctl(i,VT_GETSTATE,&stat); - event.modifiers=6; /* code for the ioctl */ - if (ioctl(i,TIOCLINUX,&(event.modifiers))<0) - gpm_report(GPM_PR_OOPS,GPM_MESS_GET_SHIFT_STATE); - close(i); - event.vc = stat.v_active; - event.x=statusX; event.y=statusY; - event.dx=maxx; event.dy=maxy; - event.buttons= statusB; - event.clicks=statusC; - /* fall through */ - /* missing break or do you want this ??? */ - - case GPM_REQ_BUTTONS: - event.type= (opt_three==1 ? 3 : 2); /* buttons */ - write(ci->fd,&event,sizeof(Gpm_Event)); - break; + /* propagate movement */ + if (!opt->absolute) { /* mouse */ + if (abs(nEvent.dx) + abs(nEvent.dy) > opt->delta) + nEvent.dx *= opt->accel, nEvent.dy *= opt->accel; - case GPM_REQ_NOPASTE: - disable_paste(vc); - break; + /* increment the reported dx,dy */ + event->dx += nEvent.dx; + event->dy += nEvent.dy; + } else { /* a pen */ + /* get dx,dy to check if there has been movement */ + event->dx = nEvent.x - event->x; + event->dy = nEvent.y - event->y; + } + + /* propagate wheel */ + event->wdx += nEvent.wdx; + event->wdy += nEvent.wdy; + + } while (i++ < opt->cluster && more_data_waiting(mouse->dev.fd)); + } /* if(eventFlag) */ + + /*....................................... update the button number */ + + if ((event->buttons & GPM_B_MIDDLE) && !opt->three_button) opt->three_button++; + + /*....................................... we're a repeater, aren't we? */ + + if (!text_mode) { + if (repeater.fd != -1 && !repeater.raw) + handle_repeater(opt->absolute, &nEvent, event); + oldB = nEvent.buttons; + return MOUSE_NO_DATA; /* no events nor information for clients */ } - return 0; -} +/*....................................... no, we arent a repeater, go on */ -/*-------------------------------------------------------------------*/ -static inline int processConn(int fd) /* returns newfd or -1 */ -{ - Gpm_Cinfo *info; - Gpm_Connect *request; - Gpm_Cinfo *next; - int vc, newfd; -#if !defined(__GLIBC__) - int len; -#else /* __GLIBC__ */ - size_t len; /* isn't that generally defined in C ??? -- nico */ -#endif /* __GLIBC__ */ - struct sockaddr_un addr; /* reuse this each time */ - struct stat statbuf; - uid_t uid; - char *tty = NULL; - -/*....................................... Accept */ - - bzero((char *)&addr,sizeof(addr)); - addr.sun_family=AF_UNIX; - - len=sizeof(addr); - if ((newfd=accept(fd,(struct sockaddr *)&addr, &len))<0) { - gpm_report(GPM_PR_ERR,GPM_MESS_ACCEPT_FAILED,strerror(errno)); - return -1; - } - - gpm_report(GPM_PR_INFO,GPM_MESS_CONECT_AT,newfd); - - info=malloc(sizeof(Gpm_Cinfo)); - if (!info) gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM); - request=&(info->data); - - if(get_data(request,newfd)==-1) { - free(info); - close(newfd); - return -1; - } - - if ((vc=request->vc)>MAX_VC) { - gpm_report(GPM_PR_WARN,GPM_MESS_REQUEST_ON, vc, MAX_VC); - free(info); - close(newfd); - return -1; - } - -#ifndef SO_PEERCRED - if (stat (addr.sun_path, &statbuf) == -1 || !S_ISSOCK(statbuf.st_mode)) { - gpm_report(GPM_PR_ERR,GPM_MESS_ADDRES_NSOCKET,addr.sun_path); - free(info); /* itz 10-12-95 verify client's right */ - close(newfd); - return -1; /* to read requested tty */ + /* use fine delta values now, if delta is the information */ + if (!opt->absolute) { + fine_dx += event->dx; + fine_dy += event->dy; + event->dx = fine_dx / opt->scalex; + event->dy = fine_dy / opt->scaley; + fine_dx %= opt->scalex; + fine_dy %= opt->scaley; } - - unlink(addr.sun_path); /* delete socket */ - staletime = time(0) - 30; - if (statbuf.st_atime < staletime - || statbuf.st_ctime < staletime - || statbuf.st_mtime < staletime) { - gpm_report(GPM_PR_ERR,GPM_MESS_SOCKET_OLD); - free (info); - close(newfd); - return -1; /* socket is ancient */ + /* up and down, up and down, ... who does a do..while(0) loop ??? + and then makes a break into it... argh ! */ + + if (!event->dx && !event->dy && event->buttons == oldB) { + static time_t awaketime; + /* + * Ret information also if never happens, but enough time has elapsed. + * Note: return 1 will segfault due to missing event->vc; FIXME! + */ + if (time(NULL) <= awaketime) return MOUSE_NO_DATA; + awaketime = time(NULL) + 1; } - uid = statbuf.st_uid; /* owner of socket */ -#else - { - struct ucred sucred; - socklen_t credlen = sizeof(struct ucred); - - if(getsockopt(newfd, SOL_SOCKET, SO_PEERCRED, &sucred, &credlen) == -1) { - gpm_report(GPM_PR_ERR,GPM_MESS_GETSOCKOPT, strerror(errno)); - free(info); - close(newfd); - return -1; - } - uid = sucred.uid; - gpm_report(GPM_PR_DEBUG,GPM_MESS_PEER_SCK_UID, uid); - } -#endif - if (uid != 0) { - if(( tty = - malloc(strlen(option.consolename)+Gpm_cnt_digits(vc) + sizeof(char))) == NULL) - gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM); - - strncpy(tty,option.consolename,strlen(option.consolename)-1); - sprintf(&tty[strlen(option.consolename)-1],"%d",vc); + /*....................................... fill missing fields */ + event->x += event->dx; event->y += event->dy; - if(stat(tty, &statbuf) == -1) { - gpm_report(GPM_PR_ERR,GPM_MESS_STAT_FAILS,tty); - free(info); - free(tty); - close(newfd); - return -1; - } - if (uid != statbuf.st_uid) { - gpm_report(GPM_PR_WARN,GPM_MESS_FAILED_CONNECT, uid, tty); /*SUSPECT!*/ - free(info); - free(tty); - close(newfd); - return -1; + event->vc = get_console_state(&shift_state); + if (event->vc != last_active) { + handle_console_resize(event); + last_active = event->vc; + } + event->modifiers |= shift_state; + + if (oldB == event->buttons) + event->type = (event->buttons ? (GPM_DRAG | GPM_MFLAG) : GPM_MOVE); + else { + if (event->buttons > oldB) + event->type = GPM_DOWN; + else { + event->type &= GPM_MFLAG; + event->type |= GPM_UP; + event->buttons ^= oldB; /* for button-up, tell which one */ } - free(tty); /* at least here it's not needed anymore */ } + calculate_clicks(event, opt->time); + snap_to_screen_limits(event); + + gpm_report(GPM_PR_DEBUG,"M: %3i %3i (%3i %3i) - butt=%i vc=%i cl=%i", + event->dx, event->dy, event->x, event->y, + event->buttons, event->vc, event->clicks); - /* register the connection information in the right place */ - info->next=next=cinfo[vc]; - info->fd=newfd; - cinfo[vc]=info; - gpm_report(GPM_PR_DEBUG,GPM_MESS_LONG_STATUS, - request->pid, request->vc, request->eventMask, request->defaultMask, - request->minMod, request->maxMod); - - /* if the client gets motions, give it the current position */ - if(request->eventMask & GPM_MOVE) { - Gpm_Event event={0,0,vc,0,0,statusX,statusY,GPM_MOVE,0,0}; - do_client(info, &event); - } + oldB = nEvent.buttons; - return newfd; + if (opt_special && (event->type & GPM_DOWN) && !processSpecial(event)) + rslt = MOUSE_NO_DATA; + + return rslt; } -/*-------------------------------------------------------------------*/ -void get_console_size(Gpm_Event *ePtr) +static int wait_for_data(fd_set *connSet, int maxfd, fd_set *selSet) { - int i, prevmaxx, prevmaxy; - struct mouse_features *which_mouse; /* local */ + struct micetab *mouse; + struct timeval now, timeout = { 0, 0 }; + int mouse_tmo, tmo = INT_MAX; - /* before asking the new console size, save the previous values */ - prevmaxx = maxx; prevmaxy = maxy; + GET_TIME(now); - i=open_console(O_RDONLY); - ioctl(i, TIOCGWINSZ, &win); - close(i); - if (!win.ws_col || !win.ws_row) { - gpm_report(GPM_PR_DEBUG,GPM_MESS_ZERO_SCREEN_DIM); - win.ws_col=80; win.ws_row=25; - } - maxx=win.ws_col; maxy=win.ws_row; - gpm_report(GPM_PR_DEBUG,GPM_MESS_SCREEN_SIZE,maxx,maxy); - - if (!prevmaxx) { /* first invocation, place the pointer in the middle */ - statusX = ePtr->x = maxx/2; - statusY = ePtr->y = maxy/2; - } else { /* keep the pointer in the same position where it was */ - statusX = ePtr->x = ePtr->x * maxx / prevmaxx; - statusY = ePtr->y = ePtr->y * maxy / prevmaxy; - } - - for (i=1; i <= 1+opt_double; i++) { - which_mouse=mouse_table+i; /* used to access options */ - /* - * the following operation is based on the observation that 80x50 - * has square cells. (An author-centric observation ;-) - */ - opt_scaley=opt_scale*50*maxx/80/maxy; - gpm_report(GPM_PR_DEBUG,GPM_MESS_X_Y_VAL,opt_scale,opt_scaley); + *selSet = *connSet; + for (mouse = micelist; mouse; mouse = mouse->next) { + FD_SET(mouse->dev.fd, selSet); + maxfd = max(maxfd, mouse->dev.fd); + if (mouse->dev.timeout >= 0) { + mouse_tmo = mouse->dev.timeout - DIF_TIME(mouse->timestamp, now); + tmo = min(tmo, mouse_tmo); + } } + + if (tmo == INT_MAX) + timeout.tv_sec = SELECT_TIME; + else if (tmo > 0) { + timeout.tv_sec = tmo / 1000; + timeout.tv_usec = (tmo % 1000) * 1000; + } + + return select(maxfd + 1, selSet, NULL_SET, NULL_SET, &timeout); } -/*-------------------------------------------------------------------*/ -static void gpm_killed(int signo) -{ - if(signo==SIGWINCH) { - gpm_report(GPM_PR_WARN,GPM_MESS_RESIZING, option.progname, getpid()); - opt_resize++; - return; - } - if (signo==SIGUSR1) - gpm_report(GPM_PR_WARN,GPM_MESS_KILLED_BY,option.progname, getpid(),option.progname); - exit(0); -} + /*-------------------------------------------------------------------*/ int old_main() { - int ctlfd, newfd; - struct sockaddr_un ctladdr; - int i, len, kd_mode, fd; - struct timeval timeout; - int maxfd=-1; - int pending; + int ctlfd; + int i, text_mode; + struct timeval now; + int maxfd = -1; + int pending, attempt; + int timed_out; Gpm_Event event; + struct micetab *mouse; + struct client_info *ci; + fd_set selSet, connSet; + enum mouse_rslt rslt; - for (i = 1; i <= 1+opt_double; i++) { - which_mouse=mouse_table+i; /* used to access options */ - - if (!opt_dev) gpm_report(GPM_PR_OOPS,GPM_MESS_NEED_MDEV); - - if(!strcmp(opt_dev,"-")) fd=0; /* use stdin */ - else if( (fd=open(opt_dev,O_RDWR | O_NDELAY)) < 0) - gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,opt_dev); - - /* and then reset the flag */ - fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NDELAY); - - /* create argc and argv for this device */ - mouse_argv[i] = build_argv(opt_type, opt_options, &mouse_argc[i], ','); - - /* init the device, and use the return value as new mouse type */ - if (m_type->init) - m_type=(m_type->init)(fd, m_type->flags, m_type, mouse_argc[i], - mouse_argv[i]); - if (!m_type) gpm_report(GPM_PR_OOPS,GPM_MESS_MOUSE_INIT); - - which_mouse->fd=fd; - maxfd=max(fd, maxfd); - } - -/*....................................... catch interesting signals */ - + /*....................................... catch interesting signals */ signal(SIGTERM, gpm_killed); signal(SIGINT, gpm_killed); signal(SIGUSR1, gpm_killed); /* usr1 is used by a new gpm killing the old */ signal(SIGWINCH,gpm_killed); /* winch can be sent if console is resized */ + signal(SIGPIPE, SIG_IGN); /* WARN */ -/*....................................... create your nodes */ - - /* control node */ - - if((ctlfd=socket(AF_UNIX,SOCK_STREAM,0))==-1) gpm_report(GPM_PR_OOPS,GPM_MESS_SOCKET_PROB); - bzero((char *)&ctladdr,sizeof(ctladdr)); - ctladdr.sun_family=AF_UNIX; - strcpy(ctladdr.sun_path,GPM_NODE_CTL); - unlink(GPM_NODE_CTL); - - len=sizeof(ctladdr.sun_family)+strlen(GPM_NODE_CTL); - if(bind(ctlfd,(struct sockaddr *)(&ctladdr),len) == -1) - gpm_report(GPM_PR_OOPS,GPM_MESS_BIND_PROB,ctladdr.sun_path); - maxfd=max(maxfd,ctlfd); - - /* needs to be 0777, so all users can _try_ to access gpm */ - chmod(GPM_NODE_CTL,0777); - - get_console_size(&event); /* get screen dimensions */ - -/*....................................... wait for mouse and connections */ - - listen(ctlfd, 5); /* Queue up calls */ - -#define NULL_SET ((fd_set *)NULL) -#define resetTimeout() (timeout.tv_sec=SELECT_TIME,timeout.tv_usec=0) + init_mice(); + handle_console_resize(&event); /* get screen dimensions */ + ctlfd = listen_for_clients(); + /*....................................... wait for mouse and connections */ FD_ZERO(&connSet); - FD_SET(ctlfd,&connSet); - - if (opt_double) FD_SET(mouse_table[2].fd,&connSet); - - readySet=connSet; - FD_SET(mouse_table[1].fd,&readySet); - - signal(SIGPIPE,SIG_IGN); /* WARN */ - -/*--------------------------------------- main loop begins here */ + FD_SET(ctlfd, &connSet); + maxfd = max(maxfd, ctlfd); + + /*--------------------------------------- main loop begins here */ - while(1) { - selSet=readySet; - resetTimeout(); - if (opt_test) timeout.tv_sec=0; + while (1) { - if (eventFlag) { /* an event left over by clustering */ - pending=1; - FD_ZERO(&selSet); - FD_SET(mouse_table[eventFlag].fd,&selSet); - } - else - while((pending=select(maxfd+1,&selSet,NULL_SET,NULL_SET,&timeout))==0){ - selSet=readySet; - resetTimeout(); - } /* go on */ - - if(opt_resize) { /* did the console resize? */ - get_console_size(&event); - opt_resize--; - signal(SIGWINCH,gpm_killed); /* reinstall handler */ - - /* and notify clients */ - for(i=0; inext) kill(ci->data.pid,SIGWINCH); - } + pending = wait_for_data(&connSet, maxfd, &selSet); + + if (console_resized) { /* did the console resize? */ + handle_console_resize(&event); + console_resized = 0; + signal(SIGWINCH, gpm_killed); /* reinstall handler */ + notify_clients_resize(); } if (pending < 0) { - if (errno==EBADF) gpm_report(GPM_PR_OOPS,GPM_MESS_SELECT_PROB); - gpm_report(GPM_PR_ERR,GPM_MESS_SELECT_STRING,strerror(errno)); - selSet=readySet; - resetTimeout(); + if (errno == EBADF) gpm_report(GPM_PR_OOPS,GPM_MESS_SELECT_PROB); + gpm_report(GPM_PR_ERR, GPM_MESS_SELECT_STRING, strerror(errno)); continue; } - gpm_report(GPM_PR_DEBUG,GPM_MESS_SELECT_TIMES,pending); + gpm_report(GPM_PR_DEBUG, GPM_MESS_SELECT_TIMES, pending); -/*....................................... manage graphic mode */ + /*....................................... manage graphic mode */ - /* - * Be sure to be in text mode. This used to be before select, - * but actually it only matters if you have events. - */ - { - int fd = open_console(O_RDONLY); - if (ioctl(fd, KDGETMODE, &kd_mode) < 0) - gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_KDGETMODE); - close(fd); - if(kd_mode != KD_TEXT && !option.repeater) { - wait_text(&mouse_table[1].fd); - maxfd=max(maxfd,mouse_table[1].fd); - readySet=connSet; - FD_SET(mouse_table[1].fd,&readySet); + /* + * Be sure to be in text mode. This used to be before select, + * but actually it only matters if you have events. + */ + text_mode = is_text_console(); + if (!text_mode && !repeater.type && !repeater.raw) { + /* if we don;t have repeater then there is only one mouse so + * we can safely use micelist + */ + close(micelist->dev.fd); + wait_text_console(); + /* reopen, reinit (the function is only used if we have one mouse device) */ + if ((micelist->dev.fd = open(micelist->device, O_RDWR)) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN, micelist->device); + if (micelist->type->init) + micelist->type->init(&micelist->dev, &micelist->options, micelist->type); continue; /* reselect */ } - } -/*....................................... got mouse, process event */ -/* - * Well, actually, run a loop to maintain inlining of functions without - * lenghtening the file. This is not too clean a code, but it works.... - */ - - for (i=1; i <= 1+opt_double; i++) { - which_mouse=mouse_table+i; /* used to access options */ - if (FD_ISSET(which_mouse->fd,&selSet)) { - FD_CLR(which_mouse->fd,&selSet); pending--; - if (processMouse(which_mouse->fd, &event, m_type, kd_mode)) - /* pass it to the client, if any - * or to the default handler, if any - * or to the selection handler - */ /* FIXME -- check event.vc */ - /* can't we please rewrite the following a bit nicer?*/ - (cinfo[event.vc] && do_client(cinfo[event.vc], &event)) - || (cinfo[0] && do_client(cinfo[0], &event)) - || do_selection(&event); + /*....................................... got mouse, process event */ + /* + * Well, actually, run a loop to maintain inlining of functions without + * lenghtening the file. This is not too clean a code, but it works.... + */ + GET_TIME(now); + for (mouse = micelist; mouse; mouse = mouse->next) { + timed_out = mouse->dev.timeout >= 0 && + DIF_TIME(mouse->timestamp, now) >= mouse->dev.timeout; + if (timed_out || FD_ISSET(mouse->dev.fd, &selSet)) { + if (FD_ISSET(mouse->dev.fd, &selSet)) { + FD_CLR(mouse->dev.fd, &selSet); + pending--; } + attempt = 0; + do { + rslt = processMouse(mouse, timed_out, ++attempt, &event, text_mode); + if (rslt != MOUSE_NO_DATA) { + /* pass it to the client or to the default handler, + * or to the selection handler + */ + if (event.vc > MAX_VC) event.vc = 0; + if (event.vc == 0 || !cinfo[event.vc] || !do_client(cinfo[event.vc], &event)) + if (!cinfo[0] || !do_client(cinfo[0], &event)) + do_selection(&event, mouse->options.three_button); + } + } while (rslt == MOUSE_MORE_DATA); + } } /*..................... got connection, process it */ - - if (pending && FD_ISSET(ctlfd,&selSet)) { - FD_CLR(ctlfd,&selSet); pending--; - newfd=processConn(ctlfd); - if (newfd>=0) { - FD_SET(newfd,&connSet); - FD_SET(newfd,&readySet); - maxfd=max(maxfd,newfd); + if (pending && FD_ISSET(ctlfd, &selSet)) { + FD_CLR(ctlfd, &selSet); + pending--; + if ((ci = accept_client_connection(ctlfd))) { + if (ci->data.eventMask & GPM_MOVE) { + Gpm_Event e = { 0, 0, ci->data.vc, 0, 0, + event.x, event.y, GPM_MOVE, 0, 0 }; + do_client(ci, &e); + } + FD_SET(ci->fd, &connSet); + maxfd = max(maxfd, ci->fd); } } /*........................ got request */ - - /* itz 10-22-96 check _all_ clients, not just those on top! */ - for (i=0; pending && (i<=MAX_VC); i++) { - Gpm_Cinfo* ci; + /* itz 10-22-96 check _all_ clients, not just those on top! */ + for (i = 0; pending && i <= MAX_VC; i++) { for (ci = cinfo[i]; pending && ci; ci = ci->next) { - if (FD_ISSET(ci->fd,&selSet)) { - FD_CLR(ci->fd,&selSet); pending--; - /* itz Sat Sep 12 21:10:22 PDT 1998 */ - /* this code is clearly incorrect; the next highest - descriptor after the one we're closing is not necessarily - being used. Fortunately, it doesn't hurt simply to leave this - out. */ - -#ifdef NOTDEF - if ((processRequest(ci,i)==-1) && maxfd==ci->fd) maxfd--; -#else - (void)processRequest(ci,i); -#endif + if (FD_ISSET(ci->fd, &selSet)) { + FD_CLR(ci->fd, &selSet); + pending--; + if (!process_client_request(ci, i, event.x, event.y, event.clicks, + event.buttons, micelist->options.three_button)) { + FD_CLR(ci->fd, &connSet); + remove_client(ci, i); + } } } } /*.................. look for a spare fd */ - /* itz 10-22-96 this shouldn't happen now! */ - for (i=0; pending && i<=maxfd; i++) { - if (FD_ISSET(i,&selSet)) { - FD_CLR(i,&selSet); + for (i = 0; pending && i <= maxfd; i++) { + if (FD_ISSET(i, &selSet)) { + FD_CLR(i, &selSet); pending--; - gpm_report(GPM_PR_WARN,GPM_MESS_STRANGE_DATA,i); + gpm_report(GPM_PR_WARN, GPM_MESS_STRANGE_DATA,i); } } /*................... all done. */ - - if(pending) gpm_report(GPM_PR_OOPS,GPM_MESS_SELECT_PROB); + if (pending) gpm_report(GPM_PR_OOPS, GPM_MESS_SELECT_PROB); } /* while(1) */ } diff -urN gpm-1.20.1/src/gpn.c gpm/src/gpn.c --- gpm-1.20.1/src/gpn.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/gpn.c 2003-10-02 01:22:42.000000000 -0500 @@ -28,201 +28,104 @@ #include #include /* strerror(); ?!? memcpy() */ #include /* isdigit */ -#include -#include /* Log uses it */ -#include #include /* getopt(),symlink() */ -#include /* mkdir() */ -#include -#include /* timeval */ -#include /* wait() */ -#include /* socket() */ -#include /* socket() */ -#include /* struct sockaddr_un */ -#include /* __u32 */ - -#ifdef SIGTSTP /* true if BSD system */ -#include -#include -#endif - -#ifndef HAVE___U32 -# ifndef _I386_TYPES_H /* /usr/include/asm/types.h */ -typedef unsigned int __u32; -# endif -#endif #include "headers/message.h" #include "headers/gpmInt.h" #include "headers/gpm.h" +#include "headers/console.h" +#include "headers/selection.h" -extern int errno; - -/*===================================================================*/ -/* octal digit */ -static int isodigit(const unsigned char c) +/* usage: display for usage informations */ +int usage(char *whofailed) { - return ((c & ~7) == '0'); + if (whofailed) { + gpm_report(GPM_PR_ERR, GPM_MESS_SPEC_ERR, whofailed, option.progname); + return 1; + } + printf(GPM_MESS_USAGE, option.progname, DEF_ACCEL, DEF_BAUD, DEF_SEQUENCE, + DEF_DELTA, DEF_TIME, DEF_LUT, DEF_SCALE, DEF_SAMPLE, DEF_TYPE); + return 1; } -/* routine to convert digits from octal notation (Andries Brouwer) */ -static int getsym(const unsigned char *p0, unsigned char *res) +/***************************************************************************** + * the function returns a valid type pointer or NULL if not found + *****************************************************************************/ +static struct Gpm_Type *find_mouse_by_name(char *name) { - const unsigned char *p = p0; - char c; + Gpm_Type *type; + char *s; + int len = strlen(name); - c = *p++; - if (c == '\\' && *p) { - c = *p++; - if (isodigit(c)) { - c -= '0'; - if (isodigit(*p)) c = 8*c + (*p++ - '0'); - if (isodigit(*p)) c = 8*c + (*p++ - '0'); + for (type = mice; type->fun; type++) { + if (!strcasecmp(name, type->name)) break; + /* otherwise, look in the synonym list */ + for (s = type->synonyms; s; s = strchr(s, ' ')) { + while (*s && isspace(*s)) s++; /* skip spaces */ + if (!strncasecmp(name, s, len) && !isprint(*(s + len))) break;/*found*/ } + if (s) break; /* found a synonym */ } - *res = c; - return (p - p0); + return type->fun ? type : NULL; } -/* description missing! FIXME */ -int loadlut(char *charset) +static void init_button_sequence(struct miceopt *opt, char *arg) { - int i, c, fd; - unsigned char this, next; - static __u32 long_array[9]={ - 0x05050505, /* ugly, but preserves alignment */ - 0x00000000, /* control chars */ - 0x00000000, /* digits */ - 0x00000000, /* uppercase and '_' */ - 0x00000000, /* lowercase */ - 0x00000000, /* Latin-1 control */ - 0x00000000, /* Latin-1 misc */ - 0x00000000, /* Latin-1 uppercase */ - 0x00000000 /* Latin-1 lowercase */ + int i; + static struct { + char *in; + char *out; + } seq[] = { + {"123", "01234567"}, + {"132", "02134657"}, + {"213", "01452367"}, /* warning: these must be readable as integers... */ + {"231", "02461357"}, + {"312", "04152637"}, + {"321", "04261537"}, + {NULL, NULL} }; + if (strlen(arg) != 3 || atoi(arg) < 100) + exit(usage("sequence")); -#define inwordLut (long_array+1) - - for (i=0; charset[i]; ) { - i += getsym(charset+i, &this); - if (charset[i] == '-' && charset[i + 1] != '\0') - i += getsym(charset+i+1, &next) + 1; - else - next = this; - for (c = this; c <= next; c++) - inwordLut[c>>5] |= 1 << (c&0x1F); - } - - if ((fd=open(option.consolename, O_WRONLY)) < 0) { - /* try /dev/console, if /dev/tty0 failed -- is that really senseful ??? */ - free(option.consolename); /* allocated by main */ - if((option.consolename=malloc(strlen(GPM_SYS_CONSOLE)+1)) == NULL) - gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM); - strcpy(option.consolename,GPM_SYS_CONSOLE); - - if ((fd=open(option.consolename, O_WRONLY)) < 0) gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN_CON); - } - if (ioctl(fd, TIOCLINUX, &long_array) < 0) { /* fd <0 is checked */ - if (errno==EPERM && getuid()) - gpm_report(GPM_PR_WARN,GPM_MESS_ROOT); /* why do we still continue?*/ - else if (errno==EINVAL) - gpm_report(GPM_PR_OOPS,GPM_MESS_CSELECT); - } - close(fd); - - return 0; + for (i = 0; seq[i].in && strcmp(seq[i].in, arg); i++); + if (!seq[i].in) + exit(usage("button sequence")); + opt->sequence = strdup(seq[i].out); /* I can rewrite on it */ } -/* usage: display for usage informations */ -int usage(char *whofailed) +static void validate_mouse(struct micetab *mouse, int mouse_no) { - if (whofailed) { - gpm_report(GPM_PR_ERR,GPM_MESS_SPEC_ERR,whofailed,option.progname); - return 1; - } - printf(GPM_MESS_USAGE,option.progname, DEF_ACCEL, DEF_BAUD, DEF_SEQUENCE, - DEF_DELTA, DEF_TIME, DEF_LUT,DEF_SCALE, DEF_SAMPLE, DEF_TYPE); - return 1; -} - -/* itz Sat Sep 12 10:55:51 PDT 1998 Added this as replacement for the - unwanted functionality in check_uniqueness. */ - -void check_kill(void) -{ - int old_pid; - FILE* fp = fopen(GPM_NODE_PID, "r"); - - /* if we cannot find the old pid file, leave */ - if (fp == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN, GPM_NODE_PID); - - /* else read the pid */ - if (fscanf(fp,"%d",&old_pid) != 1) - gpm_report(GPM_PR_OOPS,GPM_MESS_READ_PROB,GPM_NODE_PID); - fclose(fp); - - gpm_report(GPM_PR_DEBUG,GPM_MESS_KILLING,old_pid); - - /* first check if we run */ - if (kill(old_pid,0) == -1) { - gpm_report(GPM_PR_INFO,GPM_MESS_STALE_PID, GPM_NODE_PID); - unlink(GPM_NODE_PID); + if (!mouse->device) { + if (!mouse->type && mouse_no > 1) + gpm_report(GPM_PR_OOPS, + "No device/protocol specified for mouse #%d, probably extra -M option?", mouse_no); + else + gpm_report(GPM_PR_OOPS, "No device specified for mouse #%d", mouse_no); } - /* then kill us (not directly, but the other instance ... ) */ - if (kill(old_pid,SIGTERM) == -1) - gpm_report(GPM_PR_OOPS,GPM_MESS_CANT_KILL, old_pid); - gpm_report(GPM_PR_INFO,GPM_MESS_KILLED,old_pid); - exit(0); -} + if (!mouse->type) + mouse->type = find_mouse_by_name(DEF_TYPE); -/* itz Sat Sep 12 10:30:05 PDT 1998 this function used to mix two - completely different things; opening a socket to a running daemon - and checking that a running daemon existed. Ugly. */ -/* rewritten mostly on 20th of February 2002 - nico */ -void check_uniqueness(void) -{ - FILE *fp = 0; - int old_pid = -1; + mouse->options.absolute = mouse->type->absolute; - if((fp = fopen(GPM_NODE_PID, "r")) != NULL) { - fscanf(fp, "%d", &old_pid); - if (kill(old_pid,0) == -1) { - gpm_report(GPM_PR_INFO,GPM_MESS_STALE_PID, GPM_NODE_PID); - unlink(GPM_NODE_PID); - } else /* we are really running, exit asap! */ - gpm_report(GPM_PR_OOPS,GPM_MESS_ALREADY_RUN, old_pid); - } - /* now try to sign ourself */ - if ((fp = fopen(GPM_NODE_PID,"w")) != NULL) { - fprintf(fp,"%d\n",getpid()); - fclose(fp); - } else { - gpm_report(GPM_PR_OOPS,GPM_MESS_NOTWRITE,GPM_NODE_PID); - } + if (!mouse->options.sequence) + init_button_sequence(&mouse->options, DEF_SEQUENCE); } -/***************************************************************************** - * the function returns a valid type pointer or NULL if not found - *****************************************************************************/ -struct Gpm_Type *find_mouse_by_name(char *name) +static void validate_repeater(char *type) { - Gpm_Type *type; - char *s; - int len = strlen(name); - - for (type=mice; type->fun; type++) { - if (!strcasecmp(name, type->name)) break; - /* otherwise, look in the synonym list */ - for (s = type->synonyms; s; s = strchr(s, ' ')) { - while (*s && isspace(*s)) s++; /* skip spaces */ - if(!strncasecmp(name, s, len) && !isprint(*(s + len))) break;/*found*/ - } - if(s) break; /* found a synonym */ + if (strcmp(type, "raw") == 0) + repeater.raw = 1; + else { + repeater.raw = 0; + + if (!(repeater.type = find_mouse_by_name(type))) + exit(M_listTypes()); /* not found */ + + if (!repeater.type->repeat_fun) /* unsupported translation */ + gpm_report(GPM_PR_OOPS, GPM_MESS_NO_REPEAT, type); } - if (!type->fun) return NULL; - return type; } /***************************************************************************** @@ -230,60 +133,86 @@ * Can't believe it, today cmdline() really does what the name tries to say *****************************************************************************/ void cmdline(int argc, char **argv) -{ - extern struct options option; +{ + struct micetab *mouse; + struct miceopt *opt; char options[]="a:A::b:B:d:Dg:hi:kl:m:Mo:pr:R::s:S:t:TuvV::23"; - int opt; + int opt_char, tmp; + int mouse_no = 1; + + mouse = add_mouse(); + opt = &mouse->options; - /* initialize for the dual mouse */ - mouse_table[2]=mouse_table[1]=mouse_table[0]; /* copy defaults */ - which_mouse=mouse_table+1; /* use the first */ - - while ((opt = getopt(argc, argv, options)) != -1) { - switch (opt) { - case 'a': opt_accel = atoi(optarg); break; - case 'A': opt_aged++; - if (optarg) - opt_age_limit = atoi(optarg); break; - case 'b': opt_baud = atoi(optarg); break; - case 'B': opt_sequence = optarg; break; - case 'd': opt_delta = atoi(optarg); break; - case 'D': option.run_status = GPM_RUN_DEBUG; break; - case 'g': opt_glidepoint_tap=atoi(optarg); break; - case 'h': exit(usage(NULL)); - case 'i': opt_time=atoi(optarg); break; - case 'k': check_kill(); break; - case 'l': opt_lut = optarg; break; - case 'm': add_mouse(GPM_ADD_DEVICE,optarg); - opt_dev = optarg; break; /* GO AWAY!*/ - case 'M': opt_double++; option.repeater++; - if (option.repeater_type == 0) - option.repeater_type = "msc"; - which_mouse=mouse_table+2; break; - case 'o': add_mouse(GPM_ADD_OPTIONS,optarg); - gpm_report(GPM_PR_DEBUG,"options: %s",optarg); - opt_options = optarg; break; /* GO AWAY */ - case 'p': opt_ptrdrag = 0; break; - case 'r': - /* being called responsiveness, I must take the inverse */ - opt_scale=atoi(optarg); - if(!opt_scale || opt_scale > 100) opt_scale=100; /* the maximum */ - else opt_scale=100/opt_scale; break; - case 'R': - option.repeater++; - if (optarg) option.repeater_type = optarg; - else option.repeater_type = "msc"; break; - case 's': opt_sample = atoi(optarg); break; - case 'S': if (optarg) opt_special = optarg; - else opt_special=""; break; - case 't': add_mouse(GPM_ADD_TYPE,optarg); - opt_type = optarg; break; /* GO AWAY */ - case 'u': option.autodetect = 1; break; - case 'T': opt_test++; break; - case 'v': printf(GPM_MESS_VERSION "\n"); exit(0); - case '2': opt_three = -1; break; - case '3': opt_three = 1; break; - default: exit(usage("commandline")); + while ((opt_char = getopt(argc, argv, options)) != -1) { + switch (opt_char) { + case 'a': if ((opt->accel = atoi(optarg)) < 1) + exit(usage("acceleration")); + break; + case 'A': sel_opts.aged = 1; + if (optarg) + sel_opts.age_limit = atoi(optarg); + break; + case 'b': opt->baud = atoi(optarg); + break; + case 'B': init_button_sequence(opt, optarg); + break; + case 'd': if ((opt->delta = atoi(optarg)) < 2) + exit(usage("delta")); + break; + case 'D': option.run_status = GPM_RUN_DEBUG; + break; + case 'g': if (atoi(optarg) > 3) + exit(usage("glidepoint tap button")); + opt->glidepoint_tap = GPM_B_LEFT >> (atoi(optarg) - 1); + break; + case 'h': exit(usage(NULL)); + case 'i': opt->time = atoi(optarg); + break; + case 'k': kill_gpm(); + break; + case 'l': console.charset = optarg; + break; + case 'm': mouse->device = optarg; + break; + case 'M': validate_mouse(mouse, mouse_no); + mouse = add_mouse(); + opt = &mouse->options; + mouse_no++; + if (!repeater.type && !repeater.raw) + repeater.type = find_mouse_by_name(DEF_REP_TYPE); + break; + case 'o': gpm_report(GPM_PR_DEBUG,"options: %s", optarg); + opt->text = optarg; + break; + case 'p': sel_opts.ptrdrag = 0; + break; + case 'r': /* being called responsiveness, I must take the inverse */ + tmp = atoi(optarg); + if (!tmp || tmp > 100) tmp = 1; + opt->scalex = 100 / tmp; + break; + case 'R': validate_repeater((optarg) ? optarg : DEF_REP_TYPE); + break; + case 's': opt->sample = atoi(optarg); + break; + case 'S': if (optarg) opt_special = optarg; + else opt_special=""; + break; + case 't': mouse->type = find_mouse_by_name(optarg); + if (!mouse->type) + exit(M_listTypes()); + break; + case 'u': option.autodetect = 1; + break; + case 'v': printf(GPM_MESS_VERSION "\n"); + exit(0); + case '2': opt->three_button = -1; + break; + case '3': opt->three_button = 1; + break; + default: exit(usage("commandline")); } } + + validate_mouse(micelist, mouse_no); } diff -urN gpm-1.20.1/src/headers/client.h gpm/src/headers/client.h --- gpm-1.20.1/src/headers/client.h 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/headers/client.h 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,57 @@ +/* -*-mode:C;tab-width:3-*- + * client.h - GPM client handling (server side) + * + * Copyright (C) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#ifndef __GPM_CLIENT_H +#define __GPM_CLIENT_H_ + +#ifdef HAVE_LINUX_TTY_H +#include +#endif + +#include "headers/gpm.h" + +/* FIXME: still needed ?? */ +/* How many virtual consoles are managed? */ +#ifndef MAX_NR_CONSOLES +# define MAX_NR_CONSOLES 64 /* this is always sure */ +#endif + +#define MAX_VC MAX_NR_CONSOLES /* doesn't work before 1.3.77 */ + +struct client_info { + Gpm_Connect data; + int fd; + struct client_info *next; +}; + +struct Gpm_Event; + +extern struct client_info *cinfo[MAX_VC + 1]; + +int listen_for_clients(void); +struct client_info *accept_client_connection(int fd); +void remove_client(struct client_info *ci, int vc); +void notify_clients_resize(void); +int do_client(struct client_info *cinfo, struct Gpm_Event *event); +int process_client_request(struct client_info *ci, int vc, + int x, int y, int buttons, int clicks, + int three_button_mouse); + +#endif /* __GPM_CLIENT_H_ */ diff -urN gpm-1.20.1/src/headers/console.h gpm/src/headers/console.h --- gpm-1.20.1/src/headers/console.h 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/headers/console.h 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,42 @@ +/* -*-mode:C;tab-width:3-*- + * console.h - GPM console and selection/paste handling + * + * Copyright (C) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#ifndef __GPM_CONSOLE_H_ +#define __GPM_CONSOLE_H_ + +struct gpm_console { + char *device; + char *charset; + int max_x, max_y; +}; + +extern struct gpm_console console; + +int open_console(int mode); +char *get_console_name(); +char *compose_vc_name(int vc); +int is_text_console(void); +void wait_text_console(void); +void refresh_console_size(void); +int is_console_owner(int vc, uid_t uid); +int get_console_state(unsigned char *shift_state); +void console_load_lut(void); + +#endif /* __GPM_CONSOLE_H_ */ diff -urN gpm-1.20.1/src/headers/gpmInt.h gpm/src/headers/gpmInt.h --- gpm-1.20.1/src/headers/gpmInt.h 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/headers/gpmInt.h 2003-10-02 01:22:42.000000000 -0500 @@ -23,8 +23,7 @@ #ifndef _GPMINT_INCLUDED #define _GPMINT_INCLUDED -#include /* time_t */ /* for whom ???? FIXME */ - +#include /* timeval */ #include "gpm.h" #if !defined(__GNUC__) @@ -35,23 +34,12 @@ /* timeout for the select() syscall */ #define SELECT_TIME 86400 /* one day */ -#ifdef HAVE_LINUX_TTY_H -#include -#endif - -/* FIXME: still needed ?? */ -/* How many virtual consoles are managed? */ -#ifndef MAX_NR_CONSOLES -# define MAX_NR_CONSOLES 64 /* this is always sure */ -#endif - -#define MAX_VC MAX_NR_CONSOLES /* doesn't work before 1.3.77 */ - /* How many buttons may the mouse have? */ /* #define MAX_BUTTONS 3 ===> not used, it is hardwired :-( */ /* all the default values */ #define DEF_TYPE "ms" +#define DEF_REP_TYPE "msc" #define DEF_DEV NULL /* use the type-related one */ #define DEF_LUT "-a-zA-Z0-9_./\300-\326\330-\366\370-\377" #define DEF_SEQUENCE "123" /* how buttons are reordered */ @@ -62,12 +50,10 @@ #define DEF_SCALE 10 #define DEF_TIME 250 /* time interval (ms) for multiple clicks */ #define DEF_THREE 0 /* have three buttons? */ -#define DEF_KERNEL 0 /* no kernel module, by default */ /* 10 on old computers (<=386), 0 on current machines */ #define DEF_CLUSTER 0 /* maximum number of clustered events */ -#define DEF_TEST 0 #define DEF_PTRDRAG 1 /* double or triple click */ #define DEF_GLIDEPOINT_TAP 0 /* tapping emulates no buttons by default */ @@ -84,11 +70,6 @@ #define GPM_DEVFS_CONSOLE "/dev/vc/0" #define GPM_OLD_CONSOLE "/dev/tty0" -/* for adding a mouse; add_mouse */ -#define GPM_ADD_DEVICE 0 -#define GPM_ADD_TYPE 1 -#define GPM_ADD_OPTIONS 2 - /*** mouse commands ***/ #define GPM_AUX_SEND_ID 0xF2 @@ -117,126 +98,95 @@ /*....................................... Structures */ +struct micedev { + int fd; + int timeout; /* the protocol driver wants to be called + after X msec even if there is no new data + arrived (-1 to disable/default) */ + void *private; /* private data maintained by protocol driver */ +}; + +struct miceopt { + char *sequence; + int baud; + int sample; + int delta; + int accel; + int scalex, scaley; + int time; + int cluster; + int three_button; + int glidepoint_tap; + int absolute; /* device reports absolute coordinates - initially copied + from Gpm_Type; allows same protocol (type) control devices + in absolute and relative mode */ + char *text; /* extra textual options supplied via '-o text' */ +}; + /* * and this is the entry in the mouse-type table */ typedef struct Gpm_Type { - char *name; - char *desc; /* a descriptive line */ - char *synonyms; /* extra names (the XFree name etc) as a list */ - int (*fun)(Gpm_Event *state, unsigned char *data); - struct Gpm_Type *(*init)(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv); - unsigned short flags; - unsigned char proto[4]; - int packetlen; - int howmany; /* how many bytes to read at a time */ - int getextra; /* does it get an extra byte? (only mouseman) */ - int absolute; /* flag indicating absolute pointing device */ + char *name; + char *desc; /* a descriptive line */ + char *synonyms; /* extra names (the XFree name etc) as a list */ + int (*fun)(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state); + int (*init)(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type); + unsigned short flags; + unsigned char proto[4]; + int packetlen; + int howmany; /* how many bytes to read at a time */ + int getextra; /* does it get an extra byte? (only mouseman) */ + int absolute; /* flag indicating absolute pointing device */ - int (*repeat_fun)(Gpm_Event *state, int fd); /* repeat this event into fd */ + int (*repeat_fun)(Gpm_Event *state, int fd); /* repeat this event into fd */ /* itz Mon Jan 11 23:27:54 PST 1999 */ } Gpm_Type; #define GPM_EXTRA_MAGIC_1 0xAA #define GPM_EXTRA_MAGIC_2 0x55 -typedef struct Gpm_Cinfo { - Gpm_Connect data; - int fd; - struct Gpm_Cinfo *next; -} Gpm_Cinfo; - - -/*....................................... Global variables */ - -/* this structure is used to hide the dual-mouse stuff */ - -struct mouse_features { - char *opt_type, *opt_dev, *opt_sequence; - int opt_baud,opt_sample,opt_delta, opt_accel, opt_scale, opt_scaley; - int opt_time, opt_cluster, opt_three, opt_glidepoint_tap; - char *opt_options; /* extra textual configuration */ - Gpm_Type *m_type; - int fd; -}; - -extern struct mouse_features mouse_table[3], *which_mouse; /*the current one*/ - -// looks unused; delete -//typedef struct Opt_struct_type {int a,B,d,i,p,r,V,A;} Opt_struct_type; - -/* this is not very clean, actually, but it works fine */ -#define opt_type (which_mouse->opt_type) -#define opt_dev (which_mouse->opt_dev) -#define opt_sequence (which_mouse->opt_sequence) -#define opt_baud (which_mouse->opt_baud) -#define opt_sample (which_mouse->opt_sample) -#define opt_delta (which_mouse->opt_delta) -#define opt_accel (which_mouse->opt_accel) -#define opt_scale (which_mouse->opt_scale) -#define opt_scaley (which_mouse->opt_scaley) -#define opt_time (which_mouse->opt_time) -#define opt_cluster (which_mouse->opt_cluster) -#define opt_three (which_mouse->opt_three) -#define opt_glidepoint_tap (which_mouse->opt_glidepoint_tap) -#define opt_options (which_mouse->opt_options) - -#define m_type (which_mouse->m_type) - -/* the other variables */ - -extern char *opt_lut; -extern int opt_test, opt_ptrdrag; -extern int opt_kill; -extern int opt_kernel, opt_explicittype; -extern int opt_aged; -extern time_t opt_age_limit; extern char *opt_special; -extern int opt_rawrep; -extern int fifofd; -extern int opt_double; - -extern Gpm_Type *repeated_type; extern Gpm_Type mice[]; /* where the hell are the descriptions...*/ -extern struct winsize win; -extern int maxx, maxy; -extern Gpm_Cinfo *cinfo[MAX_VC+1]; /* new variables */ /* structure prototypes */ +struct repeater { + int fd; + int raw; + Gpm_Type *type; +}; /* contains all mice */ struct micetab { struct micetab *next; - char *device; - char *protocol; - char *options; + struct micedev dev; + struct miceopt options; + Gpm_Type *type; + char *device; + int buttons; /* mouse's button state from last read */ + struct timeval timestamp; /* last time mouse data arrived */ }; struct options { int autodetect; /* -u [aUtodetect..'A' is not available] */ - int no_mice; /* number of mice */ - int repeater; /* repeat data */ - char *repeater_type; /* repeat data as which mouse type */ int run_status; /* startup/daemon/debug */ char *progname; /* hopefully gpm ;) */ - struct micetab *micelist; /* mice and their options */ - char *consolename; /* /dev/tty0 || /dev/vc/0 */ }; /* global variables */ struct options option; /* one should be enough for us */ +extern struct repeater repeater; /* again, only one */ +extern struct micetab *micelist; /* new variables */ - /*....................................... Prototypes */ /* server_tools.c */ -void add_mouse (int type, char *value); -int init_mice (struct micetab *micelist); -int reset_mice(struct micetab *micelist); +struct micetab *add_mouse(void); +void init_mice(void); +void cleanup_mice(void); /* startup.c */ void startup(int argc, char **argv); @@ -246,17 +196,15 @@ /* gpn.c */ void cmdline(int argc, char **argv); -int giveInfo(int request, int fd); -int loadlut(char *charset); -int usage(char *whofailed); -struct Gpm_Type *find_mouse_by_name(char *name); +int giveInfo(int request, int fd); +int usage(char *whofailed); void check_uniqueness(void); -void check_kill(void); - +void kill_gpm(void); /* mice.c */ extern int M_listTypes(void); - /* special.c */ + + /* special.c */ int processSpecial(Gpm_Event *event); int twiddler_key(unsigned long message); int twiddler_key_init(void); diff -urN gpm-1.20.1/src/headers/input-defines.h gpm/src/headers/input-defines.h --- gpm-1.20.1/src/headers/input-defines.h 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/headers/input-defines.h 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,81 @@ +/* + * input-defines.h - complements adding missing bits + * + * Copyright (C) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ +#ifndef __GPM_INPUT_DEFINES_H +#define __GPM_INPUT_DEFINES_H + +#include +#include "headers/config.h" + +#ifndef ABS_TOOL_WIDTH +#define ABS_TOOL_WIDTH 0x1c +#endif + +#ifndef BTN_TOOL_FINGER +#define BTN_TOOL_FINGER 0x145 +#endif + +#ifndef BTN_TOUCH +#define BTN_TOUCH 0x14a +#endif + +#ifndef BTN_TOOL_DOUBLETAP +#define BTN_TOOL_DOUBLETAP 0x14d +#endif + +#ifndef BTN_TOOL_TRIPLETAP +#define BTN_TOOL_TRIPLETAP 0x14e +#endif + +#ifndef MSC_GESTURE +#define MSC_GESTURE 2 +#endif + +#ifndef EV_SYNC +#define EV_SYNC 0 +#endif + +#ifndef SYN_REPORT +#define SYN_REPORT 0 +#endif + +#ifndef PSMOUSE_SYNAPTICS +#define PSMOUSE_SYNAPTICS 7 +#endif + +#ifndef HAVE_INPUT_ID +struct input_id { + unsigned short bustype; + unsigned short vendor; + unsigned short product; + unsigned short version; +}; +#endif + +#ifndef HAVE_INPUT_ABSINFO +struct input_absinfo { + int value; + int minimum; + int maximum; + int fuzz; + int flat; +}; +#endif + +#endif diff -urN gpm-1.20.1/src/headers/message.h gpm/src/headers/message.h --- gpm-1.20.1/src/headers/message.h 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/headers/message.h 2003-10-02 01:22:42.000000000 -0500 @@ -96,7 +96,6 @@ " -S [commands] enable special commands (see man page)\n" \ " -t mouse-type sets mouse type (default '%s')\n" \ " Use a non-existent type (e.g. \"help\") to get a list\n" \ - " -T test: read mouse, no clients\n" \ " -v print version and exit\n" \ " -V verbosity increase number of logged messages\n\n\n" \ " Examples:\n\n" \ @@ -168,7 +167,8 @@ #define GPM_MESS_SELECT_TIMES "selected %i times" #define GPM_MESS_OPTION_NO_ARG "%s: Option \"%s\" takes no argument: ignoring \"%s\"" -#define GPM_MESS_INVALID_ARG "%s: Invalid arg. \"%s\" to \"%s\"" +#define GPM_MESS_INVALID_ARG "%s: Invalid argument \"%s\" for option \"%s\"" +#define GPM_MESS_MISSING_ARG "%s: Option \"%s\" requires an argument" #define GPM_MESS_CONT_WITH_ERR "%s: Continuing despite errors in option parsing" #define GPM_MESS_TOO_MANY_OPTS "%s: Too many options for \"-t %s\"" @@ -196,7 +196,7 @@ /* warnings */ #define GPM_MESS_REQUEST_ON "Request on vc %i > %i" -#define GPM_MESS_FAILED_CONNECT "Failed gpm connect attempt by uid %d for vc %s" +#define GPM_MESS_FAILED_CONNECT "Failed gpm connect attempt by uid %d for vc %d" #define GPM_MESS_ZERO_SCREEN_DIM "zero screen dimension, assuming 80x25" #define GPM_MESS_STRANGE_DATA "Data on strange file descriptor %d" #define GPM_MESS_RESIZING "%s pid %i is resizing :-)" diff -urN gpm-1.20.1/src/headers/optparser.h gpm/src/headers/optparser.h --- gpm-1.20.1/src/headers/optparser.h 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/headers/optparser.h 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,50 @@ +/* + * optparser.h - GPM mouse options parser + * + * Copyright (C) 1993 Andrew Haylett + * Copyright (C) 1994-2000 Alessandro Rubini + * Copyright (C) 1998,1999 Ian Zimmerman + * Copyright (C) 2001,2002 Nico Schottelius + * Copyright (C) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ +#ifndef __GPM_OPTPARSER_H_ +#define __GPM_OPTPARSER_H_ + +enum option_type { + OPT_BOOL = 1, + OPT_INT, /* "%i" */ + OPT_DEC, /* "%d" */ + OPT_STRING, + /* other types must be added */ + OPT_END = 0 +}; + +struct option_helper { + char *name; + enum option_type type; + union u { + int *iptr; /* used for int and bool arguments */ + char **sptr; /* used for string arguments, by strdup()ing the value */ + } u; + int value; /* used for boolean arguments */ + int present; +}; + +int parse_options(const char *who, const char *opt, char sep, struct option_helper *info); +int check_no_options(const char *proto, const char *opts, char sep); +int is_option_present(struct option_helper *info, const char *name); +#endif diff -urN gpm-1.20.1/src/headers/selection.h gpm/src/headers/selection.h --- gpm-1.20.1/src/headers/selection.h 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/headers/selection.h 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,37 @@ +/* + * console.h - GPM selection/paste handling + * + * Copyright (C) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#ifndef __GPM_SELECTION_H_ +#define __GPM_SELECTION_H_ + +struct sel_options { + int aged; + int age_limit; + int ptrdrag; +}; + +struct Gpm_Event; + +extern struct sel_options sel_opts; /* only one exists */ + +void do_selection(struct Gpm_Event *event, int three_button_mode); +void selection_disable_paste(void); + +#endif /* __GPM_CONSOLE_H_ */ diff -urN gpm-1.20.1/src/headers/synaptics.h gpm/src/headers/synaptics.h --- gpm-1.20.1/src/headers/synaptics.h 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/headers/synaptics.h 2003-10-02 01:22:42.000000000 -0500 @@ -62,7 +62,7 @@ ** ** Process the touchpad 6/7/8 byte data. */ -void syn_process_serial_data (Gpm_Event *state, +void syn_process_serial_data (int fd, Gpm_Event *state, unsigned char *data); @@ -72,7 +72,7 @@ ** ** Process the touchpad 6 byte data. */ -void syn_process_ps2_data (Gpm_Event *state, +void syn_process_ps2_data (int fd, Gpm_Event *state, unsigned char *data); diff -urN gpm-1.20.1/src/lib/liblow.c gpm/src/lib/liblow.c --- gpm-1.20.1/src/lib/liblow.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/lib/liblow.c 2003-10-02 01:22:42.000000000 -0500 @@ -80,6 +80,8 @@ int gpm_consolefd=-1; /* used to invoke ioctl() */ int gpm_morekeys=0; +static char *consolename; + int gpm_convert_event(unsigned char *mdata, Gpm_Event *ePtr); /*----------------------------------------------------------------------------* @@ -192,14 +194,13 @@ char *tty = NULL; char *term = NULL; int i; - extern struct options option; static int checked_con = 0; struct sockaddr_un addr; struct winsize win; Gpm_Stst *new = NULL; char* sock_name = 0; - option.consolename = NULL; + consolename = NULL; gpm_report(GPM_PR_DEBUG,"VC: %d",flag); @@ -216,7 +217,7 @@ /* check whether we know what name the console is: what's with the lib??? */ if(checked_con == 0) { - option.consolename = Gpm_get_console(); + consolename = Gpm_get_console(); checked_con++; } @@ -245,10 +246,10 @@ conn->vc=0; /* default handler */ if (flag > 0) { /* forced vc number */ conn->vc=flag; - if((tty = malloc(strlen(option.consolename)+Gpm_cnt_digits(flag))) == NULL) + if((tty = malloc(strlen(consolename)+Gpm_cnt_digits(flag))) == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM); - memcpy(tty,option.consolename,strlen(option.consolename)-1); - sprintf(&tty[strlen(option.consolename)-1],"%i",flag); + memcpy(tty,consolename,strlen(consolename)-1); + sprintf(&tty[strlen(consolename)-1],"%i",flag); } else { /* use your current vc */ if (isatty(0)) tty = ttyname(0); /* stdin */ if (!tty && isatty(1)) tty = ttyname(1); /* stdout */ @@ -258,13 +259,13 @@ goto err; } /* do we really need this check ? */ - if(strncmp(tty,option.consolename,strlen(option.consolename)-1) - || !isdigit(tty[strlen(option.consolename)-1])) { - gpm_report(GPM_PR_ERR,"strncmp/isdigit/option.consolename failed"); + if(strncmp(tty,consolename,strlen(consolename)-1) + || !isdigit(tty[strlen(consolename)-1])) { + gpm_report(GPM_PR_ERR,"strncmp/isdigit/consolename failed"); goto err; } - conn->vc=atoi(&tty[strlen(option.consolename)-1]); + conn->vc=atoi(&tty[strlen(consolename)-1]); } if (gpm_consolefd == -1) @@ -272,6 +273,8 @@ gpm_report(GPM_PR_ERR,GPM_MESS_DOUBLE_S,tty,strerror(errno)); goto err; } + + if (flag > 0) free(tty); } new->info=*conn; diff -urN gpm-1.20.1/src/lib/tools.c gpm/src/lib/tools.c --- gpm-1.20.1/src/lib/tools.c 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/lib/tools.c 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,93 @@ +/* + * tools.c - tools which are needed by client and server + * + * Copyright (c) 2001 Nico Schottelius + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#include /* NULL */ +#include +#include +#include /* these three are */ +#include /* needed for */ +#include /* stat() */ + +#include "headers/gpmInt.h" /* only used for some defines */ +#include "headers/message.h" + +/***************************************************************************** + * check, whether devfs is used or not. + * See /usr/src/linux/Documentation/filesystems/devfs/ for details. + * Returns: the name of the console (/dev/tty0 or /dev/vc/0) + *****************************************************************************/ +char *Gpm_get_console( void ) +{ + + char *back = NULL, *tmp = NULL; + struct stat buf; + + /* first try the devfs device, because in the next time this will be + * the preferred one. If that fails, take the old console */ + + /* Check for open new console */ + if (stat(GPM_DEVFS_CONSOLE,&buf) == 0) + tmp = GPM_DEVFS_CONSOLE; + + /* Failed, try OLD console */ + else if(stat(GPM_OLD_CONSOLE,&buf) == 0) + tmp = GPM_OLD_CONSOLE; + + if(tmp != NULL) + if((back = malloc(strlen(tmp) + sizeof(char)) ) != NULL) + strcpy(back,tmp); + + return(back); +} + +/* what's the english name for potenz ? */ +int Gpm_x_high_y(int base, int pot_y) +{ + int val = 1; + + if(pot_y == 0) val = 1; + else if(pot_y < 0) val = 0; /* ugly hack ;) */ + else while(pot_y > 0) { + val = val * base; + pot_y--; + } + return val; +} + +/* return characters needed to display int */ +int Gpm_cnt_digits(int number) +{ + /* 0-9 = 1 10^0 <-> (10^1)-1 + * 10 - 99 = 2 10^1 <-> (10^2)-1 + * 100 - 999 = 3 10^2 <-> (10^3)-1 + * 1000 - 9999 = 4 ... */ + + int ret = 0, num = 0; + + /* non negative, please */ + if(number < 0) number *= -1; + else if(number == 0) ret = 1; + else while(number > num) { + ret++; + num = (Gpm_x_high_y(10,ret) - 1); + } + + return(ret); +} diff -urN gpm-1.20.1/src/Makefile.in gpm/src/Makefile.in --- gpm-1.20.1/src/Makefile.in 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/Makefile.in 2003-10-02 01:22:42.000000000 -0500 @@ -12,15 +12,16 @@ include $(top_builddir)/Makefile.include # Main portion: regular build rules +MICESRC = mice.c twiddler.c synaptics.c @EVDEV_SRCS@ -GSRC = main.c gpm.c gpn.c mice.c special.c twiddler.c synaptics.c \ - startup.c server_tools.c +GSRC = main.c gpm.c gpn.c special.c startup.c server_tools.c console.c \ + selection.c client.c optparser.c $(MICESRC) -GOBJ = $(GSRC:.c=.o) report.o tools.o +GOBJ = $(GSRC:.c=.o) report.o -LSRC = lib/liblow.c lib/libhigh.c lib/libxtra.c lib/report-lib.c +LSRC = lib/liblow.c lib/libhigh.c lib/libxtra.c lib/report-lib.c lib/tools.c -LOBJ = $(LSRC:.c=.o) tools.o @CURSES_OBJS@ +LOBJ = $(LSRC:.c=.o) @CURSES_OBJS@ PICS = $(LOBJ:.o=.lo) @@ -143,7 +144,7 @@ $(CC) -I. @CPPFLAGS@ $(CPPFLAGS) @CFLAGS@ $(CFLAGS) -c -o $@.o $< $(CC) @LDFLAGS@ $(LDFLAGS) -o $@ $@.o @LIBS@ $(LIBS) lib/libgpm.a -prog/mouse-test: mice.o twiddler.o synaptics.o +prog/mouse-test: $(MICESRC:.c=.o) console.o optparser.o $(PROG): lib/libgpm.so lib/@SHLIB@ lib/libgpm.a diff -urN gpm-1.20.1/src/mice.c gpm/src/mice.c --- gpm-1.20.1/src/mice.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/mice.c 2003-10-02 01:22:42.000000000 -0500 @@ -46,15 +46,11 @@ #include #include #include -#include -#include #include #include #include -#include #include /* stat() */ -#include /* select() */ #include /* MAJOR */ #include @@ -72,135 +68,40 @@ #include "headers/gpmInt.h" +#include "headers/console.h" #include "headers/twiddler.h" #include "headers/synaptics.h" #include "headers/message.h" - -/*========================================================================*/ -/* Parsing argv: helper dats struct function (should they get elsewhere?) */ -/*========================================================================*/ - -enum argv_type { - ARGV_BOOL = 1, - ARGV_INT, /* "%i" */ - ARGV_DEC, /* "%d" */ - ARGV_STRING, - /* other types must be added */ - ARGV_END = 0 -}; - -typedef struct argv_helper { - char *name; - enum argv_type type; - union u { - int *iptr; /* used for int and bool arguments */ - char **sptr; /* used for string arguments, by strdup()ing the value */ - } u; - int value; /* used for boolean arguments */ -} argv_helper; - -static int parse_argv(argv_helper *info, int argc, char **argv) -{ - int i, j = 0, errors = 0; - long l; - argv_helper *p; - char *s, *t; - int base = 0; /* for strtol */ - - - for (i=1; itype != ARGV_END; p++) { - j = strlen(p->name); - if (strncmp(p->name, argv[i], j)) - continue; - if (isalnum(argv[i][j])) - continue; - break; - } - if (p->type == ARGV_END) { /* not found */ - fprintf(stderr, "%s: Uknown option \"%s\" for pointer \"%s\"\n", - option.progname, argv[i], argv[0]); - errors++; - continue; - } - /* Found. Look for trailing stuff, if any */ - s = argv[i]+j; - while (*s && isspace(*s)) s++; /* skip spaces */ - if (*s == '=') s++; /* skip equal */ - while (*s && isspace(*s)) s++; /* skip other spaces */ - - /* Now parse what s is */ - switch(p->type) { - case ARGV_BOOL: - if (*s) { - gpm_report(GPM_PR_ERR,GPM_MESS_OPTION_NO_ARG,option.progname,p->name,s); - errors++; - } - *(p->u.iptr) = p->value; - break; - - case ARGV_DEC: - base = 10; /* and fall through */ - case ARGV_INT: - l = strtol(s, &t, base); - if (*t) { - gpm_report(GPM_PR_ERR,GPM_MESS_INVALID_ARG, option.progname, s, p->name); - errors++; - break; - } - *(p->u.iptr) = (int)l; - break; - - case ARGV_STRING: - *(p->u.sptr) = strdup(s); - break; - - case ARGV_END: /* let's please "-Wall" */ - break; - } - } /* for i in argc */ - if (errors) gpm_report(GPM_PR_ERR,GPM_MESS_CONT_WITH_ERR, option.progname); - return errors; -} - -/*========================================================================*/ -/* Provide a common error engine by parsing with an empty option-set */ -/*========================================================================*/ -static volatile int check_no_argv(int argc, char **argv) -{ - static argv_helper optioninfo[] = { - {"", ARGV_END} - }; - return parse_argv(optioninfo, argc, argv); -} +#include "headers/optparser.h" /*========================================================================*/ /* Parse the "old" -o options */ /*========================================================================*/ -static int option_modem_lines(int fd, int argc, char **argv) +static int option_modem_lines(int fd, char *proto, char *opts) { - static unsigned int err, lines, reallines; + static unsigned int lines, reallines; + static struct option_helper optioninfo[] = { + {"dtr", OPT_BOOL, u: {iptr: &lines}, value: TIOCM_DTR}, + {"rts", OPT_BOOL, u: {iptr: &lines}, value: TIOCM_RTS}, + {"both", OPT_BOOL, u: {iptr: &lines}, value: TIOCM_DTR | TIOCM_RTS}, + {"", OPT_END} + }; - static argv_helper optioninfo[] = { - {"dtr", ARGV_BOOL, u: {iptr: &lines}, value: TIOCM_DTR}, - {"rts", ARGV_BOOL, u: {iptr: &lines}, value: TIOCM_RTS}, - {"both", ARGV_BOOL, u: {iptr: &lines}, value: TIOCM_DTR | TIOCM_RTS}, - {"", ARGV_END} - }; + int rslt = parse_options(proto, opts, ',', optioninfo); - if (argc<2) return 0; - if (argc > 2) { - gpm_report(GPM_PR_ERR,GPM_MESS_TOO_MANY_OPTS,option.progname, argv[0]); + if (rslt < 0) { + errno = EINVAL; + return -1; + } else if (rslt > 1) { + gpm_report(GPM_PR_ERR, GPM_MESS_TOO_MANY_OPTS, option.progname, proto); errno = EINVAL; /* used by gpm_oops(), if the caller reports failure */ return -1; + } else if (rslt == 1) { + /* ok, move the lines */ + ioctl(fd, TIOCMGET, &reallines); + reallines &= ~lines; + ioctl(fd, TIOCMSET, &reallines); } - err = parse_argv(optioninfo, argc, argv); - if(err) return 0; /* a message has been printed, but go on as good */ - - /* ok, move the lines */ - ioctl(fd, TIOCMGET, &reallines); - reallines &= ~lines; - ioctl(fd, TIOCMSET, &reallines); return 0; } @@ -233,28 +134,12 @@ /*========================================================================*/ #ifdef HAVE_LINUX_INPUT_H -static int M_evdev (Gpm_Event * state, unsigned char *data) -{ - struct input_event thisevent; - (void) memcpy (&thisevent, data, sizeof (struct input_event)); - if (thisevent.type == EV_REL) { - if (thisevent.code == REL_X) - state->dx = (signed char) thisevent.value; - else if (thisevent.code == REL_Y) - state->dy = (signed char) thisevent.value; - } else if (thisevent.type == EV_KEY) { - switch(thisevent.code) { - case BTN_LEFT: state->buttons ^= GPM_B_LEFT; break; - case BTN_MIDDLE: state->buttons ^= GPM_B_MIDDLE; break; - case BTN_RIGHT: state->buttons ^= GPM_B_RIGHT; break; - case BTN_SIDE: state->buttons ^= GPM_B_MIDDLE; break; - } - } - return 0; -} +/* defined in evdev.c */ +extern int M_evdev(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state); +extern int I_evdev(struct micedev *dev, struct miceopt *opt, Gpm_Type *type); #endif /* HAVE_LINUX_INPUT_H */ -static int M_ms(Gpm_Event *state, unsigned char *data) +static int M_ms(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* * some devices report a change of middle-button state by @@ -273,7 +158,7 @@ return 0; } -static int M_ms_plus(Gpm_Event *state, unsigned char *data) +static int M_ms_plus(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { static unsigned char prev=0; @@ -293,7 +178,7 @@ return 0; } -static int M_ms_plus_lr(Gpm_Event *state, unsigned char *data) +static int M_ms_plus_lr(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* * Same as M_ms_plus but with an addition by Edmund GRIMLEY EVANS @@ -329,19 +214,19 @@ int SUMMA_BORDER=100; int summamaxx,summamaxy; char summaid=-1; -static int M_summa(Gpm_Event *state, unsigned char *data) +static int M_summa(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { int x, y; x = ((data[2]<<7) | data[1])-SUMMA_BORDER; if (x<0) x=0; if (x>summamaxx) x=summamaxx; - state->x = (x * win.ws_col / summamaxx); + state->x = (x * console.max_x / summamaxx); realposx = (x * 16383 / summamaxx); y = ((data[4]<<7) | data[3])-SUMMA_BORDER; if (y<0) y=0; if (y>summamaxy) y=summamaxy; - state->y = 1 + y * (win.ws_row-1)/summamaxy; + state->y = 1 + y * (console.max_y-1)/summamaxy; realposy = y * 16383 / summamaxy; state->buttons= @@ -396,7 +281,7 @@ /* 'Genitizer' (kw@dtek.chalmers.se 11/12/97) */ -static int M_geni(Gpm_Event *state, unsigned char *data) +static int M_geni(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* this is a little confusing. If we use the stylus, we * have three buttons (tip, lower, upper), and if @@ -419,7 +304,7 @@ /* m$ 'Intellimouse' (steveb 20/7/97) */ -static int M_ms3(Gpm_Event *state, unsigned char *data) +static int M_ms3(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->wdx = state->wdy = 0; state->buttons= ((data[0] & 0x20) >> 3) /* left */ @@ -470,7 +355,7 @@ } /* M_brw is a variant of m$ 'Intellimouse' the middle button is different */ -static int M_brw(Gpm_Event *state, unsigned char *data) +static int M_brw(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->buttons= ((data[0] & 0x20) >> 3) /* left */ | ((data[3] & 0x20) >> 4) /* middle */ @@ -491,7 +376,7 @@ return 0; } -static int M_bare(Gpm_Event *state, unsigned char *data) +static int M_bare(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* a bare ms protocol */ state->buttons= ((data[0] & 0x20) >> 3) | ((data[0] & 0x10) >> 4); @@ -500,7 +385,7 @@ return 0; } -static int M_sun(Gpm_Event *state, unsigned char *data) +static int M_sun(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->buttons= (~data[0]) & 0x07; state->dx= (signed char)(data[1]); @@ -508,7 +393,7 @@ return 0; } -static int M_msc(Gpm_Event *state, unsigned char *data) +static int M_msc(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->buttons= (~data[0]) & 0x07; state->dx= (signed char)(data[1]) + (signed char)(data[3]); @@ -558,7 +443,7 @@ } -static int M_logimsc(Gpm_Event *state, unsigned char *data) /* same as msc */ +static int M_logimsc(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->buttons= (~data[0]) & 0x07; state->dx= (signed char)(data[1]) + (signed char)(data[3]); @@ -566,7 +451,7 @@ return 0; } -static int M_mm(Gpm_Event *state, unsigned char *data) +static int M_mm(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->buttons= data[0] & 0x07; state->dx= (data[0] & 0x10) ? data[1] : - data[1]; @@ -574,7 +459,7 @@ return 0; } -static int M_logi(Gpm_Event *state, unsigned char *data) /* equal to mm */ +static int M_logi(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->buttons= data[0] & 0x07; state->dx= (data[0] & 0x10) ? data[1] : - data[1]; @@ -582,7 +467,7 @@ return 0; } -static int M_bm(Gpm_Event *state, unsigned char *data) /* equal to sun */ +static int M_bm(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { state->buttons= (~data[0]) & 0x07; state->dx= (signed char)data[1]; @@ -590,7 +475,7 @@ return 0; } -static int M_ps2(Gpm_Event *state, unsigned char *data) +static int M_ps2(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { static int tap_active=0; /* there exist glidepoint ps2 mice */ @@ -599,8 +484,8 @@ !!(data[0]&2) * GPM_B_RIGHT + !!(data[0]&4) * GPM_B_MIDDLE; - if (data[0]==0 && opt_glidepoint_tap) /* by default this is false */ - state->buttons = tap_active = opt_glidepoint_tap; + if (data[0]==0 && opt->glidepoint_tap) /* by default this is false */ + state->buttons = tap_active = opt->glidepoint_tap; else if (tap_active) { if (data[0]==8) state->buttons = tap_active = 0; @@ -623,10 +508,11 @@ state->dy= -((data[0] & 0x20) ? data[2]-256 : data[2]); else state->dy = 0; + return 0; } -static int M_imps2(Gpm_Event *state, unsigned char *data) +static int M_imps2(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { static int tap_active=0; /* there exist glidepoint ps2 mice */ @@ -636,8 +522,8 @@ state->buttons= ((data[0] & 1) << 2) /* left */ | ((data[0] & 6) >> 1); /* middle and right */ - if (data[0]==0 && opt_glidepoint_tap) // by default this is false - state->buttons = tap_active = opt_glidepoint_tap; + if (data[0]==0 && opt->glidepoint_tap) // by default this is false + state->buttons = tap_active = opt->glidepoint_tap; else if (tap_active) { if (data[0]==8) state->buttons = tap_active = 0; @@ -667,7 +553,7 @@ } -static int M_netmouse(Gpm_Event *state, unsigned char *data) +static int M_netmouse(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* Avoid these beasts if you can. They connect to normal PS/2 port, * but their protocol is one byte longer... So if you have notebook @@ -706,47 +592,45 @@ } /* standard ps2 */ -static Gpm_Type *I_ps2(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +int I_ps2(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { static unsigned char s[] = { 246, 230, 244, 243, 100, 232, 3, }; - write (fd, s, sizeof (s)); + write(dev->fd, s, sizeof (s)); usleep (30000); - tcflush (fd, TCIFLUSH); - return type; + tcflush (dev->fd, TCIFLUSH); + return 0; } -static Gpm_Type *I_netmouse(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_netmouse(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { unsigned char magic[6] = { 0xe8, 0x03, 0xe6, 0xe6, 0xe6, 0xe9 }; int i; - if (check_no_argv(argc, argv)) return NULL; + if (!check_no_options(type->name, opt->text, ',')) return -1; for (i=0; i<6; i++) { unsigned char c = 0; - write( fd, magic+i, 1 ); - read( fd, &c, 1 ); + write(dev->fd, magic+i, 1 ); + read(dev->fd, &c, 1 ); if (c != 0xfa) { gpm_report(GPM_PR_ERR,GPM_MESS_NETM_NO_ACK,c); - return NULL; + return -1; } } { unsigned char rep[3] = { 0, 0, 0 }; - read( fd, rep, 1 ); - read( fd, rep+1, 1 ); - read( fd, rep+2, 1 ); + read( dev->fd, rep, 1 ); + read( dev->fd, rep+1, 1 ); + read( dev->fd, rep+2, 1 ); if (rep[0] || (rep[1] != 0x33) || (rep[2] != 0x55)) { gpm_report(GPM_PR_ERR,GPM_MESS_NETM_INV_MAGIC, rep[0], rep[1], rep[2]); - return NULL; + return -1; } } - return type; + return 0; } #define GPM_B_BOTH (GPM_B_LEFT|GPM_B_RIGHT) -static int M_mman(Gpm_Event *state, unsigned char *data) +static int M_mman(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* * the damned MouseMan has 3/4 bytes packets. The extra byte @@ -784,7 +668,7 @@ mytype->getextra=1; } else { if (b & 0x2) prev |= GPM_B_MIDDLE; - if (b & 0x1) prev |= opt_glidepoint_tap; + if (b & 0x1) prev |= opt->glidepoint_tap; } } state->buttons=prev; @@ -828,7 +712,7 @@ #define IsA(m) ((WacomModell==(-1))? 0:!strcmp(#m,wcmodell[WacomModell].name)) -static int M_wacom(Gpm_Event *state, unsigned char *data) +static int M_wacom(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { static int ox=-1, oy; int x, y; @@ -878,8 +762,8 @@ if (WacomAbsoluteWanted) { /* Absolute Mode */ if (x>wmaxx) x=wmaxx; if (x<0) x=0; if (y>wmaxy) y=wmaxy; if (y<0) y=0; - state->x = (x * win.ws_col / wmaxx); - state->y = (y * win.ws_row / wmaxy); + state->x = (x * console.max_x / wmaxx); + state->y = (y * console.max_y / wmaxy); realposx = (x / wmaxx); /* this two lines come from the summa driver. */ realposy = (y / wmaxy); /* they seem to be buggy (always give zero). */ @@ -889,8 +773,8 @@ if( abs(x-ox)>(wmaxx/wcmodell[WacomModell].treshold) || abs(y-oy)>(wmaxy/wcmodell[WacomModell].treshold) ) ox=x; oy=y; - state->dx= (x-ox) / (wmaxx / win.ws_col / wcmodell[WacomModell].treshold); - state->dy= (y-oy) / (wmaxy / win.ws_row / wcmodell[WacomModell].treshold); + state->dx= (x-ox) / (wmaxx / console.max_x / wcmodell[WacomModell].treshold); + state->dy= (y-oy) / (wmaxy / console.max_y / wcmodell[WacomModell].treshold); } ox=x; oy=y; @@ -918,7 +802,7 @@ #define CAL_Y_MAX 0xF40 #define CAL_Y_SIZE (CAL_Y_MAX - CAL_Y_MIN) -static int M_calus(Gpm_Event *state, unsigned char *data) +static int M_calus(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { int x, y; @@ -932,12 +816,12 @@ state->dx = 0; state->dy = 0; state->x = x < CAL_X_MIN ? 0 - : x > CAL_X_MAX ? win.ws_col+1 - : (long)(x-CAL_X_MIN) * (long)(win.ws_col-1) / CAL_X_SIZE+2; + : x > CAL_X_MAX ? console.max_x+1 + : (long)(x-CAL_X_MIN) * (long)(console.max_x-1) / CAL_X_SIZE+2; - state->y = y < CAL_Y_MIN ? win.ws_row + 1 + state->y = y < CAL_Y_MIN ? console.max_y + 1 : y > CAL_Y_MAX ? 0 - : (long)(CAL_Y_MAX-y) * (long)win.ws_row / CAL_Y_SIZE + 1; + : (long)(CAL_Y_MAX-y) * (long)console.max_y / CAL_Y_SIZE + 1; realposx = x < CAL_X_MIN ? 0 : x > CAL_X_MAX ? 16384 @@ -950,7 +834,7 @@ return 0; } -static int M_calus_rel(Gpm_Event *state, unsigned char *data) +static int M_calus_rel(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { static int ox=-1, oy; int x, y; @@ -984,7 +868,7 @@ #define NCR_DELTA_X (NCR_RIGHT_X - NCR_LEFT_X) #define NCR_DELTA_Y (NCR_TOP_Y - NCR_BOTTOM_Y) -static int M_ncr(Gpm_Event *state, unsigned char *data) +static int M_ncr(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { int x,y; @@ -1002,14 +886,14 @@ state->x = x < NCR_LEFT_X ? 0 : x > NCR_RIGHT_X - ? win.ws_col+1 - : (long)(x-NCR_LEFT_X) * (long)(win.ws_col-1) / NCR_DELTA_X+2; + ? console.max_x+1 + : (long)(x-NCR_LEFT_X) * (long)(console.max_x-1) / NCR_DELTA_X+2; state->y = y < NCR_BOTTOM_Y - ? win.ws_row + 1 + ? console.max_y + 1 : y > NCR_TOP_Y ? 0 - : (long)(NCR_TOP_Y-y) * (long)win.ws_row / NCR_DELTA_Y + 1; + : (long)(NCR_TOP_Y-y) * (long)console.max_y / NCR_DELTA_Y + 1; realposx = x < NCR_LEFT_X ? 0 @@ -1026,7 +910,7 @@ return 0; } -static int M_twid(Gpm_Event *state, unsigned char *data) +static int M_twid(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { unsigned long message=0UL; int i,h,v; static int lasth, lastv, lastkey, key, lock=0, autorepeat=0; @@ -1144,7 +1028,7 @@ #ifdef HAVE_LINUX_JOYSTICK_H /* Joystick mouse emulation (David Given) */ -static int M_js(Gpm_Event *state, unsigned char *data) +static int M_js(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { struct JS_DATA_TYPE *jdata = (void*)data; static int centerx = 0; @@ -1193,21 +1077,21 @@ #endif /* have joystick.h */ /* Synaptics TouchPad mouse emulation (Henry Davies) */ -static int M_synaptics_serial(Gpm_Event *state, unsigned char *data) +static int M_synaptics_serial(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { - syn_process_serial_data (state, data); + syn_process_serial_data(dev->fd, state, data); return 0; } /* Synaptics TouchPad mouse emulation (Henry Davies) */ -static int M_synaptics_ps2(Gpm_Event *state, unsigned char *data) +static int M_synaptics_ps2(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { - syn_process_ps2_data(state, data); + syn_process_ps2_data(dev->fd, state, data); return 0; } -static int M_mtouch(Gpm_Event *state, unsigned char *data) +static int M_mtouch(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* * This is a simple decoder for the MicroTouch touch screen @@ -1219,8 +1103,8 @@ static int upx, upy; /* keep track of last finger-up place */ static struct timeval uptv, tv; /* time of last up, and down events */ - #define REAL_TO_XCELL(x) (x * win.ws_col / 0x3FFF) - #define REAL_TO_YCELL(y) (y * win.ws_row / 0x3FFF) + #define REAL_TO_XCELL(x) (x * console.max_x / 0x3FFF) + #define REAL_TO_YCELL(y) (y * console.max_y / 0x3FFF) #define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL)) #define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \ @@ -1245,7 +1129,7 @@ if (avgx < 0) { /* press event */ GET_TIME(tv); - if (DIF_TIME(uptv, tv) < opt_time) { + if (DIF_TIME(uptv, tv) < opt->time) { /* count as button press placed at finger-up pixel */ state->buttons = GPM_B_LEFT; realposx = avgx = upx; state->x = REAL_TO_XCELL(realposx); @@ -1287,7 +1171,7 @@ static int gunze_calib[4]; /* x0,y0 x1,y1 (measured at 1/8 and 7/8) */ static int gunze_debounce = 100; /* milliseconds: ignore shorter taps */ -static int M_gunze(Gpm_Event *state, unsigned char *data) +static int M_gunze(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* * This generates button-1 events, by now. @@ -1300,8 +1184,8 @@ static struct timeval uptv, tv; /* time of last up, and down events */ int timediff; - #define REAL_TO_XCELL(x) (x * win.ws_col / 0x3FFF) - #define REAL_TO_YCELL(y) (y * win.ws_row / 0x3FFF) + #define REAL_TO_XCELL(x) (x * console.max_x / 0x3FFF) + #define REAL_TO_YCELL(y) (y * console.max_y / 0x3FFF) #define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL)) #define DIF_TIME(t1,t2) ((t2.tv_sec -t1.tv_sec) *1000+ \ @@ -1350,7 +1234,7 @@ GET_TIME(tv); timediff = DIF_TIME(uptv, tv); released = 0; - if (timediff > gunze_debounce && timediff < opt_time) { + if (timediff > gunze_debounce && timediff < opt->time) { /* count as button press placed at finger-up pixel */ dragging = 1; state->buttons = GPM_B_LEFT; @@ -1399,7 +1283,7 @@ /* corresponding correction of the protocol identification */ /* mask) 2001/07/12 by Maciej W. Rozycki (macro@ds2.pg.gda.pl) */ -static int M_vsxxx_aa(Gpm_Event *state, unsigned char *data) +static int M_vsxxx_aa(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { /* The mouse protocol is as follows: @@ -1449,16 +1333,16 @@ /* Genius Wizardpad tablet -- Matt Kimball (mkimball@xmission.com) */ static int wizardpad_width = -1; static int wizardpad_height = -1; -static int M_wp(Gpm_Event *state, unsigned char *data) +static int M_wp(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state) { int x, y, pressure; x = ((data[4] & 0x1f) << 12) | ((data[3] & 0x3f) << 6) | (data[2] & 0x3f); - state->x = x * win.ws_col / (wizardpad_width * 40); + state->x = x * console.max_x / (wizardpad_width * 40); realposx = x * 16383 / (wizardpad_width * 40); y = ((data[7] & 0x1f) << 12) | ((data[6] & 0x3f) << 6) | (data[5] & 0x3f); - state->y = win.ws_row - y * win.ws_row / (wizardpad_height * 40) - 1; + state->y = console.max_y - y * console.max_y / (wizardpad_height * 40) - 1; realposy = 16383 - y * 16383 / (wizardpad_height * 40) - 1; pressure = ((data[9] & 0x0f) << 4) | (data[8] & 0x0f); @@ -1475,11 +1359,9 @@ /*========================================================================*/ /* Then, mice should be initialized */ -static Gpm_Type* I_empty(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_empty(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { - if (check_no_argv(argc, argv)) return NULL; - return type; + return check_no_options(type->name, opt->text, ',') ? 0 : -1; } static int setspeed(int fd,int old,int new,int needtowrite,unsigned short flags) @@ -1536,28 +1418,27 @@ {125,"Q"}, {1E9,"N"}, }; -static Gpm_Type* I_serial(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_serial(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { int i; unsigned char c; fd_set set; struct timeval timeout={0,0}; /* used when not debugging */ /* accept "-o dtr", "-o rts" and "-o both" */ - if (option_modem_lines(fd, argc, argv)) return NULL; + if (option_modem_lines(dev->fd, type->name, opt->text)) return -1; #ifndef DEBUG /* flush any pending input (thanks, Miguel) */ FD_ZERO(&set); for(i=0; /* always */ ; i++) { - FD_SET(fd,&set); - switch(select(fd+1,&set,(fd_set *)NULL,(fd_set *)NULL,&timeout/*zero*/)){ - case 1: if (read(fd,&c,1)==0) break; + FD_SET(dev->fd,&set); + switch(select(dev->fd+1,&set,(fd_set *)NULL,(fd_set *)NULL,&timeout/*zero*/)){ + case 1: if (read(dev->fd,&c,1)==0) break; case -1: continue; } break; } - if (type->fun==M_logimsc) write(fd, "QU", 2 ); + if (type->fun==M_logimsc) write(dev->fd, "QU", 2 ); #if 0 /* Did this ever work? -- I don't know, but should we not remove it, * if it doesn't work ??? -- Nico */ @@ -1570,7 +1451,7 @@ /* Non mman: change from any available speed to the chosen one */ for (i=9600; i>=1200; i/=2) - setspeed(fd, i, opt_baud, (type->fun != M_mman) /* write */, flags); + setspeed(dev->fd, i, opt->baud, (type->fun != M_mman) /* write */, type->flags); /* * reset the MouseMan/TrackMan to use the 3/4 byte protocol @@ -1578,51 +1459,50 @@ * Changed after 1.14; why not having "I_mman" now? */ if (type->fun==M_mman) { - setspeed(fd, 1200, 1200, 0, flags); /* no write */ - write(fd, "*X", 2); - setspeed(fd, 1200, opt_baud, 0, flags); /* no write */ - return type; + setspeed(dev->fd, 1200, 1200, 0, type->flags); /* no write */ + write(dev->fd, "*X", 2); + setspeed(dev->fd, 1200, opt->baud, 0, type->flags); /* no write */ + return 0; } if(type->fun==M_geni) { gpm_report(GPM_PR_INFO,GPM_MESS_INIT_GENI); - setspeed(fd, 1200, 9600, 1, flags); /* write */ - write(fd, ":" ,1); - write(fd, "E" ,1); /* setup tablet. relative mode, resolution... */ - write(fd, "@" ,1); /* setup tablet. relative mode, resolution... */ + setspeed(dev->fd, 1200, 9600, 1, type->flags); /* write */ + write(dev->fd, ":" ,1); + write(dev->fd, "E" ,1); /* setup tablet. relative mode, resolution... */ + write(dev->fd, "@" ,1); /* setup tablet. relative mode, resolution... */ } if (type->fun==M_synaptics_serial) { int packet_length; - setspeed (fd, 1200, 1200, 1, flags); - packet_length = syn_serial_init (fd); - setspeed (fd, 1200, 9600, 1, flags); + setspeed (dev->fd, 1200, 1200, 1, type->flags); + packet_length = syn_serial_init (dev->fd); + setspeed (dev->fd, 1200, 9600, 1, type->flags); type->packetlen = packet_length; type->howmany = packet_length; } if (type->fun==M_vsxxx_aa) { - setspeed (fd, 4800, 4800, 0, flags); /* no write */ - write(fd, "R", 1); /* initialize a mouse; without getting an "R" */ + setspeed (dev->fd, 4800, 4800, 0, type->flags); /* no write */ + write(dev->fd, "R", 1); /* initialize a mouse; without getting an "R" */ /* a mouse does not send a bytestream */ } - return type; + return 0; } -static Gpm_Type* I_logi(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_logi(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { int i; struct stat buf; int busmouse; - if (check_no_argv(argc, argv)) return NULL; + if (!check_no_options(type->name, opt->text, ',')) return -1; /* is this a serial- or a bus- mouse? */ - if(fstat(fd,&buf)==-1) gpm_report(GPM_PR_OOPS,GPM_MESS_FSTAT); + if(fstat(dev->fd,&buf)==-1) gpm_report(GPM_PR_OOPS,GPM_MESS_FSTAT); i=MAJOR(buf.st_rdev); /* I don't know why this is herein, but I remove it. I don't think a @@ -1635,21 +1515,20 @@ type->howmany = busmouse ? 3 : 1; /* change from any available speed to the chosen one */ - for (i=9600; i>=1200; i/=2) setspeed(fd, i, opt_baud, 1 /* write */, flags); + for (i=9600; i>=1200; i/=2) setspeed(dev->fd, i, opt->baud, 1 /* write */, type->flags); /* this stuff is peculiar of logitech mice, also for the serial ones */ - write(fd, "S", 1); - setspeed(fd, opt_baud, opt_baud, 1 /* write */, + write(dev->fd, "S", 1); + setspeed(dev->fd, opt->baud, opt->baud, 1 /* write */, CS8 |PARENB |PARODD |CREAD |CLOCAL |HUPCL); /* configure the sample rate */ - for (i=0;opt_sample<=sampletab[i].sample;i++) ; - write(fd,sampletab[i].code,1); - return type; + for (i=0;opt->sample<=sampletab[i].sample;i++) ; + write(dev->fd,sampletab[i].code,1); + return 0; } -static Gpm_Type *I_wacom(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_wacom(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { /* wacom graphire tablet */ #define UD_RESETBAUD "\r$" /* reset baud rate to default (wacom V) */ @@ -1664,19 +1543,19 @@ { /* Init Wacom communication; this is modified from xf86Wacom.so module */ /* Set speed to 19200 */ - setspeed (fd, 1200, 19200, 0, B19200|CS8|CREAD|CLOCAL|HUPCL); + setspeed (dev->fd, 1200, 19200, 0, B19200|CS8|CREAD|CLOCAL|HUPCL); /* Send Reset Baudrate Command */ - write(fd, UD_RESETBAUD, strlen(UD_RESETBAUD)); + write(dev->fd, UD_RESETBAUD, strlen(UD_RESETBAUD)); usleep(250000); /* Send Reset Command */ - write(fd, UD_RESET, strlen(UD_RESET)); + write(dev->fd, UD_RESET, strlen(UD_RESET)); usleep(75000); /* Set speed to 9600bps */ - setspeed (fd, 1200, 9600, 0, B9600|CS8|CREAD|CLOCAL|HUPCL); + setspeed (dev->fd, 1200, 9600, 0, B9600|CS8|CREAD|CLOCAL|HUPCL); /* Send Reset Command */ - write(fd, UD_RESET, strlen(UD_RESET)); + write(dev->fd, UD_RESET, strlen(UD_RESET)); usleep(250000); - write(fd, UD_STOP, strlen(UD_STOP)); + write(dev->fd, UD_STOP, strlen(UD_STOP)); usleep(100000); } @@ -1690,7 +1569,7 @@ struct timeval timeout; fd_set readfds; int err; - FD_ZERO(&readfds); FD_SET(fd, &readfds); + FD_ZERO(&readfds); FD_SET(dev->fd, &readfds); timeout.tv_sec = 0; timeout.tv_usec = 200000; err = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); return((err>0)?1:err); @@ -1706,11 +1585,11 @@ * Get Data to buffer until full or timeout. * Give back 0 for timeout and !0 for buffer full */ - if (cmd) write(fd,cmd,strlen(cmd)); + if (cmd) write(dev->fd,cmd,strlen(cmd)); memset(buffer,0,sizeof(buffer)); p=buffer; err=wait_wacom(); while (err != -1 && err && (p-buffer)<(sizeof(buffer)-1)) { - p+= read(fd,p,(sizeof(buffer)-1)-(p-buffer)); + p+= read(dev->fd,p,(sizeof(buffer)-1)-(p-buffer)); err=wait_wacom(); } /* return 1 for buffer full */ @@ -1728,13 +1607,14 @@ */ /* accept boolean options absolute and relative */ - static argv_helper optioninfo[] = { - {"absolute", ARGV_BOOL, u: {iptr: &WacomAbsoluteWanted}, value: !0}, - {"relative", ARGV_BOOL, u: {iptr: &WacomAbsoluteWanted}, value: 0}, - {"", ARGV_END} + static struct option_helper optioninfo[] = { + {"absolute", OPT_BOOL, u: {iptr: &WacomAbsoluteWanted}, value: !0}, + {"relative", OPT_BOOL, u: {iptr: &WacomAbsoluteWanted}, value: 0}, + {"", OPT_END} }; - parse_argv(optioninfo, argc, argv); - type->absolute = WacomAbsoluteWanted; + + parse_options(type->name, opt->text, ',', optioninfo); + opt->absolute = WacomAbsoluteWanted; reset_wacom(); /* "Flush" input queque */ @@ -1756,7 +1636,7 @@ } if(WacomModell >= (sizeof(wcmodell) / sizeof(struct WC_MODELL))) WacomModell=-1; - gpm_report(GPM_PR_INFO,GPM_MESS_WACOM_MOD, type->absolute? 'A':'R', + gpm_report(GPM_PR_INFO,GPM_MESS_WACOM_MOD, opt->absolute? 'A':'R', (WacomModell==(-1))? "Unknown" : wcmodell[WacomModell].name, buffer+2); @@ -1767,24 +1647,23 @@ wmaxx = (wmaxx-wcmodell[WacomModell].border); wmaxy = (wmaxy-wcmodell[WacomModell].border); } - write(fd,UD_SENDCOORDS,4); + write(dev->fd,UD_SENDCOORDS,4); - return type; + return 0; } -static Gpm_Type *I_pnp(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_pnp(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { struct termios tty; /* accept "-o dtr", "-o rts" and "-o both" */ - if (option_modem_lines(fd, argc, argv)) return NULL; + if (option_modem_lines(dev->fd, type->name, opt->text)) return -1; /* * Just put the device to 1200 baud. Thanks to Francois Chastrette * for his great help and debugging with his own pnp device. */ - tcgetattr(fd, &tty); + tcgetattr(dev->fd, &tty); tty.c_iflag = IGNBRK | IGNPAR; tty.c_oflag = 0; @@ -1792,15 +1671,15 @@ tty.c_line = 0; tty.c_cc[VTIME] = 0; tty.c_cc[VMIN] = 1; - tty.c_cflag = flags | B1200; - tcsetattr(fd, TCSAFLUSH, &tty); /* set parameters */ + tty.c_cflag = type->flags | B1200; + tcsetattr(dev->fd, TCSAFLUSH, &tty); /* set parameters */ /* * Don't read the silly initialization string. I don't want to see * the vendor name: it is only propaganda, with no information. */ - return type; + return 0; } /* @@ -1848,8 +1727,7 @@ /* intellimouse, ps2 version: Ben Pfaff and Colin Plumb */ /* Autodetect: Steve Bennett */ -static Gpm_Type *I_imps2(int fd, unsigned short flags, struct Gpm_Type *type, - int argc, char **argv) +static int I_imps2(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { int id; static unsigned char basic_init[] = { GPM_AUX_ENABLE_DEV, GPM_AUX_SET_SAMPLE, 100 }; @@ -1857,36 +1735,36 @@ static unsigned char ps2_init[] = { GPM_AUX_SET_SCALE11, GPM_AUX_ENABLE_DEV, GPM_AUX_SET_SAMPLE, 100, GPM_AUX_SET_RES, 3, }; /* Do a basic init in case the mouse is confused */ - write_to_mouse(fd, basic_init, sizeof (basic_init)); + write_to_mouse(dev->fd, basic_init, sizeof (basic_init)); /* Now try again and make sure we have a PS/2 mouse */ - if (write_to_mouse(fd, basic_init, sizeof (basic_init)) != 0) { + if (write_to_mouse(dev->fd, basic_init, sizeof (basic_init)) != 0) { gpm_report(GPM_PR_ERR,GPM_MESS_IMPS2_INIT); - return(NULL); + return -1; } /* Try to switch to 3 button mode */ - if (write_to_mouse(fd, imps2_init, sizeof (imps2_init)) != 0) { + if (write_to_mouse(dev->fd, imps2_init, sizeof (imps2_init)) != 0) { gpm_report(GPM_PR_ERR,GPM_MESS_IMPS2_FAILED); - return(NULL); + return -1; } /* Read the mouse id */ - id = read_mouse_id(fd); + id = read_mouse_id(dev->fd); if (id == GPM_AUX_ID_ERROR) { gpm_report(GPM_PR_ERR,GPM_MESS_IMPS2_MID_FAIL); id = GPM_AUX_ID_PS2; } /* And do the real initialisation */ - if (write_to_mouse(fd, ps2_init, sizeof (ps2_init)) != 0) { + if (write_to_mouse(dev->fd, ps2_init, sizeof (ps2_init)) != 0) { gpm_report(GPM_PR_ERR,GPM_MESS_IMPS2_SETUP_FAIL); } if (id == GPM_AUX_ID_IMPS2) { /* Really an intellipoint, so initialise 3 button mode (4 byte packets) */ gpm_report(GPM_PR_INFO,GPM_MESS_IMPS2_AUTO); - return type; + return 0; } if (id != GPM_AUX_ID_PS2) { gpm_report(GPM_PR_ERR,GPM_MESS_IMPS2_BAD_ID, id); @@ -1894,69 +1772,64 @@ else gpm_report(GPM_PR_INFO,GPM_MESS_IMPS2_PS2); for (type=mice; type->fun; type++) - if (strcmp(type->name, "ps2") == 0) return(type); + if (strcmp(type->name, "ps2") == 0) return 0; /* ps2 was not found!!! */ - return(NULL); + return -1; } /* * This works with Dexxa Optical Mouse, but because in X same initstring * is named ExplorerPS/2 so I named it in the same way. */ -static Gpm_Type *I_exps2(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_exps2(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { static unsigned char s1[] = { 243, 200, 243, 200, 243, 80, }; - if (check_no_argv(argc, argv)) return NULL; + if (!check_no_options(type->name, opt->text, ',')) return -1; - write (fd, s1, sizeof (s1)); + write (dev->fd, s1, sizeof (s1)); usleep (30000); - tcflush (fd, TCIFLUSH); - return type; + tcflush (dev->fd, TCIFLUSH); + return 0; } -static Gpm_Type *I_twid(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_twid(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { - if (check_no_argv(argc, argv)) return NULL; + if (!check_no_options(type->name, opt->text, ',')) return -1; - if (twiddler_key_init() != 0) return NULL; + if (twiddler_key_init() != 0) return -1; /* * the twiddler is a serial mouse: just drop dtr * and run at 2400 (unless specified differently) */ - if(opt_baud==DEF_BAUD) opt_baud = 2400; - argv[1] = "dtr"; /* argv[1] is guaranteed to be NULL (this is dirty) */ - return I_serial(fd, flags, type, argc, argv); + if (opt->baud == DEF_BAUD) opt->baud = 2400; + opt->text = "dtr"; + return I_serial(dev, opt, type); } -static Gpm_Type *I_calus(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_calus(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { - if (check_no_argv(argc, argv)) return NULL; + if (!check_no_options(type->name, opt->text, ',')) return -1; - if (opt_baud == 1200) opt_baud=9600; /* default to 9600 */ - return I_serial(fd, flags, type, argc, argv); + if (opt->baud == 1200) opt->baud = 9600; /* default to 9600 */ + return I_serial(dev, opt, type); } /* synaptics touchpad, ps2 version: Henry Davies */ -static Gpm_Type *I_synps2(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_synps2(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { - syn_ps2_init (fd); - return type; + syn_ps2_init (dev->fd); + return 0; } -static Gpm_Type *I_summa(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_summa(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { void resetsumma() { - write(fd,0,1); /* Reset */ + write(dev->fd,0,1); /* Reset */ usleep(400000); /* wait */ } int waitsumma() @@ -1964,7 +1837,7 @@ struct timeval timeout; fd_set readfds; int err; - FD_ZERO(&readfds); FD_SET(fd, &readfds); + FD_ZERO(&readfds); FD_SET(dev->fd, &readfds); timeout.tv_sec = 0; timeout.tv_usec = 200000; err = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); return(err); @@ -1987,34 +1860,34 @@ char GEN_MODELL=0x7f; /* Set speed to 9600bps */ - setspeed (fd, 1200, 9600, 1, B9600|CS8|CREAD|CLOCAL|HUPCL|PARENB|PARODD); + setspeed (dev->fd, 1200, 9600, 1, B9600|CS8|CREAD|CLOCAL|HUPCL|PARENB|PARODD); resetsumma(); - write(fd, SS_PROMPT_MODE, strlen(SS_PROMPT_MODE)); + write(dev->fd, SS_PROMPT_MODE, strlen(SS_PROMPT_MODE)); if (strstr(type->name,"acecad")!=NULL) summaid=11; if (summaid<0) { /* Summagraphics test */ /* read the Summa Firm-ID */ - write(fd, SS_FIRMID, strlen(SS_FIRMID)); + write(dev->fd, SS_FIRMID, strlen(SS_FIRMID)); err=waitsumma(); if (!((err == -1) || (!err))) { summaid=10; /* Original Summagraphics */ - read(fd, buffer, 255); /* Read Firm-ID */ + read(dev->fd, buffer, 255); /* Read Firm-ID */ } } if (summaid<0) { /* Genius-test */ resetsumma(); - write(fd,GEN_MMSERIES,1); - write(fd,&GEN_MODELL,1); /* Read modell */ + write(dev->fd,GEN_MMSERIES,1); + write(dev->fd,&GEN_MODELL,1); /* Read modell */ err=waitsumma(); if (!((err == -1) || (!err))) { /* read Genius-ID */ err=waitsumma(); if (!((err == -1) || (!err))) { err=waitsumma(); if (!((err == -1) || (!err))) { - read(fd,&config,1); + read(dev->fd,&config,1); summaid=(config[0] & 224) >> 5; /* genius tablet-id (0-7)*/ } } @@ -2024,30 +1897,29 @@ /* unknown tablet ?*/ if ((summaid<0) || (summaid==11)) { resetsumma(); - write(fd, SS_BINARY_FMT SS_PROMPT_MODE, 3); + write(dev->fd, SS_BINARY_FMT SS_PROMPT_MODE, 3); } /* read tablet size */ err=waitsumma(); - if (!((err == -1) || (!err))) read(fd,buffer,sizeof(buffer)); - write(fd,SS_READCONFIG,1); - read(fd,&config,5); + if (!((err == -1) || (!err))) read(dev->fd,buffer,sizeof(buffer)); + write(dev->fd,SS_READCONFIG,1); + read(dev->fd,&config,5); summamaxx=(config[2]<<7 | config[1])-(SUMMA_BORDER*2); summamaxy=(config[4]<<7 | config[3])-(SUMMA_BORDER*2); - write(fd,SS_ABSOLUTE SS_STREAM_MODE SS_UPPER_ORIGIN,3); - if (summaid<0) write(fd,SS_500LPI SS_TABID0 SS_BINARY_FMT,4); + write(dev->fd,SS_ABSOLUTE SS_STREAM_MODE SS_UPPER_ORIGIN,3); + if (summaid<0) write(dev->fd,SS_500LPI SS_TABID0 SS_BINARY_FMT,4); - return type; + return 0; } -static Gpm_Type *I_mtouch(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_mtouch(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { struct termios tty; /* Set speed to 9600bps (copied from I_summa, above :) */ - tcgetattr(fd, &tty); + tcgetattr(dev->fd, &tty); tty.c_iflag = IGNBRK | IGNPAR; tty.c_oflag = 0; tty.c_lflag = 0; @@ -2055,18 +1927,17 @@ tty.c_cc[VTIME] = 0; tty.c_cc[VMIN] = 1; tty.c_cflag = B9600|CS8|CREAD|CLOCAL|HUPCL; - tcsetattr(fd, TCSAFLUSH, &tty); + tcsetattr(dev->fd, TCSAFLUSH, &tty); /* Turn it to "format tablet" and "mode stream" */ - write(fd,"\001MS\r\n\001FT\r\n",10); + write(dev->fd,"\001MS\r\n\001FT\r\n",10); - return type; + return 0; } /* simple initialization for the gunze touchscreen */ -static Gpm_Type *I_gunze(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_gunze(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { struct termios tty; FILE *f; @@ -2075,29 +1946,29 @@ #define GUNZE_CALIBRATION_FILE SYSCONFDIR "/gpm-calibration" /* accept a few options */ - static argv_helper optioninfo[] = { - {"smooth", ARGV_INT, u: {iptr: &gunze_avg}}, - {"debounce", ARGV_INT, u: {iptr: &gunze_debounce}}, + static struct option_helper optioninfo[] = { + {"smooth", OPT_INT, u: {iptr: &gunze_avg}}, + {"debounce", OPT_INT, u: {iptr: &gunze_debounce}}, /* FIXME: add corner tapping */ - {"", ARGV_END} + {"", OPT_END} }; - parse_argv(optioninfo, argc, argv); + parse_options(type->name, opt->text, ',', optioninfo); /* check that the baud rate is valid */ - if (opt_baud == DEF_BAUD) opt_baud = 19200; /* force 19200 as default */ - if (opt_baud != 9600 && opt_baud != 19200) { - gpm_report(GPM_PR_ERR,GPM_MESS_GUNZE_WRONG_BAUD,option.progname, argv[0]); - opt_baud = 19200; + if (opt->baud == DEF_BAUD) opt->baud = 19200; /* force 19200 as default */ + if (opt->baud != 9600 && opt->baud != 19200) { + gpm_report(GPM_PR_ERR, GPM_MESS_GUNZE_WRONG_BAUD, option.progname, type->name); + opt->baud = 19200; } - tcgetattr(fd, &tty); + tcgetattr(dev->fd, &tty); tty.c_iflag = IGNBRK | IGNPAR; tty.c_oflag = 0; tty.c_lflag = 0; tty.c_line = 0; tty.c_cc[VTIME] = 0; tty.c_cc[VMIN] = 1; - tty.c_cflag = (opt_baud == 9600 ? B9600 : B19200) |CS8|CREAD|CLOCAL|HUPCL; - tcsetattr(fd, TCSAFLUSH, &tty); + tty.c_cflag = (opt->baud == 9600 ? B9600 : B19200) |CS8|CREAD|CLOCAL|HUPCL; + tcsetattr(dev->fd, TCSAFLUSH, &tty); /* FIXME: try to find some information about the device */ @@ -2120,19 +1991,18 @@ gunze_calib[0] = gunze_calib[1] = 128; /* 1/8 */ gunze_calib[2] = gunze_calib[3] = 896; /* 7/8 */ } - return type; + return 0; } /* Genius Wizardpad tablet -- Matt Kimball (mkimball@xmission.com) */ -static Gpm_Type *I_wp(int fd, unsigned short flags, - struct Gpm_Type *type, int argc, char **argv) +static int I_wp(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type) { struct termios tty; char tablet_info[256]; int count, pos, size; /* Set speed to 9600bps (copied from I_summa, above :) */ - tcgetattr(fd, &tty); + tcgetattr(dev->fd, &tty); tty.c_iflag = IGNBRK | IGNPAR; tty.c_oflag = 0; tty.c_lflag = 0; @@ -2140,22 +2010,22 @@ tty.c_cc[VTIME] = 0; tty.c_cc[VMIN] = 1; tty.c_cflag = B9600|CS8|CREAD|CLOCAL|HUPCL; - tcsetattr(fd, TCSAFLUSH, &tty); + tcsetattr(dev->fd, TCSAFLUSH, &tty); /* Reset the tablet (':') and put it in remote mode ('S') so that it isn't sending anything to us. */ - write(fd, ":S", 2); - tcsetattr(fd, TCSAFLUSH, &tty); + write(dev->fd, ":S", 2); + tcsetattr(dev->fd, TCSAFLUSH, &tty); /* Query the model of the tablet */ - write(fd, "T", 1); + write(dev->fd, "T", 1); sleep(1); - count = read(fd, tablet_info, 255); + count = read(dev->fd, tablet_info, 255); /* The tablet information should start with "KW" followed by the rest of the model number. If it isn't there, it probably isn't a WizardPad. */ - if(count < 2) return NULL; - if(tablet_info[0] != 'K' || tablet_info[1] != 'W') return NULL; + if(count < 2) return -1; + if(tablet_info[0] != 'K' || tablet_info[1] != 'W') return -1; /* Now, we want the width and height of the tablet. They should be of the form "X###" and "Y###" where ### is the number of units of @@ -2177,9 +2047,9 @@ } /* Set the tablet to stream mode with 180 updates per sec. ('O') */ - write(fd, "O", 1); + write(dev->fd, "O", 1); - return type; + return 0; } /*========================================================================*/ @@ -2241,7 +2111,7 @@ {0x80, 0x80, 0x80, 0x00}, 6, 6, 0, 0, 0}, #ifdef HAVE_LINUX_INPUT_H {"evdev", "Linux Event Device", - "", M_evdev, I_empty, STD_FLG, + "", M_evdev, I_evdev, STD_FLG, {0x00, 0x00, 0x00, 0x00} , 16, 16, 0, 0, NULL}, #endif /* HAVE_LINUX_INPUT_H */ {"exps2", "IntelliMouse Explorer (ps2) - 3 buttons, wheel unused", diff -urN gpm-1.20.1/src/optparser.c gpm/src/optparser.c --- gpm-1.20.1/src/optparser.c 1969-12-31 19:00:00.000000000 -0500 +++ gpm/src/optparser.c 2003-10-02 01:22:42.000000000 -0500 @@ -0,0 +1,155 @@ +/* + * optparser.c - GPM mouse options parser + * + * Copyright (C) 1993 Andrew Haylett + * Copyright (C) 1994-2000 Alessandro Rubini + * Copyright (C) 1998,1999 Ian Zimmerman + * Copyright (C) 2001,2002 Nico Schottelius + * Copyright (C) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#include +#include +#include +#include + +#include "headers/gpmInt.h" +#include "headers/message.h" +#include "headers/optparser.h" + +int parse_options(const char *proto, const char *opts, char sep, struct option_helper *info) +{ + int len, n, n_opts = 0, errors = 0; + long l; + struct option_helper *p; + char *s, *t, *str; + int base; /* for strtol */ + + for (p = info; p->type != OPT_END; p++) + p->present = 0; + + if (!opts) + return 0; + + if (!(str = strdup(opts))) + gpm_report(GPM_PR_OOPS, GPM_MESS_ALLOC_FAILED); + + /* split input string */ + for (s = str, n = 1; sep && (s = strchr(s, sep)); s++, n++) + *s = '\0'; + + for (s = str; n; s += strlen(s) + 1, n--) { + if (strlen(s) == 0) + continue; + + for (p = info; p->type != OPT_END; p++) { + len = strlen(p->name); + if (!strncmp(p->name, s, len) && !isalnum(s[len])) + break; + } + if (p->type == OPT_END) { /* not found */ + gpm_report(GPM_PR_ERR, "%s: Uknown option \"%s\" for protocol \"%s\"\n", + option.progname, s, proto); + errors++; + continue; + } + if (p->present) { + gpm_report(GPM_PR_ERR, "%s: option \"%s\" has already been seen, ignored (\"%s\")\n", + option.progname, s, proto); + continue; + } + p->present = 1; + n_opts++; + /* Found. Look for trailing stuff, if any */ + s += len; + while (*s && isspace(*s)) s++; /* skip spaces */ + if (*s == '=') s++; /* skip equal */ + while (*s && isspace(*s)) s++; /* skip other spaces */ + + /* Now parse what s is */ + base = 0; + switch(p->type) { + case OPT_BOOL: + if (*s) { + gpm_report(GPM_PR_ERR, GPM_MESS_OPTION_NO_ARG, option.progname, p->name, s); + errors++; + } + *(p->u.iptr) = p->value; + break; + + case OPT_DEC: + base = 10; /* and fall through */ + + case OPT_INT: + if (*s == '\0') { + gpm_report(GPM_PR_ERR, GPM_MESS_MISSING_ARG, option.progname, p->name); + } else { + l = strtol(s, &t, base); + if (*t) { + gpm_report(GPM_PR_ERR, GPM_MESS_INVALID_ARG, option.progname, s, p->name); + errors++; + break; + } + *(p->u.iptr) = (int)l; + } + break; + + case OPT_STRING: + if (*s == '\0') + gpm_report(GPM_PR_ERR, GPM_MESS_MISSING_ARG, option.progname, p->name); + else + *(p->u.sptr) = strdup(s); + break; + + case OPT_END: /* let's please "-Wall" */ + break; + } + } /* for i in argc */ + + free(str); + + if (errors) { + gpm_report(GPM_PR_ERR,GPM_MESS_CONT_WITH_ERR, option.progname); + return -errors; + } + return n_opts; +} + +int check_no_options(const char *proto, const char *opts, char sep) +{ + static struct option_helper info[] = { + { "", OPT_END } + }; + + return parse_options(proto, opts, sep, info) == 0; +} + +int is_option_present(struct option_helper *info, const char *name) +{ + struct option_helper *p; + int len; + + for (p = info; p->type != OPT_END; p++) { + len = strlen(p->name); + if (!strncmp(p->name, name, len) && !isalnum(name[len])) + return p->present; + } + + gpm_report(GPM_PR_ERR, "%s: Uknown option \"%s\"\n", option.progname, name); + return 0; +} + diff -urN gpm-1.20.1/src/prog/mouse-test.c gpm/src/prog/mouse-test.c --- gpm-1.20.1/src/prog/mouse-test.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/prog/mouse-test.c 2003-10-02 01:22:42.000000000 -0500 @@ -50,22 +50,9 @@ #define max(a,b) ((a)>(b)?(a):(b)) #endif - -/* this material is needed to pass options to mice.c */ -struct mouse_features mymouse = { - DEF_TYPE, DEF_DEV, DEF_SEQUENCE, - DEF_BAUD, DEF_SAMPLE, DEF_DELTA, DEF_ACCEL, DEF_SCALE, DEF_SCALE /*scaley*/, - DEF_TIME, DEF_CLUSTER, DEF_THREE, DEF_GLIDEPOINT_TAP, - (char *)NULL /* extra */, - (Gpm_Type *)NULL, - -1 /* fd */ -}; - /* and this is a workaroud */ struct winsize win; -struct mouse_features *which_mouse=&mymouse; - char *progname; char *consolename; int devcount=0; @@ -78,9 +65,9 @@ struct device { char *name; - int fd; + struct micedev mdev; struct device *next; -}; +} *devlist; static int message(void) { @@ -148,47 +135,48 @@ /*----------------------------------------------------------------------------- Place the description here. -----------------------------------------------------------------------------*/ -struct device **gpm_makedev(struct device **current, char *name) +void gpm_makedev(char *name) { - int fd; int modes; + struct device *dev; + int fd; + int modes; + if ((fd=open(name,O_RDWR|O_NONBLOCK))==-1) { perror(name); - return current; - } - modes = fcntl(fd, F_GETFL); - if (0 > fcntl(fd, F_SETFL, modes & ~O_NONBLOCK)) { - close(fd); - perror(name); - return current; + } else { + modes = fcntl(fd, F_GETFL); + if (0 > fcntl(fd, F_SETFL, modes & ~O_NONBLOCK)) { + close(fd); + perror(name); + } else { + dev = malloc(sizeof(struct device)); + if (!dev) gpm_report(GPM_PR_OOPS,"malloc()"); + dev->name=strdup(name); + if (!dev->name) gpm_report(GPM_PR_OOPS,"malloc()"); + dev->mdev.fd=fd; + dev->mdev.private = NULL; + dev->next=devlist; + devlist = dev; + devcount++; + } } - - *current=malloc(sizeof(struct device)); - if (!*current) gpm_report(GPM_PR_OOPS,"malloc()"); - (*current)->name=strdup(name); - if (!(*current)->name) gpm_report(GPM_PR_OOPS,"malloc()"); - (*current)->fd=fd; - (*current)->next=NULL; - devcount++; - return &((*current)->next); } -Gpm_Type *(*I_serial)(int fd, unsigned short flags, struct Gpm_Type *type, - int argc, char **argv); +int (*I_serial)(struct micedev *dev, struct miceopt *opt, struct Gpm_Type *type); /*----------------------------------------------------------------------------- Place the description here. -----------------------------------------------------------------------------*/ -int mousereopen(int oldfd, char *name, Gpm_Type *type) +int mousereopen(struct micedev *dev, char *name, Gpm_Type *type, struct miceopt *opts) { - int fd; if (!type) type=mice+1; /* ms */ - close(oldfd); + close(dev->fd); usleep(100000); - fd=open(name,O_RDWR); - if (fd < 0) gpm_report(GPM_PR_OOPS,name); - (*I_serial)(fd,type->flags,type,1,&type->name); /* ms initialization */ - return fd; + dev->fd=open(name,O_RDWR); + if (dev->fd < 0) gpm_report(GPM_PR_OOPS,name); + I_serial(dev, opts, type); /* ms initialization */ + return dev->fd; } int noneofthem(void) @@ -281,10 +269,9 @@ { struct item *list=NULL; struct item **nextitem; - struct device *devlist=NULL; - struct device **nextdev; + struct device *nextdev; Gpm_Type *cursor; - int i, mousefd; + int i; char *mousename; #define BUFLEN 512 char buf[BUFLEN]; @@ -294,6 +281,9 @@ int trial, readamount,packetsize,got; int baudtab[4]={1200,9600,4800,2400}; #define BAUD(i) (baudtab[(i)%4]) + struct miceopt opt = {0}; + struct micedev mdev = {0}; + consolename = Gpm_get_console(); if (!isatty(fileno(stdin))) { @@ -306,8 +296,8 @@ /* init the list of possible devices */ - for (nextdev=&devlist, i=1; inext)) { - printf("\t%s\r\n", (*nextdev)->name); - FD_SET((*nextdev)->fd,&devSet); - maxfd=max((*nextdev)->fd,maxfd); - (*I_serial)((*nextdev)->fd,(mice+1)->flags,mice+1, - 1, &(mice+1)->name); /* try ms mode */ + for (nextdev=devlist; nextdev; nextdev=nextdev->next) { + printf("\t%s\r\n", nextdev->name); + FD_SET(nextdev->mdev.fd, &devSet); + maxfd=max(nextdev->mdev.fd,maxfd); + I_serial(&nextdev->mdev, &opt, mice+1); /* try ms mode */ } savSet=devSet; @@ -379,43 +368,43 @@ getchar(); break; } - for (nextdev=&devlist; *nextdev; nextdev=&((*nextdev)->next)) - if (FD_ISSET((*nextdev)->fd,&devSet)) { + for (nextdev=devlist; nextdev; nextdev=nextdev->next) + if (FD_ISSET(nextdev->mdev.fd,&devSet)) { gotthem++; - FD_CLR((*nextdev)->fd,&savSet); - FD_SET((*nextdev)->fd,&gotSet); + FD_CLR(nextdev->mdev.fd,&savSet); + FD_SET(nextdev->mdev.fd,&gotSet); } } - if (gotthem) for (nextdev=&devlist; *nextdev; /* nothing */ ) { - cur=*nextdev; - if (!FD_ISSET(cur->fd,&gotSet)) { + if (gotthem) for (nextdev=devlist; nextdev; /* nothing */ ) { + cur=nextdev; + if (!FD_ISSET(cur->mdev.fd,&gotSet)) { printf("removing \"%s\" from the list\r\n",cur->name); - *nextdev=cur->next; - close(cur->fd); + nextdev=cur->next; + close(cur->mdev.fd); free(cur->name); free(cur); devcount--; } else { - read(cur->fd,buf,80); /* flush */ - nextdev=&(cur->next); /* follow list */ + read(cur->mdev.fd,buf,80); /* flush */ + nextdev=cur->next; /* follow list */ } } } /* devcount>1 */ - mousefd=devlist->fd; + mdev=devlist->mdev; mousename=devlist->name; free(devlist); printf("\r\nOk, so your mouse device is \"%s\"\r\n",mousename); /* now close and reopen it, complete with initialization */ - opt_baud=BAUD(0); - mousefd=mousereopen(mousefd,mousename,NULL); - + opt.baud=BAUD(0); + mousereopen(&mdev, mousename, NULL,&opt); + FD_ZERO(&checkSet); - FD_SET(mousefd,&checkSet); + FD_SET(mdev.fd,&checkSet); FD_SET(fileno(stdin),&checkSet); - maxfd=max(mousefd,fileno(stdin)); + maxfd=max(mdev.fd, fileno(stdin)); /*====================================== Identify mouse type */ @@ -440,7 +429,7 @@ printf("\r\nNow please press and release your left mouse button,\r\n" "one time only\r\n\r\n"); - i=read(mousefd,buf,1); + i=read(mdev.fd, buf, 1); if (i==-1 && errno==EINVAL) readamount=3; else @@ -466,7 +455,7 @@ else nextitem=&(cur->next); } - read(mousefd,buf,BUFLEN); /* flush */ + read(mdev.fd, buf, BUFLEN); /* flush */ /*====================================== Packet size - second step */ @@ -484,12 +473,12 @@ while (packetsize==1) { int success3=0,success5=0; - opt_baud=BAUD(trial); - printf("\tBaud rate is %i\r\n",opt_baud); - mousefd=mousereopen(mousefd,mousename,NULL); + opt.baud=BAUD(trial); + printf("\tBaud rate is %i\r\n",opt.baud); + mousereopen(&mdev, mousename,NULL, &opt); printf("\r\n==> Detecting the packet size\r\n"); - got=eventlist(mousefd,buf,BUFLEN,GPM_B_LEFT,readamount); + got=eventlist(mdev.fd,buf,BUFLEN,GPM_B_LEFT,readamount); /* try three -- look at repeating arrays of 6 bytes */ for (i=0;ithis->proto)[0]) == (cur->this->proto)[1]) && ((buf[i+1]&(cur->this->proto)[2]) == (cur->this->proto)[3]) ) { packetheads++; - if ((*(cur->this->fun))(&event,buf+i)==-1) { + if ((*(cur->this->fun))(&mdev, &opt, buf+i, &event)==-1) { packetheads--; continue; } @@ -594,7 +582,7 @@ * First trial: remove the "-t ms" extension if spurious buttons come in */ - got=eventlist(mousefd,buf,BUFLEN,0,readamount); + got=eventlist(mdev.fd,buf,BUFLEN,0,readamount); pending=0; for (nextitem=&list; *nextitem; /* nothing */) { struct item *cur=*nextitem; @@ -604,7 +592,7 @@ for (i=0;ithis->proto)[0]) == (cur->this->proto)[1]) && ((buf[i+1]&(cur->this->proto)[2]) == (cur->this->proto)[3]) ) { - if ((*(cur->this->fun))(&event,buf+i)==-1) continue; + if ((*(cur->this->fun))(&mdev, &opt, buf+i, &event)==-1) continue; i+=packetsize-1; if (event.buttons) pending--; } @@ -624,8 +612,8 @@ */ printf("\r\n==> Looking for '-t mman'and enhanced ms\r\n"); - mousefd=mousereopen(mousefd,mousename, mice /* mman */); - got=eventlist(mousefd,buf,BUFLEN,GPM_B_MIDDLE,readamount); + mousereopen(&mdev, mousename, mice /* mman */, &opt); + got=eventlist(mdev.fd, buf, BUFLEN, GPM_B_MIDDLE, readamount); /* if it uses the 4-byte protocol, find it in a rude way */ for (pending=0,i=0;ithis->proto)[0]) == (cur->this->proto)[1]) && ((buf[i+1]&(cur->this->proto)[2]) == (cur->this->proto)[3]) ) { - if ((*(cur->this->fun))(&event,buf+i)==-1) continue; + if ((*(cur->this->fun))(&mdev,&opt,buf+i,&event)==-1) continue; i+=packetsize-1; if (event.buttons && event.buttons!=GPM_B_MIDDLE) pending--; if (event.buttons==GPM_B_MIDDLE) pending++; @@ -677,16 +665,16 @@ char *Xtognames[3]={"'ClearDTR' and 'ClearRTS'","'ClearDTR'","'ClearRTS'"}; int alllines,lines, index; - ioctl(mousefd, TIOCMGET, &alllines); + ioctl(mdev.fd, TIOCMGET, &alllines); printf("\r\nSome mice change protocol to three-buttons-aware if some\r\n" "\r\ncontrol lines are toggled after opening\r\n"); for (index=0;index<3;index++) { - mousereopen(mousefd,mousename,NULL); + mousereopen(&mdev, mousename, NULL, &opt); lines = alllines & ~toggle[index]; - ioctl(mousefd, TIOCMSET, &lines); + ioctl(mdev.fd, TIOCMSET, &lines); printf("\r\n==> Trying with '-o %s'\r\n",tognames[index]); - got=eventlist(mousefd,buf,BUFLEN,GPM_B_MIDDLE,readamount); + got=eventlist(mdev.fd, buf, BUFLEN, GPM_B_MIDDLE, readamount); /* if it uses the 5-byte protocol, find it in a rude way */ for (pending=0,i=0;i + * Copyright (C) 1994-1999 Alessandro Rubini + * Copyright (C) 1998 Ian Zimmerman + * Copyright (c) 2001,2002 Nico Schottelius + * Copyright (c) 2003 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + ********/ + +#include +#include +#include /* strerror(); ?!? */ +#include +#include /* select(); */ +#include /* time() */ +#include /* O_RDONLY */ +#include /* mkdir() */ +#include /* __u32 */ + +#include /* VT_GETSTATE */ +#include /* KDGETMODE */ +#include /* winsize */ + +#include "headers/gpmInt.h" +#include "headers/message.h" +#include "headers/console.h" +#include "headers/selection.h" + +struct sel_options sel_opts = { 0, 0, DEF_PTRDRAG }; +static time_t last_selection_time; + +/*-------------------------------------------------------------------*/ +static void selection_copy(int x1, int y1, int x2, int y2, int mode) +{ +/* + * The approach in "selection" causes a bus error when run under SunOS 4.1 + * due to alignment problems... + */ + unsigned char buf[6 * sizeof(short)]; + unsigned short *arg = (unsigned short *)buf + 1; + int fd; + + buf[sizeof(short) - 1] = 2; /* set selection */ + + arg[0] = (unsigned short)x1; + arg[1] = (unsigned short)y1; + arg[2] = (unsigned short)x2; + arg[3] = (unsigned short)y2; + arg[4] = (unsigned short)mode; + + if ((fd = open_console(O_WRONLY)) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN_CON); + + gpm_report(GPM_PR_DEBUG, "ctl %i, mode %i", (int)*buf, arg[4]); + if (ioctl(fd, TIOCLINUX, buf + sizeof(short) - 1) < 0) + gpm_report(GPM_PR_OOPS,GPM_MESS_IOCTL_TIOCLINUX); + close(fd); + + if (mode < 3) { + sel_opts.aged = 0; + last_selection_time = time(0); + } +} + +/*-------------------------------------------------------------------*/ +static void selection_paste(void) +{ + char c = 3; + int fd; + + if (!sel_opts.aged && + sel_opts.age_limit != 0 && + last_selection_time + sel_opts.age_limit < time(0)) { + sel_opts.aged = 1; + } + + if (sel_opts.aged) { + gpm_report(GPM_PR_DEBUG, GPM_MESS_SKIP_PASTE); + } else { + fd = open_console(O_WRONLY); + if (ioctl(fd, TIOCLINUX, &c) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_IOCTL_TIOCLINUX); + close(fd); + } +} + +/*-------------------------------------------------------------------*/ +void do_selection(Gpm_Event *event, int three_button_mode) +{ + static int x1 = 1, y1 = 1; + int x2, y2; + + x2 = event->x; y2 = event->y; + switch(GPM_BARE_EVENTS(event->type)) { + case GPM_MOVE: + if (x2 < 1) x2++; else if (x2 > console.max_x) x2--; + if (y2 < 1) y2++; else if (y2 > console.max_y) y2--; + selection_copy(x2, y2, x2, y2, 3); /* just highlight pointer */ + break; + + case GPM_DRAG: + if (event->buttons == GPM_B_LEFT) { + switch(event->margin) { /* fix margins */ + case GPM_TOP: x2 = 1; y2++; break; + case GPM_BOT: x2 = console.max_x; y2--; break; + case GPM_RGT: x2--; break; + case GPM_LFT: y2 <= y1 ? x2++ : (x2 = console.max_x, y2--); break; + default: break; + } + selection_copy(x1, y1, x2, y2, event->clicks); + if (event->clicks >= sel_opts.ptrdrag && !event->margin) /* pointer */ + selection_copy(x2, y2, x2, y2, 3); + } /* if */ + break; + + case GPM_DOWN: + switch (event->buttons) { + case GPM_B_LEFT: + x1 = x2; y1 = y2; + selection_copy(x1, y1, x2, y2, event->clicks); /* start selection */ + break; + + case GPM_B_MIDDLE: + selection_paste(); + break; + + case GPM_B_RIGHT: + if (three_button_mode == 1) + selection_copy(x1, y1, x2, y2, event->clicks); + else + selection_paste(); + break; + } + } /* switch above */ +} + +/*-------------------------------------------------------------------*/ +void selection_disable_paste(void) +{ + sel_opts.aged = 1; +} diff -urN gpm-1.20.1/src/server_tools.c gpm/src/server_tools.c --- gpm-1.20.1/src/server_tools.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/server_tools.c 2003-10-02 01:22:42.000000000 -0500 @@ -21,151 +21,80 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ********/ +#include +#include /* malloc() */ +#include + #include "headers/gpmInt.h" #include "headers/message.h" -#include /* malloc() */ +struct micetab *micelist; -/* DESCR: add this to the list of mice. initialization follows later */ -/* RETURN: - */ +/* DESCR: allocate a new mouse and to the list of mice. initialization follows later */ +/* RETURN: new mouse structure */ /* COMMENT: does error handling and exiting itself */ -void add_mouse(int type, char *value) +struct micetab *add_mouse(void) { - struct micetab *tmp = option.micelist; + struct micetab *mouse; - /* PREAMBLE for all work: */ - /* -m /dev/misc/psaux -t ps2 [ -o options ] */ + gpm_report(GPM_PR_DEBUG, "adding mouse device"); + if (!(mouse = malloc(sizeof(struct micetab)))) + gpm_report(GPM_PR_OOPS, GPM_MESS_NO_MEM); + + memset(mouse, 0, sizeof(struct micetab)); + + mouse->dev.timeout = -1; + + mouse->options.sequence = NULL; + mouse->options.sample = DEF_SAMPLE; + mouse->options.delta = DEF_DELTA; + mouse->options.accel = DEF_ACCEL; + mouse->options.scalex = DEF_SCALE; + mouse->options.scaley = DEF_SCALE; + mouse->options.time = DEF_TIME; + mouse->options.cluster = DEF_CLUSTER; + mouse->options.three_button = DEF_THREE; + mouse->options.glidepoint_tap = DEF_GLIDEPOINT_TAP; + mouse->options.text = NULL; - switch(type) { + mouse->next = micelist; + micelist = mouse; - /*---------------------------------------------------------------------*/ - /********************** -m mousedevice *********************************/ - /*---------------------------------------------------------------------*/ - - case GPM_ADD_DEVICE: - - /* first invocation */ - if(option.micelist == NULL) { - gpm_report(GPM_PR_DEBUG,"adding mouse device: %s",value); - option.micelist = (struct micetab *) malloc(sizeof(struct micetab)); - if(!option.micelist) gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM); - option.micelist->next = NULL; - option.micelist->device = value; - option.micelist->protocol = NULL; - option.micelist->options = NULL; - return; - } - - /* find actual mouse */ - while(tmp->device != NULL && tmp->protocol != NULL && tmp->next !=NULL) - tmp = tmp->next; - - gpm_report(GPM_PR_DEBUG,"finished searching"); - - /* found end of micelist, add new mouse */ - if(tmp->next == NULL && tmp->protocol != NULL) { - gpm_report(GPM_PR_DEBUG,"next mouse making"); - tmp->next = (struct micetab *) malloc(sizeof(struct micetab)); - if(!tmp) gpm_report(GPM_PR_OOPS,GPM_MESS_NO_MEM); - tmp->next = NULL; - tmp->device = value; - tmp->protocol = NULL; - tmp->options = NULL; - return; - } else gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV); - - //} else if(tmp->device != NULL && tmp->protocol == NULL) - // gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV); /* -m -m */ - - - break; - - /*---------------------------------------------------------------------*/ - /************************* -t type / protocol **************************/ - /*---------------------------------------------------------------------*/ - - case GPM_ADD_TYPE: - if(option.micelist == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV); - - /* skip to next mouse, where either device or protocol is missing */ - while(tmp->device != NULL && tmp->protocol != NULL && tmp->next !=NULL) - tmp = tmp->next; - - /* check whether device (-m) is there, if so, write protocol */ - if(tmp->device == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV); - else { - gpm_report(GPM_PR_DEBUG,"adding mouse type: %s",value); - tmp->protocol = value; - option.no_mice++; /* finally we got our mouse */ - } - - break; - - /*---------------------------------------------------------------------*/ - /*************************** -o options ********************************/ - /*---------------------------------------------------------------------*/ - - case GPM_ADD_OPTIONS: - if(option.micelist == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV); - - /* look for the last mouse */ - tmp = option.micelist; - while(tmp->next != NULL) tmp = tmp->next; - - /* if -m or -t are missing exit */ - if(tmp->device == NULL || tmp->protocol == NULL) - gpm_report(GPM_PR_OOPS,GPM_MESS_FIRST_DEV); - else { - gpm_report(GPM_PR_DEBUG,"adding mouse options: %s",value); - tmp->options = value; - } - break; - } + return mouse; } -/* DESCR: mice initialization. currently print mice. */ -/* RETURN: 0 - failed to init one or more devices - 1 - init was fine */ +/* DESCR: mice initialization. calls appropriate init functions. */ /* COMMENT: does error handling and exiting itself */ -int init_mice(struct micetab *micelist) +void init_mice(void) { - struct micetab *tmp = micelist; + struct micetab *mouse; + + for (mouse = micelist; mouse; mouse = mouse->next) { + if (!strcmp(mouse->device, "-")) + mouse->dev.fd = 0; /* use stdin */ + else if ((mouse->dev.fd = open(mouse->device, O_RDWR | O_NDELAY)) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN, mouse->device); - while(tmp != NULL) { /* there are still mice to init */ - gpm_report(GPM_PR_DEBUG,"initialize %s with proto %s",tmp->device,tmp->protocol); - if(tmp->options != NULL) { - gpm_report(GPM_PR_DEBUG,"and options %s",tmp->options); - } - tmp = tmp->next; + /* and then reset the flag */ + fcntl(mouse->dev.fd, F_SETFL, fcntl(mouse->dev.fd, F_GETFL) & ~O_NDELAY); + + /* init the device, and use the return value as new mouse type */ + if (mouse->type->init) + if (mouse->type->init(&mouse->dev, &mouse->options, mouse->type)) + gpm_report(GPM_PR_OOPS, GPM_MESS_MOUSE_INIT); } - - gpm_report(GPM_PR_DEBUG,"finished initialization"); - return 1; } /* DESCR: when leaving, we should reset mice to their normal state */ -/* RETURN: 0 - failed to reset one or more devices - 1 - reset was fine */ /* COMMENT: does error handling and exiting itself */ -int reset_mice(struct micetab *micelist) +void cleanup_mice(void) { - struct micetab *tmp = micelist; - struct micetab *end = tmp; - - while(tmp != NULL) { /* FIXME! I never get NULL, as free()d before */ - end = tmp; - while(tmp->next != NULL) { /* set end to the last mouse */ - end = tmp; - tmp = tmp->next; - } - - gpm_report(GPM_PR_DEBUG,"reset: %s with proto %s",end->device,end->protocol); - if(tmp->options != NULL) { - gpm_report(GPM_PR_DEBUG,"and options %s",end->options); - } - free(end); /* be clean() */ - tmp = micelist; /* reset to the first mice again */ + struct micetab *tmp; + + while ((tmp = micelist)) { + if (micelist->dev.private) + free(micelist->dev.private); + micelist = micelist->next; + free(tmp); } - - return 1; } diff -urN gpm-1.20.1/src/special.c gpm/src/special.c --- gpm-1.20.1/src/special.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/special.c 2003-10-02 01:22:42.000000000 -0500 @@ -37,6 +37,7 @@ #include #include "headers/gpmInt.h" +#include "headers/console.h" /* * This function is only called at button press, to avoid unnecessary @@ -78,7 +79,7 @@ return 1; /* devfs change */ - consolef=fopen(option.consolename,"w"); + consolef = fopen(console.device, "w"); if (!consolef) consolef=stderr; if (event->type & GPM_TRIPLE) /* just triggered: make noise and return */ { @@ -153,7 +154,7 @@ case 0: /* child */ close(0); close(1); close(2); open(GPM_NULL_DEV,O_RDONLY); /* stdin */ - open(option.consolename,O_WRONLY); /* stdout */ + open(console.device, O_WRONLY); /* stdout */ dup(1); /* stderr */ for (i=3;i /* strlen() */ #include /* errno */ #include /* unlink,geteuid */ +#include #include /* geteuid, mknod */ #include /* mknod */ #include /* mknod */ @@ -34,11 +35,13 @@ #include "headers/gpmInt.h" #include "headers/message.h" +#include "headers/console.h" +#include "headers/selection.h" /* what todo atexit */ static void gpm_exited(void) { - gpm_report(GPM_PR_DEBUG,GPM_MESS_REMOVE_FILES, GPM_NODE_PID, GPM_NODE_CTL); + gpm_report(GPM_PR_DEBUG, GPM_MESS_REMOVE_FILES, GPM_NODE_PID, GPM_NODE_CTL); unlink(GPM_NODE_PID); unlink(GPM_NODE_CTL); } @@ -48,34 +51,12 @@ extern struct options option; extern int errno; - int i,opt; - - static struct { - char *in; - char *out; - } seq[] = { - {"123","01234567"}, - {"132","02134657"}, - {"213","01452367"}, /* warning: these must be readable as integers... */ - {"231","02461357"}, - {"312","04152637"}, - {"321","04261537"}, - {NULL,NULL} - }; - /* basic settings */ option.run_status = GPM_RUN_STARTUP; /* 10,9,8,... let's go */ option.autodetect = 0; /* no mouse autodection */ option.progname = argv[0]; /* who we are */ - option.consolename = Gpm_get_console(); /* get consolename */ - - /* basic2: are not necessary for oops()ing, if not root */ - option.no_mice = 0; /* counts -m + -t */ - option.micelist = NULL; /* no mice found yet */ - option.repeater = 0; /* repeat data */ - option.repeater_type = NULL; /* type of */ - + get_console_name(); cmdline(argc, argv); /* parse command line */ if (geteuid() != 0) gpm_report(GPM_PR_OOPS,GPM_MESS_ROOT); /* root or exit */ @@ -87,54 +68,18 @@ /****************** OLD CODE from gpn.c ***********************/ openlog(option.progname, LOG_PID, - option.run_status != GPM_RUN_DEBUG ? LOG_DAEMON : LOG_USER); - loadlut(opt_lut); - - if (option.repeater) { - if(mkfifo(GPM_NODE_FIFO,0666) && errno!=EEXIST) - gpm_report(GPM_PR_OOPS,GPM_MESS_CREATE_FIFO,GPM_NODE_FIFO); - if((fifofd=open(GPM_NODE_FIFO, O_RDWR|O_NONBLOCK)) < 0) - gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN, GPM_NODE_FIFO); - } - - /* duplicate initialization */ - for (i=1; i <= 1+opt_double; i++) { - which_mouse=mouse_table+i; /* used to access options */ - if (opt_accel < 1) exit(usage("acceleration")); - if (opt_delta < 2) exit(usage("delta")); - if (strlen(opt_sequence) != 3 || atoi(opt_sequence)<100) - exit(usage("sequence")); - if (opt_glidepoint_tap > 3) exit(usage("glidepoint tap button")); - if (opt_glidepoint_tap) - opt_glidepoint_tap=GPM_B_LEFT >> (opt_glidepoint_tap-1); - - /* choose the sequence */ - for (opt=0; seq[opt].in && strcmp(seq[opt].in,opt_sequence); opt++) ; - if(!seq[opt].in) exit(usage("button sequence")); - opt_sequence=strdup(seq[opt].out); /* I can rewrite on it */ - - /* look for the mouse type */ - m_type = find_mouse_by_name(opt_type); - if (!m_type) /* not found */ - exit(M_listTypes()); - } + option.run_status != GPM_RUN_DEBUG ? LOG_DAEMON : LOG_USER); - /* Check repeater status */ - if (option.repeater) { - if (strcmp(option.repeater_type,"raw") == 0) - opt_rawrep = 1; - else { - /* look for the type */ - repeated_type = find_mouse_by_name(option.repeater_type); + console_load_lut(); - if(!repeated_type) exit(M_listTypes()); /* not found */ - - if (!(repeated_type->repeat_fun)) /* unsupported translation */ - gpm_report(GPM_PR_OOPS,GPM_MESS_NO_REPEAT,option.repeater_type); - } + if (repeater.raw || repeater.type) { + if (mkfifo(GPM_NODE_FIFO, 0666) && errno != EEXIST) + gpm_report(GPM_PR_OOPS, GPM_MESS_CREATE_FIFO, GPM_NODE_FIFO); + if ((repeater.fd = open(GPM_NODE_FIFO, O_RDWR|O_NONBLOCK)) < 0) + gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN, GPM_NODE_FIFO); } - if(option.run_status == GPM_RUN_STARTUP ) { /* else is debugging */ + if(option.run_status == GPM_RUN_STARTUP) { /* else is debugging */ /* goto background and become a session leader (Stefan Giessler) */ switch(fork()) { case -1: gpm_report(GPM_PR_OOPS,GPM_MESS_FORK_FAILED); /* error */ @@ -152,13 +97,63 @@ /* is changing to root needed, because of relative paths ? or can we just * remove and ignore it ?? FIXME */ if (chdir("/") < 0) gpm_report(GPM_PR_OOPS,GPM_MESS_CHDIR_FAILED); - - //return mouse_table[1].fd; /* the second is handled in the main() */ + atexit(gpm_exited); /* call gpm_exited at the end */ +} - /****************** OLD CODE from gpn.c END ***********************/ +/* itz Sat Sep 12 10:30:05 PDT 1998 this function used to mix two + completely different things; opening a socket to a running daemon + and checking that a running daemon existed. Ugly. */ +/* rewritten mostly on 20th of February 2002 - nico */ +void check_uniqueness(void) +{ + FILE *fp = 0; + int old_pid = -1; - init_mice(option.micelist); /* reads option.micelist */ - atexit(gpm_exited); /* call gpm_exited at the end */ + if ((fp = fopen(GPM_NODE_PID, "r")) != NULL) { + fscanf(fp, "%d", &old_pid); + if (kill(old_pid, 0) == -1) { + gpm_report(GPM_PR_INFO,GPM_MESS_STALE_PID, GPM_NODE_PID); + unlink(GPM_NODE_PID); + } else /* we are really running, exit asap! */ + gpm_report(GPM_PR_OOPS, GPM_MESS_ALREADY_RUN, old_pid); + } + /* now try to sign ourself */ + if ((fp = fopen(GPM_NODE_PID,"w")) != NULL) { + fprintf(fp,"%d\n",getpid()); + fclose(fp); + } else { + gpm_report(GPM_PR_OOPS,GPM_MESS_NOTWRITE,GPM_NODE_PID); + } +} +/* itz Sat Sep 12 10:55:51 PDT 1998 Added this as replacement for the + unwanted functionality in check_uniqueness. */ +void kill_gpm(void) +{ + int old_pid; + FILE* fp = fopen(GPM_NODE_PID, "r"); + + /* if we cannot find the old pid file, leave */ + if (fp == NULL) gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN, GPM_NODE_PID); + + /* else read the pid */ + if (fscanf(fp, "%d", &old_pid) != 1) + gpm_report(GPM_PR_OOPS, GPM_MESS_READ_PROB, GPM_NODE_PID); + fclose(fp); + + gpm_report(GPM_PR_DEBUG, GPM_MESS_KILLING, old_pid); + + /* first check if we run */ + if (kill(old_pid,0) == -1) { + gpm_report(GPM_PR_INFO, GPM_MESS_STALE_PID, GPM_NODE_PID); + unlink(GPM_NODE_PID); + } + /* then kill us (not directly, but the other instance ... ) */ + if (kill(old_pid, SIGTERM) == -1) + gpm_report(GPM_PR_OOPS, GPM_MESS_CANT_KILL, old_pid); + + gpm_report(GPM_PR_INFO, GPM_MESS_KILLED, old_pid); + exit(0); } + diff -urN gpm-1.20.1/src/synaptics.c gpm/src/synaptics.c --- gpm-1.20.1/src/synaptics.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/synaptics.c 2003-10-02 01:22:42.000000000 -0500 @@ -865,7 +865,7 @@ static int scrolling_speed_timer = 0; static int scrolling_amount_left = 0; /* Tells how much to scroll up or down */ - +static int mouse_fd; @@ -882,6 +882,7 @@ ** which makes reading the debug data harder, only dump the report if it is different ** than the previously dumped. */ +#if DEBUG_REPORTS static void tp_dump_report_data (report_type report, int edges, Gpm_Event* state) @@ -934,7 +935,7 @@ (multi_finger_pressure>4500 && multi_finger_xy>50000? 'f':' ')); } - +#endif /* syn_dump_info ** @@ -1158,8 +1159,8 @@ status = GPM_B_NOT_SET; break; case Reset_Touchpad_Action: - syn_ps2_reset(which_mouse->fd); - syn_ps2_absolute_mode(which_mouse->fd); + syn_ps2_reset(mouse_fd); + syn_ps2_absolute_mode(mouse_fd); status = GPM_B_NOT_SET; break; case Toggle_Four_Way_Button_Action: @@ -2950,10 +2951,8 @@ data [0],data [1],data [2],data [3],data [4],data [5]); if (reset_on_error_enabled) { - /* Hack to get the fd: which_mouse is the current mouse, - and as the synaptic code is called, it is the current mouse. */ - syn_ps2_reset(which_mouse->fd); - syn_ps2_absolute_mode(which_mouse->fd); + syn_ps2_reset(mouse_fd); + syn_ps2_absolute_mode(mouse_fd); } report->left = 0; @@ -3108,7 +3107,7 @@ ** ** Process the touchpad 6 byte report. */ -void syn_process_serial_data (Gpm_Event *state, +void syn_process_serial_data (int fd, Gpm_Event *state, unsigned char *data) { /* initialize the state */ @@ -3116,6 +3115,8 @@ state->dx = 0; state->dy = 0; + mouse_fd = fd; /* cheat */ + syn_serial_translate_data (data, &cur_report); if (wmode_enabled){ syn_process_wmode_report(&cur_report); @@ -3196,7 +3197,7 @@ ** ** Process the touchpad 6 byte report. */ -void syn_process_ps2_data (Gpm_Event *state, +void syn_process_ps2_data (int fd, Gpm_Event *state, unsigned char *data) { /* gpm_report(GPM_PR_DEBUG,"Data %02x %02x %02x %02x %02x %02x",data[0],data[1],data[2],data[3],data[4],data[5]); */ @@ -3206,6 +3207,7 @@ state->dx = 0; state->dy = 0; + mouse_fd = fd; /* cheat */ if (wmode_enabled) { syn_ps2_translate_wmode_data (data, &cur_report); diff -urN gpm-1.20.1/src/tools.c gpm/src/tools.c --- gpm-1.20.1/src/tools.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/tools.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,93 +0,0 @@ -/* - * tools.c - tools which are needed by client and server - * - * Copyright (c) 2001 Nico Schottelius - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - ********/ - -#include /* NULL */ -#include -#include -#include /* these three are */ -#include /* needed for */ -#include /* stat() */ - -#include "headers/gpmInt.h" /* only used for some defines */ -#include "headers/message.h" - -/***************************************************************************** - * check, whether devfs is used or not. - * See /usr/src/linux/Documentation/filesystems/devfs/ for details. - * Returns: the name of the console (/dev/tty0 or /dev/vc/0) - *****************************************************************************/ -char *Gpm_get_console( void ) -{ - - char *back = NULL, *tmp = NULL; - struct stat buf; - - /* first try the devfs device, because in the next time this will be - * the preferred one. If that fails, take the old console */ - - /* Check for open new console */ - if (stat(GPM_DEVFS_CONSOLE,&buf) == 0) - tmp = GPM_DEVFS_CONSOLE; - - /* Failed, try OLD console */ - else if(stat(GPM_OLD_CONSOLE,&buf) == 0) - tmp = GPM_OLD_CONSOLE; - - if(tmp != NULL) - if((back = malloc(strlen(tmp) + sizeof(char)) ) != NULL) - strcpy(back,tmp); - - return(back); -} - -/* what's the english name for potenz ? */ -int Gpm_x_high_y(int base, int pot_y) -{ - int val = 1; - - if(pot_y == 0) val = 1; - else if(pot_y < 0) val = 0; /* ugly hack ;) */ - else while(pot_y > 0) { - val = val * base; - pot_y--; - } - return val; -} - -/* return characters needed to display int */ -int Gpm_cnt_digits(int number) -{ - /* 0-9 = 1 10^0 <-> (10^1)-1 - * 10 - 99 = 2 10^1 <-> (10^2)-1 - * 100 - 999 = 3 10^2 <-> (10^3)-1 - * 1000 - 9999 = 4 ... */ - - int ret = 0, num = 0; - - /* non negative, please */ - if(number < 0) number *= -1; - else if(number == 0) ret = 1; - else while(number > num) { - ret++; - num = (Gpm_x_high_y(10,ret) - 1); - } - - return(ret); -} diff -urN gpm-1.20.1/src/twiddler.c gpm/src/twiddler.c --- gpm-1.20.1/src/twiddler.c 2002-12-24 17:57:16.000000000 -0500 +++ gpm/src/twiddler.c 2003-10-02 01:22:42.000000000 -0500 @@ -54,6 +54,7 @@ #include "headers/gpm.h" #include "headers/gpmInt.h" #include "headers/message.h" +#include "headers/console.h" #include "headers/twiddler.h" @@ -134,17 +135,6 @@ int (*fun)(char *string); }; - -/* The same silly function as in gpm.c */ -static inline int open_console(const int mode) -{ - int fd; - extern struct options option; - if ((fd=open(option.consolename, mode)) < 0) gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,option.consolename); - return fd; -} - - /*===================================================================*/ /* This part deals with pushing keys */ @@ -175,7 +165,7 @@ int twiddler_exec(char *s) { int pid; - extern struct options option; + switch(pid=fork()) { case -1: return -1; case 0: @@ -184,7 +174,7 @@ close(2); /* very rude! */ open(GPM_NULL_DEV,O_RDONLY); - open(option.consolename,O_WRONLY); + open(console.device, O_WRONLY); dup(1); execl("/bin/sh", "sh", "-c", s, NULL); exit(1); /* shouldn't happen */