162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Event char devices, giving access to raw input device events. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 1999-2002 Vojtech Pavlik 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define EVDEV_MINOR_BASE 64 1162306a36Sopenharmony_ci#define EVDEV_MINORS 32 1262306a36Sopenharmony_ci#define EVDEV_MIN_BUFFER_SIZE 64U 1362306a36Sopenharmony_ci#define EVDEV_BUF_PACKETS 8 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/poll.h> 1662306a36Sopenharmony_ci#include <linux/sched.h> 1762306a36Sopenharmony_ci#include <linux/slab.h> 1862306a36Sopenharmony_ci#include <linux/vmalloc.h> 1962306a36Sopenharmony_ci#include <linux/mm.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/init.h> 2262306a36Sopenharmony_ci#include <linux/input/mt.h> 2362306a36Sopenharmony_ci#include <linux/major.h> 2462306a36Sopenharmony_ci#include <linux/device.h> 2562306a36Sopenharmony_ci#include <linux/cdev.h> 2662306a36Sopenharmony_ci#include "input-compat.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistruct evdev { 2962306a36Sopenharmony_ci int open; 3062306a36Sopenharmony_ci struct input_handle handle; 3162306a36Sopenharmony_ci struct evdev_client __rcu *grab; 3262306a36Sopenharmony_ci struct list_head client_list; 3362306a36Sopenharmony_ci spinlock_t client_lock; /* protects client_list */ 3462306a36Sopenharmony_ci struct mutex mutex; 3562306a36Sopenharmony_ci struct device dev; 3662306a36Sopenharmony_ci struct cdev cdev; 3762306a36Sopenharmony_ci bool exist; 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct evdev_client { 4162306a36Sopenharmony_ci unsigned int head; 4262306a36Sopenharmony_ci unsigned int tail; 4362306a36Sopenharmony_ci unsigned int packet_head; /* [future] position of the first element of next packet */ 4462306a36Sopenharmony_ci spinlock_t buffer_lock; /* protects access to buffer, head and tail */ 4562306a36Sopenharmony_ci wait_queue_head_t wait; 4662306a36Sopenharmony_ci struct fasync_struct *fasync; 4762306a36Sopenharmony_ci struct evdev *evdev; 4862306a36Sopenharmony_ci struct list_head node; 4962306a36Sopenharmony_ci enum input_clock_type clk_type; 5062306a36Sopenharmony_ci bool revoked; 5162306a36Sopenharmony_ci unsigned long *evmasks[EV_CNT]; 5262306a36Sopenharmony_ci unsigned int bufsize; 5362306a36Sopenharmony_ci struct input_event buffer[]; 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic size_t evdev_get_mask_cnt(unsigned int type) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci static const size_t counts[EV_CNT] = { 5962306a36Sopenharmony_ci /* EV_SYN==0 is EV_CNT, _not_ SYN_CNT, see EVIOCGBIT */ 6062306a36Sopenharmony_ci [EV_SYN] = EV_CNT, 6162306a36Sopenharmony_ci [EV_KEY] = KEY_CNT, 6262306a36Sopenharmony_ci [EV_REL] = REL_CNT, 6362306a36Sopenharmony_ci [EV_ABS] = ABS_CNT, 6462306a36Sopenharmony_ci [EV_MSC] = MSC_CNT, 6562306a36Sopenharmony_ci [EV_SW] = SW_CNT, 6662306a36Sopenharmony_ci [EV_LED] = LED_CNT, 6762306a36Sopenharmony_ci [EV_SND] = SND_CNT, 6862306a36Sopenharmony_ci [EV_FF] = FF_CNT, 6962306a36Sopenharmony_ci }; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci return (type < EV_CNT) ? counts[type] : 0; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* requires the buffer lock to be held */ 7562306a36Sopenharmony_cistatic bool __evdev_is_filtered(struct evdev_client *client, 7662306a36Sopenharmony_ci unsigned int type, 7762306a36Sopenharmony_ci unsigned int code) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci unsigned long *mask; 8062306a36Sopenharmony_ci size_t cnt; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* EV_SYN and unknown codes are never filtered */ 8362306a36Sopenharmony_ci if (type == EV_SYN || type >= EV_CNT) 8462306a36Sopenharmony_ci return false; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci /* first test whether the type is filtered */ 8762306a36Sopenharmony_ci mask = client->evmasks[0]; 8862306a36Sopenharmony_ci if (mask && !test_bit(type, mask)) 8962306a36Sopenharmony_ci return true; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* unknown values are never filtered */ 9262306a36Sopenharmony_ci cnt = evdev_get_mask_cnt(type); 9362306a36Sopenharmony_ci if (!cnt || code >= cnt) 9462306a36Sopenharmony_ci return false; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci mask = client->evmasks[type]; 9762306a36Sopenharmony_ci return mask && !test_bit(code, mask); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/* flush queued events of type @type, caller must hold client->buffer_lock */ 10162306a36Sopenharmony_cistatic void __evdev_flush_queue(struct evdev_client *client, unsigned int type) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci unsigned int i, head, num; 10462306a36Sopenharmony_ci unsigned int mask = client->bufsize - 1; 10562306a36Sopenharmony_ci bool is_report; 10662306a36Sopenharmony_ci struct input_event *ev; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci BUG_ON(type == EV_SYN); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci head = client->tail; 11162306a36Sopenharmony_ci client->packet_head = client->tail; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* init to 1 so a leading SYN_REPORT will not be dropped */ 11462306a36Sopenharmony_ci num = 1; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci for (i = client->tail; i != client->head; i = (i + 1) & mask) { 11762306a36Sopenharmony_ci ev = &client->buffer[i]; 11862306a36Sopenharmony_ci is_report = ev->type == EV_SYN && ev->code == SYN_REPORT; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci if (ev->type == type) { 12162306a36Sopenharmony_ci /* drop matched entry */ 12262306a36Sopenharmony_ci continue; 12362306a36Sopenharmony_ci } else if (is_report && !num) { 12462306a36Sopenharmony_ci /* drop empty SYN_REPORT groups */ 12562306a36Sopenharmony_ci continue; 12662306a36Sopenharmony_ci } else if (head != i) { 12762306a36Sopenharmony_ci /* move entry to fill the gap */ 12862306a36Sopenharmony_ci client->buffer[head] = *ev; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci num++; 13262306a36Sopenharmony_ci head = (head + 1) & mask; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (is_report) { 13562306a36Sopenharmony_ci num = 0; 13662306a36Sopenharmony_ci client->packet_head = head; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci client->head = head; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic void __evdev_queue_syn_dropped(struct evdev_client *client) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci ktime_t *ev_time = input_get_timestamp(client->evdev->handle.dev); 14662306a36Sopenharmony_ci struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]); 14762306a36Sopenharmony_ci struct input_event ev; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci ev.input_event_sec = ts.tv_sec; 15062306a36Sopenharmony_ci ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC; 15162306a36Sopenharmony_ci ev.type = EV_SYN; 15262306a36Sopenharmony_ci ev.code = SYN_DROPPED; 15362306a36Sopenharmony_ci ev.value = 0; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci client->buffer[client->head++] = ev; 15662306a36Sopenharmony_ci client->head &= client->bufsize - 1; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (unlikely(client->head == client->tail)) { 15962306a36Sopenharmony_ci /* drop queue but keep our SYN_DROPPED event */ 16062306a36Sopenharmony_ci client->tail = (client->head - 1) & (client->bufsize - 1); 16162306a36Sopenharmony_ci client->packet_head = client->tail; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic void evdev_queue_syn_dropped(struct evdev_client *client) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci unsigned long flags; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci spin_lock_irqsave(&client->buffer_lock, flags); 17062306a36Sopenharmony_ci __evdev_queue_syn_dropped(client); 17162306a36Sopenharmony_ci spin_unlock_irqrestore(&client->buffer_lock, flags); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci unsigned long flags; 17762306a36Sopenharmony_ci enum input_clock_type clk_type; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci switch (clkid) { 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci case CLOCK_REALTIME: 18262306a36Sopenharmony_ci clk_type = INPUT_CLK_REAL; 18362306a36Sopenharmony_ci break; 18462306a36Sopenharmony_ci case CLOCK_MONOTONIC: 18562306a36Sopenharmony_ci clk_type = INPUT_CLK_MONO; 18662306a36Sopenharmony_ci break; 18762306a36Sopenharmony_ci case CLOCK_BOOTTIME: 18862306a36Sopenharmony_ci clk_type = INPUT_CLK_BOOT; 18962306a36Sopenharmony_ci break; 19062306a36Sopenharmony_ci default: 19162306a36Sopenharmony_ci return -EINVAL; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci if (client->clk_type != clk_type) { 19562306a36Sopenharmony_ci client->clk_type = clk_type; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* 19862306a36Sopenharmony_ci * Flush pending events and queue SYN_DROPPED event, 19962306a36Sopenharmony_ci * but only if the queue is not empty. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ci spin_lock_irqsave(&client->buffer_lock, flags); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (client->head != client->tail) { 20462306a36Sopenharmony_ci client->packet_head = client->head = client->tail; 20562306a36Sopenharmony_ci __evdev_queue_syn_dropped(client); 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci spin_unlock_irqrestore(&client->buffer_lock, flags); 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic void __pass_event(struct evdev_client *client, 21562306a36Sopenharmony_ci const struct input_event *event) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci client->buffer[client->head++] = *event; 21862306a36Sopenharmony_ci client->head &= client->bufsize - 1; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci if (unlikely(client->head == client->tail)) { 22162306a36Sopenharmony_ci /* 22262306a36Sopenharmony_ci * This effectively "drops" all unconsumed events, leaving 22362306a36Sopenharmony_ci * EV_SYN/SYN_DROPPED plus the newest event in the queue. 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_ci client->tail = (client->head - 2) & (client->bufsize - 1); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci client->buffer[client->tail] = (struct input_event) { 22862306a36Sopenharmony_ci .input_event_sec = event->input_event_sec, 22962306a36Sopenharmony_ci .input_event_usec = event->input_event_usec, 23062306a36Sopenharmony_ci .type = EV_SYN, 23162306a36Sopenharmony_ci .code = SYN_DROPPED, 23262306a36Sopenharmony_ci .value = 0, 23362306a36Sopenharmony_ci }; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci client->packet_head = client->tail; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (event->type == EV_SYN && event->code == SYN_REPORT) { 23962306a36Sopenharmony_ci client->packet_head = client->head; 24062306a36Sopenharmony_ci kill_fasync(&client->fasync, SIGIO, POLL_IN); 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic void evdev_pass_values(struct evdev_client *client, 24562306a36Sopenharmony_ci const struct input_value *vals, unsigned int count, 24662306a36Sopenharmony_ci ktime_t *ev_time) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci const struct input_value *v; 24962306a36Sopenharmony_ci struct input_event event; 25062306a36Sopenharmony_ci struct timespec64 ts; 25162306a36Sopenharmony_ci bool wakeup = false; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (client->revoked) 25462306a36Sopenharmony_ci return; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci ts = ktime_to_timespec64(ev_time[client->clk_type]); 25762306a36Sopenharmony_ci event.input_event_sec = ts.tv_sec; 25862306a36Sopenharmony_ci event.input_event_usec = ts.tv_nsec / NSEC_PER_USEC; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* Interrupts are disabled, just acquire the lock. */ 26162306a36Sopenharmony_ci spin_lock(&client->buffer_lock); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci for (v = vals; v != vals + count; v++) { 26462306a36Sopenharmony_ci if (__evdev_is_filtered(client, v->type, v->code)) 26562306a36Sopenharmony_ci continue; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (v->type == EV_SYN && v->code == SYN_REPORT) { 26862306a36Sopenharmony_ci /* drop empty SYN_REPORT */ 26962306a36Sopenharmony_ci if (client->packet_head == client->head) 27062306a36Sopenharmony_ci continue; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci wakeup = true; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci event.type = v->type; 27662306a36Sopenharmony_ci event.code = v->code; 27762306a36Sopenharmony_ci event.value = v->value; 27862306a36Sopenharmony_ci __pass_event(client, &event); 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci spin_unlock(&client->buffer_lock); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (wakeup) 28462306a36Sopenharmony_ci wake_up_interruptible_poll(&client->wait, 28562306a36Sopenharmony_ci EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * Pass incoming events to all connected clients. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_cistatic void evdev_events(struct input_handle *handle, 29262306a36Sopenharmony_ci const struct input_value *vals, unsigned int count) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci struct evdev *evdev = handle->private; 29562306a36Sopenharmony_ci struct evdev_client *client; 29662306a36Sopenharmony_ci ktime_t *ev_time = input_get_timestamp(handle->dev); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci rcu_read_lock(); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci client = rcu_dereference(evdev->grab); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (client) 30362306a36Sopenharmony_ci evdev_pass_values(client, vals, count, ev_time); 30462306a36Sopenharmony_ci else 30562306a36Sopenharmony_ci list_for_each_entry_rcu(client, &evdev->client_list, node) 30662306a36Sopenharmony_ci evdev_pass_values(client, vals, count, ev_time); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci rcu_read_unlock(); 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/* 31262306a36Sopenharmony_ci * Pass incoming event to all connected clients. 31362306a36Sopenharmony_ci */ 31462306a36Sopenharmony_cistatic void evdev_event(struct input_handle *handle, 31562306a36Sopenharmony_ci unsigned int type, unsigned int code, int value) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci struct input_value vals[] = { { type, code, value } }; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci evdev_events(handle, vals, 1); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic int evdev_fasync(int fd, struct file *file, int on) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct evdev_client *client = file->private_data; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci return fasync_helper(fd, file, on, &client->fasync); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic void evdev_free(struct device *dev) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci struct evdev *evdev = container_of(dev, struct evdev, dev); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci input_put_device(evdev->handle.dev); 33462306a36Sopenharmony_ci kfree(evdev); 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/* 33862306a36Sopenharmony_ci * Grabs an event device (along with underlying input device). 33962306a36Sopenharmony_ci * This function is called with evdev->mutex taken. 34062306a36Sopenharmony_ci */ 34162306a36Sopenharmony_cistatic int evdev_grab(struct evdev *evdev, struct evdev_client *client) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci int error; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci if (evdev->grab) 34662306a36Sopenharmony_ci return -EBUSY; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci error = input_grab_device(&evdev->handle); 34962306a36Sopenharmony_ci if (error) 35062306a36Sopenharmony_ci return error; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci rcu_assign_pointer(evdev->grab, client); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci return 0; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct evdev_client *grab = rcu_dereference_protected(evdev->grab, 36062306a36Sopenharmony_ci lockdep_is_held(&evdev->mutex)); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (grab != client) 36362306a36Sopenharmony_ci return -EINVAL; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci rcu_assign_pointer(evdev->grab, NULL); 36662306a36Sopenharmony_ci synchronize_rcu(); 36762306a36Sopenharmony_ci input_release_device(&evdev->handle); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return 0; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic void evdev_attach_client(struct evdev *evdev, 37362306a36Sopenharmony_ci struct evdev_client *client) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci spin_lock(&evdev->client_lock); 37662306a36Sopenharmony_ci list_add_tail_rcu(&client->node, &evdev->client_list); 37762306a36Sopenharmony_ci spin_unlock(&evdev->client_lock); 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_cistatic void evdev_detach_client(struct evdev *evdev, 38162306a36Sopenharmony_ci struct evdev_client *client) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci spin_lock(&evdev->client_lock); 38462306a36Sopenharmony_ci list_del_rcu(&client->node); 38562306a36Sopenharmony_ci spin_unlock(&evdev->client_lock); 38662306a36Sopenharmony_ci synchronize_rcu(); 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic int evdev_open_device(struct evdev *evdev) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci int retval; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci retval = mutex_lock_interruptible(&evdev->mutex); 39462306a36Sopenharmony_ci if (retval) 39562306a36Sopenharmony_ci return retval; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci if (!evdev->exist) 39862306a36Sopenharmony_ci retval = -ENODEV; 39962306a36Sopenharmony_ci else if (!evdev->open++) { 40062306a36Sopenharmony_ci retval = input_open_device(&evdev->handle); 40162306a36Sopenharmony_ci if (retval) 40262306a36Sopenharmony_ci evdev->open--; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci mutex_unlock(&evdev->mutex); 40662306a36Sopenharmony_ci return retval; 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_cistatic void evdev_close_device(struct evdev *evdev) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci mutex_lock(&evdev->mutex); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (evdev->exist && !--evdev->open) 41462306a36Sopenharmony_ci input_close_device(&evdev->handle); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci mutex_unlock(&evdev->mutex); 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci/* 42062306a36Sopenharmony_ci * Wake up users waiting for IO so they can disconnect from 42162306a36Sopenharmony_ci * dead device. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_cistatic void evdev_hangup(struct evdev *evdev) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct evdev_client *client; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci spin_lock(&evdev->client_lock); 42862306a36Sopenharmony_ci list_for_each_entry(client, &evdev->client_list, node) { 42962306a36Sopenharmony_ci kill_fasync(&client->fasync, SIGIO, POLL_HUP); 43062306a36Sopenharmony_ci wake_up_interruptible_poll(&client->wait, EPOLLHUP | EPOLLERR); 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci spin_unlock(&evdev->client_lock); 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int evdev_release(struct inode *inode, struct file *file) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct evdev_client *client = file->private_data; 43862306a36Sopenharmony_ci struct evdev *evdev = client->evdev; 43962306a36Sopenharmony_ci unsigned int i; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci mutex_lock(&evdev->mutex); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (evdev->exist && !client->revoked) 44462306a36Sopenharmony_ci input_flush_device(&evdev->handle, file); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci evdev_ungrab(evdev, client); 44762306a36Sopenharmony_ci mutex_unlock(&evdev->mutex); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci evdev_detach_client(evdev, client); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci for (i = 0; i < EV_CNT; ++i) 45262306a36Sopenharmony_ci bitmap_free(client->evmasks[i]); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci kvfree(client); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci evdev_close_device(evdev); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci return 0; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic unsigned int evdev_compute_buffer_size(struct input_dev *dev) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci unsigned int n_events = 46462306a36Sopenharmony_ci max(dev->hint_events_per_packet * EVDEV_BUF_PACKETS, 46562306a36Sopenharmony_ci EVDEV_MIN_BUFFER_SIZE); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci return roundup_pow_of_two(n_events); 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic int evdev_open(struct inode *inode, struct file *file) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); 47362306a36Sopenharmony_ci unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); 47462306a36Sopenharmony_ci struct evdev_client *client; 47562306a36Sopenharmony_ci int error; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci client = kvzalloc(struct_size(client, buffer, bufsize), GFP_KERNEL); 47862306a36Sopenharmony_ci if (!client) 47962306a36Sopenharmony_ci return -ENOMEM; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci init_waitqueue_head(&client->wait); 48262306a36Sopenharmony_ci client->bufsize = bufsize; 48362306a36Sopenharmony_ci spin_lock_init(&client->buffer_lock); 48462306a36Sopenharmony_ci client->evdev = evdev; 48562306a36Sopenharmony_ci evdev_attach_client(evdev, client); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci error = evdev_open_device(evdev); 48862306a36Sopenharmony_ci if (error) 48962306a36Sopenharmony_ci goto err_free_client; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci file->private_data = client; 49262306a36Sopenharmony_ci stream_open(inode, file); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci err_free_client: 49762306a36Sopenharmony_ci evdev_detach_client(evdev, client); 49862306a36Sopenharmony_ci kvfree(client); 49962306a36Sopenharmony_ci return error; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic ssize_t evdev_write(struct file *file, const char __user *buffer, 50362306a36Sopenharmony_ci size_t count, loff_t *ppos) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci struct evdev_client *client = file->private_data; 50662306a36Sopenharmony_ci struct evdev *evdev = client->evdev; 50762306a36Sopenharmony_ci struct input_event event; 50862306a36Sopenharmony_ci int retval = 0; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci if (count != 0 && count < input_event_size()) 51162306a36Sopenharmony_ci return -EINVAL; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci retval = mutex_lock_interruptible(&evdev->mutex); 51462306a36Sopenharmony_ci if (retval) 51562306a36Sopenharmony_ci return retval; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci if (!evdev->exist || client->revoked) { 51862306a36Sopenharmony_ci retval = -ENODEV; 51962306a36Sopenharmony_ci goto out; 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci while (retval + input_event_size() <= count) { 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (input_event_from_user(buffer + retval, &event)) { 52562306a36Sopenharmony_ci retval = -EFAULT; 52662306a36Sopenharmony_ci goto out; 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci retval += input_event_size(); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci input_inject_event(&evdev->handle, 53162306a36Sopenharmony_ci event.type, event.code, event.value); 53262306a36Sopenharmony_ci cond_resched(); 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci out: 53662306a36Sopenharmony_ci mutex_unlock(&evdev->mutex); 53762306a36Sopenharmony_ci return retval; 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_cistatic int evdev_fetch_next_event(struct evdev_client *client, 54162306a36Sopenharmony_ci struct input_event *event) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci int have_event; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci spin_lock_irq(&client->buffer_lock); 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci have_event = client->packet_head != client->tail; 54862306a36Sopenharmony_ci if (have_event) { 54962306a36Sopenharmony_ci *event = client->buffer[client->tail++]; 55062306a36Sopenharmony_ci client->tail &= client->bufsize - 1; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci spin_unlock_irq(&client->buffer_lock); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci return have_event; 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic ssize_t evdev_read(struct file *file, char __user *buffer, 55962306a36Sopenharmony_ci size_t count, loff_t *ppos) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci struct evdev_client *client = file->private_data; 56262306a36Sopenharmony_ci struct evdev *evdev = client->evdev; 56362306a36Sopenharmony_ci struct input_event event; 56462306a36Sopenharmony_ci size_t read = 0; 56562306a36Sopenharmony_ci int error; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci if (count != 0 && count < input_event_size()) 56862306a36Sopenharmony_ci return -EINVAL; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci for (;;) { 57162306a36Sopenharmony_ci if (!evdev->exist || client->revoked) 57262306a36Sopenharmony_ci return -ENODEV; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci if (client->packet_head == client->tail && 57562306a36Sopenharmony_ci (file->f_flags & O_NONBLOCK)) 57662306a36Sopenharmony_ci return -EAGAIN; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* 57962306a36Sopenharmony_ci * count == 0 is special - no IO is done but we check 58062306a36Sopenharmony_ci * for error conditions (see above). 58162306a36Sopenharmony_ci */ 58262306a36Sopenharmony_ci if (count == 0) 58362306a36Sopenharmony_ci break; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci while (read + input_event_size() <= count && 58662306a36Sopenharmony_ci evdev_fetch_next_event(client, &event)) { 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci if (input_event_to_user(buffer + read, &event)) 58962306a36Sopenharmony_ci return -EFAULT; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci read += input_event_size(); 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci if (read) 59562306a36Sopenharmony_ci break; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci if (!(file->f_flags & O_NONBLOCK)) { 59862306a36Sopenharmony_ci error = wait_event_interruptible(client->wait, 59962306a36Sopenharmony_ci client->packet_head != client->tail || 60062306a36Sopenharmony_ci !evdev->exist || client->revoked); 60162306a36Sopenharmony_ci if (error) 60262306a36Sopenharmony_ci return error; 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci return read; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci/* No kernel lock - fine */ 61062306a36Sopenharmony_cistatic __poll_t evdev_poll(struct file *file, poll_table *wait) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci struct evdev_client *client = file->private_data; 61362306a36Sopenharmony_ci struct evdev *evdev = client->evdev; 61462306a36Sopenharmony_ci __poll_t mask; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci poll_wait(file, &client->wait, wait); 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (evdev->exist && !client->revoked) 61962306a36Sopenharmony_ci mask = EPOLLOUT | EPOLLWRNORM; 62062306a36Sopenharmony_ci else 62162306a36Sopenharmony_ci mask = EPOLLHUP | EPOLLERR; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if (client->packet_head != client->tail) 62462306a36Sopenharmony_ci mask |= EPOLLIN | EPOLLRDNORM; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci return mask; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) 63262306a36Sopenharmony_ci#define BITS_TO_LONGS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1) 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci#ifdef __BIG_ENDIAN 63562306a36Sopenharmony_cistatic int bits_to_user(unsigned long *bits, unsigned int maxbit, 63662306a36Sopenharmony_ci unsigned int maxlen, void __user *p, int compat) 63762306a36Sopenharmony_ci{ 63862306a36Sopenharmony_ci int len, i; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (compat) { 64162306a36Sopenharmony_ci len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t); 64262306a36Sopenharmony_ci if (len > maxlen) 64362306a36Sopenharmony_ci len = maxlen; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci for (i = 0; i < len / sizeof(compat_long_t); i++) 64662306a36Sopenharmony_ci if (copy_to_user((compat_long_t __user *) p + i, 64762306a36Sopenharmony_ci (compat_long_t *) bits + 64862306a36Sopenharmony_ci i + 1 - ((i % 2) << 1), 64962306a36Sopenharmony_ci sizeof(compat_long_t))) 65062306a36Sopenharmony_ci return -EFAULT; 65162306a36Sopenharmony_ci } else { 65262306a36Sopenharmony_ci len = BITS_TO_LONGS(maxbit) * sizeof(long); 65362306a36Sopenharmony_ci if (len > maxlen) 65462306a36Sopenharmony_ci len = maxlen; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (copy_to_user(p, bits, len)) 65762306a36Sopenharmony_ci return -EFAULT; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci return len; 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic int bits_from_user(unsigned long *bits, unsigned int maxbit, 66462306a36Sopenharmony_ci unsigned int maxlen, const void __user *p, int compat) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci int len, i; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (compat) { 66962306a36Sopenharmony_ci if (maxlen % sizeof(compat_long_t)) 67062306a36Sopenharmony_ci return -EINVAL; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t); 67362306a36Sopenharmony_ci if (len > maxlen) 67462306a36Sopenharmony_ci len = maxlen; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci for (i = 0; i < len / sizeof(compat_long_t); i++) 67762306a36Sopenharmony_ci if (copy_from_user((compat_long_t *) bits + 67862306a36Sopenharmony_ci i + 1 - ((i % 2) << 1), 67962306a36Sopenharmony_ci (compat_long_t __user *) p + i, 68062306a36Sopenharmony_ci sizeof(compat_long_t))) 68162306a36Sopenharmony_ci return -EFAULT; 68262306a36Sopenharmony_ci if (i % 2) 68362306a36Sopenharmony_ci *((compat_long_t *) bits + i - 1) = 0; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci } else { 68662306a36Sopenharmony_ci if (maxlen % sizeof(long)) 68762306a36Sopenharmony_ci return -EINVAL; 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci len = BITS_TO_LONGS(maxbit) * sizeof(long); 69062306a36Sopenharmony_ci if (len > maxlen) 69162306a36Sopenharmony_ci len = maxlen; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci if (copy_from_user(bits, p, len)) 69462306a36Sopenharmony_ci return -EFAULT; 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci return len; 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci#else 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic int bits_to_user(unsigned long *bits, unsigned int maxbit, 70362306a36Sopenharmony_ci unsigned int maxlen, void __user *p, int compat) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci int len = compat ? 70662306a36Sopenharmony_ci BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t) : 70762306a36Sopenharmony_ci BITS_TO_LONGS(maxbit) * sizeof(long); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci if (len > maxlen) 71062306a36Sopenharmony_ci len = maxlen; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci return copy_to_user(p, bits, len) ? -EFAULT : len; 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_cistatic int bits_from_user(unsigned long *bits, unsigned int maxbit, 71662306a36Sopenharmony_ci unsigned int maxlen, const void __user *p, int compat) 71762306a36Sopenharmony_ci{ 71862306a36Sopenharmony_ci size_t chunk_size = compat ? sizeof(compat_long_t) : sizeof(long); 71962306a36Sopenharmony_ci int len; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci if (maxlen % chunk_size) 72262306a36Sopenharmony_ci return -EINVAL; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci len = compat ? BITS_TO_LONGS_COMPAT(maxbit) : BITS_TO_LONGS(maxbit); 72562306a36Sopenharmony_ci len *= chunk_size; 72662306a36Sopenharmony_ci if (len > maxlen) 72762306a36Sopenharmony_ci len = maxlen; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci return copy_from_user(bits, p, len) ? -EFAULT : len; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci#endif /* __BIG_ENDIAN */ 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci#else 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic int bits_to_user(unsigned long *bits, unsigned int maxbit, 73762306a36Sopenharmony_ci unsigned int maxlen, void __user *p, int compat) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci int len = BITS_TO_LONGS(maxbit) * sizeof(long); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci if (len > maxlen) 74262306a36Sopenharmony_ci len = maxlen; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci return copy_to_user(p, bits, len) ? -EFAULT : len; 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_cistatic int bits_from_user(unsigned long *bits, unsigned int maxbit, 74862306a36Sopenharmony_ci unsigned int maxlen, const void __user *p, int compat) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci int len; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci if (maxlen % sizeof(long)) 75362306a36Sopenharmony_ci return -EINVAL; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci len = BITS_TO_LONGS(maxbit) * sizeof(long); 75662306a36Sopenharmony_ci if (len > maxlen) 75762306a36Sopenharmony_ci len = maxlen; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci return copy_from_user(bits, p, len) ? -EFAULT : len; 76062306a36Sopenharmony_ci} 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci#endif /* CONFIG_COMPAT */ 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_cistatic int str_to_user(const char *str, unsigned int maxlen, void __user *p) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci int len; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci if (!str) 76962306a36Sopenharmony_ci return -ENOENT; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci len = strlen(str) + 1; 77262306a36Sopenharmony_ci if (len > maxlen) 77362306a36Sopenharmony_ci len = maxlen; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci return copy_to_user(p, str, len) ? -EFAULT : len; 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic int handle_eviocgbit(struct input_dev *dev, 77962306a36Sopenharmony_ci unsigned int type, unsigned int size, 78062306a36Sopenharmony_ci void __user *p, int compat_mode) 78162306a36Sopenharmony_ci{ 78262306a36Sopenharmony_ci unsigned long *bits; 78362306a36Sopenharmony_ci int len; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci switch (type) { 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci case 0: bits = dev->evbit; len = EV_MAX; break; 78862306a36Sopenharmony_ci case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; 78962306a36Sopenharmony_ci case EV_REL: bits = dev->relbit; len = REL_MAX; break; 79062306a36Sopenharmony_ci case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; 79162306a36Sopenharmony_ci case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; 79262306a36Sopenharmony_ci case EV_LED: bits = dev->ledbit; len = LED_MAX; break; 79362306a36Sopenharmony_ci case EV_SND: bits = dev->sndbit; len = SND_MAX; break; 79462306a36Sopenharmony_ci case EV_FF: bits = dev->ffbit; len = FF_MAX; break; 79562306a36Sopenharmony_ci case EV_SW: bits = dev->swbit; len = SW_MAX; break; 79662306a36Sopenharmony_ci default: return -EINVAL; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci return bits_to_user(bits, len, size, p, compat_mode); 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic int evdev_handle_get_keycode(struct input_dev *dev, void __user *p) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci struct input_keymap_entry ke = { 80562306a36Sopenharmony_ci .len = sizeof(unsigned int), 80662306a36Sopenharmony_ci .flags = 0, 80762306a36Sopenharmony_ci }; 80862306a36Sopenharmony_ci int __user *ip = (int __user *)p; 80962306a36Sopenharmony_ci int error; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci /* legacy case */ 81262306a36Sopenharmony_ci if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) 81362306a36Sopenharmony_ci return -EFAULT; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci error = input_get_keycode(dev, &ke); 81662306a36Sopenharmony_ci if (error) 81762306a36Sopenharmony_ci return error; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci if (put_user(ke.keycode, ip + 1)) 82062306a36Sopenharmony_ci return -EFAULT; 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci return 0; 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_cistatic int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci struct input_keymap_entry ke; 82862306a36Sopenharmony_ci int error; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci if (copy_from_user(&ke, p, sizeof(ke))) 83162306a36Sopenharmony_ci return -EFAULT; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci error = input_get_keycode(dev, &ke); 83462306a36Sopenharmony_ci if (error) 83562306a36Sopenharmony_ci return error; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci if (copy_to_user(p, &ke, sizeof(ke))) 83862306a36Sopenharmony_ci return -EFAULT; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci return 0; 84162306a36Sopenharmony_ci} 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_cistatic int evdev_handle_set_keycode(struct input_dev *dev, void __user *p) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci struct input_keymap_entry ke = { 84662306a36Sopenharmony_ci .len = sizeof(unsigned int), 84762306a36Sopenharmony_ci .flags = 0, 84862306a36Sopenharmony_ci }; 84962306a36Sopenharmony_ci int __user *ip = (int __user *)p; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) 85262306a36Sopenharmony_ci return -EFAULT; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci if (get_user(ke.keycode, ip + 1)) 85562306a36Sopenharmony_ci return -EFAULT; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci return input_set_keycode(dev, &ke); 85862306a36Sopenharmony_ci} 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_cistatic int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci struct input_keymap_entry ke; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci if (copy_from_user(&ke, p, sizeof(ke))) 86562306a36Sopenharmony_ci return -EFAULT; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci if (ke.len > sizeof(ke.scancode)) 86862306a36Sopenharmony_ci return -EINVAL; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci return input_set_keycode(dev, &ke); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci/* 87462306a36Sopenharmony_ci * If we transfer state to the user, we should flush all pending events 87562306a36Sopenharmony_ci * of the same type from the client's queue. Otherwise, they might end up 87662306a36Sopenharmony_ci * with duplicate events, which can screw up client's state tracking. 87762306a36Sopenharmony_ci * If bits_to_user fails after flushing the queue, we queue a SYN_DROPPED 87862306a36Sopenharmony_ci * event so user-space will notice missing events. 87962306a36Sopenharmony_ci * 88062306a36Sopenharmony_ci * LOCKING: 88162306a36Sopenharmony_ci * We need to take event_lock before buffer_lock to avoid dead-locks. But we 88262306a36Sopenharmony_ci * need the even_lock only to guarantee consistent state. We can safely release 88362306a36Sopenharmony_ci * it while flushing the queue. This allows input-core to handle filters while 88462306a36Sopenharmony_ci * we flush the queue. 88562306a36Sopenharmony_ci */ 88662306a36Sopenharmony_cistatic int evdev_handle_get_val(struct evdev_client *client, 88762306a36Sopenharmony_ci struct input_dev *dev, unsigned int type, 88862306a36Sopenharmony_ci unsigned long *bits, unsigned int maxbit, 88962306a36Sopenharmony_ci unsigned int maxlen, void __user *p, 89062306a36Sopenharmony_ci int compat) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci int ret; 89362306a36Sopenharmony_ci unsigned long *mem; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci mem = bitmap_alloc(maxbit, GFP_KERNEL); 89662306a36Sopenharmony_ci if (!mem) 89762306a36Sopenharmony_ci return -ENOMEM; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci spin_lock_irq(&dev->event_lock); 90062306a36Sopenharmony_ci spin_lock(&client->buffer_lock); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci bitmap_copy(mem, bits, maxbit); 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci spin_unlock(&dev->event_lock); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci __evdev_flush_queue(client, type); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci spin_unlock_irq(&client->buffer_lock); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci ret = bits_to_user(mem, maxbit, maxlen, p, compat); 91162306a36Sopenharmony_ci if (ret < 0) 91262306a36Sopenharmony_ci evdev_queue_syn_dropped(client); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci bitmap_free(mem); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci return ret; 91762306a36Sopenharmony_ci} 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_cistatic int evdev_handle_mt_request(struct input_dev *dev, 92062306a36Sopenharmony_ci unsigned int size, 92162306a36Sopenharmony_ci int __user *ip) 92262306a36Sopenharmony_ci{ 92362306a36Sopenharmony_ci const struct input_mt *mt = dev->mt; 92462306a36Sopenharmony_ci unsigned int code; 92562306a36Sopenharmony_ci int max_slots; 92662306a36Sopenharmony_ci int i; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (get_user(code, &ip[0])) 92962306a36Sopenharmony_ci return -EFAULT; 93062306a36Sopenharmony_ci if (!mt || !input_is_mt_value(code)) 93162306a36Sopenharmony_ci return -EINVAL; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci max_slots = (size - sizeof(__u32)) / sizeof(__s32); 93462306a36Sopenharmony_ci for (i = 0; i < mt->num_slots && i < max_slots; i++) { 93562306a36Sopenharmony_ci int value = input_mt_get_value(&mt->slots[i], code); 93662306a36Sopenharmony_ci if (put_user(value, &ip[1 + i])) 93762306a36Sopenharmony_ci return -EFAULT; 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci return 0; 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_cistatic int evdev_revoke(struct evdev *evdev, struct evdev_client *client, 94462306a36Sopenharmony_ci struct file *file) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci client->revoked = true; 94762306a36Sopenharmony_ci evdev_ungrab(evdev, client); 94862306a36Sopenharmony_ci input_flush_device(&evdev->handle, file); 94962306a36Sopenharmony_ci wake_up_interruptible_poll(&client->wait, EPOLLHUP | EPOLLERR); 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci return 0; 95262306a36Sopenharmony_ci} 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci/* must be called with evdev-mutex held */ 95562306a36Sopenharmony_cistatic int evdev_set_mask(struct evdev_client *client, 95662306a36Sopenharmony_ci unsigned int type, 95762306a36Sopenharmony_ci const void __user *codes, 95862306a36Sopenharmony_ci u32 codes_size, 95962306a36Sopenharmony_ci int compat) 96062306a36Sopenharmony_ci{ 96162306a36Sopenharmony_ci unsigned long flags, *mask, *oldmask; 96262306a36Sopenharmony_ci size_t cnt; 96362306a36Sopenharmony_ci int error; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci /* we allow unknown types and 'codes_size > size' for forward-compat */ 96662306a36Sopenharmony_ci cnt = evdev_get_mask_cnt(type); 96762306a36Sopenharmony_ci if (!cnt) 96862306a36Sopenharmony_ci return 0; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci mask = bitmap_zalloc(cnt, GFP_KERNEL); 97162306a36Sopenharmony_ci if (!mask) 97262306a36Sopenharmony_ci return -ENOMEM; 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci error = bits_from_user(mask, cnt - 1, codes_size, codes, compat); 97562306a36Sopenharmony_ci if (error < 0) { 97662306a36Sopenharmony_ci bitmap_free(mask); 97762306a36Sopenharmony_ci return error; 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci spin_lock_irqsave(&client->buffer_lock, flags); 98162306a36Sopenharmony_ci oldmask = client->evmasks[type]; 98262306a36Sopenharmony_ci client->evmasks[type] = mask; 98362306a36Sopenharmony_ci spin_unlock_irqrestore(&client->buffer_lock, flags); 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci bitmap_free(oldmask); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci return 0; 98862306a36Sopenharmony_ci} 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci/* must be called with evdev-mutex held */ 99162306a36Sopenharmony_cistatic int evdev_get_mask(struct evdev_client *client, 99262306a36Sopenharmony_ci unsigned int type, 99362306a36Sopenharmony_ci void __user *codes, 99462306a36Sopenharmony_ci u32 codes_size, 99562306a36Sopenharmony_ci int compat) 99662306a36Sopenharmony_ci{ 99762306a36Sopenharmony_ci unsigned long *mask; 99862306a36Sopenharmony_ci size_t cnt, size, xfer_size; 99962306a36Sopenharmony_ci int i; 100062306a36Sopenharmony_ci int error; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci /* we allow unknown types and 'codes_size > size' for forward-compat */ 100362306a36Sopenharmony_ci cnt = evdev_get_mask_cnt(type); 100462306a36Sopenharmony_ci size = sizeof(unsigned long) * BITS_TO_LONGS(cnt); 100562306a36Sopenharmony_ci xfer_size = min_t(size_t, codes_size, size); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (cnt > 0) { 100862306a36Sopenharmony_ci mask = client->evmasks[type]; 100962306a36Sopenharmony_ci if (mask) { 101062306a36Sopenharmony_ci error = bits_to_user(mask, cnt - 1, 101162306a36Sopenharmony_ci xfer_size, codes, compat); 101262306a36Sopenharmony_ci if (error < 0) 101362306a36Sopenharmony_ci return error; 101462306a36Sopenharmony_ci } else { 101562306a36Sopenharmony_ci /* fake mask with all bits set */ 101662306a36Sopenharmony_ci for (i = 0; i < xfer_size; i++) 101762306a36Sopenharmony_ci if (put_user(0xffU, (u8 __user *)codes + i)) 101862306a36Sopenharmony_ci return -EFAULT; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci if (xfer_size < codes_size) 102362306a36Sopenharmony_ci if (clear_user(codes + xfer_size, codes_size - xfer_size)) 102462306a36Sopenharmony_ci return -EFAULT; 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci return 0; 102762306a36Sopenharmony_ci} 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_cistatic long evdev_do_ioctl(struct file *file, unsigned int cmd, 103062306a36Sopenharmony_ci void __user *p, int compat_mode) 103162306a36Sopenharmony_ci{ 103262306a36Sopenharmony_ci struct evdev_client *client = file->private_data; 103362306a36Sopenharmony_ci struct evdev *evdev = client->evdev; 103462306a36Sopenharmony_ci struct input_dev *dev = evdev->handle.dev; 103562306a36Sopenharmony_ci struct input_absinfo abs; 103662306a36Sopenharmony_ci struct input_mask mask; 103762306a36Sopenharmony_ci struct ff_effect effect; 103862306a36Sopenharmony_ci int __user *ip = (int __user *)p; 103962306a36Sopenharmony_ci unsigned int i, t, u, v; 104062306a36Sopenharmony_ci unsigned int size; 104162306a36Sopenharmony_ci int error; 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* First we check for fixed-length commands */ 104462306a36Sopenharmony_ci switch (cmd) { 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci case EVIOCGVERSION: 104762306a36Sopenharmony_ci return put_user(EV_VERSION, ip); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci case EVIOCGID: 105062306a36Sopenharmony_ci if (copy_to_user(p, &dev->id, sizeof(struct input_id))) 105162306a36Sopenharmony_ci return -EFAULT; 105262306a36Sopenharmony_ci return 0; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci case EVIOCGREP: 105562306a36Sopenharmony_ci if (!test_bit(EV_REP, dev->evbit)) 105662306a36Sopenharmony_ci return -ENOSYS; 105762306a36Sopenharmony_ci if (put_user(dev->rep[REP_DELAY], ip)) 105862306a36Sopenharmony_ci return -EFAULT; 105962306a36Sopenharmony_ci if (put_user(dev->rep[REP_PERIOD], ip + 1)) 106062306a36Sopenharmony_ci return -EFAULT; 106162306a36Sopenharmony_ci return 0; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci case EVIOCSREP: 106462306a36Sopenharmony_ci if (!test_bit(EV_REP, dev->evbit)) 106562306a36Sopenharmony_ci return -ENOSYS; 106662306a36Sopenharmony_ci if (get_user(u, ip)) 106762306a36Sopenharmony_ci return -EFAULT; 106862306a36Sopenharmony_ci if (get_user(v, ip + 1)) 106962306a36Sopenharmony_ci return -EFAULT; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); 107262306a36Sopenharmony_ci input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci return 0; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci case EVIOCRMFF: 107762306a36Sopenharmony_ci return input_ff_erase(dev, (int)(unsigned long) p, file); 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci case EVIOCGEFFECTS: 108062306a36Sopenharmony_ci i = test_bit(EV_FF, dev->evbit) ? 108162306a36Sopenharmony_ci dev->ff->max_effects : 0; 108262306a36Sopenharmony_ci if (put_user(i, ip)) 108362306a36Sopenharmony_ci return -EFAULT; 108462306a36Sopenharmony_ci return 0; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci case EVIOCGRAB: 108762306a36Sopenharmony_ci if (p) 108862306a36Sopenharmony_ci return evdev_grab(evdev, client); 108962306a36Sopenharmony_ci else 109062306a36Sopenharmony_ci return evdev_ungrab(evdev, client); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci case EVIOCREVOKE: 109362306a36Sopenharmony_ci if (p) 109462306a36Sopenharmony_ci return -EINVAL; 109562306a36Sopenharmony_ci else 109662306a36Sopenharmony_ci return evdev_revoke(evdev, client, file); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci case EVIOCGMASK: { 109962306a36Sopenharmony_ci void __user *codes_ptr; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci if (copy_from_user(&mask, p, sizeof(mask))) 110262306a36Sopenharmony_ci return -EFAULT; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci codes_ptr = (void __user *)(unsigned long)mask.codes_ptr; 110562306a36Sopenharmony_ci return evdev_get_mask(client, 110662306a36Sopenharmony_ci mask.type, codes_ptr, mask.codes_size, 110762306a36Sopenharmony_ci compat_mode); 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci case EVIOCSMASK: { 111162306a36Sopenharmony_ci const void __user *codes_ptr; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci if (copy_from_user(&mask, p, sizeof(mask))) 111462306a36Sopenharmony_ci return -EFAULT; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci codes_ptr = (const void __user *)(unsigned long)mask.codes_ptr; 111762306a36Sopenharmony_ci return evdev_set_mask(client, 111862306a36Sopenharmony_ci mask.type, codes_ptr, mask.codes_size, 111962306a36Sopenharmony_ci compat_mode); 112062306a36Sopenharmony_ci } 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci case EVIOCSCLOCKID: 112362306a36Sopenharmony_ci if (copy_from_user(&i, p, sizeof(unsigned int))) 112462306a36Sopenharmony_ci return -EFAULT; 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci return evdev_set_clk_type(client, i); 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci case EVIOCGKEYCODE: 112962306a36Sopenharmony_ci return evdev_handle_get_keycode(dev, p); 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci case EVIOCSKEYCODE: 113262306a36Sopenharmony_ci return evdev_handle_set_keycode(dev, p); 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci case EVIOCGKEYCODE_V2: 113562306a36Sopenharmony_ci return evdev_handle_get_keycode_v2(dev, p); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci case EVIOCSKEYCODE_V2: 113862306a36Sopenharmony_ci return evdev_handle_set_keycode_v2(dev, p); 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci size = _IOC_SIZE(cmd); 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci /* Now check variable-length commands */ 114462306a36Sopenharmony_ci#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) 114562306a36Sopenharmony_ci switch (EVIOC_MASK_SIZE(cmd)) { 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci case EVIOCGPROP(0): 114862306a36Sopenharmony_ci return bits_to_user(dev->propbit, INPUT_PROP_MAX, 114962306a36Sopenharmony_ci size, p, compat_mode); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci case EVIOCGMTSLOTS(0): 115262306a36Sopenharmony_ci return evdev_handle_mt_request(dev, size, ip); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci case EVIOCGKEY(0): 115562306a36Sopenharmony_ci return evdev_handle_get_val(client, dev, EV_KEY, dev->key, 115662306a36Sopenharmony_ci KEY_MAX, size, p, compat_mode); 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci case EVIOCGLED(0): 115962306a36Sopenharmony_ci return evdev_handle_get_val(client, dev, EV_LED, dev->led, 116062306a36Sopenharmony_ci LED_MAX, size, p, compat_mode); 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci case EVIOCGSND(0): 116362306a36Sopenharmony_ci return evdev_handle_get_val(client, dev, EV_SND, dev->snd, 116462306a36Sopenharmony_ci SND_MAX, size, p, compat_mode); 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci case EVIOCGSW(0): 116762306a36Sopenharmony_ci return evdev_handle_get_val(client, dev, EV_SW, dev->sw, 116862306a36Sopenharmony_ci SW_MAX, size, p, compat_mode); 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci case EVIOCGNAME(0): 117162306a36Sopenharmony_ci return str_to_user(dev->name, size, p); 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci case EVIOCGPHYS(0): 117462306a36Sopenharmony_ci return str_to_user(dev->phys, size, p); 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci case EVIOCGUNIQ(0): 117762306a36Sopenharmony_ci return str_to_user(dev->uniq, size, p); 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci case EVIOC_MASK_SIZE(EVIOCSFF): 118062306a36Sopenharmony_ci if (input_ff_effect_from_user(p, size, &effect)) 118162306a36Sopenharmony_ci return -EFAULT; 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci error = input_ff_upload(dev, &effect, file); 118462306a36Sopenharmony_ci if (error) 118562306a36Sopenharmony_ci return error; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) 118862306a36Sopenharmony_ci return -EFAULT; 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci return 0; 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci /* Multi-number variable-length handlers */ 119462306a36Sopenharmony_ci if (_IOC_TYPE(cmd) != 'E') 119562306a36Sopenharmony_ci return -EINVAL; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci if (_IOC_DIR(cmd) == _IOC_READ) { 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) 120062306a36Sopenharmony_ci return handle_eviocgbit(dev, 120162306a36Sopenharmony_ci _IOC_NR(cmd) & EV_MAX, size, 120262306a36Sopenharmony_ci p, compat_mode); 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci if (!dev->absinfo) 120762306a36Sopenharmony_ci return -EINVAL; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci t = _IOC_NR(cmd) & ABS_MAX; 121062306a36Sopenharmony_ci abs = dev->absinfo[t]; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci if (copy_to_user(p, &abs, min_t(size_t, 121362306a36Sopenharmony_ci size, sizeof(struct input_absinfo)))) 121462306a36Sopenharmony_ci return -EFAULT; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci return 0; 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci } 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci if (_IOC_DIR(cmd) == _IOC_WRITE) { 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci if (!dev->absinfo) 122562306a36Sopenharmony_ci return -EINVAL; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci t = _IOC_NR(cmd) & ABS_MAX; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci if (copy_from_user(&abs, p, min_t(size_t, 123062306a36Sopenharmony_ci size, sizeof(struct input_absinfo)))) 123162306a36Sopenharmony_ci return -EFAULT; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci if (size < sizeof(struct input_absinfo)) 123462306a36Sopenharmony_ci abs.resolution = 0; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci /* We can't change number of reserved MT slots */ 123762306a36Sopenharmony_ci if (t == ABS_MT_SLOT) 123862306a36Sopenharmony_ci return -EINVAL; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci /* 124162306a36Sopenharmony_ci * Take event lock to ensure that we are not 124262306a36Sopenharmony_ci * changing device parameters in the middle 124362306a36Sopenharmony_ci * of event. 124462306a36Sopenharmony_ci */ 124562306a36Sopenharmony_ci spin_lock_irq(&dev->event_lock); 124662306a36Sopenharmony_ci dev->absinfo[t] = abs; 124762306a36Sopenharmony_ci spin_unlock_irq(&dev->event_lock); 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci return 0; 125062306a36Sopenharmony_ci } 125162306a36Sopenharmony_ci } 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci return -EINVAL; 125462306a36Sopenharmony_ci} 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_cistatic long evdev_ioctl_handler(struct file *file, unsigned int cmd, 125762306a36Sopenharmony_ci void __user *p, int compat_mode) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci struct evdev_client *client = file->private_data; 126062306a36Sopenharmony_ci struct evdev *evdev = client->evdev; 126162306a36Sopenharmony_ci int retval; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci retval = mutex_lock_interruptible(&evdev->mutex); 126462306a36Sopenharmony_ci if (retval) 126562306a36Sopenharmony_ci return retval; 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci if (!evdev->exist || client->revoked) { 126862306a36Sopenharmony_ci retval = -ENODEV; 126962306a36Sopenharmony_ci goto out; 127062306a36Sopenharmony_ci } 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci retval = evdev_do_ioctl(file, cmd, p, compat_mode); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci out: 127562306a36Sopenharmony_ci mutex_unlock(&evdev->mutex); 127662306a36Sopenharmony_ci return retval; 127762306a36Sopenharmony_ci} 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_cistatic long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 128062306a36Sopenharmony_ci{ 128162306a36Sopenharmony_ci return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0); 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 128562306a36Sopenharmony_cistatic long evdev_ioctl_compat(struct file *file, 128662306a36Sopenharmony_ci unsigned int cmd, unsigned long arg) 128762306a36Sopenharmony_ci{ 128862306a36Sopenharmony_ci return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1); 128962306a36Sopenharmony_ci} 129062306a36Sopenharmony_ci#endif 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_cistatic const struct file_operations evdev_fops = { 129362306a36Sopenharmony_ci .owner = THIS_MODULE, 129462306a36Sopenharmony_ci .read = evdev_read, 129562306a36Sopenharmony_ci .write = evdev_write, 129662306a36Sopenharmony_ci .poll = evdev_poll, 129762306a36Sopenharmony_ci .open = evdev_open, 129862306a36Sopenharmony_ci .release = evdev_release, 129962306a36Sopenharmony_ci .unlocked_ioctl = evdev_ioctl, 130062306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 130162306a36Sopenharmony_ci .compat_ioctl = evdev_ioctl_compat, 130262306a36Sopenharmony_ci#endif 130362306a36Sopenharmony_ci .fasync = evdev_fasync, 130462306a36Sopenharmony_ci .llseek = no_llseek, 130562306a36Sopenharmony_ci}; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci/* 130862306a36Sopenharmony_ci * Mark device non-existent. This disables writes, ioctls and 130962306a36Sopenharmony_ci * prevents new users from opening the device. Already posted 131062306a36Sopenharmony_ci * blocking reads will stay, however new ones will fail. 131162306a36Sopenharmony_ci */ 131262306a36Sopenharmony_cistatic void evdev_mark_dead(struct evdev *evdev) 131362306a36Sopenharmony_ci{ 131462306a36Sopenharmony_ci mutex_lock(&evdev->mutex); 131562306a36Sopenharmony_ci evdev->exist = false; 131662306a36Sopenharmony_ci mutex_unlock(&evdev->mutex); 131762306a36Sopenharmony_ci} 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_cistatic void evdev_cleanup(struct evdev *evdev) 132062306a36Sopenharmony_ci{ 132162306a36Sopenharmony_ci struct input_handle *handle = &evdev->handle; 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci evdev_mark_dead(evdev); 132462306a36Sopenharmony_ci evdev_hangup(evdev); 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci /* evdev is marked dead so no one else accesses evdev->open */ 132762306a36Sopenharmony_ci if (evdev->open) { 132862306a36Sopenharmony_ci input_flush_device(handle, NULL); 132962306a36Sopenharmony_ci input_close_device(handle); 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci} 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci/* 133462306a36Sopenharmony_ci * Create new evdev device. Note that input core serializes calls 133562306a36Sopenharmony_ci * to connect and disconnect. 133662306a36Sopenharmony_ci */ 133762306a36Sopenharmony_cistatic int evdev_connect(struct input_handler *handler, struct input_dev *dev, 133862306a36Sopenharmony_ci const struct input_device_id *id) 133962306a36Sopenharmony_ci{ 134062306a36Sopenharmony_ci struct evdev *evdev; 134162306a36Sopenharmony_ci int minor; 134262306a36Sopenharmony_ci int dev_no; 134362306a36Sopenharmony_ci int error; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true); 134662306a36Sopenharmony_ci if (minor < 0) { 134762306a36Sopenharmony_ci error = minor; 134862306a36Sopenharmony_ci pr_err("failed to reserve new minor: %d\n", error); 134962306a36Sopenharmony_ci return error; 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); 135362306a36Sopenharmony_ci if (!evdev) { 135462306a36Sopenharmony_ci error = -ENOMEM; 135562306a36Sopenharmony_ci goto err_free_minor; 135662306a36Sopenharmony_ci } 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci INIT_LIST_HEAD(&evdev->client_list); 135962306a36Sopenharmony_ci spin_lock_init(&evdev->client_lock); 136062306a36Sopenharmony_ci mutex_init(&evdev->mutex); 136162306a36Sopenharmony_ci evdev->exist = true; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci dev_no = minor; 136462306a36Sopenharmony_ci /* Normalize device number if it falls into legacy range */ 136562306a36Sopenharmony_ci if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS) 136662306a36Sopenharmony_ci dev_no -= EVDEV_MINOR_BASE; 136762306a36Sopenharmony_ci dev_set_name(&evdev->dev, "event%d", dev_no); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci evdev->handle.dev = input_get_device(dev); 137062306a36Sopenharmony_ci evdev->handle.name = dev_name(&evdev->dev); 137162306a36Sopenharmony_ci evdev->handle.handler = handler; 137262306a36Sopenharmony_ci evdev->handle.private = evdev; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); 137562306a36Sopenharmony_ci evdev->dev.class = &input_class; 137662306a36Sopenharmony_ci evdev->dev.parent = &dev->dev; 137762306a36Sopenharmony_ci evdev->dev.release = evdev_free; 137862306a36Sopenharmony_ci device_initialize(&evdev->dev); 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci error = input_register_handle(&evdev->handle); 138162306a36Sopenharmony_ci if (error) 138262306a36Sopenharmony_ci goto err_free_evdev; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci cdev_init(&evdev->cdev, &evdev_fops); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci error = cdev_device_add(&evdev->cdev, &evdev->dev); 138762306a36Sopenharmony_ci if (error) 138862306a36Sopenharmony_ci goto err_cleanup_evdev; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci return 0; 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci err_cleanup_evdev: 139362306a36Sopenharmony_ci evdev_cleanup(evdev); 139462306a36Sopenharmony_ci input_unregister_handle(&evdev->handle); 139562306a36Sopenharmony_ci err_free_evdev: 139662306a36Sopenharmony_ci put_device(&evdev->dev); 139762306a36Sopenharmony_ci err_free_minor: 139862306a36Sopenharmony_ci input_free_minor(minor); 139962306a36Sopenharmony_ci return error; 140062306a36Sopenharmony_ci} 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_cistatic void evdev_disconnect(struct input_handle *handle) 140362306a36Sopenharmony_ci{ 140462306a36Sopenharmony_ci struct evdev *evdev = handle->private; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci cdev_device_del(&evdev->cdev, &evdev->dev); 140762306a36Sopenharmony_ci evdev_cleanup(evdev); 140862306a36Sopenharmony_ci input_free_minor(MINOR(evdev->dev.devt)); 140962306a36Sopenharmony_ci input_unregister_handle(handle); 141062306a36Sopenharmony_ci put_device(&evdev->dev); 141162306a36Sopenharmony_ci} 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_cistatic const struct input_device_id evdev_ids[] = { 141462306a36Sopenharmony_ci { .driver_info = 1 }, /* Matches all devices */ 141562306a36Sopenharmony_ci { }, /* Terminating zero entry */ 141662306a36Sopenharmony_ci}; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(input, evdev_ids); 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_cistatic struct input_handler evdev_handler = { 142162306a36Sopenharmony_ci .event = evdev_event, 142262306a36Sopenharmony_ci .events = evdev_events, 142362306a36Sopenharmony_ci .connect = evdev_connect, 142462306a36Sopenharmony_ci .disconnect = evdev_disconnect, 142562306a36Sopenharmony_ci .legacy_minors = true, 142662306a36Sopenharmony_ci .minor = EVDEV_MINOR_BASE, 142762306a36Sopenharmony_ci .name = "evdev", 142862306a36Sopenharmony_ci .id_table = evdev_ids, 142962306a36Sopenharmony_ci}; 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_cistatic int __init evdev_init(void) 143262306a36Sopenharmony_ci{ 143362306a36Sopenharmony_ci return input_register_handler(&evdev_handler); 143462306a36Sopenharmony_ci} 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_cistatic void __exit evdev_exit(void) 143762306a36Sopenharmony_ci{ 143862306a36Sopenharmony_ci input_unregister_handler(&evdev_handler); 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_cimodule_init(evdev_init); 144262306a36Sopenharmony_cimodule_exit(evdev_exit); 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ciMODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 144562306a36Sopenharmony_ciMODULE_DESCRIPTION("Input driver event char devices"); 144662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1447