diff options
| author | David Herrmann <dh.herrmann@googlemail.com> | 2012-06-10 09:16:17 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2012-06-18 07:42:00 -0400 |
| 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 93860826d629..31e8379cfd15 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | struct uhid_device { | 30 | struct uhid_device { |
| 31 | struct mutex devlock; | 31 | struct mutex devlock; |
| 32 | struct hid_device *hid; | 32 | struct hid_device *hid; |
| 33 | struct uhid_event input_buf; | ||
| 33 | 34 | ||
| 34 | wait_queue_head_t waitq; | 35 | wait_queue_head_t waitq; |
| 35 | spinlock_t qlock; | 36 | spinlock_t qlock; |
| @@ -156,7 +157,35 @@ try_again: | |||
| 156 | static ssize_t uhid_char_write(struct file *file, const char __user *buffer, | 157 | static ssize_t uhid_char_write(struct file *file, const char __user *buffer, |
| 157 | size_t count, loff_t *ppos) | 158 | size_t count, loff_t *ppos) |
| 158 | { | 159 | { |
| 159 | return 0; | 160 | struct uhid_device *uhid = file->private_data; |
| 161 | int ret; | ||
| 162 | size_t len; | ||
| 163 | |||
| 164 | /* we need at least the "type" member of uhid_event */ | ||
| 165 | if (count < sizeof(__u32)) | ||
| 166 | return -EINVAL; | ||
| 167 | |||
| 168 | ret = mutex_lock_interruptible(&uhid->devlock); | ||
| 169 | if (ret) | ||
| 170 | return ret; | ||
| 171 | |||
| 172 | memset(&uhid->input_buf, 0, sizeof(uhid->input_buf)); | ||
| 173 | len = min(count, sizeof(uhid->input_buf)); | ||
| 174 | if (copy_from_user(&uhid->input_buf, buffer, len)) { | ||
| 175 | ret = -EFAULT; | ||
| 176 | goto unlock; | ||
| 177 | } | ||
| 178 | |||
| 179 | switch (uhid->input_buf.type) { | ||
| 180 | default: | ||
| 181 | ret = -EOPNOTSUPP; | ||
| 182 | } | ||
| 183 | |||
| 184 | unlock: | ||
| 185 | mutex_unlock(&uhid->devlock); | ||
| 186 | |||
| 187 | /* return "count" not "len" to not confuse the caller */ | ||
| 188 | return ret ? ret : count; | ||
| 160 | } | 189 | } |
| 161 | 190 | ||
| 162 | static unsigned int uhid_char_poll(struct file *file, poll_table *wait) | 191 | static unsigned int uhid_char_poll(struct file *file, poll_table *wait) |
