mapping single-key input devices to buttons
Johannes Berg
johannes at sipsolutions.net
Fri Apr 28 15:25:32 PDT 2006
After some discussion on IRC I came up with the following patch.
I *don't* understand why any input devices get a 'button' capability,
and this isn't addressed by my patch. If that capability is removed (I
wouldn't have expected it to be present after discussing this with
davidz), then the check_btn routine needs to add it. It should also
probably handle more types of buttons...
In any case, this patch fixes an issue with test_bit -- a kernel
compatible implementation should be used or junk ensues.
Signed-off-by: Johannes Berg <johannes at sipsolutions.net>
--- a/hal/hald/linux2/probing/probe-input.c
+++ b/hal/hald/linux2/probing/probe-input.c
@@ -42,13 +42,19 @@
#include "shared.h"
-#define test_bit(bit, array) (array[(bit) / 8] & (1 << ((bit) % 8)))
+/* we must use this kernel-compatible implementation */
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x) ((x)%BITS_PER_LONG)
+#define BIT(x) (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
static void
check_abs (int fd, LibHalContext *ctx, const char *udi)
{
- char bitmask[(ABS_MAX + 7) / 8];
- char bitmask_touch[(KEY_MAX + 7) / 8];
+ long bitmask[NBITS(ABS_MAX)];
+ long bitmask_touch[NBITS(KEY_MAX)];
DBusError error;
if (ioctl (fd, EVIOCGBIT(EV_ABS, sizeof (bitmask)), bitmask) < 0) {
@@ -81,7 +87,7 @@
check_key (int fd, LibHalContext *ctx, const char *udi)
{
unsigned int i;
- char bitmask[(KEY_MAX + 7) / 8];
+ long bitmask[NBITS(KEY_MAX)];
int is_keyboard;
DBusError error;
@@ -112,7 +118,7 @@
static void
check_rel (int fd, LibHalContext *ctx, const char *udi)
{
- char bitmask[(REL_MAX + 7) / 8];
+ long bitmask[NBITS(REL_MAX)];
DBusError error;
if (ioctl (fd, EVIOCGBIT(EV_REL, sizeof (bitmask)), bitmask) < 0) {
@@ -132,6 +138,43 @@
;
}
+static void
+check_btn (int fd, LibHalContext *ctx, const char *udi)
+{
+ unsigned int i;
+ long bitmask[NBITS(KEY_MAX)];
+ int buttons = 0, button = KEY_RESERVED;
+ DBusError error;
+
+ if (ioctl (fd, EVIOCGBIT(EV_KEY, sizeof (bitmask)), bitmask) < 0) {
+ fprintf(stderr, "ioctl EVIOCGBIT failed\n");
+ goto out;
+ }
+
+ /* All devices that have just a single button... */
+ for (i = KEY_RESERVED + 1; i < KEY_MAX; i++) {
+ if (test_bit (i, bitmask)) {
+ buttons++;
+ button = i;
+ break;
+ }
+ }
+ if (buttons == 1) {
+ dbus_error_init (&error);
+ switch (button) {
+ case KEY_POWER:
+ libhal_device_property_strlist_append (ctx, udi, "button.type", "power", &error);
+ break;
+ case KEY_EJECTCD:
+ libhal_device_property_strlist_append (ctx, udi, "button.type", "eject-cd", &error);
+ break;
+ }
+ }
+
+out:
+ ;
+}
+
int
main (int argc, char *argv[])
{
@@ -189,6 +232,7 @@
case 17: /* TODO: x86 legacy port; use symbol instead of hardcoded constant */
case 21: /* BUS_HOST, not hotpluggable */
case 23: /* ADB on Apple computers */
+ case 32: /* PMU on Apple computers (unmerged as of now) */
break;
default:
goto out;
@@ -208,6 +252,7 @@
check_abs (fd, ctx, udi);
check_rel (fd, ctx, udi);
check_key (fd, ctx, udi);
+ check_btn (fd, ctx, udi);
/* success */
ret = 0;
More information about the hal
mailing list