blob: 7256647d9418e3efd3b13a8ce82e4f16b8f6878f [file] [log] [blame]
David Herrmann1ccd7a22012-06-10 15:16:13 +02001/*
2 * User-space I/O driver support for HID subsystem
3 * Copyright (c) 2012 David Herrmann
4 */
5
6/*
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 */
12
13#include <linux/atomic.h>
Dmitry Torokhovbefde022013-02-18 11:26:11 +010014#include <linux/compat.h>
Eric Biggersab26f7f2018-11-14 13:55:09 -080015#include <linux/cred.h>
David Herrmann1ccd7a22012-06-10 15:16:13 +020016#include <linux/device.h>
17#include <linux/fs.h>
18#include <linux/hid.h>
19#include <linux/input.h>
20#include <linux/miscdevice.h>
21#include <linux/module.h>
22#include <linux/mutex.h>
23#include <linux/poll.h>
24#include <linux/sched.h>
25#include <linux/spinlock.h>
26#include <linux/uhid.h>
27#include <linux/wait.h>
Eric Biggersab26f7f2018-11-14 13:55:09 -080028#include <linux/uaccess.h>
David Herrmann1ccd7a22012-06-10 15:16:13 +020029
30#define UHID_NAME "uhid"
David Herrmannace3d862012-06-10 15:16:14 +020031#define UHID_BUFSIZE 32
32
Dmitry Torokhov98350982017-05-30 14:46:26 -070033static DEFINE_MUTEX(uhid_open_mutex);
34
David Herrmannace3d862012-06-10 15:16:14 +020035struct uhid_device {
David Herrmannd937ae52012-06-10 15:16:16 +020036 struct mutex devlock;
David Herrmannd365c6c2012-06-10 15:16:18 +020037 bool running;
38
39 __u8 *rd_data;
40 uint rd_size;
41
David Herrmannace3d862012-06-10 15:16:14 +020042 struct hid_device *hid;
David Herrmann6664ef72012-06-10 15:16:17 +020043 struct uhid_event input_buf;
David Herrmannace3d862012-06-10 15:16:14 +020044
45 wait_queue_head_t waitq;
46 spinlock_t qlock;
47 __u8 head;
48 __u8 tail;
49 struct uhid_event *outq[UHID_BUFSIZE];
David Herrmannfcfcf0d2012-06-10 15:16:25 +020050
David Herrmann8cad5b02014-07-29 17:14:19 +020051 /* blocking GET_REPORT support; state changes protected by qlock */
David Herrmannfcfcf0d2012-06-10 15:16:25 +020052 struct mutex report_lock;
53 wait_queue_head_t report_wait;
David Herrmann5942b842014-07-29 17:14:20 +020054 bool report_running;
David Herrmann8cad5b02014-07-29 17:14:19 +020055 u32 report_id;
David Herrmann11c22152014-07-29 17:14:24 +020056 u32 report_type;
David Herrmannfcfcf0d2012-06-10 15:16:25 +020057 struct uhid_event report_buf;
Roderick Colenbrander67f8ecc2016-05-18 13:11:09 -070058 struct work_struct worker;
David Herrmannace3d862012-06-10 15:16:14 +020059};
David Herrmann1ccd7a22012-06-10 15:16:13 +020060
61static struct miscdevice uhid_misc;
62
Roderick Colenbrander67f8ecc2016-05-18 13:11:09 -070063static void uhid_device_add_worker(struct work_struct *work)
64{
65 struct uhid_device *uhid = container_of(work, struct uhid_device, worker);
66 int ret;
67
68 ret = hid_add_device(uhid->hid);
69 if (ret) {
70 hid_err(uhid->hid, "Cannot register HID device: error %d\n", ret);
71
72 hid_destroy_device(uhid->hid);
73 uhid->hid = NULL;
74 uhid->running = false;
75 }
76}
77
David Herrmannace3d862012-06-10 15:16:14 +020078static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev)
79{
80 __u8 newhead;
81
82 newhead = (uhid->head + 1) % UHID_BUFSIZE;
83
84 if (newhead != uhid->tail) {
85 uhid->outq[uhid->head] = ev;
86 uhid->head = newhead;
87 wake_up_interruptible(&uhid->waitq);
88 } else {
89 hid_warn(uhid->hid, "Output queue is full\n");
90 kfree(ev);
91 }
92}
93
94static int uhid_queue_event(struct uhid_device *uhid, __u32 event)
95{
96 unsigned long flags;
97 struct uhid_event *ev;
98
99 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
100 if (!ev)
101 return -ENOMEM;
102
103 ev->type = event;
104
105 spin_lock_irqsave(&uhid->qlock, flags);
106 uhid_queue(uhid, ev);
107 spin_unlock_irqrestore(&uhid->qlock, flags);
108
109 return 0;
110}
111
David Herrmannd365c6c2012-06-10 15:16:18 +0200112static int uhid_hid_start(struct hid_device *hid)
113{
David Herrmannec4b7de2012-06-10 15:16:21 +0200114 struct uhid_device *uhid = hid->driver_data;
David Herrmannc2b2f162014-07-29 17:14:25 +0200115 struct uhid_event *ev;
116 unsigned long flags;
David Herrmannec4b7de2012-06-10 15:16:21 +0200117
David Herrmannc2b2f162014-07-29 17:14:25 +0200118 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
119 if (!ev)
120 return -ENOMEM;
121
122 ev->type = UHID_START;
123
124 if (hid->report_enum[HID_FEATURE_REPORT].numbered)
125 ev->u.start.dev_flags |= UHID_DEV_NUMBERED_FEATURE_REPORTS;
126 if (hid->report_enum[HID_OUTPUT_REPORT].numbered)
127 ev->u.start.dev_flags |= UHID_DEV_NUMBERED_OUTPUT_REPORTS;
128 if (hid->report_enum[HID_INPUT_REPORT].numbered)
129 ev->u.start.dev_flags |= UHID_DEV_NUMBERED_INPUT_REPORTS;
130
131 spin_lock_irqsave(&uhid->qlock, flags);
132 uhid_queue(uhid, ev);
133 spin_unlock_irqrestore(&uhid->qlock, flags);
134
135 return 0;
David Herrmannd365c6c2012-06-10 15:16:18 +0200136}
137
138static void uhid_hid_stop(struct hid_device *hid)
139{
David Herrmannec4b7de2012-06-10 15:16:21 +0200140 struct uhid_device *uhid = hid->driver_data;
141
142 hid->claimed = 0;
143 uhid_queue_event(uhid, UHID_STOP);
David Herrmannd365c6c2012-06-10 15:16:18 +0200144}
145
146static int uhid_hid_open(struct hid_device *hid)
147{
David Herrmanne7191472012-06-10 15:16:22 +0200148 struct uhid_device *uhid = hid->driver_data;
Dmitry Torokhov98350982017-05-30 14:46:26 -0700149 int retval = 0;
David Herrmanne7191472012-06-10 15:16:22 +0200150
Dmitry Torokhov98350982017-05-30 14:46:26 -0700151 mutex_lock(&uhid_open_mutex);
152 if (!hid->open++) {
153 retval = uhid_queue_event(uhid, UHID_OPEN);
154 if (retval)
155 hid->open--;
156 }
157 mutex_unlock(&uhid_open_mutex);
158 return retval;
David Herrmannd365c6c2012-06-10 15:16:18 +0200159}
160
161static void uhid_hid_close(struct hid_device *hid)
162{
David Herrmanne7191472012-06-10 15:16:22 +0200163 struct uhid_device *uhid = hid->driver_data;
164
Dmitry Torokhov98350982017-05-30 14:46:26 -0700165 mutex_lock(&uhid_open_mutex);
166 if (!--hid->open)
167 uhid_queue_event(uhid, UHID_CLOSE);
168 mutex_unlock(&uhid_open_mutex);
David Herrmannd365c6c2012-06-10 15:16:18 +0200169}
170
David Herrmannd365c6c2012-06-10 15:16:18 +0200171static int uhid_hid_parse(struct hid_device *hid)
172{
David Herrmann037c0612012-06-10 15:16:20 +0200173 struct uhid_device *uhid = hid->driver_data;
174
175 return hid_parse_report(hid, uhid->rd_data, uhid->rd_size);
David Herrmannd365c6c2012-06-10 15:16:18 +0200176}
177
David Herrmann11c22152014-07-29 17:14:24 +0200178/* must be called with report_lock held */
179static int __uhid_report_queue_and_wait(struct uhid_device *uhid,
180 struct uhid_event *ev,
181 __u32 *report_id)
Jiri Kosina289a7162014-02-17 14:49:34 +0100182{
Jiri Kosina289a7162014-02-17 14:49:34 +0100183 unsigned long flags;
184 int ret;
Jiri Kosina289a7162014-02-17 14:49:34 +0100185
186 spin_lock_irqsave(&uhid->qlock, flags);
David Herrmann11c22152014-07-29 17:14:24 +0200187 *report_id = ++uhid->report_id;
Benjamin Tissoires8493ecc2014-10-01 11:59:47 -0400188 uhid->report_type = ev->type + 1;
David Herrmann5942b842014-07-29 17:14:20 +0200189 uhid->report_running = true;
Jiri Kosina289a7162014-02-17 14:49:34 +0100190 uhid_queue(uhid, ev);
191 spin_unlock_irqrestore(&uhid->qlock, flags);
192
193 ret = wait_event_interruptible_timeout(uhid->report_wait,
David Herrmann5942b842014-07-29 17:14:20 +0200194 !uhid->report_running || !uhid->running,
195 5 * HZ);
David Herrmann11c22152014-07-29 17:14:24 +0200196 if (!ret || !uhid->running || uhid->report_running)
Jiri Kosina289a7162014-02-17 14:49:34 +0100197 ret = -EIO;
David Herrmann11c22152014-07-29 17:14:24 +0200198 else if (ret < 0)
Jiri Kosina289a7162014-02-17 14:49:34 +0100199 ret = -ERESTARTSYS;
David Herrmann11c22152014-07-29 17:14:24 +0200200 else
201 ret = 0;
Jiri Kosina289a7162014-02-17 14:49:34 +0100202
David Herrmann5942b842014-07-29 17:14:20 +0200203 uhid->report_running = false;
Jiri Kosina289a7162014-02-17 14:49:34 +0100204
David Herrmann11c22152014-07-29 17:14:24 +0200205 return ret;
206}
207
208static void uhid_report_wake_up(struct uhid_device *uhid, u32 id,
209 const struct uhid_event *ev)
210{
211 unsigned long flags;
212
213 spin_lock_irqsave(&uhid->qlock, flags);
214
215 /* id for old report; drop it silently */
216 if (uhid->report_type != ev->type || uhid->report_id != id)
217 goto unlock;
218 if (!uhid->report_running)
219 goto unlock;
220
221 memcpy(&uhid->report_buf, ev, sizeof(*ev));
222 uhid->report_running = false;
223 wake_up_interruptible(&uhid->report_wait);
224
225unlock:
226 spin_unlock_irqrestore(&uhid->qlock, flags);
227}
228
229static int uhid_hid_get_report(struct hid_device *hid, unsigned char rnum,
230 u8 *buf, size_t count, u8 rtype)
231{
232 struct uhid_device *uhid = hid->driver_data;
233 struct uhid_get_report_reply_req *req;
234 struct uhid_event *ev;
235 int ret;
236
237 if (!uhid->running)
238 return -EIO;
239
240 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
241 if (!ev)
242 return -ENOMEM;
243
244 ev->type = UHID_GET_REPORT;
245 ev->u.get_report.rnum = rnum;
246 ev->u.get_report.rtype = rtype;
247
248 ret = mutex_lock_interruptible(&uhid->report_lock);
249 if (ret) {
250 kfree(ev);
251 return ret;
252 }
253
254 /* this _always_ takes ownership of @ev */
255 ret = __uhid_report_queue_and_wait(uhid, ev, &ev->u.get_report.id);
256 if (ret)
257 goto unlock;
258
259 req = &uhid->report_buf.u.get_report_reply;
260 if (req->err) {
261 ret = -EIO;
262 } else {
263 ret = min3(count, (size_t)req->size, (size_t)UHID_DATA_MAX);
264 memcpy(buf, req->data, ret);
265 }
266
Jiri Kosina289a7162014-02-17 14:49:34 +0100267unlock:
268 mutex_unlock(&uhid->report_lock);
David Herrmann11c22152014-07-29 17:14:24 +0200269 return ret;
270}
271
272static int uhid_hid_set_report(struct hid_device *hid, unsigned char rnum,
273 const u8 *buf, size_t count, u8 rtype)
274{
275 struct uhid_device *uhid = hid->driver_data;
276 struct uhid_event *ev;
277 int ret;
278
279 if (!uhid->running || count > UHID_DATA_MAX)
280 return -EIO;
281
282 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
283 if (!ev)
284 return -ENOMEM;
285
286 ev->type = UHID_SET_REPORT;
287 ev->u.set_report.rnum = rnum;
288 ev->u.set_report.rtype = rtype;
289 ev->u.set_report.size = count;
290 memcpy(ev->u.set_report.data, buf, count);
291
292 ret = mutex_lock_interruptible(&uhid->report_lock);
293 if (ret) {
294 kfree(ev);
295 return ret;
296 }
297
298 /* this _always_ takes ownership of @ev */
299 ret = __uhid_report_queue_and_wait(uhid, ev, &ev->u.set_report.id);
300 if (ret)
301 goto unlock;
302
303 if (uhid->report_buf.u.set_report_reply.err)
304 ret = -EIO;
305 else
306 ret = count;
307
308unlock:
309 mutex_unlock(&uhid->report_lock);
310 return ret;
Jiri Kosina289a7162014-02-17 14:49:34 +0100311}
312
David Herrmann7c4003b2014-07-29 17:14:23 +0200313static int uhid_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
314 __u8 *buf, size_t len, unsigned char rtype,
315 int reqtype)
316{
David Herrmann11c22152014-07-29 17:14:24 +0200317 u8 u_rtype;
318
319 switch (rtype) {
320 case HID_FEATURE_REPORT:
321 u_rtype = UHID_FEATURE_REPORT;
322 break;
323 case HID_OUTPUT_REPORT:
324 u_rtype = UHID_OUTPUT_REPORT;
325 break;
326 case HID_INPUT_REPORT:
327 u_rtype = UHID_INPUT_REPORT;
328 break;
329 default:
330 return -EINVAL;
331 }
332
David Herrmann7c4003b2014-07-29 17:14:23 +0200333 switch (reqtype) {
334 case HID_REQ_GET_REPORT:
David Herrmann11c22152014-07-29 17:14:24 +0200335 return uhid_hid_get_report(hid, reportnum, buf, len, u_rtype);
David Herrmann7c4003b2014-07-29 17:14:23 +0200336 case HID_REQ_SET_REPORT:
David Herrmann11c22152014-07-29 17:14:24 +0200337 return uhid_hid_set_report(hid, reportnum, buf, len, u_rtype);
David Herrmann7c4003b2014-07-29 17:14:23 +0200338 default:
339 return -EIO;
340 }
341}
342
David Herrmannd365c6c2012-06-10 15:16:18 +0200343static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
344 unsigned char report_type)
345{
David Herrmann3b3baa82012-06-10 15:16:24 +0200346 struct uhid_device *uhid = hid->driver_data;
347 __u8 rtype;
348 unsigned long flags;
349 struct uhid_event *ev;
350
351 switch (report_type) {
352 case HID_FEATURE_REPORT:
353 rtype = UHID_FEATURE_REPORT;
354 break;
355 case HID_OUTPUT_REPORT:
356 rtype = UHID_OUTPUT_REPORT;
357 break;
358 default:
359 return -EINVAL;
360 }
361
362 if (count < 1 || count > UHID_DATA_MAX)
363 return -EINVAL;
364
365 ev = kzalloc(sizeof(*ev), GFP_KERNEL);
366 if (!ev)
367 return -ENOMEM;
368
369 ev->type = UHID_OUTPUT;
370 ev->u.output.size = count;
371 ev->u.output.rtype = rtype;
372 memcpy(ev->u.output.data, buf, count);
373
374 spin_lock_irqsave(&uhid->qlock, flags);
375 uhid_queue(uhid, ev);
376 spin_unlock_irqrestore(&uhid->qlock, flags);
377
378 return count;
David Herrmannd365c6c2012-06-10 15:16:18 +0200379}
380
Frank Praznik596cfdd2014-01-22 13:49:43 -0500381static int uhid_hid_output_report(struct hid_device *hid, __u8 *buf,
382 size_t count)
383{
Benjamin Tissoires41abfb32014-02-10 12:58:46 -0500384 return uhid_hid_output_raw(hid, buf, count, HID_OUTPUT_REPORT);
Frank Praznik596cfdd2014-01-22 13:49:43 -0500385}
386
David Herrmannd365c6c2012-06-10 15:16:18 +0200387static struct hid_ll_driver uhid_hid_driver = {
388 .start = uhid_hid_start,
389 .stop = uhid_hid_stop,
390 .open = uhid_hid_open,
391 .close = uhid_hid_close,
David Herrmannd365c6c2012-06-10 15:16:18 +0200392 .parse = uhid_hid_parse,
David Herrmann7c4003b2014-07-29 17:14:23 +0200393 .raw_request = uhid_hid_raw_request,
Frank Praznik596cfdd2014-01-22 13:49:43 -0500394 .output_report = uhid_hid_output_report,
David Herrmannd365c6c2012-06-10 15:16:18 +0200395};
396
Dmitry Torokhovbefde022013-02-18 11:26:11 +0100397#ifdef CONFIG_COMPAT
398
399/* Apparently we haven't stepped on these rakes enough times yet. */
400struct uhid_create_req_compat {
401 __u8 name[128];
402 __u8 phys[64];
403 __u8 uniq[64];
404
405 compat_uptr_t rd_data;
406 __u16 rd_size;
407
408 __u16 bus;
409 __u32 vendor;
410 __u32 product;
411 __u32 version;
412 __u32 country;
413} __attribute__((__packed__));
414
415static int uhid_event_from_user(const char __user *buffer, size_t len,
416 struct uhid_event *event)
417{
Andy Lutomirski7365abb2016-03-22 14:25:24 -0700418 if (in_compat_syscall()) {
Dmitry Torokhovbefde022013-02-18 11:26:11 +0100419 u32 type;
420
421 if (get_user(type, buffer))
422 return -EFAULT;
423
424 if (type == UHID_CREATE) {
425 /*
426 * This is our messed up request with compat pointer.
427 * It is largish (more than 256 bytes) so we better
428 * allocate it from the heap.
429 */
430 struct uhid_create_req_compat *compat;
431
David Herrmann80897aa2013-11-26 13:58:18 +0100432 compat = kzalloc(sizeof(*compat), GFP_KERNEL);
Dmitry Torokhovbefde022013-02-18 11:26:11 +0100433 if (!compat)
434 return -ENOMEM;
435
436 buffer += sizeof(type);
437 len -= sizeof(type);
438 if (copy_from_user(compat, buffer,
439 min(len, sizeof(*compat)))) {
440 kfree(compat);
441 return -EFAULT;
442 }
443
444 /* Shuffle the data over to proper structure */
445 event->type = type;
446
447 memcpy(event->u.create.name, compat->name,
448 sizeof(compat->name));
449 memcpy(event->u.create.phys, compat->phys,
450 sizeof(compat->phys));
451 memcpy(event->u.create.uniq, compat->uniq,
452 sizeof(compat->uniq));
453
454 event->u.create.rd_data = compat_ptr(compat->rd_data);
455 event->u.create.rd_size = compat->rd_size;
456
457 event->u.create.bus = compat->bus;
458 event->u.create.vendor = compat->vendor;
459 event->u.create.product = compat->product;
460 event->u.create.version = compat->version;
461 event->u.create.country = compat->country;
462
463 kfree(compat);
464 return 0;
465 }
466 /* All others can be copied directly */
467 }
468
469 if (copy_from_user(event, buffer, min(len, sizeof(*event))))
470 return -EFAULT;
471
472 return 0;
473}
474#else
475static int uhid_event_from_user(const char __user *buffer, size_t len,
476 struct uhid_event *event)
477{
478 if (copy_from_user(event, buffer, min(len, sizeof(*event))))
479 return -EFAULT;
480
481 return 0;
482}
483#endif
484
Petri Gynther45226432014-03-24 13:50:01 -0700485static int uhid_dev_create2(struct uhid_device *uhid,
486 const struct uhid_event *ev)
487{
488 struct hid_device *hid;
David Herrmann25be7fe2014-07-29 17:14:18 +0200489 size_t rd_size, len;
David Herrmann41c4a462014-07-29 17:14:17 +0200490 void *rd_data;
Petri Gynther45226432014-03-24 13:50:01 -0700491 int ret;
492
493 if (uhid->running)
494 return -EALREADY;
495
David Herrmann41c4a462014-07-29 17:14:17 +0200496 rd_size = ev->u.create2.rd_size;
497 if (rd_size <= 0 || rd_size > HID_MAX_DESCRIPTOR_SIZE)
Petri Gynther45226432014-03-24 13:50:01 -0700498 return -EINVAL;
499
David Herrmann41c4a462014-07-29 17:14:17 +0200500 rd_data = kmemdup(ev->u.create2.rd_data, rd_size, GFP_KERNEL);
501 if (!rd_data)
Petri Gynther45226432014-03-24 13:50:01 -0700502 return -ENOMEM;
503
David Herrmann41c4a462014-07-29 17:14:17 +0200504 uhid->rd_size = rd_size;
505 uhid->rd_data = rd_data;
506
Petri Gynther45226432014-03-24 13:50:01 -0700507 hid = hid_allocate_device();
508 if (IS_ERR(hid)) {
509 ret = PTR_ERR(hid);
510 goto err_free;
511 }
512
David Herrmann25be7fe2014-07-29 17:14:18 +0200513 len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1;
514 strncpy(hid->name, ev->u.create2.name, len);
515 len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1;
516 strncpy(hid->phys, ev->u.create2.phys, len);
517 len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1;
518 strncpy(hid->uniq, ev->u.create2.uniq, len);
Petri Gynther45226432014-03-24 13:50:01 -0700519
520 hid->ll_driver = &uhid_hid_driver;
521 hid->bus = ev->u.create2.bus;
522 hid->vendor = ev->u.create2.vendor;
523 hid->product = ev->u.create2.product;
524 hid->version = ev->u.create2.version;
525 hid->country = ev->u.create2.country;
526 hid->driver_data = uhid;
527 hid->dev.parent = uhid_misc.this_device;
528
529 uhid->hid = hid;
530 uhid->running = true;
531
Roderick Colenbrander67f8ecc2016-05-18 13:11:09 -0700532 /* Adding of a HID device is done through a worker, to allow HID drivers
533 * which use feature requests during .probe to work, without they would
534 * be blocked on devlock, which is held by uhid_char_write.
535 */
536 schedule_work(&uhid->worker);
Petri Gynther45226432014-03-24 13:50:01 -0700537
538 return 0;
539
Petri Gynther45226432014-03-24 13:50:01 -0700540err_free:
541 kfree(uhid->rd_data);
David Herrmann41c4a462014-07-29 17:14:17 +0200542 uhid->rd_data = NULL;
543 uhid->rd_size = 0;
Petri Gynther45226432014-03-24 13:50:01 -0700544 return ret;
545}
546
David Herrmann56c47752014-07-29 17:14:16 +0200547static int uhid_dev_create(struct uhid_device *uhid,
548 struct uhid_event *ev)
549{
550 struct uhid_create_req orig;
551
552 orig = ev->u.create;
553
554 if (orig.rd_size <= 0 || orig.rd_size > HID_MAX_DESCRIPTOR_SIZE)
555 return -EINVAL;
556 if (copy_from_user(&ev->u.create2.rd_data, orig.rd_data, orig.rd_size))
557 return -EFAULT;
558
559 memcpy(ev->u.create2.name, orig.name, sizeof(orig.name));
560 memcpy(ev->u.create2.phys, orig.phys, sizeof(orig.phys));
561 memcpy(ev->u.create2.uniq, orig.uniq, sizeof(orig.uniq));
562 ev->u.create2.rd_size = orig.rd_size;
563 ev->u.create2.bus = orig.bus;
564 ev->u.create2.vendor = orig.vendor;
565 ev->u.create2.product = orig.product;
566 ev->u.create2.version = orig.version;
567 ev->u.create2.country = orig.country;
568
569 return uhid_dev_create2(uhid, ev);
570}
571
David Herrmannd365c6c2012-06-10 15:16:18 +0200572static int uhid_dev_destroy(struct uhid_device *uhid)
573{
574 if (!uhid->running)
575 return -EINVAL;
576
577 uhid->running = false;
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200578 wake_up_interruptible(&uhid->report_wait);
David Herrmannd365c6c2012-06-10 15:16:18 +0200579
Roderick Colenbrander67f8ecc2016-05-18 13:11:09 -0700580 cancel_work_sync(&uhid->worker);
581
David Herrmannd365c6c2012-06-10 15:16:18 +0200582 hid_destroy_device(uhid->hid);
583 kfree(uhid->rd_data);
584
585 return 0;
586}
587
David Herrmann5e87a362012-06-10 15:16:19 +0200588static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)
589{
590 if (!uhid->running)
591 return -EINVAL;
592
593 hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input.data,
594 min_t(size_t, ev->u.input.size, UHID_DATA_MAX), 0);
595
596 return 0;
597}
598
Petri Gynther45226432014-03-24 13:50:01 -0700599static int uhid_dev_input2(struct uhid_device *uhid, struct uhid_event *ev)
600{
601 if (!uhid->running)
602 return -EINVAL;
603
604 hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data,
605 min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0);
606
607 return 0;
608}
609
David Herrmannfa71f322014-07-29 17:14:21 +0200610static int uhid_dev_get_report_reply(struct uhid_device *uhid,
611 struct uhid_event *ev)
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200612{
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200613 if (!uhid->running)
614 return -EINVAL;
615
David Herrmann11c22152014-07-29 17:14:24 +0200616 uhid_report_wake_up(uhid, ev->u.get_report_reply.id, ev);
617 return 0;
618}
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200619
David Herrmann11c22152014-07-29 17:14:24 +0200620static int uhid_dev_set_report_reply(struct uhid_device *uhid,
621 struct uhid_event *ev)
622{
623 if (!uhid->running)
624 return -EINVAL;
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200625
David Herrmann11c22152014-07-29 17:14:24 +0200626 uhid_report_wake_up(uhid, ev->u.set_report_reply.id, ev);
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200627 return 0;
628}
629
David Herrmann1ccd7a22012-06-10 15:16:13 +0200630static int uhid_char_open(struct inode *inode, struct file *file)
631{
David Herrmannace3d862012-06-10 15:16:14 +0200632 struct uhid_device *uhid;
633
634 uhid = kzalloc(sizeof(*uhid), GFP_KERNEL);
635 if (!uhid)
636 return -ENOMEM;
637
David Herrmannd937ae52012-06-10 15:16:16 +0200638 mutex_init(&uhid->devlock);
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200639 mutex_init(&uhid->report_lock);
David Herrmannace3d862012-06-10 15:16:14 +0200640 spin_lock_init(&uhid->qlock);
641 init_waitqueue_head(&uhid->waitq);
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200642 init_waitqueue_head(&uhid->report_wait);
David Herrmannd365c6c2012-06-10 15:16:18 +0200643 uhid->running = false;
Roderick Colenbrander67f8ecc2016-05-18 13:11:09 -0700644 INIT_WORK(&uhid->worker, uhid_device_add_worker);
David Herrmannace3d862012-06-10 15:16:14 +0200645
646 file->private_data = uhid;
647 nonseekable_open(inode, file);
648
David Herrmann1ccd7a22012-06-10 15:16:13 +0200649 return 0;
650}
651
652static int uhid_char_release(struct inode *inode, struct file *file)
653{
David Herrmannace3d862012-06-10 15:16:14 +0200654 struct uhid_device *uhid = file->private_data;
655 unsigned int i;
656
David Herrmannd365c6c2012-06-10 15:16:18 +0200657 uhid_dev_destroy(uhid);
658
David Herrmannace3d862012-06-10 15:16:14 +0200659 for (i = 0; i < UHID_BUFSIZE; ++i)
660 kfree(uhid->outq[i]);
661
662 kfree(uhid);
663
David Herrmann1ccd7a22012-06-10 15:16:13 +0200664 return 0;
665}
666
667static ssize_t uhid_char_read(struct file *file, char __user *buffer,
668 size_t count, loff_t *ppos)
669{
David Herrmannd937ae52012-06-10 15:16:16 +0200670 struct uhid_device *uhid = file->private_data;
671 int ret;
672 unsigned long flags;
673 size_t len;
674
675 /* they need at least the "type" member of uhid_event */
676 if (count < sizeof(__u32))
677 return -EINVAL;
678
679try_again:
680 if (file->f_flags & O_NONBLOCK) {
681 if (uhid->head == uhid->tail)
682 return -EAGAIN;
683 } else {
684 ret = wait_event_interruptible(uhid->waitq,
685 uhid->head != uhid->tail);
686 if (ret)
687 return ret;
688 }
689
690 ret = mutex_lock_interruptible(&uhid->devlock);
691 if (ret)
692 return ret;
693
694 if (uhid->head == uhid->tail) {
695 mutex_unlock(&uhid->devlock);
696 goto try_again;
697 } else {
698 len = min(count, sizeof(**uhid->outq));
Vinicius Costa Gomesadefb692012-07-14 18:59:25 -0300699 if (copy_to_user(buffer, uhid->outq[uhid->tail], len)) {
David Herrmannd937ae52012-06-10 15:16:16 +0200700 ret = -EFAULT;
701 } else {
702 kfree(uhid->outq[uhid->tail]);
703 uhid->outq[uhid->tail] = NULL;
704
705 spin_lock_irqsave(&uhid->qlock, flags);
706 uhid->tail = (uhid->tail + 1) % UHID_BUFSIZE;
707 spin_unlock_irqrestore(&uhid->qlock, flags);
708 }
709 }
710
711 mutex_unlock(&uhid->devlock);
712 return ret ? ret : len;
David Herrmann1ccd7a22012-06-10 15:16:13 +0200713}
714
715static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
716 size_t count, loff_t *ppos)
717{
David Herrmann6664ef72012-06-10 15:16:17 +0200718 struct uhid_device *uhid = file->private_data;
719 int ret;
720 size_t len;
721
722 /* we need at least the "type" member of uhid_event */
723 if (count < sizeof(__u32))
724 return -EINVAL;
725
726 ret = mutex_lock_interruptible(&uhid->devlock);
727 if (ret)
728 return ret;
729
730 memset(&uhid->input_buf, 0, sizeof(uhid->input_buf));
731 len = min(count, sizeof(uhid->input_buf));
Dmitry Torokhovbefde022013-02-18 11:26:11 +0100732
733 ret = uhid_event_from_user(buffer, len, &uhid->input_buf);
734 if (ret)
David Herrmann6664ef72012-06-10 15:16:17 +0200735 goto unlock;
David Herrmann6664ef72012-06-10 15:16:17 +0200736
737 switch (uhid->input_buf.type) {
David Herrmannd365c6c2012-06-10 15:16:18 +0200738 case UHID_CREATE:
Eric Biggersab26f7f2018-11-14 13:55:09 -0800739 /*
740 * 'struct uhid_create_req' contains a __user pointer which is
741 * copied from, so it's unsafe to allow this with elevated
742 * privileges (e.g. from a setuid binary) or via kernel_write().
743 */
744 if (file->f_cred != current_cred() || uaccess_kernel()) {
745 pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n",
746 task_tgid_vnr(current), current->comm);
747 ret = -EACCES;
748 goto unlock;
749 }
David Herrmannd365c6c2012-06-10 15:16:18 +0200750 ret = uhid_dev_create(uhid, &uhid->input_buf);
751 break;
Petri Gynther45226432014-03-24 13:50:01 -0700752 case UHID_CREATE2:
753 ret = uhid_dev_create2(uhid, &uhid->input_buf);
754 break;
David Herrmannd365c6c2012-06-10 15:16:18 +0200755 case UHID_DESTROY:
756 ret = uhid_dev_destroy(uhid);
757 break;
David Herrmann5e87a362012-06-10 15:16:19 +0200758 case UHID_INPUT:
759 ret = uhid_dev_input(uhid, &uhid->input_buf);
760 break;
Petri Gynther45226432014-03-24 13:50:01 -0700761 case UHID_INPUT2:
762 ret = uhid_dev_input2(uhid, &uhid->input_buf);
763 break;
David Herrmannfa71f322014-07-29 17:14:21 +0200764 case UHID_GET_REPORT_REPLY:
765 ret = uhid_dev_get_report_reply(uhid, &uhid->input_buf);
David Herrmannfcfcf0d2012-06-10 15:16:25 +0200766 break;
David Herrmann11c22152014-07-29 17:14:24 +0200767 case UHID_SET_REPORT_REPLY:
768 ret = uhid_dev_set_report_reply(uhid, &uhid->input_buf);
769 break;
David Herrmann6664ef72012-06-10 15:16:17 +0200770 default:
771 ret = -EOPNOTSUPP;
772 }
773
774unlock:
775 mutex_unlock(&uhid->devlock);
776
777 /* return "count" not "len" to not confuse the caller */
778 return ret ? ret : count;
David Herrmann1ccd7a22012-06-10 15:16:13 +0200779}
780
781static unsigned int uhid_char_poll(struct file *file, poll_table *wait)
782{
David Herrmann1f9dec12012-06-10 15:16:15 +0200783 struct uhid_device *uhid = file->private_data;
784
785 poll_wait(file, &uhid->waitq, wait);
786
787 if (uhid->head != uhid->tail)
788 return POLLIN | POLLRDNORM;
789
David Herrmann1ccd7a22012-06-10 15:16:13 +0200790 return 0;
791}
792
793static const struct file_operations uhid_fops = {
794 .owner = THIS_MODULE,
795 .open = uhid_char_open,
796 .release = uhid_char_release,
797 .read = uhid_char_read,
798 .write = uhid_char_write,
799 .poll = uhid_char_poll,
800 .llseek = no_llseek,
801};
802
803static struct miscdevice uhid_misc = {
804 .fops = &uhid_fops,
David Herrmann19872d22013-09-09 18:33:54 +0200805 .minor = UHID_MINOR,
David Herrmann1ccd7a22012-06-10 15:16:13 +0200806 .name = UHID_NAME,
807};
PrasannaKumar Muralidharanca75d602016-08-25 22:30:49 +0530808module_misc_device(uhid_misc);
David Herrmann1ccd7a22012-06-10 15:16:13 +0200809
David Herrmann1ccd7a22012-06-10 15:16:13 +0200810MODULE_LICENSE("GPL");
811MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
812MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
David Herrmann19872d22013-09-09 18:33:54 +0200813MODULE_ALIAS_MISCDEV(UHID_MINOR);
Marcel Holtmann60cbd532013-09-01 11:02:46 -0700814MODULE_ALIAS("devname:" UHID_NAME);