aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2010-07-03 00:06:57 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-08-02 14:04:19 -0400
commit4a62a5ab59742331a4e17ccaa894968d40ed9b16 (patch)
tree59912f9892b55442327f5b2189ba4d0abbd0f74a /drivers
parent7a12f4b50dad4fdffd218c6fba6b9564bf86185e (diff)
V4L/DVB: IR: add lirc device interface
v2: currently unused ioctls are included, but #if 0'd out Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/IR/Kconfig11
-rw-r--r--drivers/media/IR/Makefile1
-rw-r--r--drivers/media/IR/lirc_dev.c761
-rw-r--r--drivers/media/IR/lirc_dev.h226
4 files changed, 999 insertions, 0 deletions
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
index 797a6c36d984..5d2c37dcf11a 100644
--- a/drivers/media/IR/Kconfig
+++ b/drivers/media/IR/Kconfig
@@ -8,6 +8,17 @@ config VIDEO_IR
8 depends on IR_CORE 8 depends on IR_CORE
9 default IR_CORE 9 default IR_CORE
10 10
11config LIRC
12 tristate
13 default y
14
15 ---help---
16 Enable this option to build the Linux Infrared Remote
17 Control (LIRC) core device interface driver. The LIRC
18 interface passes raw IR to and from userspace, where the
19 LIRC daemon handles protocol decoding for IR reception ann
20 encoding for IR transmitting (aka "blasting").
21
11source "drivers/media/IR/keymaps/Kconfig" 22source "drivers/media/IR/keymaps/Kconfig"
12 23
13config IR_NEC_DECODER 24config IR_NEC_DECODER
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
index b43fe36d88b2..3ba00bb8bea0 100644
--- a/drivers/media/IR/Makefile
+++ b/drivers/media/IR/Makefile
@@ -5,6 +5,7 @@ obj-y += keymaps/
5 5
6obj-$(CONFIG_IR_CORE) += ir-core.o 6obj-$(CONFIG_IR_CORE) += ir-core.o
7obj-$(CONFIG_VIDEO_IR) += ir-common.o 7obj-$(CONFIG_VIDEO_IR) += ir-common.o
8obj-$(CONFIG_LIRC) += lirc_dev.o
8obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o 9obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
9obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o 10obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
10obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o 11obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c
new file mode 100644
index 000000000000..9e141d51df91
--- /dev/null
+++ b/drivers/media/IR/lirc_dev.c
@@ -0,0 +1,761 @@
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/sched.h>
25#include <linux/errno.h>
26#include <linux/ioctl.h>
27#include <linux/fs.h>
28#include <linux/poll.h>
29#include <linux/completion.h>
30#include <linux/errno.h>
31#include <linux/mutex.h>
32#include <linux/wait.h>
33#include <linux/unistd.h>
34#include <linux/kthread.h>
35#include <linux/bitops.h>
36#include <linux/device.h>
37#include <linux/cdev.h>
38
39#include <media/lirc.h>
40#include "lirc_dev.h"
41
42static int debug;
43
44#define IRCTL_DEV_NAME "BaseRemoteCtl"
45#define NOPLUG -1
46#define LOGHEAD "lirc_dev (%s[%d]): "
47
48static dev_t lirc_base_dev;
49
50struct irctl {
51 struct lirc_driver d;
52 int attached;
53 int open;
54
55 struct mutex irctl_lock;
56 struct lirc_buffer *buf;
57 unsigned int chunk_size;
58
59 struct task_struct *task;
60 long jiffies_to_wait;
61
62 struct cdev cdev;
63};
64
65static DEFINE_MUTEX(lirc_dev_lock);
66
67static struct irctl *irctls[MAX_IRCTL_DEVICES];
68
69/* Only used for sysfs but defined to void otherwise */
70static struct class *lirc_class;
71
72/* helper function
73 * initializes the irctl structure
74 */
75static void init_irctl(struct irctl *ir)
76{
77 dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
78 ir->d.name, ir->d.minor);
79 mutex_init(&ir->irctl_lock);
80 ir->d.minor = NOPLUG;
81}
82
83static void cleanup(struct irctl *ir)
84{
85 dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
86
87 device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
88
89 if (ir->buf != ir->d.rbuf) {
90 lirc_buffer_free(ir->buf);
91 kfree(ir->buf);
92 }
93 ir->buf = NULL;
94}
95
96/* helper function
97 * reads key codes from driver and puts them into buffer
98 * returns 0 on success
99 */
100static int add_to_buf(struct irctl *ir)
101{
102 if (ir->d.add_to_buf) {
103 int res = -ENODATA;
104 int got_data = 0;
105
106 /*
107 * service the device as long as it is returning
108 * data and we have space
109 */
110get_data:
111 res = ir->d.add_to_buf(ir->d.data, ir->buf);
112 if (res == 0) {
113 got_data++;
114 goto get_data;
115 }
116
117 if (res == -ENODEV)
118 kthread_stop(ir->task);
119
120 return got_data ? 0 : res;
121 }
122
123 return 0;
124}
125
126/* main function of the polling thread
127 */
128static int lirc_thread(void *irctl)
129{
130 struct irctl *ir = irctl;
131
132 dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
133 ir->d.name, ir->d.minor);
134
135 do {
136 if (ir->open) {
137 if (ir->jiffies_to_wait) {
138 set_current_state(TASK_INTERRUPTIBLE);
139 schedule_timeout(ir->jiffies_to_wait);
140 }
141 if (kthread_should_stop())
142 break;
143 if (!add_to_buf(ir))
144 wake_up_interruptible(&ir->buf->wait_poll);
145 } else {
146 set_current_state(TASK_INTERRUPTIBLE);
147 schedule();
148 }
149 } while (!kthread_should_stop());
150
151 dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
152 ir->d.name, ir->d.minor);
153
154 return 0;
155}
156
157
158static struct file_operations fops = {
159 .owner = THIS_MODULE,
160 .read = lirc_dev_fop_read,
161 .write = lirc_dev_fop_write,
162 .poll = lirc_dev_fop_poll,
163 .ioctl = lirc_dev_fop_ioctl,
164 .open = lirc_dev_fop_open,
165 .release = lirc_dev_fop_close,
166};
167
168static int lirc_cdev_add(struct irctl *ir)
169{
170 int retval;
171 struct lirc_driver *d = &ir->d;
172
173 if (d->fops) {
174 cdev_init(&ir->cdev, d->fops);
175 ir->cdev.owner = d->owner;
176 } else {
177 cdev_init(&ir->cdev, &fops);
178 ir->cdev.owner = THIS_MODULE;
179 }
180 kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
181
182 retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
183 if (retval)
184 kobject_put(&ir->cdev.kobj);
185
186 return retval;
187}
188
189int lirc_register_driver(struct lirc_driver *d)
190{
191 struct irctl *ir;
192 int minor;
193 int bytes_in_key;
194 unsigned int chunk_size;
195 unsigned int buffer_size;
196 int err;
197
198 if (!d) {
199 printk(KERN_ERR "lirc_dev: lirc_register_driver: "
200 "driver pointer must be not NULL!\n");
201 err = -EBADRQC;
202 goto out;
203 }
204
205 if (MAX_IRCTL_DEVICES <= d->minor) {
206 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
207 "\"minor\" must be between 0 and %d (%d)!\n",
208 MAX_IRCTL_DEVICES-1, d->minor);
209 err = -EBADRQC;
210 goto out;
211 }
212
213 if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
214 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
215 "code length in bits for minor (%d) "
216 "must be less than %d!\n",
217 d->minor, BUFLEN * 8);
218 err = -EBADRQC;
219 goto out;
220 }
221
222 dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
223 d->sample_rate);
224 if (d->sample_rate) {
225 if (2 > d->sample_rate || HZ < d->sample_rate) {
226 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
227 "sample_rate must be between 2 and %d!\n", HZ);
228 err = -EBADRQC;
229 goto out;
230 }
231 if (!d->add_to_buf) {
232 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
233 "add_to_buf cannot be NULL when "
234 "sample_rate is set\n");
235 err = -EBADRQC;
236 goto out;
237 }
238 } else if (!(d->fops && d->fops->read) && !d->rbuf) {
239 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
240 "fops->read and rbuf cannot all be NULL!\n");
241 err = -EBADRQC;
242 goto out;
243 } else if (!d->rbuf) {
244 if (!(d->fops && d->fops->read && d->fops->poll &&
245 d->fops->ioctl)) {
246 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
247 "neither read, poll nor ioctl can be NULL!\n");
248 err = -EBADRQC;
249 goto out;
250 }
251 }
252
253 mutex_lock(&lirc_dev_lock);
254
255 minor = d->minor;
256
257 if (minor < 0) {
258 /* find first free slot for driver */
259 for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
260 if (!irctls[minor])
261 break;
262 if (MAX_IRCTL_DEVICES == minor) {
263 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
264 "no free slots for drivers!\n");
265 err = -ENOMEM;
266 goto out_lock;
267 }
268 } else if (irctls[minor]) {
269 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
270 "minor (%d) just registered!\n", minor);
271 err = -EBUSY;
272 goto out_lock;
273 }
274
275 ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
276 if (!ir) {
277 err = -ENOMEM;
278 goto out_lock;
279 }
280 init_irctl(ir);
281 irctls[minor] = ir;
282 d->minor = minor;
283
284 if (d->sample_rate) {
285 ir->jiffies_to_wait = HZ / d->sample_rate;
286 } else {
287 /* it means - wait for external event in task queue */
288 ir->jiffies_to_wait = 0;
289 }
290
291 /* some safety check 8-) */
292 d->name[sizeof(d->name)-1] = '\0';
293
294 bytes_in_key = BITS_TO_LONGS(d->code_length) +
295 (d->code_length % 8 ? 1 : 0);
296 buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
297 chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key;
298
299 if (d->rbuf) {
300 ir->buf = d->rbuf;
301 } else {
302 ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
303 if (!ir->buf) {
304 err = -ENOMEM;
305 goto out_lock;
306 }
307 err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
308 if (err) {
309 kfree(ir->buf);
310 goto out_lock;
311 }
312 }
313 ir->chunk_size = ir->buf->chunk_size;
314
315 if (d->features == 0)
316 d->features = LIRC_CAN_REC_LIRCCODE;
317
318 ir->d = *d;
319 ir->d.minor = minor;
320
321 device_create(lirc_class, ir->d.dev,
322 MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
323 "lirc%u", ir->d.minor);
324
325 if (d->sample_rate) {
326 /* try to fire up polling thread */
327 ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
328 if (IS_ERR(ir->task)) {
329 dev_err(d->dev, "lirc_dev: lirc_register_driver: "
330 "cannot run poll thread for minor = %d\n",
331 d->minor);
332 err = -ECHILD;
333 goto out_sysfs;
334 }
335 }
336
337 err = lirc_cdev_add(ir);
338 if (err)
339 goto out_sysfs;
340
341 ir->attached = 1;
342 mutex_unlock(&lirc_dev_lock);
343
344 dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
345 ir->d.name, ir->d.minor);
346 return minor;
347
348out_sysfs:
349 device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
350out_lock:
351 mutex_unlock(&lirc_dev_lock);
352out:
353 return err;
354}
355EXPORT_SYMBOL(lirc_register_driver);
356
357int lirc_unregister_driver(int minor)
358{
359 struct irctl *ir;
360
361 if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
362 printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
363 "\"minor (%d)\" must be between 0 and %d!\n",
364 minor, MAX_IRCTL_DEVICES-1);
365 return -EBADRQC;
366 }
367
368 ir = irctls[minor];
369
370 mutex_lock(&lirc_dev_lock);
371
372 if (ir->d.minor != minor) {
373 printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
374 "minor (%d) device not registered!", minor);
375 mutex_unlock(&lirc_dev_lock);
376 return -ENOENT;
377 }
378
379 /* end up polling thread */
380 if (ir->task)
381 kthread_stop(ir->task);
382
383 dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
384 ir->d.name, ir->d.minor);
385
386 ir->attached = 0;
387 if (ir->open) {
388 dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
389 ir->d.name, ir->d.minor);
390 wake_up_interruptible(&ir->buf->wait_poll);
391 mutex_lock(&ir->irctl_lock);
392 ir->d.set_use_dec(ir->d.data);
393 module_put(ir->d.owner);
394 mutex_unlock(&ir->irctl_lock);
395 cdev_del(&ir->cdev);
396 } else {
397 cleanup(ir);
398 cdev_del(&ir->cdev);
399 kfree(ir);
400 irctls[minor] = NULL;
401 }
402
403 mutex_unlock(&lirc_dev_lock);
404
405 return 0;
406}
407EXPORT_SYMBOL(lirc_unregister_driver);
408
409int lirc_dev_fop_open(struct inode *inode, struct file *file)
410{
411 struct irctl *ir;
412 int retval = 0;
413
414 if (iminor(inode) >= MAX_IRCTL_DEVICES) {
415 printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
416 iminor(inode));
417 return -ENODEV;
418 }
419
420 if (mutex_lock_interruptible(&lirc_dev_lock))
421 return -ERESTARTSYS;
422
423 ir = irctls[iminor(inode)];
424 if (!ir) {
425 retval = -ENODEV;
426 goto error;
427 }
428
429 dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
430
431 if (ir->d.minor == NOPLUG) {
432 retval = -ENODEV;
433 goto error;
434 }
435
436 if (ir->open) {
437 retval = -EBUSY;
438 goto error;
439 }
440
441 if (try_module_get(ir->d.owner)) {
442 ++ir->open;
443 retval = ir->d.set_use_inc(ir->d.data);
444
445 if (retval) {
446 module_put(ir->d.owner);
447 --ir->open;
448 } else {
449 lirc_buffer_clear(ir->buf);
450 }
451 if (ir->task)
452 wake_up_process(ir->task);
453 }
454
455error:
456 if (ir)
457 dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
458 ir->d.name, ir->d.minor, retval);
459
460 mutex_unlock(&lirc_dev_lock);
461
462 return retval;
463}
464EXPORT_SYMBOL(lirc_dev_fop_open);
465
466int lirc_dev_fop_close(struct inode *inode, struct file *file)
467{
468 struct irctl *ir = irctls[iminor(inode)];
469
470 dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
471
472 WARN_ON(mutex_lock_killable(&lirc_dev_lock));
473
474 --ir->open;
475 if (ir->attached) {
476 ir->d.set_use_dec(ir->d.data);
477 module_put(ir->d.owner);
478 } else {
479 cleanup(ir);
480 irctls[ir->d.minor] = NULL;
481 kfree(ir);
482 }
483
484 mutex_unlock(&lirc_dev_lock);
485
486 return 0;
487}
488EXPORT_SYMBOL(lirc_dev_fop_close);
489
490unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
491{
492 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
493 unsigned int ret;
494
495 dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
496
497 if (!ir->attached) {
498 mutex_unlock(&ir->irctl_lock);
499 return POLLERR;
500 }
501
502 poll_wait(file, &ir->buf->wait_poll, wait);
503
504 if (ir->buf)
505 if (lirc_buffer_empty(ir->buf))
506 ret = 0;
507 else
508 ret = POLLIN | POLLRDNORM;
509 else
510 ret = POLLERR;
511
512 dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
513 ir->d.name, ir->d.minor, ret);
514
515 return ret;
516}
517EXPORT_SYMBOL(lirc_dev_fop_poll);
518
519int lirc_dev_fop_ioctl(struct inode *inode, struct file *file,
520 unsigned int cmd, unsigned long arg)
521{
522 unsigned long mode;
523 int result = 0;
524 struct irctl *ir = irctls[iminor(inode)];
525
526 dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
527 ir->d.name, ir->d.minor, cmd);
528
529 if (ir->d.minor == NOPLUG || !ir->attached) {
530 dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
531 ir->d.name, ir->d.minor);
532 return -ENODEV;
533 }
534
535 mutex_lock(&ir->irctl_lock);
536
537 switch (cmd) {
538 case LIRC_GET_FEATURES:
539 result = put_user(ir->d.features, (unsigned long *)arg);
540 break;
541 case LIRC_GET_REC_MODE:
542 if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
543 result = -ENOSYS;
544 break;
545 }
546
547 result = put_user(LIRC_REC2MODE
548 (ir->d.features & LIRC_CAN_REC_MASK),
549 (unsigned long *)arg);
550 break;
551 case LIRC_SET_REC_MODE:
552 if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
553 result = -ENOSYS;
554 break;
555 }
556
557 result = get_user(mode, (unsigned long *)arg);
558 if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
559 result = -EINVAL;
560 /*
561 * FIXME: We should actually set the mode somehow but
562 * for now, lirc_serial doesn't support mode changing either
563 */
564 break;
565 case LIRC_GET_LENGTH:
566 result = put_user(ir->d.code_length, (unsigned long *)arg);
567 break;
568 case LIRC_GET_MIN_TIMEOUT:
569 if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
570 ir->d.min_timeout == 0) {
571 result = -ENOSYS;
572 break;
573 }
574
575 result = put_user(ir->d.min_timeout, (unsigned long *)arg);
576 break;
577 case LIRC_GET_MAX_TIMEOUT:
578 if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
579 ir->d.max_timeout == 0) {
580 result = -ENOSYS;
581 break;
582 }
583
584 result = put_user(ir->d.max_timeout, (unsigned long *)arg);
585 break;
586 default:
587 result = -EINVAL;
588 }
589
590 dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
591 ir->d.name, ir->d.minor, result);
592
593 mutex_unlock(&ir->irctl_lock);
594
595 return result;
596}
597EXPORT_SYMBOL(lirc_dev_fop_ioctl);
598
599ssize_t lirc_dev_fop_read(struct file *file,
600 char *buffer,
601 size_t length,
602 loff_t *ppos)
603{
604 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
605 unsigned char buf[ir->chunk_size];
606 int ret = 0, written = 0;
607 DECLARE_WAITQUEUE(wait, current);
608
609 dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
610
611 if (mutex_lock_interruptible(&ir->irctl_lock))
612 return -ERESTARTSYS;
613 if (!ir->attached) {
614 mutex_unlock(&ir->irctl_lock);
615 return -ENODEV;
616 }
617
618 if (length % ir->chunk_size) {
619 dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
620 ir->d.name, ir->d.minor);
621 mutex_unlock(&ir->irctl_lock);
622 return -EINVAL;
623 }
624
625 /*
626 * we add ourselves to the task queue before buffer check
627 * to avoid losing scan code (in case when queue is awaken somewhere
628 * between while condition checking and scheduling)
629 */
630 add_wait_queue(&ir->buf->wait_poll, &wait);
631 set_current_state(TASK_INTERRUPTIBLE);
632
633 /*
634 * while we didn't provide 'length' bytes, device is opened in blocking
635 * mode and 'copy_to_user' is happy, wait for data.
636 */
637 while (written < length && ret == 0) {
638 if (lirc_buffer_empty(ir->buf)) {
639 /* According to the read(2) man page, 'written' can be
640 * returned as less than 'length', instead of blocking
641 * again, returning -EWOULDBLOCK, or returning
642 * -ERESTARTSYS */
643 if (written)
644 break;
645 if (file->f_flags & O_NONBLOCK) {
646 ret = -EWOULDBLOCK;
647 break;
648 }
649 if (signal_pending(current)) {
650 ret = -ERESTARTSYS;
651 break;
652 }
653
654 mutex_unlock(&ir->irctl_lock);
655 schedule();
656 set_current_state(TASK_INTERRUPTIBLE);
657
658 if (mutex_lock_interruptible(&ir->irctl_lock)) {
659 ret = -ERESTARTSYS;
660 break;
661 }
662
663 if (!ir->attached) {
664 ret = -ENODEV;
665 break;
666 }
667 } else {
668 lirc_buffer_read(ir->buf, buf);
669 ret = copy_to_user((void *)buffer+written, buf,
670 ir->buf->chunk_size);
671 written += ir->buf->chunk_size;
672 }
673 }
674
675 remove_wait_queue(&ir->buf->wait_poll, &wait);
676 set_current_state(TASK_RUNNING);
677 mutex_unlock(&ir->irctl_lock);
678
679 dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
680 ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
681
682 return ret ? ret : written;
683}
684EXPORT_SYMBOL(lirc_dev_fop_read);
685
686void *lirc_get_pdata(struct file *file)
687{
688 void *data = NULL;
689
690 if (file && file->f_dentry && file->f_dentry->d_inode &&
691 file->f_dentry->d_inode->i_rdev) {
692 struct irctl *ir;
693 ir = irctls[iminor(file->f_dentry->d_inode)];
694 data = ir->d.data;
695 }
696
697 return data;
698}
699EXPORT_SYMBOL(lirc_get_pdata);
700
701
702ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
703 size_t length, loff_t *ppos)
704{
705 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
706
707 dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
708
709 if (!ir->attached)
710 return -ENODEV;
711
712 return -EINVAL;
713}
714EXPORT_SYMBOL(lirc_dev_fop_write);
715
716
717static int __init lirc_dev_init(void)
718{
719 int retval;
720
721 lirc_class = class_create(THIS_MODULE, "lirc");
722 if (IS_ERR(lirc_class)) {
723 retval = PTR_ERR(lirc_class);
724 printk(KERN_ERR "lirc_dev: class_create failed\n");
725 goto error;
726 }
727
728 retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
729 IRCTL_DEV_NAME);
730 if (retval) {
731 class_destroy(lirc_class);
732 printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
733 goto error;
734 }
735
736
737 printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
738 "major %d \n", MAJOR(lirc_base_dev));
739
740error:
741 return retval;
742}
743
744
745
746static void __exit lirc_dev_exit(void)
747{
748 class_destroy(lirc_class);
749 unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
750 printk(KERN_INFO "lirc_dev: module unloaded\n");
751}
752
753module_init(lirc_dev_init);
754module_exit(lirc_dev_exit);
755
756MODULE_DESCRIPTION("LIRC base driver module");
757MODULE_AUTHOR("Artur Lipowski");
758MODULE_LICENSE("GPL");
759
760module_param(debug, bool, S_IRUGO | S_IWUSR);
761MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/media/IR/lirc_dev.h b/drivers/media/IR/lirc_dev.h
new file mode 100644
index 000000000000..4afd96a38a43
--- /dev/null
+++ b/drivers/media/IR/lirc_dev.h
@@ -0,0 +1,226 @@
1/*
2 * LIRC base driver
3 *
4 * by Artur Lipowski <alipowski@interia.pl>
5 * This code is licensed under GNU GPL
6 *
7 */
8
9#ifndef _LINUX_LIRC_DEV_H
10#define _LINUX_LIRC_DEV_H
11
12#define MAX_IRCTL_DEVICES 4
13#define BUFLEN 16
14
15#define mod(n, div) ((n) % (div))
16
17#include <linux/slab.h>
18#include <linux/fs.h>
19#include <linux/ioctl.h>
20#include <linux/poll.h>
21#include <linux/kfifo.h>
22#include <media/lirc.h>
23
24struct lirc_buffer {
25 wait_queue_head_t wait_poll;
26 spinlock_t fifo_lock;
27 unsigned int chunk_size;
28 unsigned int size; /* in chunks */
29 /* Using chunks instead of bytes pretends to simplify boundary checking
30 * And should allow for some performance fine tunning later */
31 struct kfifo fifo;
32 u8 fifo_initialized;
33};
34
35static inline void lirc_buffer_clear(struct lirc_buffer *buf)
36{
37 unsigned long flags;
38
39 if (buf->fifo_initialized) {
40 spin_lock_irqsave(&buf->fifo_lock, flags);
41 kfifo_reset(&buf->fifo);
42 spin_unlock_irqrestore(&buf->fifo_lock, flags);
43 } else
44 WARN(1, "calling %s on an uninitialized lirc_buffer\n",
45 __func__);
46}
47
48static inline int lirc_buffer_init(struct lirc_buffer *buf,
49 unsigned int chunk_size,
50 unsigned int size)
51{
52 int ret;
53
54 init_waitqueue_head(&buf->wait_poll);
55 spin_lock_init(&buf->fifo_lock);
56 buf->chunk_size = chunk_size;
57 buf->size = size;
58 ret = kfifo_alloc(&buf->fifo, size * chunk_size, GFP_KERNEL);
59 if (ret == 0)
60 buf->fifo_initialized = 1;
61
62 return ret;
63}
64
65static inline void lirc_buffer_free(struct lirc_buffer *buf)
66{
67 if (buf->fifo_initialized) {
68 kfifo_free(&buf->fifo);
69 buf->fifo_initialized = 0;
70 } else
71 WARN(1, "calling %s on an uninitialized lirc_buffer\n",
72 __func__);
73}
74
75static inline int lirc_buffer_len(struct lirc_buffer *buf)
76{
77 int len;
78 unsigned long flags;
79
80 spin_lock_irqsave(&buf->fifo_lock, flags);
81 len = kfifo_len(&buf->fifo);
82 spin_unlock_irqrestore(&buf->fifo_lock, flags);
83
84 return len;
85}
86
87static inline int lirc_buffer_full(struct lirc_buffer *buf)
88{
89 return lirc_buffer_len(buf) == buf->size * buf->chunk_size;
90}
91
92static inline int lirc_buffer_empty(struct lirc_buffer *buf)
93{
94 return !lirc_buffer_len(buf);
95}
96
97static inline int lirc_buffer_available(struct lirc_buffer *buf)
98{
99 return buf->size - (lirc_buffer_len(buf) / buf->chunk_size);
100}
101
102static inline unsigned int lirc_buffer_read(struct lirc_buffer *buf,
103 unsigned char *dest)
104{
105 unsigned int ret = 0;
106
107 if (lirc_buffer_len(buf) >= buf->chunk_size)
108 ret = kfifo_out_locked(&buf->fifo, dest, buf->chunk_size,
109 &buf->fifo_lock);
110 return ret;
111
112}
113
114static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
115 unsigned char *orig)
116{
117 unsigned int ret;
118
119 ret = kfifo_in_locked(&buf->fifo, orig, buf->chunk_size,
120 &buf->fifo_lock);
121
122 return ret;
123}
124
125struct lirc_driver {
126 char name[40];
127 int minor;
128 unsigned long code_length;
129 unsigned int buffer_size; /* in chunks holding one code each */
130 int sample_rate;
131 unsigned long features;
132
133 unsigned int chunk_size;
134
135 void *data;
136 int min_timeout;
137 int max_timeout;
138 int (*add_to_buf) (void *data, struct lirc_buffer *buf);
139 struct lirc_buffer *rbuf;
140 int (*set_use_inc) (void *data);
141 void (*set_use_dec) (void *data);
142 struct file_operations *fops;
143 struct device *dev;
144 struct module *owner;
145};
146
147/* name:
148 * this string will be used for logs
149 *
150 * minor:
151 * indicates minor device (/dev/lirc) number for registered driver
152 * if caller fills it with negative value, then the first free minor
153 * number will be used (if available)
154 *
155 * code_length:
156 * length of the remote control key code expressed in bits
157 *
158 * sample_rate:
159 *
160 * data:
161 * it may point to any driver data and this pointer will be passed to
162 * all callback functions
163 *
164 * add_to_buf:
165 * add_to_buf will be called after specified period of the time or
166 * triggered by the external event, this behavior depends on value of
167 * the sample_rate this function will be called in user context. This
168 * routine should return 0 if data was added to the buffer and
169 * -ENODATA if none was available. This should add some number of bits
170 * evenly divisible by code_length to the buffer
171 *
172 * rbuf:
173 * if not NULL, it will be used as a read buffer, you will have to
174 * write to the buffer by other means, like irq's (see also
175 * lirc_serial.c).
176 *
177 * set_use_inc:
178 * set_use_inc will be called after device is opened
179 *
180 * set_use_dec:
181 * set_use_dec will be called after device is closed
182 *
183 * fops:
184 * file_operations for drivers which don't fit the current driver model.
185 *
186 * Some ioctl's can be directly handled by lirc_dev if the driver's
187 * ioctl function is NULL or if it returns -ENOIOCTLCMD (see also
188 * lirc_serial.c).
189 *
190 * owner:
191 * the module owning this struct
192 *
193 */
194
195
196/* following functions can be called ONLY from user context
197 *
198 * returns negative value on error or minor number
199 * of the registered device if success
200 * contents of the structure pointed by p is copied
201 */
202extern int lirc_register_driver(struct lirc_driver *d);
203
204/* returns negative value on error or 0 if success
205*/
206extern int lirc_unregister_driver(int minor);
207
208/* Returns the private data stored in the lirc_driver
209 * associated with the given device file pointer.
210 */
211void *lirc_get_pdata(struct file *file);
212
213/* default file operations
214 * used by drivers if they override only some operations
215 */
216int lirc_dev_fop_open(struct inode *inode, struct file *file);
217int lirc_dev_fop_close(struct inode *inode, struct file *file);
218unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
219int lirc_dev_fop_ioctl(struct inode *inode, struct file *file,
220 unsigned int cmd, unsigned long arg);
221ssize_t lirc_dev_fop_read(struct file *file, char *buffer, size_t length,
222 loff_t *ppos);
223ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, size_t length,
224 loff_t *ppos);
225
226#endif