Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input fixes from Dmitry Torokhov:
 "Just a few small fixups here"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: imx_sc_key - only take the valid data from SCU firmware as key state
  Input: add safety guards to input_set_keycode()
  Input: input_event - fix struct padding on sparc64
  Input: uinput - always report EPOLLOUT
This commit is contained in:
Linus Torvalds 2020-01-09 15:37:40 -08:00
commit b5b3159cff
5 changed files with 43 additions and 25 deletions

View file

@ -224,13 +224,13 @@ static void __pass_event(struct evdev_client *client,
*/ */
client->tail = (client->head - 2) & (client->bufsize - 1); client->tail = (client->head - 2) & (client->bufsize - 1);
client->buffer[client->tail].input_event_sec = client->buffer[client->tail] = (struct input_event) {
event->input_event_sec; .input_event_sec = event->input_event_sec,
client->buffer[client->tail].input_event_usec = .input_event_usec = event->input_event_usec,
event->input_event_usec; .type = EV_SYN,
client->buffer[client->tail].type = EV_SYN; .code = SYN_DROPPED,
client->buffer[client->tail].code = SYN_DROPPED; .value = 0,
client->buffer[client->tail].value = 0; };
client->packet_head = client->tail; client->packet_head = client->tail;
} }

View file

@ -878,16 +878,18 @@ static int input_default_setkeycode(struct input_dev *dev,
} }
} }
__clear_bit(*old_keycode, dev->keybit); if (*old_keycode <= KEY_MAX) {
__set_bit(ke->keycode, dev->keybit); __clear_bit(*old_keycode, dev->keybit);
for (i = 0; i < dev->keycodemax; i++) {
for (i = 0; i < dev->keycodemax; i++) { if (input_fetch_keycode(dev, i) == *old_keycode) {
if (input_fetch_keycode(dev, i) == *old_keycode) { __set_bit(*old_keycode, dev->keybit);
__set_bit(*old_keycode, dev->keybit); /* Setting the bit twice is useless, so break */
break; /* Setting the bit twice is useless, so break */ break;
}
} }
} }
__set_bit(ke->keycode, dev->keybit);
return 0; return 0;
} }
@ -943,9 +945,13 @@ int input_set_keycode(struct input_dev *dev,
* Simulate keyup event if keycode is not present * Simulate keyup event if keycode is not present
* in the keymap anymore * in the keymap anymore
*/ */
if (test_bit(EV_KEY, dev->evbit) && if (old_keycode > KEY_MAX) {
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) && dev_warn(dev->dev.parent ?: &dev->dev,
__test_and_clear_bit(old_keycode, dev->key)) { "%s: got too big old keycode %#x\n",
__func__, old_keycode);
} else if (test_bit(EV_KEY, dev->evbit) &&
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(old_keycode, dev->key)) {
struct input_value vals[] = { struct input_value vals[] = {
{ EV_KEY, old_keycode, 0 }, { EV_KEY, old_keycode, 0 },
input_value_sync input_value_sync

View file

@ -78,7 +78,13 @@ static void imx_sc_check_for_events(struct work_struct *work)
return; return;
} }
state = (bool)msg.state; /*
* The response data from SCU firmware is 4 bytes,
* but ONLY the first byte is the key state, other
* 3 bytes could be some dirty data, so we should
* ONLY take the first byte as key state.
*/
state = (bool)(msg.state & 0xff);
if (state ^ priv->keystate) { if (state ^ priv->keystate) {
priv->keystate = state; priv->keystate = state;

View file

@ -74,12 +74,16 @@ static int uinput_dev_event(struct input_dev *dev,
struct uinput_device *udev = input_get_drvdata(dev); struct uinput_device *udev = input_get_drvdata(dev);
struct timespec64 ts; struct timespec64 ts;
udev->buff[udev->head].type = type;
udev->buff[udev->head].code = code;
udev->buff[udev->head].value = value;
ktime_get_ts64(&ts); ktime_get_ts64(&ts);
udev->buff[udev->head].input_event_sec = ts.tv_sec;
udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC; udev->buff[udev->head] = (struct input_event) {
.input_event_sec = ts.tv_sec,
.input_event_usec = ts.tv_nsec / NSEC_PER_USEC,
.type = type,
.code = code,
.value = value,
};
udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE; udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
wake_up_interruptible(&udev->waitq); wake_up_interruptible(&udev->waitq);
@ -689,13 +693,14 @@ static ssize_t uinput_read(struct file *file, char __user *buffer,
static __poll_t uinput_poll(struct file *file, poll_table *wait) static __poll_t uinput_poll(struct file *file, poll_table *wait)
{ {
struct uinput_device *udev = file->private_data; struct uinput_device *udev = file->private_data;
__poll_t mask = EPOLLOUT | EPOLLWRNORM; /* uinput is always writable */
poll_wait(file, &udev->waitq, wait); poll_wait(file, &udev->waitq, wait);
if (udev->head != udev->tail) if (udev->head != udev->tail)
return EPOLLIN | EPOLLRDNORM; mask |= EPOLLIN | EPOLLRDNORM;
return EPOLLOUT | EPOLLWRNORM; return mask;
} }
static int uinput_release(struct inode *inode, struct file *file) static int uinput_release(struct inode *inode, struct file *file)

View file

@ -34,6 +34,7 @@ struct input_event {
__kernel_ulong_t __sec; __kernel_ulong_t __sec;
#if defined(__sparc__) && defined(__arch64__) #if defined(__sparc__) && defined(__arch64__)
unsigned int __usec; unsigned int __usec;
unsigned int __pad;
#else #else
__kernel_ulong_t __usec; __kernel_ulong_t __usec;
#endif #endif