[PATCH] Input: Add REP_MAX_COUNT to autorepeat parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add REP_MAX_COUNT to autorepeat parameters. This enables an input device to be
configured for maximum autorepeat count, so that a keypress is not repeated
forever. This is important for Bluetooth keyboards and remote controls that may
lose the Bluetooth link at any time, e.g. right after sending a key-down event
but before sending the corresponding key-up event.

Signed-off-by: Petri Gynther <pgynther@xxxxxxxxxx>
---
 drivers/input/evdev.c      | 11 ++++++++++-
 drivers/input/input.c      |  6 +++++-
 include/linux/input.h      |  1 +
 include/uapi/linux/input.h |  5 ++++-
 4 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a06e125..be1887e 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -847,25 +847,34 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 		return 0;
 
 	case EVIOCGREP:
+	case EVIOCGREP_V2:
 		if (!test_bit(EV_REP, dev->evbit))
 			return -ENOSYS;
 		if (put_user(dev->rep[REP_DELAY], ip))
 			return -EFAULT;
 		if (put_user(dev->rep[REP_PERIOD], ip + 1))
 			return -EFAULT;
+		if (cmd == EVIOCGREP_V2 &&
+		    put_user(dev->rep[REP_MAX_COUNT], ip + 2))
+			return -EFAULT;
 		return 0;
 
 	case EVIOCSREP:
+	case EVIOCSREP_V2:
 		if (!test_bit(EV_REP, dev->evbit))
 			return -ENOSYS;
 		if (get_user(u, ip))
 			return -EFAULT;
 		if (get_user(v, ip + 1))
 			return -EFAULT;
+		if (cmd == EVIOCSREP_V2 && get_user(t, ip + 2))
+			return -EFAULT;
 
 		input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
 		input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
-
+		if (cmd == EVIOCSREP_V2)
+			input_inject_event(&evdev->handle, EV_REP,
+					   REP_MAX_COUNT, t);
 		return 0;
 
 	case EVIOCRMFF:
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 1c4c0db..a5314c5 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -78,6 +78,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code)
 	    dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
 	    dev->timer.data) {
 		dev->repeat_key = code;
+		dev->repeat_count = 0;
 		mod_timer(&dev->timer,
 			  jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
 	}
@@ -191,7 +192,8 @@ static void input_repeat_key(unsigned long data)
 
 		input_pass_values(dev, vals, ARRAY_SIZE(vals));
 
-		if (dev->rep[REP_PERIOD])
+		if (dev->rep[REP_PERIOD] && (dev->rep[REP_MAX_COUNT] == 0 ||
+		    ++dev->repeat_count <= dev->rep[REP_MAX_COUNT]))
 			mod_timer(&dev->timer, jiffies +
 					msecs_to_jiffies(dev->rep[REP_PERIOD]));
 	}
@@ -1640,6 +1642,7 @@ static void input_dev_toggle(struct input_dev *dev, bool activate)
 	if (activate && test_bit(EV_REP, dev->evbit)) {
 		dev->event(dev, EV_REP, REP_PERIOD, dev->rep[REP_PERIOD]);
 		dev->event(dev, EV_REP, REP_DELAY, dev->rep[REP_DELAY]);
+		dev->event(dev, EV_REP, REP_MAX_COUNT, dev->rep[REP_MAX_COUNT]);
 	}
 }
 
@@ -2110,6 +2113,7 @@ int input_register_device(struct input_dev *dev)
 		dev->timer.function = input_repeat_key;
 		dev->rep[REP_DELAY] = 250;
 		dev->rep[REP_PERIOD] = 33;
+		dev->rep[REP_MAX_COUNT] = 0;
 	}
 
 	if (!dev->getkeycode)
diff --git a/include/linux/input.h b/include/linux/input.h
index 82ce323..5f98714 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -151,6 +151,7 @@ struct input_dev {
 	struct ff_device *ff;
 
 	unsigned int repeat_key;
+	unsigned int repeat_count;
 	struct timer_list timer;
 
 	int rep[REP_CNT];
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index bd24470..d7e08ff 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -100,7 +100,9 @@ struct input_keymap_entry {
 #define EVIOCGVERSION		_IOR('E', 0x01, int)			/* get driver version */
 #define EVIOCGID		_IOR('E', 0x02, struct input_id)	/* get device ID */
 #define EVIOCGREP		_IOR('E', 0x03, unsigned int[2])	/* get repeat settings */
+#define EVIOCGREP_V2		_IOR('E', 0x03, unsigned int[3])
 #define EVIOCSREP		_IOW('E', 0x03, unsigned int[2])	/* set repeat settings */
+#define EVIOCSREP_V2		_IOW('E', 0x03, unsigned int[3])
 
 #define EVIOCGKEYCODE		_IOR('E', 0x04, unsigned int[2])        /* get keycode */
 #define EVIOCGKEYCODE_V2	_IOR('E', 0x04, struct input_keymap_entry)
@@ -900,7 +902,8 @@ struct input_keymap_entry {
 
 #define REP_DELAY		0x00
 #define REP_PERIOD		0x01
-#define REP_MAX			0x01
+#define REP_MAX_COUNT		0x02
+#define REP_MAX			0x02
 #define REP_CNT			(REP_MAX+1)
 
 /*
-- 
1.9.1.423.g4596e3a

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux