[RFC][PATCH] xf86-input-evdev: add pressure valuator
Peter Hutterer
peter.hutterer at who-t.net
Thu Jan 8 17:33:32 PST 2009
On Wed, Jan 07, 2009 at 11:34:25PM -0800, Matt Helsley wrote:
> If it available report pressure as the third valuator.
minor typo: If it *is* available
> I couldn't seem to get the third valuator from X with
> xf86-input-evdev master when I was testing this over the
> holidays. (tested using the GIMP)
>
> So I backported to an older version of evdev available in
> my distro (Ubuntu 8.10) and it tested successfully there.
>
> What am I missing here?
Thanks for the patch, I really consider this as quite important. Comments
regarding the patch are below.
However, and this is related more to the approach than to the actual patch:
why just pressure? We should just parse whatever the kernel offers us and add
the matching valuators instead of just adding pressure. If a device offers us
REL_Z, ABS_TILT_X, etc., we should just add those as well. Admittedly, this
would be a larger patch, but I think it would also be very useful. Do you want
to tackle this problem?
Daniel: any word on the space navigator patch? I expect there to be some overlap.
> src/evdev.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
> src/evdev.h | 6 +++--
> 2 files changed, 60 insertions(+), 8 deletions(-)
>
> Index: xf86-input-evdev/src/evdev.h
> ===================================================================
> --- xf86-input-evdev.orig/src/evdev.h
> +++ xf86-input-evdev/src/evdev.h
> @@ -58,19 +58,21 @@ typedef struct {
>
> typedef struct {
> const char *device;
> int grabDevice; /* grab the event device? */
> int screen;
> - int min_x, min_y, max_x, max_y;
> - int abs_x, abs_y, old_x, old_y;
> + int min_x, min_y, max_x, max_y, min_p, max_p;
> + int abs_x, abs_y, abs_p, old_x, old_y;
> int flags;
> int tool;
> int buttons; /* number of buttons */
> BOOL swap_axes;
> BOOL invert_x;
> BOOL invert_y;
>
> + BOOL pressure_valuator;
please rename this to has_pressure.
> +
> /* XKB stuff has to be per-device rather than per-driver */
> int noXkb;
> #ifdef XKB
> char *xkb_rules;
> char *xkb_model;
> Index: xf86-input-evdev/src/evdev.c
> ===================================================================
> --- xf86-input-evdev.orig/src/evdev.c
> +++ xf86-input-evdev/src/evdev.c
> @@ -384,10 +384,14 @@ EvdevReadInput(InputInfoPtr pInfo)
> break;
> case ABS_Y:
> pEvdev->abs_y = value;
> abs = 1;
> break;
> + case ABS_PRESSURE:
> + pEvdev->abs_p = value;
> + abs = 1;
> + break;
> }
> break;
>
> case EV_KEY:
> /* don't repeat mouse buttons */
> @@ -475,11 +479,11 @@ EvdevReadInput(InputInfoPtr pInfo)
> * pEvdev->digi here, lets us ignore that event. pEvdev is
> * initialized to 1 so devices that doesn't use this scheme still
> * just works.
> */
> if (abs && pEvdev->tool) {
> - int abs_x, abs_y;
> + int abs_x, abs_y, abs_p;
> abs_x = (pEvdev->swap_axes) ? pEvdev->abs_y : pEvdev->abs_x;
> abs_y = (pEvdev->swap_axes) ? pEvdev->abs_x : pEvdev->abs_y;
>
> if (pEvdev->flags & EVDEV_CALIBRATED)
> {
> @@ -488,17 +492,23 @@ EvdevReadInput(InputInfoPtr pInfo)
> pEvdev->calibration.max_x, pEvdev->calibration.min_x);
> abs_y = xf86ScaleAxis(abs_y,
> pEvdev->max_y, pEvdev->min_y,
> pEvdev->calibration.max_y, pEvdev->calibration.min_y);
> }
> + abs_p = pEvdev->abs_p;
>
> if (pEvdev->invert_x)
> abs_x = pEvdev->max_x - (abs_x - pEvdev->min_x);
> if (pEvdev->invert_y)
> abs_y = pEvdev->max_y - (abs_y - pEvdev->min_y);
>
> - xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, abs_x, abs_y);
> + if (pEvdev->pressure_valuator)
> + xf86PostMotionEvent(pInfo->dev, TRUE, 0, 3,
> + abs_x, abs_y, abs_p);
> + else
> + xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2,
> + abs_x, abs_y);
> }
> }
this section calls for a cleanup to use xf86PostMotionEventP(). You don't
happen to have the motivation for a follow up patch, do you?
> @@ -878,11 +888,12 @@ EvdevAddKeyClass(DeviceIntPtr device)
> static int
> EvdevAddAbsClass(DeviceIntPtr device)
> {
> InputInfoPtr pInfo;
> EvdevPtr pEvdev;
> - struct input_absinfo absinfo_x, absinfo_y;
> + struct input_absinfo absinfo_x, absinfo_y, absinfo_p;
> + int num_valuators = 2;
>
> pInfo = device->public.devicePrivate;
> pEvdev = pInfo->private;
>
> if (ioctl(pInfo->fd,
> @@ -900,11 +911,24 @@ EvdevAddAbsClass(DeviceIntPtr device)
> pEvdev->min_x = absinfo_x.minimum;
> pEvdev->max_x = absinfo_x.maximum;
> pEvdev->min_y = absinfo_y.minimum;
> pEvdev->max_y = absinfo_y.maximum;
>
> - if (!InitValuatorClassDeviceStruct(device, 2,
> + if (pEvdev->pressure_valuator && ioctl(pInfo->fd,
> + EVIOCGABS(ABS_PRESSURE), &absinfo_p) < 0) {
> + xf86Msg(X_ERROR, "ioctl EVIOCGABS ABS_PRESSURE failed: %s\n", strerror(errno));
> + return !Success;
> + }
> +
> + if (pEvdev->pressure_valuator) {
> + num_valuators++;
> + pEvdev->max_p = absinfo_p.maximum;
> + pEvdev->min_p = absinfo_p.minimum;
> + }
> +
> +
> + if (!InitValuatorClassDeviceStruct(device, num_valuators,
> #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
> GetMotionHistory,
> #endif
> GetMotionHistorySize(), Absolute))
> return !Success;
> @@ -916,10 +940,17 @@ EvdevAddAbsClass(DeviceIntPtr device)
>
> /* Y valuator */
> xf86InitValuatorAxisStruct(device, 1, pEvdev->min_y, pEvdev->max_y,
> 10000, 0, 10000);
> xf86InitValuatorDefaults(device, 1);
> +
> + if (pEvdev->pressure_valuator) {
> + xf86InitValuatorAxisStruct(device, 2, pEvdev->min_p, pEvdev->max_p,
> + 10000, 0, 10000);
> + xf86InitValuatorDefaults(device, 2);
> + }
> +
> xf86MotionHistoryAllocate(pInfo);
>
> if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
> return !Success;
>
> @@ -1365,11 +1396,11 @@ EvdevProbe(InputInfoPtr pInfo)
> }
>
> if (TestBit(ABS_X, abs_bitmask) && TestBit(ABS_Y, abs_bitmask)) {
> xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
> pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
> - if (TestBit(BTN_TOUCH, key_bitmask)) {
> + if (!pEvdev->pressure_valuator && TestBit(BTN_TOUCH, key_bitmask)) {
> if (num_buttons) {
> xf86Msg(X_INFO, "%s: Found absolute touchpad\n", pInfo->name);
> pEvdev->flags |= EVDEV_TOUCHPAD;
> pEvdev->old_x = pEvdev->old_y = -1;
> } else {
> @@ -1379,27 +1410,45 @@ EvdevProbe(InputInfoPtr pInfo)
> }
> }
> has_axes = TRUE;
> }
>
> + if (TestBit(ABS_PRESSURE, abs_bitmask)) {
> + struct input_absinfo absinfo_p;
> +
> + /* More than two pressure levels indicate it's not a button */
> + if (ioctl(pInfo->fd,
> + EVIOCGABS(ABS_PRESSURE), &absinfo_p) == 0) {
> + if ((absinfo_p.maximum - absinfo_p.minimum) > 1)
> + pEvdev->pressure_valuator = TRUE;
> + }
> + }
> +
> for (i = 0; i < BTN_MISC; i++)
> if (TestBit(i, key_bitmask))
> break;
>
> if (i < BTN_MISC) {
> xf86Msg(X_INFO, "%s: Found keys\n", pInfo->name);
> pEvdev->flags |= EVDEV_KEYBOARD_EVENTS;
> has_keys = TRUE;
> }
>
> - if (has_axes && num_buttons) {
> + if (!pEvdev->pressure_valuator && has_axes && num_buttons) {
> xf86Msg(X_INFO, "%s: Configuring as mouse\n", pInfo->name);
> pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
> XI86_CONFIGURED;
> pInfo->type_name = XI_MOUSE;
> }
>
> + if (pEvdev->pressure_valuator && has_axes && num_buttons) {
> + xf86Msg(X_INFO, "%s: Configuring as tablet\n", pInfo->name);
> + pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
> + XI86_CONFIGURED;
> + pInfo->type_name = XI_TABLET;
> + }
> +
please nest these two statements instead of having two separate, nearly
identical ones.
> if (pEvdev->flags & EVDEV_TOUCHSCREEN) {
> xf86Msg(X_INFO, "%s: Configuring as touchscreen\n", pInfo->name);
> pInfo->type_name = XI_TOUCHSCREEN;
> pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
> XI86_CONFIGURED;
> @@ -1473,10 +1522,11 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr
> /*
> * We initialize pEvdev->tool to 1 so that device that doesn't use
> * proximity will still report events.
> */
> pEvdev->tool = 1;
> + pEvdev->pressure_valuator = FALSE;
>
> device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
> if (!device) {
> xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name);
> xf86DeleteInput(pInfo, 0);
Cheers,
Peter
More information about the xorg
mailing list