From 3158106685acac8f8d4e74a17b974f160fe77c0b Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 6 Sep 2005 15:19:06 -0700 Subject: [PATCH] [PATCH] Input: Add a new switch event type The corgi keyboard has need of a switch event type with slightly type to the input system as recommended by the input maintainer. Signed-off-by: Richard Purdie Cc: Vojtech Pavlik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/input/evdev.c | 8 ++++++++ drivers/input/input.c | 11 +++++++++++ drivers/input/keyboard/corgikbd.c | 9 +++++---- include/linux/input.h | 25 +++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f8b278d3559b..19c14c4beb44 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -393,6 +393,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case EV_LED: bits = dev->ledbit; len = LED_MAX; break; case EV_SND: bits = dev->sndbit; len = SND_MAX; break; case EV_FF: bits = dev->ffbit; len = FF_MAX; break; + case EV_SW: bits = dev->swbit; len = SW_MAX; break; default: return -EINVAL; } len = NBITS(len) * sizeof(long); @@ -421,6 +422,13 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return copy_to_user(p, dev->snd, len) ? -EFAULT : len; } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) { + int len; + len = NBITS(SW_MAX) * sizeof(long); + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user(p, dev->sw, len) ? -EFAULT : len; + } + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { int len; if (!dev->name) return -ENOENT; diff --git a/drivers/input/input.c b/drivers/input/input.c index a275211c8e1e..88636a204525 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -89,6 +89,15 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in break; + case EV_SW: + + if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value) + return; + + change_bit(code, dev->sw); + + break; + case EV_ABS: if (code > ABS_MAX || !test_bit(code, dev->absbit)) @@ -402,6 +411,7 @@ static void input_call_hotplug(char *verb, struct input_dev *dev) SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED); SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND); SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF); + SPRINTF_BIT_A2(swbit, "SW=", SW_MAX, EV_SW); envp[i++] = NULL; @@ -490,6 +500,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); + SPRINTF_BIT_B2(swbit, "SW=", SW_MAX, EV_SW); len += sprintf(buf + len, "\n"); diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index 767e853dd766..cd4b6e795013 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -249,9 +249,8 @@ static void corgikbd_hinge_timer(unsigned long data) if (hinge_count >= HINGE_STABLE_COUNT) { spin_lock_irqsave(&corgikbd_data->lock, flags); - input_report_key(&corgikbd_data->input, corgikbd_data->keycode[125], (sharpsl_hinge_state == 0x00)); - input_report_key(&corgikbd_data->input, corgikbd_data->keycode[126], (sharpsl_hinge_state == 0x08)); - input_report_key(&corgikbd_data->input, corgikbd_data->keycode[127], (sharpsl_hinge_state == 0x0c)); + input_report_switch(&corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); + input_report_switch(&corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); input_sync(&corgikbd_data->input); spin_unlock_irqrestore(&corgikbd_data->lock, flags); @@ -321,7 +320,7 @@ static int __init corgikbd_probe(struct device *dev) corgikbd->input.id.vendor = 0x0001; corgikbd->input.id.product = 0x0001; corgikbd->input.id.version = 0x0100; - corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR); + corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW); corgikbd->input.keycode = corgikbd->keycode; corgikbd->input.keycodesize = sizeof(unsigned char); corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode); @@ -330,6 +329,8 @@ static int __init corgikbd_probe(struct device *dev) for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) set_bit(corgikbd->keycode[i], corgikbd->input.keybit); clear_bit(0, corgikbd->input.keybit); + set_bit(SW_0, corgikbd->input.swbit); + set_bit(SW_1, corgikbd->input.swbit); input_register_device(&corgikbd->input); mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); diff --git a/include/linux/input.h b/include/linux/input.h index bdc53c6cc962..4767e5429534 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -66,6 +66,7 @@ struct input_absinfo { #define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global keystate */ #define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */ #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 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 */ @@ -86,6 +87,7 @@ struct input_absinfo { #define EV_REL 0x02 #define EV_ABS 0x03 #define EV_MSC 0x04 +#define EV_SW 0x05 #define EV_LED 0x11 #define EV_SND 0x12 #define EV_REP 0x14 @@ -550,6 +552,20 @@ struct input_absinfo { #define ABS_MISC 0x28 #define ABS_MAX 0x3f +/* + * Switch events + */ + +#define SW_0 0x00 +#define SW_1 0x01 +#define SW_2 0x02 +#define SW_3 0x03 +#define SW_4 0x04 +#define SW_5 0x05 +#define SW_6 0x06 +#define SW_7 0x07 +#define SW_MAX 0x0f + /* * Misc events */ @@ -824,6 +840,7 @@ struct input_dev { unsigned long ledbit[NBITS(LED_MAX)]; unsigned long sndbit[NBITS(SND_MAX)]; unsigned long ffbit[NBITS(FF_MAX)]; + unsigned long swbit[NBITS(SW_MAX)]; int ff_effects_max; unsigned int keycodemax; @@ -844,6 +861,7 @@ struct input_dev { unsigned long key[NBITS(KEY_MAX)]; unsigned long led[NBITS(LED_MAX)]; unsigned long snd[NBITS(SND_MAX)]; + unsigned long sw[NBITS(SW_MAX)]; int absmax[ABS_MAX + 1]; int absmin[ABS_MAX + 1]; @@ -886,6 +904,7 @@ struct input_dev { #define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200 #define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400 #define INPUT_DEVICE_ID_MATCH_FFBIT 0x800 +#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000 #define INPUT_DEVICE_ID_MATCH_DEVICE\ (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT) @@ -906,6 +925,7 @@ struct input_device_id { unsigned long ledbit[NBITS(LED_MAX)]; unsigned long sndbit[NBITS(SND_MAX)]; unsigned long ffbit[NBITS(FF_MAX)]; + unsigned long swbit[NBITS(SW_MAX)]; unsigned long driver_info; }; @@ -998,6 +1018,11 @@ static inline void input_report_ff_status(struct input_dev *dev, unsigned int co input_event(dev, EV_FF_STATUS, code, value); } +static inline void input_report_switch(struct input_dev *dev, unsigned int code, int value) +{ + input_event(dev, EV_SW, code, !!value); +} + static inline void input_regs(struct input_dev *dev, struct pt_regs *regs) { dev->regs = regs; -- 2.34.1