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 /drivers/hid | |
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>
Diffstat (limited to 'drivers/hid')
-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) |