Skip to contentSkip to conversation

Make input drivers y2038 safe

PATCH Superseded Deepa Dinamani 3 participants 16 messages Dec 4, 2017

Subsystems (3)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#1 lore raw

PATCH v3 1/4 uinput: Add ioctl for using monotonic/ boot times

In reply to Deepa Dinamani

struct timeval which is part of struct input_event to maintain the event times is not y2038 safe.

Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz.

Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems.

Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility.

The structure to maintain input events will be changed in a different patch.

---
 drivers/input/misc/uinput.c | 57 ++++++++++++++++++++++++++++++++++++++++++++-
 include/uapi/linux/uinput.h |  3 +++
 2 files changed, 59 insertions(+), 1 deletion(-)
drivers/input/misc/uinput.c +56 -1
index 39ddd9a73feb..5a450dc04a94 100644
@@ -74,6 +74,7 @@ struct uinput_device {
 	unsigned char		tail;
 	struct input_event	buff[UINPUT_BUFFER_SIZE];
 	unsigned int		ff_effects_max;
+	unsigned int		clk_type;
 
 	struct uinput_request	*requests[UINPUT_NUM_REQUESTS];
 	wait_queue_head_t	requests_waitq;
@@ -84,11 +85,26 @@ static int uinput_dev_event(struct input_dev *dev,
 			    unsigned int type, unsigned int code, int value)
 {
 	struct uinput_device	*udev = input_get_drvdata(dev);
+	struct timespec64	ts;
 
 	udev->buff[udev->head].type = type;
 	udev->buff[udev->head].code = code;
 	udev->buff[udev->head].value = value;
-	do_gettimeofday(&udev->buff[udev->head].time);
+
+	switch (udev->clk_type) {
+	case CLOCK_REALTIME:
+		ktime_get_real_ts64(&ts);
+		break;
+	case CLOCK_MONOTONIC:
+		ktime_get_ts64(&ts);
+		break;
+	case CLOCK_BOOTTIME:
+		get_monotonic_boottime64(&ts);
+		break;
+	}
+
+	udev->buff[udev->head].time.tv_sec = ts.tv_sec;
+	udev->buff[udev->head].time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 	udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 
 	wake_up_interruptible(&udev->waitq);
@@ -370,6 +386,7 @@ static int uinput_create_device(struct uinput_device *udev)
 	if (error)
 		goto fail2;
 
+	udev->clk_type = CLOCK_REALTIME;
 	udev->state = UIST_CREATED;
 
 	return 0;
@@ -379,6 +396,38 @@ static int uinput_create_device(struct uinput_device *udev)
 	return error;
 }
 
+static int uinput_set_clk_type(struct uinput_device *udev, unsigned int clkid)
+{
+	unsigned int clk_type;
+
+	if (udev->state != UIST_CREATED)
+		return -EINVAL;
+
+	switch (clkid) {
+	/* Realtime clock is only valid until year 2038.*/
+	case CLOCK_REALTIME:
+		clk_type = CLOCK_REALTIME;
+		break;
+	case CLOCK_MONOTONIC:
+		clk_type = CLOCK_MONOTONIC;
+		break;
+	case CLOCK_BOOTTIME:
+		clk_type = CLOCK_BOOTTIME;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (udev->clk_type != clk_type) {
+		udev->clk_type = clk_type;
+
+		/* Flush pending events */
+		uinput_flush_requests(udev);
+	}
+
+	return 0;
+}
+
 static int uinput_open(struct inode *inode, struct file *file)
 {
 	struct uinput_device *newdev;
@@ -850,6 +899,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 	char			*phys;
 	const char		*name;
 	unsigned int		size;
+	int			clock_id;
 
 	retval = mutex_lock_interruptible(&udev->mutex);
 	if (retval)
@@ -881,6 +931,11 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 		retval = uinput_dev_setup(udev, p);
 		goto out;
 
+	case UI_SET_CLOCKID:
+		if (copy_from_user(&clock_id, p, sizeof(unsigned int)))
+			return -EFAULT;
+		return uinput_set_clk_type(udev, clock_id);
+
 	/* UI_ABS_SETUP is handled in the variable size ioctls */
 
 	case UI_SET_EVBIT:
include/uapi/linux/uinput.h +3 -0
index c9e677e3af1d..78b480d1b6c3 100644
@@ -134,6 +134,9 @@ struct uinput_abs_setup {
  */
 #define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
 
+/* Set clockid to be used for timestamps */
+#define UI_SET_CLOCKID _IOW(UINPUT_IOCTL_BASE, 5, int)
+
 #define UI_SET_EVBIT		_IOW(UINPUT_IOCTL_BASE, 100, int)
 #define UI_SET_KEYBIT		_IOW(UINPUT_IOCTL_BASE, 101, int)
 #define UI_SET_RELBIT		_IOW(UINPUT_IOCTL_BASE, 102, int)
Signature · 1 line
2.14.1
#7 lore raw

PATCH v3 2/4 input: evdev: Replace timeval with timespec64

In reply to Deepa Dinamani

struct timeval is not y2038 safe.

All references to timeval in the kernel will be replaced by y2038 safe structures.
Replace all references to timeval with y2038 safe struct timespec64 here.

struct input_event will be changed in a different patch.

---
 drivers/input/evdev.c | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)
drivers/input/evdev.c +23 -14
index 925571475005..e5dbfc5ff1b0 100644
@@ -156,15 +156,22 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
 static void __evdev_queue_syn_dropped(struct evdev_client *client)
 {
 	struct input_event ev;
-	ktime_t time;
+	struct timespec64 ts;
 
-	time = client->clk_type == EV_CLK_REAL ?
-			ktime_get_real() :
-			client->clk_type == EV_CLK_MONO ?
-				ktime_get() :
-				ktime_get_boottime();
+	switch (client->clk_type) {
+	case EV_CLK_REAL:
+		ktime_get_real_ts64(&ts);
+		break;
+	case EV_CLK_MONO:
+		ktime_get_ts64(&ts);
+		break;
+	case EV_CLK_BOOT:
+		get_monotonic_boottime64(&ts);
+		break;
+	}
 
-	ev.time = ktime_to_timeval(time);
+	ev.time.tv_sec = ts.tv_sec;
+	ev.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 	ev.type = EV_SYN;
 	ev.code = SYN_DROPPED;
 	ev.value = 0;
@@ -257,17 +264,20 @@ static void __pass_event(struct evdev_client *client,
 
 static void evdev_pass_values(struct evdev_client *client,
 			const struct input_value *vals, unsigned int count,
-			ktime_t *ev_time)
+			struct timespec64 *ev_time)
 {
 	struct evdev *evdev = client->evdev;
 	const struct input_value *v;
 	struct input_event event;
+	struct timespec64 ts;
 	bool wakeup = false;
 
 	if (client->revoked)
 		return;
 
-	event.time = ktime_to_timeval(ev_time[client->clk_type]);
+	ts = ev_time[client->clk_type];
+	event.time.tv_sec = ts.tv_sec;
+	event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 
 	/* Interrupts are disabled, just acquire the lock. */
 	spin_lock(&client->buffer_lock);
@@ -304,12 +314,11 @@ static void evdev_events(struct input_handle *handle,
 {
 	struct evdev *evdev = handle->private;
 	struct evdev_client *client;
-	ktime_t ev_time[EV_CLK_MAX];
+	struct timespec64 ev_time[EV_CLK_MAX];
 
-	ev_time[EV_CLK_MONO] = ktime_get();
-	ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
-	ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
-						 TK_OFFS_BOOT);
+	ktime_get_ts64(&ev_time[EV_CLK_MONO]);
+	ktime_get_real_ts64(&ev_time[EV_CLK_REAL]);
+	get_monotonic_boottime64(&ev_time[EV_CLK_BOOT]);
 
 	rcu_read_lock();
 
Signature · 1 line
2.14.1
#8 lore raw

PATCH v3 3/4 input: Deprecate real timestamps beyond year 2106

In reply to Deepa Dinamani

struct timeval is not y2038 safe.
All usage of timeval in the kernel will be replaced by y2038 safe structures.
The change is also necessary as glibc is introducing support for 32 bit applications to use 64 bit time_t. Without this change, many applications would incorrectly interpret values in the struct input_event.
More details about glibc at
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign .

struct input_event maintains time for each input event. Real time timestamps are not ideal for input as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz. Hence, having the input_event.time fields only big enough for monotonic and boot times are sufficient.

The change leaves the representation of struct input_event as is on 64 bit architectures. But uses 2 unsigned long values on 32 bit machines to support real timestamps until year 2106.
This intentionally breaks the ABI on 32 bit architectures and compat handling on 64 bit architectures.
This is as per maintainer's preference to introduce compile time errors rather than run into runtime incompatibilities.

The change requires any 32 bit userspace utilities reading or writing from event nodes to update their reading format to match the new input_event. The changes to the popular libraries will be posted once we agree on the kernel change.

---
 drivers/input/evdev.c        | 14 ++++++++------
 drivers/input/input-compat.c | 11 ++++++-----
 drivers/input/input-compat.h |  3 ++-
 include/uapi/linux/input.h   | 12 +++++++++++-
 4 files changed, 27 insertions(+), 13 deletions(-)
drivers/input/evdev.c +8 -6
index e5dbfc5ff1b0..6172af6476c0 100644
@@ -135,7 +135,8 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
 			continue;
 		} else if (head != i) {
 			/* move entry to fill the gap */
-			client->buffer[head].time = ev->time;
+			client->buffer[head].input_event_sec = ev->input_event_sec;
+			client->buffer[head].input_event_usec = ev->input_event_usec;
 			client->buffer[head].type = ev->type;
 			client->buffer[head].code = ev->code;
 			client->buffer[head].value = ev->value;
@@ -170,8 +171,8 @@ static void __evdev_queue_syn_dropped(struct evdev_client *client)
 		break;
 	}
 
-	ev.time.tv_sec = ts.tv_sec;
-	ev.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+	ev.input_event_sec = ts.tv_sec;
+	ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
 	ev.type = EV_SYN;
 	ev.code = SYN_DROPPED;
 	ev.value = 0;
@@ -248,7 +249,8 @@ static void __pass_event(struct evdev_client *client,
 		 */
 		client->tail = (client->head - 2) & (client->bufsize - 1);
 
-		client->buffer[client->tail].time = event->time;
+		client->buffer[client->tail].input_event_sec = event->input_event_sec;
+		client->buffer[client->tail].input_event_usec = event->input_event_usec;
 		client->buffer[client->tail].type = EV_SYN;
 		client->buffer[client->tail].code = SYN_DROPPED;
 		client->buffer[client->tail].value = 0;
@@ -276,8 +278,8 @@ static void evdev_pass_values(struct evdev_client *client,
 		return;
 
 	ts = ev_time[client->clk_type];
-	event.time.tv_sec = ts.tv_sec;
-	event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+	event.input_event_sec = ts.tv_sec;
+	event.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
 
 	/* Interrupts are disabled, just acquire the lock. */
 	spin_lock(&client->buffer_lock);
drivers/input/input-compat.c +6 -5
index 2186f71c9fe5..419e40b68486 100644
@@ -24,14 +24,15 @@ int input_event_from_user(const char __user *buffer,
 				   sizeof(struct input_event_compat)))
 			return -EFAULT;
 
-		event->time.tv_sec = compat_event.time.tv_sec;
-		event->time.tv_usec = compat_event.time.tv_usec;
+		event->input_event_sec = compat_event.sec;
+		event->input_event_usec = compat_event.usec;
 		event->type = compat_event.type;
 		event->code = compat_event.code;
 		event->value = compat_event.value;
 
 	} else {
-		if (copy_from_user(event, buffer, sizeof(struct input_event)))
+		if (copy_from_user(event, buffer,
+				   sizeof(struct input_event)))
 			return -EFAULT;
 	}
 
@@ -44,8 +45,8 @@ int input_event_to_user(char __user *buffer,
 	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
 		struct input_event_compat compat_event;
 
-		compat_event.time.tv_sec = event->time.tv_sec;
-		compat_event.time.tv_usec = event->time.tv_usec;
+		compat_event.sec = event->input_event_sec;
+		compat_event.usec = event->input_event_usec;
 		compat_event.type = event->type;
 		compat_event.code = event->code;
 		compat_event.value = event->value;
drivers/input/input-compat.h +2 -1
index 1563160a7af3..08cd755e73fd 100644
@@ -18,7 +18,8 @@
 #ifdef CONFIG_COMPAT
 
 struct input_event_compat {
-	struct compat_timeval time;
+	compat_ulong_t sec;
+	compat_ulong_t usec;
 	__u16 type;
 	__u16 code;
 	__s32 value;
include/uapi/linux/input.h +11 -1
index 8c5a0bf6ee35..524978e0f27a 100644
@@ -21,10 +21,20 @@
 
 /*
  * The event structure itself
+ * Note that __USE_TIME_BITS64 is defined by libc based on
+ * application's request to use 64 bit time_t.
  */
-
 struct input_event {
+#if __BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)
 	struct timeval time;
+#define input_event_sec time.tv_sec
+#define input_event_usec time.tv_usec
+#else
+	__kernel_ulong_t __sec;
+	__kernel_ulong_t __usec;
+#define input_event_sec  __sec
+#define input_event_usec __usec
+#endif
 	__u16 type;
 	__u16 code;
 	__s32 value;
Signature · 1 line
2.14.1
#11 lore raw

PATCH v3 4/4 input: serio: Replace timeval by timespec64

In reply to Deepa Dinamani

struct timeval is not y2038 safe.
All references to timeval will be deleted from the kernel to make it y2038 safe.
Replace its uses by y2038 safe struct timespec64.

The timestamps changed here only keep track of delta times. These timestamps are also internal to kernel. Hence, monotonic times are sufficient here.
The unit of the delta times is also changed in certain cases to nanoseconds rather than microseconds. This is in line with timespec64 which keeps time in nanoseconds.

---
 drivers/input/serio/hil_mlc.c    | 37 ++++++++++++++++++-------------------
 drivers/input/serio/hp_sdc.c     | 17 +++++++++--------
 drivers/input/serio/hp_sdc_mlc.c | 10 +++++-----
 include/linux/hil_mlc.h          |  6 +++---
 include/linux/hp_sdc.h           |  6 +++---
 5 files changed, 38 insertions(+), 38 deletions(-)
drivers/input/serio/hil_mlc.c +18 -19
index d66d01c5373b..b5856b4d3717 100644
@@ -274,14 +274,14 @@ static int hilse_match(hil_mlc *mlc, int unused)
 /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
 static int hilse_init_lcv(hil_mlc *mlc, int unused)
 {
-	struct timeval tv;
+	time64_t time;
 
-	do_gettimeofday(&tv);
+	time = ktime_get_seconds();
 
-	if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+	if (mlc->lcv && (time - mlc->lcv_tv.tv_sec) < 5)
 		return -1;
 
-	mlc->lcv_tv = tv;
+	mlc->lcv_tv.tv_sec = time;
 	mlc->lcv = 0;
 
 	return 0;
@@ -466,7 +466,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = {
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
 
 	/* 1  HILSEN_RESTART */
-	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,  0)
+	FUNC(hilse_inc_lcv, 10000,	HILSEN_NEXT,	HILSEN_START,  0)
 	OUT(HIL_CTRL_ONLY)			/* Disable APE */
 	CTS
 
@@ -485,7 +485,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = {
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
 
 	/* 10 HILSEN_DHR2 */
-	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
+	FUNC(hilse_inc_lcv, 10000,	HILSEN_NEXT,	HILSEN_START,	0)
 	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
 	OUT(HIL_PKT_CMD | HIL_CMD_DHR)
 	IN(300000,		HILSEN_DHR2,	HILSEN_DHR2,	HILSEN_NEXT)
@@ -515,7 +515,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = {
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_DOZE,	0)
 
 	/* 22 HILSEN_ACF2 */
-	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
+	FUNC(hilse_inc_lcv, 10000,	HILSEN_NEXT,	HILSEN_START,	0)
 	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
 	IN(20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
 
@@ -572,7 +572,7 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = {
 	OUT(HIL_PKT_CMD | HIL_CMD_RPL)
 	EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT,
 	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
-	FUNC(hilse_operate, 1,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_PROBE)
+	FUNC(hilse_operate, 1000, HILSEN_OPERATE, HILSEN_IFC,	HILSEN_PROBE)
 
 	/* 58 HILSEN_IFCACF */
 	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
@@ -584,7 +584,6 @@ static const struct hilse_node hil_mlc_se[HILSEN_END] = {
 
 static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node)
 {
-
 	switch (node->act) {
 	case HILSE_EXPECT_DISC:
 		mlc->imatch = node->object.packet;
@@ -605,7 +604,7 @@ static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node
 	}
 	mlc->istarted = 1;
 	mlc->intimeout = node->arg;
-	do_gettimeofday(&(mlc->instart));
+	ktime_get_ts64(&(mlc->instart));
 	mlc->icount = 15;
 	memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
 	BUG_ON(down_trylock(&mlc->isem));
@@ -710,7 +709,7 @@ static int hilse_donode(hil_mlc *mlc)
 			break;
 		}
 		mlc->ostarted = 0;
-		do_gettimeofday(&(mlc->instart));
+		ktime_get_ts64(&(mlc->instart));
 		write_unlock_irqrestore(&mlc->lock, flags);
 		nextidx = HILSEN_NEXT;
 		break;
@@ -731,18 +730,18 @@ static int hilse_donode(hil_mlc *mlc)
 #endif
 
 	while (nextidx & HILSEN_SCHED) {
-		struct timeval tv;
+		struct timespec64 ts;
 
 		if (!sched_long)
 			goto sched;
 
-		do_gettimeofday(&tv);
-		tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-		tv.tv_usec -= mlc->instart.tv_usec;
-		if (tv.tv_usec >= mlc->intimeout) goto sched;
-		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC;
-		if (!tv.tv_usec) goto sched;
-		mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
+		ktime_get_ts64(&ts);
+		ts.tv_nsec += NSEC_PER_SEC * (ts.tv_sec - mlc->instart.tv_sec);
+		ts.tv_nsec -= mlc->instart.tv_nsec;
+		if (ts.tv_nsec >= mlc->intimeout) goto sched;
+		ts.tv_nsec = (mlc->intimeout - ts.tv_nsec) * HZ / NSEC_PER_SEC;
+		if (!ts.tv_nsec) goto sched;
+		mod_timer(&hil_mlcs_kicker, jiffies + ts.tv_nsec);
 		break;
 	sched:
 		tasklet_schedule(&hil_mlcs_tasklet);
drivers/input/serio/hp_sdc.c +9 -8
index 1d7c7d81a5ef..c8e3eb1c98c0 100644
@@ -193,7 +193,7 @@ static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
 	curr->seq[curr->idx++] = status;
 	curr->seq[curr->idx++] = data;
 	hp_sdc.rqty -= 2;
-	do_gettimeofday(&hp_sdc.rtv);
+	ktime_get_ts64(&hp_sdc.rtv);
 
 	if (hp_sdc.rqty <= 0) {
 		/* All data has been gathered. */
@@ -306,13 +306,13 @@ static void hp_sdc_tasklet(unsigned long foo)
 	write_lock_irq(&hp_sdc.rtq_lock);
 
 	if (hp_sdc.rcurr >= 0) {
-		struct timeval tv;
+		struct timespec64 ts;
 
-		do_gettimeofday(&tv);
-		if (tv.tv_sec > hp_sdc.rtv.tv_sec)
-			tv.tv_usec += USEC_PER_SEC;
+		ktime_get_ts64(&ts);
+		if (ts.tv_sec > hp_sdc.rtv.tv_sec)
+			ts.tv_nsec += NSEC_PER_SEC;
 
-		if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+		if (ts.tv_nsec - hp_sdc.rtv.tv_nsec > HP_SDC_MAX_REG_DELAY) {
 			hp_sdc_transaction *curr;
 			uint8_t tmp;
 
@@ -322,7 +322,8 @@ static void hp_sdc_tasklet(unsigned long foo)
 			 * it back to the application. and be less verbose.
 			 */
 			printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
-			       (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
+			       (int)(ts.tv_nsec - hp_sdc.rtv.tv_nsec) /
+				     (int)NSEC_PER_USEC);
 			curr->idx += hp_sdc.rqty;
 			hp_sdc.rqty = 0;
 			tmp = curr->seq[curr->actidx];
@@ -551,7 +552,7 @@ unsigned long hp_sdc_put(void)
 
 			/* Start a new read */
 			hp_sdc.rqty = curr->seq[curr->idx];
-			do_gettimeofday(&hp_sdc.rtv);
+			ktime_get_ts64(&hp_sdc.rtv);
 			curr->idx++;
 			/* Still need to lock here in case of spurious irq. */
 			write_lock_irq(&hp_sdc.rtq_lock);
drivers/input/serio/hp_sdc_mlc.c +5 -5
index d50f0678bf47..66020cd931be 100644
@@ -149,7 +149,7 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
 
 	/* Try to down the semaphore */
 	if (down_trylock(&mlc->isem)) {
-		struct timeval tv;
+		struct timespec64 ts;
 		if (priv->emtestmode) {
 			mlc->ipacket[0] =
 				HIL_ERR_INT | (mlc->opacket &
@@ -160,11 +160,11 @@ static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
 			/* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
 			goto wasup;
 		}
-		do_gettimeofday(&tv);
-		tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
-		if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
+		ktime_get_ts64(&ts);
+		ts.tv_nsec += NSEC_PER_SEC * (ts.tv_sec - mlc->instart.tv_sec);
+		if (ts.tv_nsec - mlc->instart.tv_nsec > mlc->intimeout) {
 			/*	printk("!%i %i",
-				tv.tv_usec - mlc->instart.tv_usec,
+				tv.tv_nsec - mlc->instart.tv_nsec,
 				mlc->intimeout);
 			 */
 			rc = 1;
include/linux/hil_mlc.h +3 -3
index 394a8405dd74..f846730d6595 100644
@@ -32,7 +32,7 @@
  */
 
 #include <linux/hil.h>
-#include <linux/time.h>
+#include <linux/time64.h>
 #include <linux/interrupt.h>
 #include <linux/semaphore.h>
 #include <linux/serio.h>
@@ -144,12 +144,12 @@ struct hil_mlc {
 	hil_packet		ipacket[16];
 	hil_packet		imatch;
 	int			icount;
-	struct timeval		instart;
+	struct timespec64	instart;
 	suseconds_t		intimeout;
 
 	int			ddi;	/* Last operational device id */
 	int			lcv;	/* LCV to throttle loops */
-	struct timeval		lcv_tv; /* Time loop was started */
+	struct timespec64	lcv_tv; /* Time loop was started */
 
 	int			di_map[7]; /* Maps below items to live devs */
 	struct hil_mlc_devinfo	di[HIL_MLC_DEVMEM];
include/linux/hp_sdc.h +3 -3
index d392975d8887..d863944f5c0c 100644
@@ -47,9 +47,9 @@
 #endif
 
 
-/* No 4X status reads take longer than this (in usec).
+/* No 4X status reads take longer than this (in nsec).
  */
-#define HP_SDC_MAX_REG_DELAY 20000
+#define HP_SDC_MAX_REG_DELAY 20000000
 
 typedef void (hp_sdc_irqhook) (int irq, void *dev_id, 
 			       uint8_t status, uint8_t data);
@@ -281,7 +281,7 @@ typedef struct {
 	hp_sdc_transaction *tq[HP_SDC_QUEUE_LEN]; /* All pending read/writes */
 
 	int		rcurr, rqty;	/* Current read transact in process */
-	struct timeval	rtv;		/* Time when current read started */
+	struct timespec64 rtv;		/* Monotonic time when current read started */
 	int		wcurr;		/* Current write transact in process */
 
 	int		dev_err;	/* carries status from registration */
Signature · 1 line
2.14.1
#0 lore raw

v3 cover Make input drivers y2038 safe

The series is aimed at making input events y2038 safe. It extends the lifetime of the realtime timestamps in the events to year 2106.
The series is also a necessary update as glibc is set to provide 64 bit time_t support for 32 bit binaries. glibc plan is detailed at https://sourceware.org/glibc/wiki/Y2038ProofnessDesign .

The series is a result of discussions with Arnd Bergmann and Dmitry Torokhov at last Plumbers.

The plan is to deprecate realtime timestamps anyway as they are not appropriate for these timestamps as noted in the patch a80b83b7b8 by John Stultz.

The design also updates the format of the input events read/ written to the device nodes. This breaks 32 bit interface to the input events at compile time as preferred by the maintainer.

The userspace library changes to libevdev, libuinput and mtdev will be posted to the respective mailing groups for review.

Changes from v2:
* Updated the design to break 32 bit interfaces at compile time. Changes from v1:
* Updated changes according to review comments.
* Posted userspace library changes that go along with the series.

Deepa Dinamani (4):
uinput: Add ioctl for using monotonic/ boot times
input: evdev: Replace timeval with timespec64
input: Deprecate real timestamps beyond year 2106
input: serio: Replace timeval by timespec64

 drivers/input/evdev.c            | 43 +++++++++++++++++++-----------
 drivers/input/input-compat.c     | 11 ++++----
 drivers/input/input-compat.h     |  3 ++-
 drivers/input/misc/uinput.c      | 57 +++++++++++++++++++++++++++++++++++++++-
 drivers/input/serio/hil_mlc.c    | 37 +++++++++++++-------------
 drivers/input/serio/hp_sdc.c     | 17 ++++++------
 drivers/input/serio/hp_sdc_mlc.c | 10 +++----
 include/linux/hil_mlc.h          |  6 ++---
 include/linux/hp_sdc.h           |  6 ++---
 include/uapi/linux/input.h       | 12 ++++++++-
 include/uapi/linux/uinput.h      |  3 +++
 11 files changed, 143 insertions(+), 62 deletions(-)

base-commit: b0a84f19a5161418d4360cd57603e94ed489915e

Signature · 1 line
2.14.1
#12 lore raw

Re: [PATCH v3 4/4] input: serio: Replace timeval by timespec64

In reply to Deepa Dinamani
Quoted 12 lines · Deepa Dinamani

struct timeval is not y2038 safe.
All references to timeval will be deleted from the kernel to make it y2038 safe.
Replace its uses by y2038 safe struct timespec64.

The timestamps changed here only keep track of delta times. These timestamps are also internal to kernel. Hence, monotonic times are sufficient here.
The unit of the delta times is also changed in certain cases to nanoseconds rather than microseconds. This is in line with timespec64 which keeps time in nanoseconds.

Quoted 2 lines

Hi Deepa,

I forgot you also had these on your backlog. I submitted a different set of patches
two weeks ago for the two HP drivers, originally by Pingbo Wen, based on a different approach.

That version simplified the code in question a bit more by using jiffies, while your version is a little safer since it changes less. Both versions should be fine though, it's up to Dmitry which one he wants to pick up.

Arnd

#2 lore raw

Re: [PATCH v3 1/4] uinput: Add ioctl for using monotonic/ boot times

In reply to Deepa Dinamani
Quoted 11 lines · Deepa Dinamani

struct timeval which is part of struct input_event to maintain the event times is not y2038 safe.

Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz.

Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems.

Quoted 7 lines

Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility.

The structure to maintain input events will be changed in a different patch.

Based on Peter's comment from when you first posted this,
https://patchwork.kernel.org/patch/9381209/, I tried to follow the code path again, to see if we can come up with a way to avoid introducing a new ioctl.

There is one idea I had now: The two events we get (upload and erase) are both triggered from evdev, which gets called from user space through the EVIOCSFF and EVIOCRMFF ioctls. This device already sets the clock domain. Would it make sense to send the event to the uinput owner using the same clock domain that was set by the evdev owner, or are these two separate by definition?

Arnd

Reviewed-by on v3 3/4
#9 lore raw

Re: [PATCH v3 3/4] input: Deprecate real timestamps beyond year 2106

In reply to Deepa Dinamani
Quoted 25 lines · Deepa Dinamani

struct timeval is not y2038 safe.
All usage of timeval in the kernel will be replaced by y2038 safe structures.
The change is also necessary as glibc is introducing support for 32 bit applications to use 64 bit time_t. Without this change, many applications would incorrectly interpret values in the struct input_event.
More details about glibc at
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign .

struct input_event maintains time for each input event. Real time timestamps are not ideal for input as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz. Hence, having the input_event.time fields only big enough for monotonic and boot times are sufficient.

The change leaves the representation of struct input_event as is on 64 bit architectures. But uses 2 unsigned long values on 32 bit machines to support real timestamps until year 2106.
This intentionally breaks the ABI on 32 bit architectures and compat handling on 64 bit architectures.
This is as per maintainer's preference to introduce compile time errors rather than run into runtime incompatibilities.

Quoted 7 lines

The change requires any 32 bit userspace utilities reading or writing from event nodes to update their reading format to match the new input_event. The changes to the popular libraries will be posted once we agree on the kernel change.

This all looks good, I just have one small request:

include/uapi/linux/input.h line 37

Quoted 12 lines
include/uapi/linux/input.h +9 -1
-
 struct input_event {
+#if __BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)
        struct timeval time;
+#define input_event_sec time.tv_sec
+#define input_event_usec time.tv_usec
+#else
+       __kernel_ulong_t __sec;
+       __kernel_ulong_t __usec;
+#define input_event_sec  __sec
+#define input_event_usec __usec
+#endif

As we are getting closer to removing references to 'struct timeval' from the kernel, could you rephrase that conditional to

#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL)

so that we always see the second path in kernel sources?

It won't change the behavior of the patch, but it means we don't have to patch it again soon afterwards.

I think we need to remove the 'timeval' definition from linux/time.h since it might otherwise conflict with an incompatible user space definition from sys/time.h, if an application includes both and gets built with __USE_TIME_BITS64.

Arnd

#14 lore raw
In reply to Deepa Dinamani
Quoted 14 lines · Deepa Dinamani

The series is aimed at making input events y2038 safe. It extends the lifetime of the realtime timestamps in the events to year 2106.
The series is also a necessary update as glibc is set to provide 64 bit time_t support for 32 bit binaries. glibc plan is detailed at https://sourceware.org/glibc/wiki/Y2038ProofnessDesign .

The series is a result of discussions with Arnd Bergmann and Dmitry Torokhov at last Plumbers.

The plan is to deprecate realtime timestamps anyway as they are not appropriate for these timestamps as noted in the patch a80b83b7b8 by John Stultz.

Quoted 6 lines

The design also updates the format of the input events read/ written to the device nodes. This breaks 32 bit interface to the input events at compile time as preferred by the maintainer.

The userspace library changes to libevdev, libuinput and mtdev will be posted to the respective mailing groups for review.

Thanks a lot for following up on this!

Just to clarify, the four patches are all independent of one another and can be applied in any order, right? I had some comments for some patches, and I don't want to hold up the other ones from getting merged this time.

Arnd

#3 lore raw

Re: [PATCH v3 1/4] uinput: Add ioctl for using monotonic/ boot times

In reply to Arnd Bergmann
Quoted 25 lines · Arnd Bergmann
Quoted 11 lines · Deepa Dinamani

struct timeval which is part of struct input_event to maintain the event times is not y2038 safe.

Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz.

Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems.

Quoted 7 lines

Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility.

The structure to maintain input events will be changed in a different patch.

Based on Peter's comment from when you first posted this,
https://patchwork.kernel.org/patch/9381209/, I tried to follow the code path again, to see if we can come up with a way to avoid introducing a new ioctl.

Quoted 8 lines

There is one idea I had now: The two events we get (upload and erase) are both triggered from evdev, which gets called from user space through the EVIOCSFF and EVIOCRMFF ioctls. This device already sets the clock domain. Would it make sense to send the event to the uinput owner using the same clock domain that was set by the evdev owner, or are these two separate by definition?

uinput and evdev are two separate drivers. One is to write events to a virtual device and the other is to read from any input device. I considered both of these separate as the two events.
Let me know if you guys prefer something else.

We could also do away with this patch and just say we extend time till 2106 as we change struct input_event if we are okay with using realtime only for uinput.

-Deepa
_______________________________________________
Y2038 mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/y2038

#13 lore raw

Re: [PATCH v3 4/4] input: serio: Replace timeval by timespec64

In reply to Arnd Bergmann
Quoted 18 lines · Arnd Bergmann
Quoted 12 lines · Deepa Dinamani

struct timeval is not y2038 safe.
All references to timeval will be deleted from the kernel to make it y2038 safe.
Replace its uses by y2038 safe struct timespec64.

The timestamps changed here only keep track of delta times. These timestamps are also internal to kernel. Hence, monotonic times are sufficient here.
The unit of the delta times is also changed in certain cases to nanoseconds rather than microseconds. This is in line with timespec64 which keeps time in nanoseconds.

Quoted 2 lines

Hi Deepa,

Quoted 8 lines

I forgot you also had these on your backlog. I submitted a different set of patches
two weeks ago for the two HP drivers, originally by Pingbo Wen, based on a different approach.

That version simplified the code in question a bit more by using jiffies, while your version is a little safer since it changes less. Both versions should be fine though, it's up to Dmitry which one he wants to pick up.

Dmitry, please let me know if you would like this version. If not, I can drop the patch when I post an update.

-Deepa

#10 lore raw

Re: [PATCH v3 3/4] input: Deprecate real timestamps beyond year 2106

In reply to Arnd Bergmann
Quoted 54 lines · Arnd Bergmann
Quoted 25 lines · Deepa Dinamani

struct timeval is not y2038 safe.
All usage of timeval in the kernel will be replaced by y2038 safe structures.
The change is also necessary as glibc is introducing support for 32 bit applications to use 64 bit time_t. Without this change, many applications would incorrectly interpret values in the struct input_event.
More details about glibc at
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign .

struct input_event maintains time for each input event. Real time timestamps are not ideal for input as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz. Hence, having the input_event.time fields only big enough for monotonic and boot times are sufficient.

The change leaves the representation of struct input_event as is on 64 bit architectures. But uses 2 unsigned long values on 32 bit machines to support real timestamps until year 2106.
This intentionally breaks the ABI on 32 bit architectures and compat handling on 64 bit architectures.
This is as per maintainer's preference to introduce compile time errors rather than run into runtime incompatibilities.

Quoted 7 lines

The change requires any 32 bit userspace utilities reading or writing from event nodes to update their reading format to match the new input_event. The changes to the popular libraries will be posted once we agree on the kernel change.

This all looks good, I just have one small request:

include/uapi/linux/input.h line 37

Quoted 12 lines
include/uapi/linux/input.h +9 -1
-
 struct input_event {
+#if __BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)
        struct timeval time;
+#define input_event_sec time.tv_sec
+#define input_event_usec time.tv_usec
+#else
+       __kernel_ulong_t __sec;
+       __kernel_ulong_t __usec;
+#define input_event_sec  __sec
+#define input_event_usec __usec
+#endif

As we are getting closer to removing references to 'struct timeval' from the kernel, could you rephrase that conditional to

Quoted 1 line

#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL)

Thanks. Will do.

I just noticed that I left out the change to uinput for this patch. I will include that in the update as well.

-Deepa

#15 lore raw
In reply to Arnd Bergmann
Quoted 22 lines · Arnd Bergmann
Quoted 14 lines · Deepa Dinamani

The series is aimed at making input events y2038 safe. It extends the lifetime of the realtime timestamps in the events to year 2106.
The series is also a necessary update as glibc is set to provide 64 bit time_t support for 32 bit binaries. glibc plan is detailed at https://sourceware.org/glibc/wiki/Y2038ProofnessDesign .

The series is a result of discussions with Arnd Bergmann and Dmitry Torokhov at last Plumbers.

The plan is to deprecate realtime timestamps anyway as they are not appropriate for these timestamps as noted in the patch a80b83b7b8 by John Stultz.

Quoted 6 lines

The design also updates the format of the input events read/ written to the device nodes. This breaks 32 bit interface to the input events at compile time as preferred by the maintainer.

The userspace library changes to libevdev, libuinput and mtdev will be posted to the respective mailing groups for review.

Quoted 6 lines

Thanks a lot for following up on this!

Just to clarify, the four patches are all independent of one another and can be applied in any order, right? I had some comments for some patches, and I don't want to hold up the other ones from getting merged this time.

There is some minor dependency between patches [2/4] and [3/4]. Patch [3/4] might not apply cleanly without patch [2/4].
But, others are independent.

-Deepa

#4 lore raw

Re: [PATCH v3 1/4] uinput: Add ioctl for using monotonic/ boot times

In reply to Deepa Dinamani
Quoted 35 lines · Deepa Dinamani
Quoted 25 lines · Arnd Bergmann
Quoted 11 lines · Deepa Dinamani

struct timeval which is part of struct input_event to maintain the event times is not y2038 safe.

Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz.

Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems.

Quoted 7 lines

Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility.

The structure to maintain input events will be changed in a different patch.

Based on Peter's comment from when you first posted this,
https://patchwork.kernel.org/patch/9381209/, I tried to follow the code path again, to see if we can come up with a way to avoid introducing a new ioctl.

Quoted 8 lines

There is one idea I had now: The two events we get (upload and erase) are both triggered from evdev, which gets called from user space through the EVIOCSFF and EVIOCRMFF ioctls. This device already sets the clock domain. Would it make sense to send the event to the uinput owner using the same clock domain that was set by the evdev owner, or are these two separate by definition?

Quoted 4 lines

uinput and evdev are two separate drivers. One is to write events to a virtual device and the other is to read from any input device. I considered both of these separate as the two events.
Let me know if you guys prefer something else.

Ok

Quoted 3 lines

We could also do away with this patch and just say we extend time till 2106 as we change struct input_event if we are okay with using realtime only for uinput.

Another option might be to use monotonic times unconditionally in uinput. The DRM drivers actually did this conversion successfully:
they changed the timestamps from real-time to monotonic-time and added a module parameter to revert back to the old behavior. In the end (after a few years) it turned out that nothing relied on real time anyway, so I sent a patch to kill off the option.

It seems rather likely that this is in the same category: the user space reading the events either doesn't access the timestamps at all, or is only interested in relative times, not absolute ones.

The one program that I found that reads from /dev/uinput is this one: http://svn.navi.cx/misc/trunk/inputpipe/src/
Here, all input_events get relayed between two machines, so an input device on one can be used on the other across a socket. The input_event data that we get from uinput gets either interpreted (ignoring the timestamp) or pushed into the evdev interface on the other machine, which then ignores the timestamp in the kernel and creates a new stamp instead.

Arnd

#5 lore raw

Re: [PATCH v3 1/4] uinput: Add ioctl for using monotonic/ boot times

Quoted 58 lines · Arnd Bergmann
Quoted 35 lines · Deepa Dinamani
Quoted 25 lines · Arnd Bergmann
Quoted 11 lines · Deepa Dinamani

struct timeval which is part of struct input_event to maintain the event times is not y2038 safe.

Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz.

Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems.

Quoted 7 lines

Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility.

The structure to maintain input events will be changed in a different patch.

Based on Peter's comment from when you first posted this,
https://patchwork.kernel.org/patch/9381209/, I tried to follow the code path again, to see if we can come up with a way to avoid introducing a new ioctl.

Quoted 8 lines

There is one idea I had now: The two events we get (upload and erase) are both triggered from evdev, which gets called from user space through the EVIOCSFF and EVIOCRMFF ioctls. This device already sets the clock domain. Would it make sense to send the event to the uinput owner using the same clock domain that was set by the evdev owner, or are these two separate by definition?

Quoted 4 lines

uinput and evdev are two separate drivers. One is to write events to a virtual device and the other is to read from any input device. I considered both of these separate as the two events.
Let me know if you guys prefer something else.

Ok

Quoted 3 lines

We could also do away with this patch and just say we extend time till 2106 as we change struct input_event if we are okay with using realtime only for uinput.

Another option might be to use monotonic times unconditionally in uinput. The DRM drivers actually did this conversion successfully:
they changed the timestamps from real-time to monotonic-time and added a module parameter to revert back to the old behavior. In the end (after a few years) it turned out that nothing relied on real time anyway, so I sent a patch to kill off the option.

It seems rather likely that this is in the same category: the user space reading the events either doesn't access the timestamps at all, or is only interested in relative times, not absolute ones.

Quoted 8 lines

The one program that I found that reads from /dev/uinput is this one: http://svn.navi.cx/misc/trunk/inputpipe/src/
Here, all input_events get relayed between two machines, so an input device on one can be used on the other across a socket. The input_event data that we get from uinput gets either interpreted (ignoring the timestamp) or pushed into the evdev interface on the other machine, which then ignores the timestamp in the kernel and creates a new stamp instead.

Right. I considered using just monotonic times before. I decided against it as John did not change the default times to monotonic times in a80b83b7b8.
But, if nobody really cares about the actual timestamps and only relative timestamps matter, this might be a better option.

-Deepa

maintainer
#6 lore raw

Re: [PATCH v3 1/4] uinput: Add ioctl for using monotonic/ boot times

Quoted 68 lines · Deepa Dinamani
Quoted 58 lines · Arnd Bergmann
Quoted 35 lines · Deepa Dinamani
Quoted 25 lines · Arnd Bergmann
Quoted 11 lines · Deepa Dinamani

struct timeval which is part of struct input_event to maintain the event times is not y2038 safe.

Real time timestamps are also not ideal for input_event as this time can go backwards as noted in the patch a80b83b7b8 by John Stultz.

Arnd Bergmann suggested deprecating real time and using monotonic or other timers for all input_event times as a solution to both the above problems.

Quoted 7 lines

Add a new ioctl to let the user dictate the kind of time to be used for input events. This is similar to the evdev implementation of the feature. Realtime is still the default time. This is to maintain backward compatibility.

The structure to maintain input events will be changed in a different patch.

Based on Peter's comment from when you first posted this,
https://patchwork.kernel.org/patch/9381209/, I tried to follow the code path again, to see if we can come up with a way to avoid introducing a new ioctl.

Quoted 8 lines

There is one idea I had now: The two events we get (upload and erase) are both triggered from evdev, which gets called from user space through the EVIOCSFF and EVIOCRMFF ioctls. This device already sets the clock domain. Would it make sense to send the event to the uinput owner using the same clock domain that was set by the evdev owner, or are these two separate by definition?

Quoted 4 lines

uinput and evdev are two separate drivers. One is to write events to a virtual device and the other is to read from any input device. I considered both of these separate as the two events.
Let me know if you guys prefer something else.

Ok

Quoted 3 lines

We could also do away with this patch and just say we extend time till 2106 as we change struct input_event if we are okay with using realtime only for uinput.

Another option might be to use monotonic times unconditionally in uinput. The DRM drivers actually did this conversion successfully:
they changed the timestamps from real-time to monotonic-time and added a module parameter to revert back to the old behavior. In the end (after a few years) it turned out that nothing relied on real time anyway, so I sent a patch to kill off the option.

It seems rather likely that this is in the same category: the user space reading the events either doesn't access the timestamps at all, or is only interested in relative times, not absolute ones.

Quoted 8 lines

The one program that I found that reads from /dev/uinput is this one: http://svn.navi.cx/misc/trunk/inputpipe/src/
Here, all input_events get relayed between two machines, so an input device on one can be used on the other across a socket. The input_event data that we get from uinput gets either interpreted (ignoring the timestamp) or pushed into the evdev interface on the other machine, which then ignores the timestamp in the kernel and creates a new stamp instead.

Quoted 5 lines

Right. I considered using just monotonic times before. I decided against it as John did not change the default times to monotonic times in a80b83b7b8.
But, if nobody really cares about the actual timestamps and only relative timestamps matter, this might be a better option.

The timestamps in the kernel->userspace path in uinput are only for force feedback control messages; userspace is not supposed to analyze them but simply execute the instructions as they come in. I think we should switch to the monotonic time and see if someone screams at us. Then we can either add an option or see if there are other means of resolving the issue.

Thanks.

Signature · 1 line
Dmitry