Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/*
2 * LIRC base driver
3 *
4 * by Artur Lipowski <alipowski@interia.pl>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
20#include <linux/module.h>
21#include <linux/sched/signal.h>
22#include <linux/ioctl.h>
23#include <linux/poll.h>
24#include <linux/mutex.h>
25#include <linux/device.h>
26#include <linux/cdev.h>
27#include <linux/idr.h>
28
29#include <media/rc-core.h>
30#include <media/lirc.h>
31#include <media/lirc_dev.h>
32
33#define LOGHEAD "lirc_dev (%s[%d]): "
34
35static dev_t lirc_base_dev;
36
37/* Used to keep track of allocated lirc devices */
38#define LIRC_MAX_DEVICES 256
39static DEFINE_IDA(lirc_ida);
40
41/* Only used for sysfs but defined to void otherwise */
42static struct class *lirc_class;
43
44static void lirc_release_device(struct device *ld)
45{
46 struct lirc_dev *d = container_of(ld, struct lirc_dev, dev);
47
48 put_device(d->dev.parent);
49
50 if (d->buf_internal) {
51 lirc_buffer_free(d->buf);
52 kfree(d->buf);
53 d->buf = NULL;
54 }
55 kfree(d);
56 module_put(THIS_MODULE);
57}
58
59static int lirc_allocate_buffer(struct lirc_dev *d)
60{
61 int err;
62
63 if (d->buf) {
64 d->buf_internal = false;
65 return 0;
66 }
67
68 d->buf = kmalloc(sizeof(*d->buf), GFP_KERNEL);
69 if (!d->buf)
70 return -ENOMEM;
71
72 err = lirc_buffer_init(d->buf, d->chunk_size, d->buffer_size);
73 if (err) {
74 kfree(d->buf);
75 d->buf = NULL;
76 return err;
77 }
78
79 d->buf_internal = true;
80 return 0;
81}
82
83struct lirc_dev *
84lirc_allocate_device(void)
85{
86 struct lirc_dev *d;
87
88 d = kzalloc(sizeof(*d), GFP_KERNEL);
89 if (d) {
90 mutex_init(&d->mutex);
91 device_initialize(&d->dev);
92 d->dev.class = lirc_class;
93 d->dev.release = lirc_release_device;
94 __module_get(THIS_MODULE);
95 }
96
97 return d;
98}
99EXPORT_SYMBOL(lirc_allocate_device);
100
101void lirc_free_device(struct lirc_dev *d)
102{
103 if (!d)
104 return;
105
106 put_device(&d->dev);
107}
108EXPORT_SYMBOL(lirc_free_device);
109
110int lirc_register_device(struct lirc_dev *d)
111{
112 int minor;
113 int err;
114
115 if (!d) {
116 pr_err("driver pointer must be not NULL!\n");
117 return -EBADRQC;
118 }
119
120 if (!d->dev.parent) {
121 pr_err("dev parent pointer not filled in!\n");
122 return -EINVAL;
123 }
124
125 if (!d->fops) {
126 pr_err("fops pointer not filled in!\n");
127 return -EINVAL;
128 }
129
130 if (!d->buf && d->chunk_size < 1) {
131 pr_err("chunk_size must be set!\n");
132 return -EINVAL;
133 }
134
135 if (!d->buf && d->buffer_size < 1) {
136 pr_err("buffer_size must be set!\n");
137 return -EINVAL;
138 }
139
140 if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) {
141 dev_err(&d->dev, "code length must be less than %d bits\n",
142 BUFLEN * 8);
143 return -EBADRQC;
144 }
145
146 if (!d->buf && !(d->fops && d->fops->read &&
147 d->fops->poll && d->fops->unlocked_ioctl)) {
148 dev_err(&d->dev, "undefined read, poll, ioctl\n");
149 return -EBADRQC;
150 }
151
152 /* some safety check 8-) */
153 d->name[sizeof(d->name) - 1] = '\0';
154
155 if (d->features == 0)
156 d->features = LIRC_CAN_REC_LIRCCODE;
157
158 if (LIRC_CAN_REC(d->features)) {
159 err = lirc_allocate_buffer(d);
160 if (err)
161 return err;
162 }
163
164 minor = ida_simple_get(&lirc_ida, 0, LIRC_MAX_DEVICES, GFP_KERNEL);
165 if (minor < 0)
166 return minor;
167
168 d->minor = minor;
169 d->dev.devt = MKDEV(MAJOR(lirc_base_dev), d->minor);
170 dev_set_name(&d->dev, "lirc%d", d->minor);
171
172 cdev_init(&d->cdev, d->fops);
173 d->cdev.owner = d->owner;
174 d->attached = true;
175
176 err = cdev_device_add(&d->cdev, &d->dev);
177 if (err) {
178 ida_simple_remove(&lirc_ida, minor);
179 return err;
180 }
181
182 get_device(d->dev.parent);
183
184 dev_info(&d->dev, "lirc_dev: driver %s registered at minor = %d\n",
185 d->name, d->minor);
186
187 return 0;
188}
189EXPORT_SYMBOL(lirc_register_device);
190
191void lirc_unregister_device(struct lirc_dev *d)
192{
193 if (!d)
194 return;
195
196 dev_dbg(&d->dev, "lirc_dev: driver %s unregistered from minor = %d\n",
197 d->name, d->minor);
198
199 mutex_lock(&d->mutex);
200
201 d->attached = false;
202 if (d->open) {
203 dev_dbg(&d->dev, LOGHEAD "releasing opened driver\n",
204 d->name, d->minor);
205 wake_up_interruptible(&d->buf->wait_poll);
206 }
207
208 mutex_unlock(&d->mutex);
209
210 cdev_device_del(&d->cdev, &d->dev);
211 ida_simple_remove(&lirc_ida, d->minor);
212 put_device(&d->dev);
213}
214EXPORT_SYMBOL(lirc_unregister_device);
215
216int lirc_dev_fop_open(struct inode *inode, struct file *file)
217{
218 struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);
219 int retval;
220
221 dev_dbg(&d->dev, LOGHEAD "open called\n", d->name, d->minor);
222
223 retval = mutex_lock_interruptible(&d->mutex);
224 if (retval)
225 return retval;
226
227 if (!d->attached) {
228 retval = -ENODEV;
229 goto out;
230 }
231
232 if (d->open) {
233 retval = -EBUSY;
234 goto out;
235 }
236
237 if (d->rdev) {
238 retval = rc_open(d->rdev);
239 if (retval)
240 goto out;
241 }
242
243 if (d->buf)
244 lirc_buffer_clear(d->buf);
245
246 d->open++;
247
248 lirc_init_pdata(inode, file);
249 nonseekable_open(inode, file);
250 mutex_unlock(&d->mutex);
251
252 return 0;
253
254out:
255 mutex_unlock(&d->mutex);
256 return retval;
257}
258EXPORT_SYMBOL(lirc_dev_fop_open);
259
260int lirc_dev_fop_close(struct inode *inode, struct file *file)
261{
262 struct lirc_dev *d = file->private_data;
263
264 mutex_lock(&d->mutex);
265
266 rc_close(d->rdev);
267 d->open--;
268
269 mutex_unlock(&d->mutex);
270
271 return 0;
272}
273EXPORT_SYMBOL(lirc_dev_fop_close);
274
275unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
276{
277 struct lirc_dev *d = file->private_data;
278 unsigned int ret;
279
280 if (!d->attached)
281 return POLLHUP | POLLERR;
282
283 if (d->buf) {
284 poll_wait(file, &d->buf->wait_poll, wait);
285
286 if (lirc_buffer_empty(d->buf))
287 ret = 0;
288 else
289 ret = POLLIN | POLLRDNORM;
290 } else {
291 ret = POLLERR;
292 }
293
294 dev_dbg(&d->dev, LOGHEAD "poll result = %d\n", d->name, d->minor, ret);
295
296 return ret;
297}
298EXPORT_SYMBOL(lirc_dev_fop_poll);
299
300long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
301{
302 struct lirc_dev *d = file->private_data;
303 __u32 mode;
304 int result;
305
306 dev_dbg(&d->dev, LOGHEAD "ioctl called (0x%x)\n",
307 d->name, d->minor, cmd);
308
309 result = mutex_lock_interruptible(&d->mutex);
310 if (result)
311 return result;
312
313 if (!d->attached) {
314 result = -ENODEV;
315 goto out;
316 }
317
318 switch (cmd) {
319 case LIRC_GET_FEATURES:
320 result = put_user(d->features, (__u32 __user *)arg);
321 break;
322 case LIRC_GET_REC_MODE:
323 if (!LIRC_CAN_REC(d->features)) {
324 result = -ENOTTY;
325 break;
326 }
327
328 result = put_user(LIRC_REC2MODE
329 (d->features & LIRC_CAN_REC_MASK),
330 (__u32 __user *)arg);
331 break;
332 case LIRC_SET_REC_MODE:
333 if (!LIRC_CAN_REC(d->features)) {
334 result = -ENOTTY;
335 break;
336 }
337
338 result = get_user(mode, (__u32 __user *)arg);
339 if (!result && !(LIRC_MODE2REC(mode) & d->features))
340 result = -EINVAL;
341 /*
342 * FIXME: We should actually set the mode somehow but
343 * for now, lirc_serial doesn't support mode changing either
344 */
345 break;
346 case LIRC_GET_LENGTH:
347 result = put_user(d->code_length, (__u32 __user *)arg);
348 break;
349 default:
350 result = -ENOTTY;
351 }
352
353out:
354 mutex_unlock(&d->mutex);
355 return result;
356}
357EXPORT_SYMBOL(lirc_dev_fop_ioctl);
358
359ssize_t lirc_dev_fop_read(struct file *file,
360 char __user *buffer,
361 size_t length,
362 loff_t *ppos)
363{
364 struct lirc_dev *d = file->private_data;
365 unsigned char *buf;
366 int ret, written = 0;
367 DECLARE_WAITQUEUE(wait, current);
368
369 buf = kzalloc(d->buf->chunk_size, GFP_KERNEL);
370 if (!buf)
371 return -ENOMEM;
372
373 dev_dbg(&d->dev, LOGHEAD "read called\n", d->name, d->minor);
374
375 ret = mutex_lock_interruptible(&d->mutex);
376 if (ret) {
377 kfree(buf);
378 return ret;
379 }
380
381 if (!d->attached) {
382 ret = -ENODEV;
383 goto out_locked;
384 }
385
386 if (!LIRC_CAN_REC(d->features)) {
387 ret = -EINVAL;
388 goto out_locked;
389 }
390
391 if (length % d->buf->chunk_size) {
392 ret = -EINVAL;
393 goto out_locked;
394 }
395
396 /*
397 * we add ourselves to the task queue before buffer check
398 * to avoid losing scan code (in case when queue is awaken somewhere
399 * between while condition checking and scheduling)
400 */
401 add_wait_queue(&d->buf->wait_poll, &wait);
402
403 /*
404 * while we didn't provide 'length' bytes, device is opened in blocking
405 * mode and 'copy_to_user' is happy, wait for data.
406 */
407 while (written < length && ret == 0) {
408 if (lirc_buffer_empty(d->buf)) {
409 /* According to the read(2) man page, 'written' can be
410 * returned as less than 'length', instead of blocking
411 * again, returning -EWOULDBLOCK, or returning
412 * -ERESTARTSYS
413 */
414 if (written)
415 break;
416 if (file->f_flags & O_NONBLOCK) {
417 ret = -EWOULDBLOCK;
418 break;
419 }
420 if (signal_pending(current)) {
421 ret = -ERESTARTSYS;
422 break;
423 }
424
425 mutex_unlock(&d->mutex);
426 set_current_state(TASK_INTERRUPTIBLE);
427 schedule();
428 set_current_state(TASK_RUNNING);
429
430 ret = mutex_lock_interruptible(&d->mutex);
431 if (ret) {
432 remove_wait_queue(&d->buf->wait_poll, &wait);
433 goto out_unlocked;
434 }
435
436 if (!d->attached) {
437 ret = -ENODEV;
438 goto out_locked;
439 }
440 } else {
441 lirc_buffer_read(d->buf, buf);
442 ret = copy_to_user((void __user *)buffer+written, buf,
443 d->buf->chunk_size);
444 if (!ret)
445 written += d->buf->chunk_size;
446 else
447 ret = -EFAULT;
448 }
449 }
450
451 remove_wait_queue(&d->buf->wait_poll, &wait);
452
453out_locked:
454 mutex_unlock(&d->mutex);
455
456out_unlocked:
457 kfree(buf);
458
459 return ret ? ret : written;
460}
461EXPORT_SYMBOL(lirc_dev_fop_read);
462
463void lirc_init_pdata(struct inode *inode, struct file *file)
464{
465 struct lirc_dev *d = container_of(inode->i_cdev, struct lirc_dev, cdev);
466
467 file->private_data = d;
468}
469EXPORT_SYMBOL(lirc_init_pdata);
470
471void *lirc_get_pdata(struct file *file)
472{
473 struct lirc_dev *d = file->private_data;
474
475 return d->data;
476}
477EXPORT_SYMBOL(lirc_get_pdata);
478
479
480static int __init lirc_dev_init(void)
481{
482 int retval;
483
484 lirc_class = class_create(THIS_MODULE, "lirc");
485 if (IS_ERR(lirc_class)) {
486 pr_err("class_create failed\n");
487 return PTR_ERR(lirc_class);
488 }
489
490 retval = alloc_chrdev_region(&lirc_base_dev, 0, LIRC_MAX_DEVICES,
491 "BaseRemoteCtl");
492 if (retval) {
493 class_destroy(lirc_class);
494 pr_err("alloc_chrdev_region failed\n");
495 return retval;
496 }
497
498 pr_info("IR Remote Control driver registered, major %d\n",
499 MAJOR(lirc_base_dev));
500
501 return 0;
502}
503
504static void __exit lirc_dev_exit(void)
505{
506 class_destroy(lirc_class);
507 unregister_chrdev_region(lirc_base_dev, LIRC_MAX_DEVICES);
508 pr_info("module unloaded\n");
509}
510
511module_init(lirc_dev_init);
512module_exit(lirc_dev_exit);
513
514MODULE_DESCRIPTION("LIRC base driver module");
515MODULE_AUTHOR("Artur Lipowski");
516MODULE_LICENSE("GPL");