2006-03-13 20:54:29

by Elias Naur

[permalink] [raw]
Subject: [PATCH] Expose input device usages to userspace

Hi,

I believe that the current event input interface is missing some kind of
information about the general kind of input device (Mouse, Keyboard, Joystick
etc.) so I added a simple ioctl to do just that. The relevant line in
include/linux/input.h is:

#define EVIOCGUSAGE(len) _IOC(_IOC_READ, 'E', 0x1c, len) /* get all
usages */

It returns a bit set with the device usages. Current usages are:

#define USAGE_MOUSE 0x00
#define USAGE_JOYSTICK 0x01
#define USAGE_GAMEPAD 0x02
#define USAGE_KEYBOARD 0x03

The patch against 2.6.16-rc6 adds the bit set in input_dev and adds support
for the usage set in hid-input.c, psmouse.c and atkbd.c. The change still
needs to be added to all input devices, but I'm writing now to solicit
comments about the interface itself. For example, one might want a single
usage (like DirectInput), not a set (like the usage pairs in the Mac OS X HID
manager). Additionally, there's always the possibility that the device usages
are kept secret for a reason :)

Signed-off-by: Elias Naur <[email protected]>

---

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 745979f..f09a2f9 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -504,6 +504,9 @@ static long evdev_ioctl_handler(struct f
}
return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
}
+
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUSAGE(0)))
+ return bits_to_user(dev->usagebit, USAGE_MAX, _IOC_SIZE(cmd), p,
compat_mode);

if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ffacf6e..4b61e19 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -794,6 +794,8 @@ static void atkbd_set_device_attrs(struc

input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);

+ input_dev->usagebit[0] = BIT(USAGE_KEYBOARD);
+
if (atkbd->write) {
input_dev->evbit[0] |= BIT(EV_LED);
input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
diff --git a/drivers/input/mouse/psmouse-base.c
b/drivers/input/mouse/psmouse-base.c
index ad62174..d058960 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -1018,6 +1018,8 @@ static int psmouse_switch_protocol(struc
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) |
BIT(BTN_RIGHT);
input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);

+ input_dev->usagebit[0] = BIT(USAGE_MOUSE);
+
psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution;
psmouse->poll = psmouse_poll;
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index cb0d80f..bcde293 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -766,6 +766,38 @@ static void hidinput_close(struct input_
}

/*
+ * Register the device usages, if any
+ */
+static void hidinput_init_usages(struct hid_device *hid, struct input_dev
*input) {
+ int i;
+
+ for (i = 0; i < hid->maxcollection; i++)
+ if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
+ hid->collection[i].type == HID_COLLECTION_PHYSICAL) {
+ switch (hid->collection[i].usage) {
+ case HID_GD_POINTER: /* Fall through */
+ case HID_GD_MOUSE:
+ set_bit(USAGE_MOUSE, input->usagebit);
+ break;
+ case HID_GD_KEYBOARD: /* Fall through */
+ case HID_GD_KEYPAD:
+ set_bit(USAGE_KEYBOARD, input->usagebit);
+ break;
+ case HID_GD_JOYSTICK:
+ set_bit(USAGE_JOYSTICK, input->usagebit);
+ break;
+ case HID_GD_GAMEPAD:
+ set_bit(USAGE_GAMEPAD, input->usagebit);
+ break;
+ default: /* ignore it */
+ break;
+ }
+ }
+}
+
+
+
+/*
* Register the input device; print a message.
* Configure the input layer interface
* Read all reports and initialize the absolute field values.
@@ -833,6 +865,7 @@ int hidinput_connect(struct hid_device *
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
+ hidinput_init_usages(hid, hidinput->input);
input_register_device(hidinput->input);
hidinput = NULL;
}
@@ -843,6 +876,7 @@ int hidinput_connect(struct hid_device *
* only useful in this case, and not for multi-input quirks. */
if (hidinput) {
hid_ff_init(hid);
+ hidinput_init_usages(hid, hidinput->input);
input_register_device(hidinput->input);
}

diff --git a/include/linux/input.h b/include/linux/input.h
index 6d4cc3c..398f4ac 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -35,7 +35,7 @@ struct input_event {
* Protocol version.
*/

-#define EV_VERSION 0x010000
+#define EV_VERSION 0x010001

/*
* IOCTLs (0x00 - 0x7f)
@@ -70,6 +70,8 @@ struct input_absinfo {
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds
status */
#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch
states */

+#define EVIOCGUSAGE(len) _IOC(_IOC_READ, 'E', 0x1c, len) /* get all
usages */
+
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event
bits */
#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, struct input_absinfo) /* get
abs value/limits */
#define EVIOCSABS(abs) _IOW('E', 0xc0 + abs, struct input_absinfo) /* set
abs value/limits */
@@ -579,6 +581,15 @@ struct input_absinfo {
#define SW_MAX 0x0f

/*
+ * Usage flags
+ */
+#define USAGE_MOUSE 0x00
+#define USAGE_JOYSTICK 0x01
+#define USAGE_GAMEPAD 0x02
+#define USAGE_KEYBOARD 0x03
+#define USAGE_MAX 0x0f
+
+/*
* Misc events
*/

@@ -892,6 +903,9 @@ struct input_dev {
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
unsigned long swbit[NBITS(SW_MAX)];
+
+ unsigned long usagebit[NBITS(USAGE_MAX)];
+
int ff_effects_max;

unsigned int keycodemax;


2006-03-13 21:03:08

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace

On Mon, 2006-03-13 at 21:54 +0100, Elias Naur wrote:
> Hi,
>
> I believe that the current event input interface is missing some kind of
> information about the general kind of input device (Mouse, Keyboard, Joystick
> etc.) so I added a simple ioctl to do just that. The relevant line in
> include/linux/input.h is:
>
> #define EVIOCGUSAGE(len) _IOC(_IOC_READ, 'E', 0x1c, len) /* get all
> usages */
>
> It returns a bit set with the device usages. Current usages are:
>
> #define USAGE_MOUSE 0x00
> #define USAGE_JOYSTICK 0x01
> #define USAGE_GAMEPAD 0x02
> #define USAGE_KEYBOARD 0x03


I'm not sure that this is a good idea in general.
However when you do it, at least make it a bitmap; things can be both a
mouse and a keyboard for example.


2006-03-14 05:26:30

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace

On Monday 13 March 2006 16:02, Arjan van de Ven wrote:
> On Mon, 2006-03-13 at 21:54 +0100, Elias Naur wrote:
> > Hi,
> >
> > I believe that the current event input interface is missing some kind of
> > information about the general kind of input device (Mouse, Keyboard, Joystick
> > etc.) so I added a simple ioctl to do just that. The relevant line in
> > include/linux/input.h is:
> >
> > #define EVIOCGUSAGE(len) _IOC(_IOC_READ, 'E', 0x1c, len) /* get all
> > usages */
> >
> > It returns a bit set with the device usages. Current usages are:
> >
> > #define USAGE_MOUSE 0x00
> > #define USAGE_JOYSTICK 0x01
> > #define USAGE_GAMEPAD 0x02
> > #define USAGE_KEYBOARD 0x03
>
>
> I'm not sure that this is a good idea in general.
> However when you do it, at least make it a bitmap; things can be both a
> mouse and a keyboard for example.
>

No, I don't think this is needed at all - users should be interested in
what capabilities a particular device has, not what type it was assigned
by soneone.

--
Dmitry

2006-03-14 05:33:22

by Elias Naur

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace

On Monday 13 March 2006 22:02, Arjan van de Ven wrote:
> On Mon, 2006-03-13 at 21:54 +0100, Elias Naur wrote:
> > Hi,
> >
> > I believe that the current event input interface is missing some kind of
> > information about the general kind of input device (Mouse, Keyboard,
> > Joystick etc.) so I added a simple ioctl to do just that. The relevant
> > line in include/linux/input.h is:
> >
> > #define EVIOCGUSAGE(len) _IOC(_IOC_READ, 'E', 0x1c, len) /*
> > get all usages */
> >
> > It returns a bit set with the device usages. Current usages are:
> >
> > #define USAGE_MOUSE 0x00
> > #define USAGE_JOYSTICK 0x01
> > #define USAGE_GAMEPAD 0x02
> > #define USAGE_KEYBOARD 0x03
>
> I'm not sure that this is a good idea in general.

Can you elaborate on the reasons? My thinking is that HID is going to be
pretty much the standard for input devices, and they all expose nicely
defined usages. Furthermore, "those other OS'es" already expose device
usages :)

> However when you do it, at least make it a bitmap; things can be both a
> mouse and a keyboard for example.

It already is a bitmap. The USAGE_* constants are the bit indices, just like
the EV_* constants.

- elias

2006-03-14 07:21:15

by Elias Naur

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace

On Tuesday 14 March 2006 06:26, Dmitry Torokhov wrote:
> On Monday 13 March 2006 16:02, Arjan van de Ven wrote:
> > On Mon, 2006-03-13 at 21:54 +0100, Elias Naur wrote:
> > > Hi,
> > >
> > > I believe that the current event input interface is missing some kind
> > > of information about the general kind of input device (Mouse, Keyboard,
> > > Joystick etc.) so I added a simple ioctl to do just that. The relevant
> > > line in include/linux/input.h is:
> > >
> > > #define EVIOCGUSAGE(len) _IOC(_IOC_READ, 'E', 0x1c, len) /*
> > > get all usages */
> > >
> > > It returns a bit set with the device usages. Current usages are:
> > >
> > > #define USAGE_MOUSE 0x00
> > > #define USAGE_JOYSTICK 0x01
> > > #define USAGE_GAMEPAD 0x02
> > > #define USAGE_KEYBOARD 0x03
> >
> > I'm not sure that this is a good idea in general.
> > However when you do it, at least make it a bitmap; things can be both a
> > mouse and a keyboard for example.
>
> No, I don't think this is needed at all - users should be interested in
> what capabilities a particular device has, not what type it was assigned
> by soneone.

I see your point that an application should not rely too much on device
usages. However, the main reason I want device usages is to help applications
and users identify and (visually) represent devices. For example, games could
show an appropriate icon graphic representing each active device. The event
interface already has a few other ioctls for this kind of information:

- The name (EVIOCGNAME).
- The ID (EVIOCGID). IMHO, device usages are more useful than the "bustype"
field of struct input_id.
- The physical location (EVIOCGPHYS).

And speaking of capabilities, the event interface already exposes "types
assigned by someone" to each device component (ABS_X, KEY_ESC, BTN_TRIGGER
etc.). If no vendor assigned types should be exposed, only the raw capability
(a type (abs axis, rel axis, key) and a struct input_absinfo for absolute
axes) needed to interpret component values would be needed.

- elias

2006-03-14 08:22:45

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace


> > No, I don't think this is needed at all - users should be interested in
> > what capabilities a particular device has, not what type it was assigned
> > by soneone.
>
> I see your point that an application should not rely too much on device
> usages. However, the main reason I want device usages is to help applications
> and users identify and (visually) represent devices. For example, games could
> show an appropriate icon graphic representing each active device. The event
> interface already has a few other ioctls for this kind of information:


ok then you should consider to do it the other way around: make a way of
asking
"are you matching THIS profile".
rather than
"what profile are you"

that way devices can present multiple faces etc; which is going to be
needed as more and more weird devices come into existence.


2006-03-14 10:46:21

by Elias Naur

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace

On Tuesday 14 March 2006 09:22, Arjan van de Ven wrote:
> > > No, I don't think this is needed at all - users should be interested in
> > > what capabilities a particular device has, not what type it was
> > > assigned by soneone.
> >
> > I see your point that an application should not rely too much on device
> > usages. However, the main reason I want device usages is to help
> > applications and users identify and (visually) represent devices. For
> > example, games could show an appropriate icon graphic representing each
> > active device. The event interface already has a few other ioctls for
> > this kind of information:
>
> ok then you should consider to do it the other way around: make a way of
> asking
> "are you matching THIS profile".
> rather than
> "what profile are you"
>
> that way devices can present multiple faces etc; which is going to be
> needed as more and more weird devices come into existence.

If by profile you mean a device usage like Mouse, Keyboard, Joystick etc. is
your proposal covered by the bit field ioctl exposed by my patch? For
example, a device can already expose itself as both a joystick and a mouse
(see the hid-input.c changes from the patch).

- elias

2006-03-14 10:59:14

by Arjan van de Ven

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace

On Tue, 2006-03-14 at 11:46 +0100, Elias Naur wrote:
> On Tuesday 14 March 2006 09:22, Arjan van de Ven wrote:
> > > > No, I don't think this is needed at all - users should be interested in
> > > > what capabilities a particular device has, not what type it was
> > > > assigned by soneone.
> > >
> > > I see your point that an application should not rely too much on device
> > > usages. However, the main reason I want device usages is to help
> > > applications and users identify and (visually) represent devices. For
> > > example, games could show an appropriate icon graphic representing each
> > > active device. The event interface already has a few other ioctls for
> > > this kind of information:
> >
> > ok then you should consider to do it the other way around: make a way of
> > asking
> > "are you matching THIS profile".
> > rather than
> > "what profile are you"
> >
> > that way devices can present multiple faces etc; which is going to be
> > needed as more and more weird devices come into existence.
>
> If by profile you mean a device usage like Mouse, Keyboard, Joystick etc. is
> your proposal covered by the bit field ioctl exposed by my patch? For
> example, a device can already expose itself as both a joystick and a mouse
> (see the hid-input.c changes from the patch).


no that's not what I meant; I really mean asking "can you do THIS
profile". Example would be a device that could be either a joystick and
a mouse, or a touchpad and a mouse, but not both a touchpad and a
joystick. So the app should ask "can you do THESE", and the driver can
then do anything complex it wants to come to an answer. (Of course a
generic helper for the simple case is fine)


2006-03-14 11:46:56

by Elias Naur

[permalink] [raw]
Subject: Re: [PATCH] Expose input device usages to userspace

On Tuesday 14 March 2006 11:59, Arjan van de Ven wrote:
> On Tue, 2006-03-14 at 11:46 +0100, Elias Naur wrote:
> > On Tuesday 14 March 2006 09:22, Arjan van de Ven wrote:
> > > > > No, I don't think this is needed at all - users should be
> > > > > interested in what capabilities a particular device has, not what
> > > > > type it was assigned by soneone.
> > > >
> > > > I see your point that an application should not rely too much on
> > > > device usages. However, the main reason I want device usages is to
> > > > help applications and users identify and (visually) represent
> > > > devices. For example, games could show an appropriate icon graphic
> > > > representing each active device. The event interface already has a
> > > > few other ioctls for this kind of information:
> > >
> > > ok then you should consider to do it the other way around: make a way
> > > of asking
> > > "are you matching THIS profile".
> > > rather than
> > > "what profile are you"
> > >
> > > that way devices can present multiple faces etc; which is going to be
> > > needed as more and more weird devices come into existence.
> >
> > If by profile you mean a device usage like Mouse, Keyboard, Joystick etc.
> > is your proposal covered by the bit field ioctl exposed by my patch? For
> > example, a device can already expose itself as both a joystick and a
> > mouse (see the hid-input.c changes from the patch).
>
> no that's not what I meant; I really mean asking "can you do THIS
> profile". Example would be a device that could be either a joystick and
> a mouse, or a touchpad and a mouse, but not both a touchpad and a
> joystick. So the app should ask "can you do THESE", and the driver can
> then do anything complex it wants to come to an answer. (Of course a
> generic helper for the simple case is fine)

I think I'm beginning to understand what you mean, but it still seems way too
complicated for my taste. Devices with multiple profiles seems like a static
property more than a dynamic one, so simply splitting up these weirdo devices
into multiple logical devices at registration time seems like a better idea.
Each logical device would then have a separate set of axes, keys and, with my
patch, usages.

- elias