diff options
author | David Herrmann <dh.herrmann@googlemail.com> | 2012-06-10 15:16:17 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-06-18 13:42:00 +0200 |
commit | 6664ef72a47459f883d3409ca9b2fa200015704b (patch) | |
tree | e6ce2eb75adbe3e531374c83f62f74ededcb6bf7 | |
parent | d937ae5fae17e63aaa97f029be221a6516b25475 (diff) |
HID: uhid: implement write() on uhid devices
Similar to read() you can only write() a single event with one call to an
uhid device. To write multiple events use writev() which is supported by
uhid.
We currently always return -EOPNOTSUPP but other events will be added in
later patches.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/uhid.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 93860826d62..31e8379cfd1 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -30,6 +30,7 @@ struct uhid_device { struct mutex devlock; struct hid_device *hid; + struct uhid_event input_buf; wait_queue_head_t waitq; spinlock_t qlock; @@ -156,7 +157,35 @@ try_again: static ssize_t uhid_char_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - return 0; + struct uhid_device *uhid = file->private_data; + int ret; + size_t len; + + /* we need at least the "type" member of uhid_event */ + if (count < sizeof(__u32)) + return -EINVAL; + + ret = mutex_lock_interruptible(&uhid->devlock); + if (ret) + return ret; + + memset(&uhid->input_buf, 0, sizeof(uhid->input_buf)); + len = min(count, sizeof(uhid->input_buf)); + if (copy_from_user(&uhid->input_buf, buffer, len)) { + ret = -EFAULT; + goto unlock; + } + + switch (uhid->input_buf.type) { + default: + ret = -EOPNOTSUPP; + } + +unlock: + mutex_unlock(&uhid->devlock); + + /* return "count" not "len" to not confuse the caller */ + return ret ? ret : count; } static unsigned int uhid_char_poll(struct file *file, poll_table *wait) |