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@
This commit is contained in:
shadchin 2015-08-29 08:48:28 +00:00
parent a74e8629b1
commit d1fc35bb69
3 changed files with 111 additions and 51 deletions

View File

@ -36,6 +36,14 @@ extern int priv_open_device(const char *);
#define DEFAULT_WSMOUSE_DEV "/dev/wsmouse0" #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 static Bool
WSConsIsTouchpad(InputInfoPtr pInfo, const char *device) WSConsIsTouchpad(InputInfoPtr pInfo, const char *device)
{ {
@ -72,23 +80,42 @@ out:
return rc; return rc;
} }
static Bool static size_t
WSConsReadEvent(InputInfoPtr pInfo, struct wscons_event *event) WSConsReadEvents(InputInfoPtr pInfo)
{ {
Bool rc = TRUE; SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
struct wsconscomm_proto_data *proto_data = priv->proto_data;
ssize_t len; 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 (len <= 0) {
if (errno != EAGAIN) if (errno != EAGAIN)
xf86IDrvMsg(pInfo, X_ERROR, "read error %s\n", strerror(errno)); 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"); 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 static Bool
@ -128,16 +155,17 @@ WSConsReadHwState(InputInfoPtr pInfo,
struct CommData *comm, struct SynapticsHwState *hwRet) struct CommData *comm, struct SynapticsHwState *hwRet)
{ {
SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
struct wsconscomm_proto_data *proto_data = priv->proto_data;
struct SynapticsHwState *hw = comm->hwState; struct SynapticsHwState *hw = comm->hwState;
struct wscons_event event; struct wscons_event *event;
Bool v; Bool v;
while (WSConsReadEvent(pInfo, &event)) { while ((event = WSConsGetEvent(pInfo)) != NULL) {
switch (event.type) { switch (event->type) {
case WSCONS_EVENT_MOUSE_UP: case WSCONS_EVENT_MOUSE_UP:
case WSCONS_EVENT_MOUSE_DOWN: case WSCONS_EVENT_MOUSE_DOWN:
v = (event.type == WSCONS_EVENT_MOUSE_DOWN) ? TRUE : FALSE; v = (event->type == WSCONS_EVENT_MOUSE_DOWN) ? TRUE : FALSE;
switch (event.value) { switch (event->value) {
case 0: case 0:
hw->left = v; hw->left = v;
break; break;
@ -180,25 +208,25 @@ WSConsReadHwState(InputInfoPtr pInfo,
} }
break; break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_X: case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
hw->x = event.value; hw->x = event->value;
hw->cumulative_dx = hw->x; hw->cumulative_dx = hw->x;
break; break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_Y: 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; hw->cumulative_dy = hw->y;
break; break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_Z: case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
hw->z = event.value; hw->z = event->value;
break; break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_W: case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
if (priv->model == MODEL_ELANTECH) { if (priv->model == MODEL_ELANTECH) {
/* Elantech touchpads report number of fingers directly. */ /* Elantech touchpads report number of fingers directly. */
hw->fingerWidth = 5; hw->fingerWidth = 5;
hw->numFingers = event.value; hw->numFingers = event->value;
break; break;
} }
/* XXX magic number mapping which is mirrored in pms driver */ /* XXX magic number mapping which is mirrored in pms driver */
switch (event.value) { switch (event->value) {
case 0: case 0:
hw->fingerWidth = 5; hw->fingerWidth = 5;
hw->numFingers = 2; hw->numFingers = 2;
@ -208,7 +236,7 @@ WSConsReadHwState(InputInfoPtr pInfo,
hw->numFingers = 3; hw->numFingers = 3;
break; break;
case 4 ... 5: case 4 ... 5:
hw->fingerWidth = event.value; hw->fingerWidth = event->value;
hw->numFingers = 1; hw->numFingers = 1;
break; break;
} }
@ -226,7 +254,8 @@ WSConsReadHwState(InputInfoPtr pInfo,
hw->fingerWidth = 5; hw->fingerWidth = 5;
hw->numFingers = 2; 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); SynapticsCopyHwState(hwRet, hw);
return TRUE; return TRUE;
default: default:
@ -263,7 +292,16 @@ WSConsReadDevDimensions(InputInfoPtr pInfo)
struct wsmouse_calibcoords wsmc; struct wsmouse_calibcoords wsmc;
int wsmouse_type; 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) { 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", xf86IDrvMsg(pInfo, X_ERROR, "failed to query axis range (%s)\n",
strerror(errno)); strerror(errno));
return; return;

View File

@ -13,7 +13,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * 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 #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
@ -457,78 +457,94 @@ wsDeviceOff(DeviceIntPtr pWS)
pWS->public.on = FALSE; pWS->public.on = FALSE;
} }
static Bool static size_t
wsReadEvent(InputInfoPtr pInfo, struct wscons_event *event) wsReadEvents(InputInfoPtr pInfo)
{ {
Bool rc = TRUE; WSDevicePtr priv = (WSDevicePtr)pInfo->private;
ssize_t len; ssize_t len;
len = read(pInfo->fd, event, sizeof(struct wscons_event)); priv->events_count = priv->events_pos = 0;
if (len <= 0) { len = read(pInfo->fd, priv->events, sizeof(priv->events));
if (len < 0) {
if (errno != EAGAIN) if (errno != EAGAIN)
xf86IDrvMsgVerb(pInfo, X_ERROR, 4, "read error %s\n", xf86IDrvMsg(pInfo, X_ERROR, "read error %s\n",
strerror(errno)); strerror(errno));
rc = FALSE; } else if (len % sizeof(struct wscons_event)) {
} else if (len != sizeof(struct wscons_event)) {
xf86IDrvMsg(pInfo, X_ERROR, xf86IDrvMsg(pInfo, X_ERROR,
"read error, invalid number of bytes\n"); "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 static Bool
wsReadHwState(InputInfoPtr pInfo, wsHwState *hw) wsReadHwState(InputInfoPtr pInfo, wsHwState *hw)
{ {
WSDevicePtr priv = (WSDevicePtr)pInfo->private; WSDevicePtr priv = (WSDevicePtr)pInfo->private;
struct wscons_event event; struct wscons_event *event;
bzero(hw, sizeof(wsHwState)); bzero(hw, sizeof(wsHwState));
hw->buttons = priv->lastButtons; hw->buttons = priv->lastButtons;
hw->ax = priv->old_ax; hw->ax = priv->old_ax;
hw->ay = priv->old_ay; hw->ay = priv->old_ay;
while (wsReadEvent(pInfo, &event)) { while ((event = wsGetEvent(pInfo)) != NULL) {
switch (event.type) { switch (event->type) {
case WSCONS_EVENT_MOUSE_UP: case WSCONS_EVENT_MOUSE_UP:
hw->buttons &= ~(1 << event.value); hw->buttons &= ~(1 << event->value);
DBG(4, ErrorF("Button %d up %x\n", event.value, DBG(4, ErrorF("Button %d up %x\n", event->value,
hw->buttons)); hw->buttons));
break; break;
case WSCONS_EVENT_MOUSE_DOWN: case WSCONS_EVENT_MOUSE_DOWN:
hw->buttons |= (1 << event.value); hw->buttons |= (1 << event->value);
DBG(4, ErrorF("Button %d down %x\n", event.value, DBG(4, ErrorF("Button %d down %x\n", event->value,
hw->buttons)); hw->buttons));
break; break;
case WSCONS_EVENT_MOUSE_DELTA_X: case WSCONS_EVENT_MOUSE_DELTA_X:
hw->dx = event.value; hw->dx = event->value;
DBG(4, ErrorF("Relative X %d\n", event.value)); DBG(4, ErrorF("Relative X %d\n", event->value));
break; break;
case WSCONS_EVENT_MOUSE_DELTA_Y: case WSCONS_EVENT_MOUSE_DELTA_Y:
hw->dy = -event.value; hw->dy = -event->value;
DBG(4, ErrorF("Relative Y %d\n", event.value)); DBG(4, ErrorF("Relative Y %d\n", event->value));
break; break;
case WSCONS_EVENT_MOUSE_DELTA_Z: case WSCONS_EVENT_MOUSE_DELTA_Z:
hw->dz = event.value; hw->dz = event->value;
DBG(4, ErrorF("Relative Z %d\n", event.value)); DBG(4, ErrorF("Relative Z %d\n", event->value));
break; break;
case WSCONS_EVENT_MOUSE_DELTA_W: case WSCONS_EVENT_MOUSE_DELTA_W:
hw->dw = event.value; hw->dw = event->value;
DBG(4, ErrorF("Relative W %d\n", event.value)); DBG(4, ErrorF("Relative W %d\n", event->value));
break; break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_X: case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
hw->ax = event.value; hw->ax = event->value;
if (priv->inv_x) if (priv->inv_x)
hw->ax = priv->max_x - hw->ax + priv->min_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; break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_Y: case WSCONS_EVENT_MOUSE_ABSOLUTE_Y:
hw->ay = event.value; hw->ay = event->value;
if (priv->inv_y) if (priv->inv_y)
hw->ay = priv->max_y - hw->ay + priv->min_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; break;
case WSCONS_EVENT_MOUSE_ABSOLUTE_Z: case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
case WSCONS_EVENT_MOUSE_ABSOLUTE_W: case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
@ -539,7 +555,7 @@ wsReadHwState(InputInfoPtr pInfo, wsHwState *hw)
return TRUE; return TRUE;
default: default:
xf86IDrvMsg(pInfo, X_WARNING, xf86IDrvMsg(pInfo, X_WARNING,
"bad wsmouse event type=%d\n", event.type); "bad wsmouse event type=%d\n", event->type);
continue; continue;
} }
#ifdef __NetBSD__ #ifdef __NetBSD__

View File

@ -32,6 +32,8 @@ extern int ws_debug_level;
#define WS_NOMAP 0 #define WS_NOMAP 0
#define NWSEVENTS 16 /* size of buffer */
/* axis specific data for wheel */ /* axis specific data for wheel */
typedef struct { typedef struct {
int negative; int negative;
@ -84,6 +86,10 @@ typedef struct WSDevice {
Time expires; /* time of expiry */ Time expires; /* time of expiry */
Time timeout; Time timeout;
} emulateWheel; } emulateWheel;
struct wscons_event events[NWSEVENTS];
size_t events_count;
size_t events_pos;
} WSDeviceRec, *WSDevicePtr; } WSDeviceRec, *WSDevicePtr;
/* Middle mouse button emulation */ /* Middle mouse button emulation */