diff options
author | Henrik Rydberg <rydberg@euromail.se> | 2010-12-21 17:37:36 +0100 |
---|---|---|
committer | Henrik Rydberg <rydberg@euromail.se> | 2010-12-21 17:50:18 +0100 |
commit | bab20f4538105d9b942858634ef8ce9e962996b7 (patch) | |
tree | e46b6139a20308d93be4bcbc4ba3b56fa975f18d | |
parent | 1bc6faa48907919376b14429f3b802d0d16fc00a (diff) |
Support kernel device properties
In the upcoming 2.6.38 kernel, there is a new device property
bitfield, useful during device setup. This patch adds support
for it.
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
-rw-r--r-- | include/evemu.h | 3 | ||||
-rw-r--r-- | src/evemu-impl.h | 3 | ||||
-rw-r--r-- | src/evemu.c | 94 |
3 files changed, 87 insertions, 13 deletions
diff --git a/include/evemu.h b/include/evemu.h index 698a539..5bfcd3e 100644 --- a/include/evemu.h +++ b/include/evemu.h @@ -41,7 +41,8 @@ void evemu_delete(struct evemu_device *dev); const char *evemu_get_name(const struct evemu_device *dev); -int evemu_has(const struct evemu_device *dev, int type, int code); +int evemu_has_prop(const struct evemu_device *dev, int code); +int evemu_has_event(const struct evemu_device *dev, int type, int code); int evemu_extract(struct evemu_device *dev, int fd); int evemu_write(const struct evemu_device *dev, FILE *fp); diff --git a/src/evemu-impl.h b/src/evemu-impl.h index 2346590..1112e92 100644 --- a/src/evemu-impl.h +++ b/src/evemu-impl.h @@ -11,8 +11,9 @@ struct evemu_device { int version_major, version_minor; char name[UINPUT_MAX_NAME_SIZE]; struct input_id id; + unsigned char prop[EVPLAY_NBYTES]; unsigned char mask[EV_CNT][EVPLAY_NBYTES]; - int bytes[EV_CNT]; + int pbytes, mbytes[EV_CNT]; struct input_absinfo abs[ABS_CNT]; }; diff --git a/src/evemu.c b/src/evemu.c index 53bda86..32f8f06 100644 --- a/src/evemu.c +++ b/src/evemu.c @@ -34,6 +34,17 @@ #include <errno.h> #include <poll.h> +#ifndef UI_SET_PROPBIT +#define UI_SET_PROPBIT _IOW(UINPUT_IOCTL_BASE, 110, int) +#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) +#define INPUT_PROP_POINTER 0x00 +#define INPUT_PROP_DIRECT 0x01 +#define INPUT_PROP_BUTTONPAD 0x02 +#define INPUT_PROP_SEMI_MT 0x03 +#define INPUT_PROP_MAX 0x1f +#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) +#endif + #define SYSCALL(call) while (((call) == -1) && (errno == EINTR)) static void copy_bits(unsigned char *mask, const unsigned long *bits, int bytes) @@ -68,7 +79,12 @@ const char *evemu_get_name(const struct evemu_device *dev) return dev->name; } -int evemu_has(const struct evemu_device *dev, int type, int code) +int evemu_has_prop(const struct evemu_device *dev, int code) +{ + return (dev->prop[code >> 3] >> (code & 7)) & 1; +} + +int evemu_has_event(const struct evemu_device *dev, int type, int code) { return (dev->mask[type][code >> 3] >> (code & 7)) & 1; } @@ -91,16 +107,22 @@ int evemu_extract(struct evemu_device *dev, int fd) if (rc < 0) return rc; + SYSCALL(rc = ioctl(fd, EVIOCGPROP(sizeof(bits)), bits)); + if (rc >= 0) { + copy_bits(dev->prop, bits, rc); + dev->pbytes = rc; + } + for (i = 0; i < EV_CNT; i++) { SYSCALL(rc = ioctl(fd, EVIOCGBIT(i, sizeof(bits)), bits)); if (rc < 0) continue; copy_bits(dev->mask[i], bits, rc); - dev->bytes[i] = rc; + dev->mbytes[i] = rc; } for (i = 0; i < ABS_CNT; i++) { - if (!evemu_has(dev, EV_ABS, i)) + if (!evemu_has_event(dev, EV_ABS, i)) continue; SYSCALL(rc = ioctl(fd, EVIOCGABS(i), &dev->abs[i])); if (rc < 0) @@ -110,6 +132,15 @@ int evemu_extract(struct evemu_device *dev, int fd) return 0; } +static void write_prop(FILE * fp, const unsigned char *mask, int bytes) +{ + int i; + for (i = 0; i < bytes; i += 8) + fprintf(fp, "P: %02x %02x %02x %02x %02x %02x %02x %02x\n", + mask[i], mask[i + 1], mask[i + 2], mask[i + 3], + mask[i + 4], mask[i + 5], mask[i + 6], mask[i + 7]); +} + static void write_mask(FILE * fp, int index, const unsigned char *mask, int bytes) { @@ -136,14 +167,28 @@ int evemu_write(const struct evemu_device *dev, FILE *fp) dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); + write_prop(fp, dev->prop, dev->pbytes); + for (i = 0; i < EV_CNT; i++) - write_mask(fp, i, dev->mask[i], dev->bytes[i]); + write_mask(fp, i, dev->mask[i], dev->mbytes[i]); for (i = 0; i < ABS_CNT; i++) - if (evemu_has(dev, EV_ABS, i)) + if (evemu_has_event(dev, EV_ABS, i)) write_abs(fp, i, &dev->abs[i]); } +static void read_prop(struct evemu_device *dev, FILE *fp) +{ + unsigned int mask[8]; + int i; + while (fscanf(fp, "P: %02x %02x %02x %02x %02x %02x %02x %02x\n", + mask + 0, mask + 1, mask + 2, mask + 3, + mask + 4, mask + 5, mask + 6, mask + 7) > 0) { + for (i = 0; i < 8; i++) + dev->prop[dev->pbytes++] = mask[i]; + } +} + static void read_mask(struct evemu_device *dev, FILE *fp) { unsigned int mask[8]; @@ -152,7 +197,7 @@ static void read_mask(struct evemu_device *dev, FILE *fp) &index, mask + 0, mask + 1, mask + 2, mask + 3, mask + 4, mask + 5, mask + 6, mask + 7) > 0) { for (i = 0; i < 8; i++) - dev->mask[index][dev->bytes[index]++] = mask[i]; + dev->mask[index][dev->mbytes[index]++] = mask[i]; } } @@ -186,6 +231,8 @@ int evemu_read(struct evemu_device *dev, FILE *fp) dev->id.product = product; dev->id.version = version; + read_prop(dev, fp); + read_mask(dev, fp); read_abs(dev, fp); @@ -254,7 +301,14 @@ int evemu_play(FILE *fp, int fd) return 0; } -static int set_bit(int fd, int type, int code) +static int set_prop_bit(int fd, int code) +{ + int ret; + SYSCALL(ret = ioctl(fd, UI_SET_PROPBIT, code)); + return ret; +} + +static int set_event_bit(int fd, int type, int code) { int ret = 0; @@ -291,14 +345,28 @@ static int set_bit(int fd, int type, int code) return ret; } +static int set_prop(const struct evemu_device *dev, int fd) +{ + int bits = 8 * dev->pbytes; + int ret, i; + for (i = 0; i < bits; i++) { + if (!evemu_has_prop(dev, i)) + continue; + ret = set_prop_bit(fd, i); + if (ret < 0) + return ret; + } + return 0; +} + static int set_mask(const struct evemu_device *dev, int type, int fd) { - int bits = 8 * dev->bytes[type]; + int bits = 8 * dev->mbytes[type]; int ret, i; for (i = 0; i < bits; i++) { - if (!evemu_has(dev, type, i)) + if (!evemu_has_event(dev, type, i)) continue; - ret = set_bit(fd, type, i); + ret = set_event_bit(fd, type, i); if (ret < 0) return ret; } @@ -314,7 +382,7 @@ int evemu_create(const struct evemu_device *dev, int fd) memcpy(udev.name, dev->name, sizeof(udev.name)); udev.id = dev->id; for (i = 0; i < ABS_CNT; i++) { - if (!evemu_has(dev, EV_ABS, i)) + if (!evemu_has_event(dev, EV_ABS, i)) continue; udev.absmax[i] = dev->abs[i].maximum; udev.absmin[i] = dev->abs[i].minimum; @@ -322,6 +390,10 @@ int evemu_create(const struct evemu_device *dev, int fd) udev.absflat[i] = dev->abs[i].flat; } + ret = set_prop(dev, fd); + if (ret < 0) + return ret; + for (i = 0; i < EV_CNT; i++) { ret = set_mask(dev, i, fd); if (ret < 0) |