From d1fc35bb6981986d0ce7eb0b0f8bb58c58e91a79 Mon Sep 17 00:00:00 2001 From: shadchin Date: Sat, 29 Aug 2015 08:48:28 +0000 Subject: [PATCH] Read multiple events at once. Before: Both drivers currently do one read(2) per event, but since we use a "sync" event we have a least two of them for ws(4) but more commonly 3 for ws(4) and 4 for synaptics(4). most of the code and ok mpi@ --- driver/xf86-input-synaptics/src/wsconscomm.c | 76 ++++++++++++++----- driver/xf86-input-ws/src/ws.c | 80 ++++++++++++-------- driver/xf86-input-ws/src/ws.h | 6 ++ 3 files changed, 111 insertions(+), 51 deletions(-) diff --git a/driver/xf86-input-synaptics/src/wsconscomm.c b/driver/xf86-input-synaptics/src/wsconscomm.c index 78f47abf8..c7a6aece0 100644 --- a/driver/xf86-input-synaptics/src/wsconscomm.c +++ b/driver/xf86-input-synaptics/src/wsconscomm.c @@ -36,6 +36,14 @@ extern int priv_open_device(const char *); #define DEFAULT_WSMOUSE_DEV "/dev/wsmouse0" +#define NWSEVENTS 16 + +struct wsconscomm_proto_data { + struct wscons_event events[NWSEVENTS]; + size_t events_count; + size_t events_pos; +}; + static Bool WSConsIsTouchpad(InputInfoPtr pInfo, const char *device) { @@ -72,23 +80,42 @@ out: return rc; } -static Bool -WSConsReadEvent(InputInfoPtr pInfo, struct wscons_event *event) +static size_t +WSConsReadEvents(InputInfoPtr pInfo) { - Bool rc = TRUE; + SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; + struct wsconscomm_proto_data *proto_data = priv->proto_data; ssize_t len; - len = read(pInfo->fd, event, sizeof(struct wscons_event)); + proto_data->events_count = proto_data->events_pos = 0; + len = read(pInfo->fd, proto_data->events, sizeof(proto_data->events)); if (len <= 0) { if (errno != EAGAIN) xf86IDrvMsg(pInfo, X_ERROR, "read error %s\n", strerror(errno)); - rc = FALSE; } else if (len % sizeof(struct wscons_event)) { xf86IDrvMsg(pInfo, X_ERROR, "read error, invalid number of bytes\n"); - rc = FALSE; + } else { + proto_data->events_count = len / sizeof(struct wscons_event); } - return rc; + return proto_data->events_count; +} + +static struct wscons_event * +WSConsGetEvent(InputInfoPtr pInfo) +{ + SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; + struct wsconscomm_proto_data *proto_data = priv->proto_data; + struct wscons_event *event; + + if (proto_data->events_count == 0 && WSConsReadEvents(pInfo) == 0) + return NULL; + + event = &proto_data->events[proto_data->events_pos]; + proto_data->events_pos++; + proto_data->events_count--; + + return event; } static Bool @@ -128,16 +155,17 @@ WSConsReadHwState(InputInfoPtr pInfo, struct CommData *comm, struct SynapticsHwState *hwRet) { SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; + struct wsconscomm_proto_data *proto_data = priv->proto_data; struct SynapticsHwState *hw = comm->hwState; - struct wscons_event event; + struct wscons_event *event; Bool v; - while (WSConsReadEvent(pInfo, &event)) { - switch (event.type) { + while ((event = WSConsGetEvent(pInfo)) != NULL) { + switch (event->type) { case WSCONS_EVENT_MOUSE_UP: case WSCONS_EVENT_MOUSE_DOWN: - v = (event.type == WSCONS_EVENT_MOUSE_DOWN) ? TRUE : FALSE; - switch (event.value) { + v = (event->type == WSCONS_EVENT_MOUSE_DOWN) ? TRUE : FALSE; + switch (event->value) { case 0: hw->left = v; break; @@ -180,25 +208,25 @@ WSConsReadHwState(InputInfoPtr pInfo, } break; case WSCONS_EVENT_MOUSE_ABSOLUTE_X: - hw->x = event.value; + hw->x = event->value; hw->cumulative_dx = hw->x; break; case WSCONS_EVENT_MOUSE_ABSOLUTE_Y: - hw->y = priv->maxy - event.value + priv->miny; + hw->y = priv->maxy - event->value + priv->miny; hw->cumulative_dy = hw->y; break; case WSCONS_EVENT_MOUSE_ABSOLUTE_Z: - hw->z = event.value; + hw->z = event->value; break; case WSCONS_EVENT_MOUSE_ABSOLUTE_W: if (priv->model == MODEL_ELANTECH) { /* Elantech touchpads report number of fingers directly. */ hw->fingerWidth = 5; - hw->numFingers = event.value; + hw->numFingers = event->value; break; } /* XXX magic number mapping which is mirrored in pms driver */ - switch (event.value) { + switch (event->value) { case 0: hw->fingerWidth = 5; hw->numFingers = 2; @@ -208,7 +236,7 @@ WSConsReadHwState(InputInfoPtr pInfo, hw->numFingers = 3; break; case 4 ... 5: - hw->fingerWidth = event.value; + hw->fingerWidth = event->value; hw->numFingers = 1; break; } @@ -226,7 +254,8 @@ WSConsReadHwState(InputInfoPtr pInfo, hw->fingerWidth = 5; hw->numFingers = 2; } - hw->millis = 1000 * event.time.tv_sec + event.time.tv_nsec / 1000000; + hw->millis = 1000 * event->time.tv_sec + + event->time.tv_nsec / 1000000; SynapticsCopyHwState(hwRet, hw); return TRUE; default: @@ -263,7 +292,16 @@ WSConsReadDevDimensions(InputInfoPtr pInfo) struct wsmouse_calibcoords wsmc; int wsmouse_type; + priv->proto_data = calloc(1, sizeof(struct wsconscomm_proto_data)); + if (priv->proto_data == NULL) { + xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate protocol data (%s)\n", + strerror(errno)); + return; + } + if (ioctl(pInfo->fd, WSMOUSEIO_GCALIBCOORDS, &wsmc) != 0) { + free(priv->proto_data); + priv->proto_data = NULL; xf86IDrvMsg(pInfo, X_ERROR, "failed to query axis range (%s)\n", strerror(errno)); return; diff --git a/driver/xf86-input-ws/src/ws.c b/driver/xf86-input-ws/src/ws.c index 70bd9c24a..268d71401 100644 --- a/driver/xf86-input-ws/src/ws.c +++ b/driver/xf86-input-ws/src/ws.c @@ -13,7 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: ws.c,v 1.61 2015/02/17 08:21:14 matthieu Exp $ */ +/* $OpenBSD: ws.c,v 1.62 2015/08/29 08:48:29 shadchin Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -457,78 +457,94 @@ wsDeviceOff(DeviceIntPtr pWS) pWS->public.on = FALSE; } -static Bool -wsReadEvent(InputInfoPtr pInfo, struct wscons_event *event) +static size_t +wsReadEvents(InputInfoPtr pInfo) { - Bool rc = TRUE; + WSDevicePtr priv = (WSDevicePtr)pInfo->private; ssize_t len; - len = read(pInfo->fd, event, sizeof(struct wscons_event)); - if (len <= 0) { + priv->events_count = priv->events_pos = 0; + len = read(pInfo->fd, priv->events, sizeof(priv->events)); + if (len < 0) { if (errno != EAGAIN) - xf86IDrvMsgVerb(pInfo, X_ERROR, 4, "read error %s\n", + xf86IDrvMsg(pInfo, X_ERROR, "read error %s\n", strerror(errno)); - rc = FALSE; - } else if (len != sizeof(struct wscons_event)) { + } else if (len % sizeof(struct wscons_event)) { xf86IDrvMsg(pInfo, X_ERROR, "read error, invalid number of bytes\n"); - rc = FALSE; + } else { + priv->events_count = len / sizeof(struct wscons_event); } - return rc; + return priv->events_count; +} + +static struct wscons_event * +wsGetEvent(InputInfoPtr pInfo) +{ + WSDevicePtr priv = (WSDevicePtr)pInfo->private; + struct wscons_event *event; + + if (priv->events_count == 0 && wsReadEvents(pInfo) == 0) + return NULL; + + event = &priv->events[priv->events_pos]; + priv->events_pos++; + priv->events_count--; + + return event; } static Bool wsReadHwState(InputInfoPtr pInfo, wsHwState *hw) { WSDevicePtr priv = (WSDevicePtr)pInfo->private; - struct wscons_event event; + struct wscons_event *event; bzero(hw, sizeof(wsHwState)); - hw->buttons = priv->lastButtons; hw->ax = priv->old_ax; hw->ay = priv->old_ay; - while (wsReadEvent(pInfo, &event)) { - switch (event.type) { + while ((event = wsGetEvent(pInfo)) != NULL) { + switch (event->type) { case WSCONS_EVENT_MOUSE_UP: - hw->buttons &= ~(1 << event.value); - DBG(4, ErrorF("Button %d up %x\n", event.value, + hw->buttons &= ~(1 << event->value); + DBG(4, ErrorF("Button %d up %x\n", event->value, hw->buttons)); break; case WSCONS_EVENT_MOUSE_DOWN: - hw->buttons |= (1 << event.value); - DBG(4, ErrorF("Button %d down %x\n", event.value, + hw->buttons |= (1 << event->value); + DBG(4, ErrorF("Button %d down %x\n", event->value, hw->buttons)); break; case WSCONS_EVENT_MOUSE_DELTA_X: - hw->dx = event.value; - DBG(4, ErrorF("Relative X %d\n", event.value)); + hw->dx = event->value; + DBG(4, ErrorF("Relative X %d\n", event->value)); break; case WSCONS_EVENT_MOUSE_DELTA_Y: - hw->dy = -event.value; - DBG(4, ErrorF("Relative Y %d\n", event.value)); + hw->dy = -event->value; + DBG(4, ErrorF("Relative Y %d\n", event->value)); break; case WSCONS_EVENT_MOUSE_DELTA_Z: - hw->dz = event.value; - DBG(4, ErrorF("Relative Z %d\n", event.value)); + hw->dz = event->value; + DBG(4, ErrorF("Relative Z %d\n", event->value)); break; case WSCONS_EVENT_MOUSE_DELTA_W: - hw->dw = event.value; - DBG(4, ErrorF("Relative W %d\n", event.value)); + hw->dw = event->value; + DBG(4, ErrorF("Relative W %d\n", event->value)); break; case WSCONS_EVENT_MOUSE_ABSOLUTE_X: - hw->ax = event.value; + hw->ax = event->value; if (priv->inv_x) hw->ax = priv->max_x - hw->ax + priv->min_x; - DBG(4, ErrorF("Absolute X %d\n", event.value)); + DBG(4, ErrorF("Absolute X %d\n", event->value)); break; case WSCONS_EVENT_MOUSE_ABSOLUTE_Y: - hw->ay = event.value; + hw->ay = event->value; if (priv->inv_y) hw->ay = priv->max_y - hw->ay + priv->min_y; - DBG(4, ErrorF("Absolute Y %d\n", event.value)); + DBG(4, ErrorF("Absolute Y %d\n", event->value)); break; case WSCONS_EVENT_MOUSE_ABSOLUTE_Z: case WSCONS_EVENT_MOUSE_ABSOLUTE_W: @@ -539,7 +555,7 @@ wsReadHwState(InputInfoPtr pInfo, wsHwState *hw) return TRUE; default: xf86IDrvMsg(pInfo, X_WARNING, - "bad wsmouse event type=%d\n", event.type); + "bad wsmouse event type=%d\n", event->type); continue; } #ifdef __NetBSD__ diff --git a/driver/xf86-input-ws/src/ws.h b/driver/xf86-input-ws/src/ws.h index 09277fdf7..5efd063cc 100644 --- a/driver/xf86-input-ws/src/ws.h +++ b/driver/xf86-input-ws/src/ws.h @@ -32,6 +32,8 @@ extern int ws_debug_level; #define WS_NOMAP 0 +#define NWSEVENTS 16 /* size of buffer */ + /* axis specific data for wheel */ typedef struct { int negative; @@ -84,6 +86,10 @@ typedef struct WSDevice { Time expires; /* time of expiry */ Time timeout; } emulateWheel; + + struct wscons_event events[NWSEVENTS]; + size_t events_count; + size_t events_pos; } WSDeviceRec, *WSDevicePtr; /* Middle mouse button emulation */