1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27
28
29#include <linux/module.h>
30#include <linux/sched.h>
31#include <linux/errno.h>
32#include <linux/signal.h>
33#include <linux/fs.h>
34#include <linux/kernel.h>
35#include <linux/ioport.h>
36#include <linux/ktime.h>
37#include <linux/mm.h>
38#include <linux/delay.h>
39
40#include <linux/io.h>
41#include <linux/irq.h>
42#include <linux/uaccess.h>
43#include <asm/div64.h>
44
45#include <linux/poll.h>
46#include <linux/parport.h>
47#include <linux/platform_device.h>
48
49#include <media/lirc.h>
50#include <media/lirc_dev.h>
51
52#include "lirc_parallel.h"
53
54#define LIRC_DRIVER_NAME "lirc_parallel"
55
56#ifndef LIRC_IRQ
57#define LIRC_IRQ 7
58#endif
59#ifndef LIRC_PORT
60#define LIRC_PORT 0x378
61#endif
62#ifndef LIRC_TIMER
63#define LIRC_TIMER 65536
64#endif
65
66
67
68static bool debug;
69static bool check_pselecd;
70
71static unsigned int irq = LIRC_IRQ;
72static unsigned int io = LIRC_PORT;
73#ifdef LIRC_TIMER
74static unsigned int timer;
75static unsigned int default_timer = LIRC_TIMER;
76#endif
77
78#define RBUF_SIZE (256)
79
80static int rbuf[RBUF_SIZE];
81
82static DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
83
84static unsigned int rptr;
85static unsigned int wptr;
86static unsigned int lost_irqs;
87static int is_open;
88
89static struct parport *pport;
90static struct pardevice *ppdevice;
91static int is_claimed;
92
93static unsigned int tx_mask = 1;
94
95
96
97static unsigned int in(int offset)
98{
99 switch (offset) {
100 case LIRC_LP_BASE:
101 return parport_read_data(pport);
102 case LIRC_LP_STATUS:
103 return parport_read_status(pport);
104 case LIRC_LP_CONTROL:
105 return parport_read_control(pport);
106 }
107 return 0;
108}
109
110static void out(int offset, int value)
111{
112 switch (offset) {
113 case LIRC_LP_BASE:
114 parport_write_data(pport, value);
115 break;
116 case LIRC_LP_CONTROL:
117 parport_write_control(pport, value);
118 break;
119 case LIRC_LP_STATUS:
120 pr_info("attempt to write to status register\n");
121 break;
122 }
123}
124
125static unsigned int lirc_get_timer(void)
126{
127 return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT;
128}
129
130static unsigned int lirc_get_signal(void)
131{
132 return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT;
133}
134
135static void lirc_on(void)
136{
137 out(LIRC_PORT_DATA, tx_mask);
138}
139
140static void lirc_off(void)
141{
142 out(LIRC_PORT_DATA, 0);
143}
144
145static unsigned int init_lirc_timer(void)
146{
147 ktime_t kt, now, timeout;
148 unsigned int level, newlevel, timeelapsed, newtimer;
149 int count = 0;
150
151 kt = ktime_get();
152
153 timeout = ktime_add_ns(kt, NSEC_PER_SEC);
154 level = lirc_get_timer();
155 do {
156 newlevel = lirc_get_timer();
157 if (level == 0 && newlevel != 0)
158 count++;
159 level = newlevel;
160 now = ktime_get();
161 } while (count < 1000 && (ktime_before(now, timeout)));
162 timeelapsed = ktime_us_delta(now, kt);
163 if (count >= 1000 && timeelapsed > 0) {
164 if (default_timer == 0) {
165
166 newtimer = (1000000 * count) / timeelapsed;
167 pr_info("%u Hz timer detected\n", newtimer);
168 return newtimer;
169 }
170 newtimer = (1000000 * count) / timeelapsed;
171 if (abs(newtimer - default_timer) > default_timer / 10) {
172
173 pr_notice("bad timer: %u Hz\n", newtimer);
174 pr_notice("using default timer: %u Hz\n",
175 default_timer);
176 return default_timer;
177 }
178 pr_info("%u Hz timer detected\n", newtimer);
179 return newtimer;
180 }
181
182 pr_notice("no timer detected\n");
183 return 0;
184}
185
186static int lirc_claim(void)
187{
188 if (parport_claim(ppdevice) != 0) {
189 pr_warn("could not claim port\n");
190 pr_warn("waiting for port becoming available\n");
191 if (parport_claim_or_block(ppdevice) < 0) {
192 pr_notice("could not claim port, giving up\n");
193 return 0;
194 }
195 }
196 out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP);
197 is_claimed = 1;
198 return 1;
199}
200
201
202
203static void rbuf_write(int signal)
204{
205 unsigned int nwptr;
206
207 nwptr = (wptr + 1) & (RBUF_SIZE - 1);
208 if (nwptr == rptr) {
209
210 lost_irqs++;
211 pr_notice("buffer overrun\n");
212 return;
213 }
214 rbuf[wptr] = signal;
215 wptr = nwptr;
216}
217
218static void lirc_lirc_irq_handler(void *blah)
219{
220 ktime_t kt, delkt;
221 static ktime_t lastkt;
222 static int init;
223 long signal;
224 int data;
225 unsigned int level, newlevel;
226 unsigned int timeout;
227
228 if (!is_open)
229 return;
230
231 if (!is_claimed)
232 return;
233
234#if 0
235
236 disable_irq(irq);
237 out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN));
238#endif
239 if (check_pselecd && (in(1) & LP_PSELECD))
240 return;
241
242#ifdef LIRC_TIMER
243 if (init) {
244 kt = ktime_get();
245
246 delkt = ktime_sub(kt, lastkt);
247 if (ktime_compare(delkt, ktime_set(15, 0)) > 0)
248
249 data = PULSE_MASK;
250 else
251 data = (int)(ktime_to_us(delkt) + LIRC_SFH506_DELAY);
252
253 rbuf_write(data);
254 } else {
255 if (timer == 0) {
256
257
258
259
260 timer = init_lirc_timer();
261
262 return;
263 }
264 init = 1;
265 }
266
267 timeout = timer / 10;
268 signal = 1;
269 level = lirc_get_timer();
270 do {
271 newlevel = lirc_get_timer();
272 if (level == 0 && newlevel != 0)
273 signal++;
274 level = newlevel;
275
276
277 if (signal > timeout
278 || (check_pselecd && (in(1) & LP_PSELECD))) {
279 signal = 0;
280 pr_notice("timeout\n");
281 break;
282 }
283 } while (lirc_get_signal());
284
285 if (signal != 0) {
286
287 __u64 helper;
288
289 helper = ((__u64)signal) * 1000000;
290 do_div(helper, timer);
291 signal = (long)helper;
292
293 if (signal > LIRC_SFH506_DELAY)
294 data = signal - LIRC_SFH506_DELAY;
295 else
296 data = 1;
297 rbuf_write(PULSE_BIT | data);
298 }
299 lastkt = ktime_get();
300#else
301
302#endif
303
304 wake_up_interruptible(&lirc_wait);
305
306
307
308
309
310
311}
312
313
314
315static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
316{
317 return -ESPIPE;
318}
319
320static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n,
321 loff_t *ppos)
322{
323 int result = 0;
324 int count = 0;
325 DECLARE_WAITQUEUE(wait, current);
326
327 if (n % sizeof(int))
328 return -EINVAL;
329
330 add_wait_queue(&lirc_wait, &wait);
331 set_current_state(TASK_INTERRUPTIBLE);
332 while (count < n) {
333 if (rptr != wptr) {
334 if (copy_to_user(buf + count, &rbuf[rptr],
335 sizeof(int))) {
336 result = -EFAULT;
337 break;
338 }
339 rptr = (rptr + 1) & (RBUF_SIZE - 1);
340 count += sizeof(int);
341 } else {
342 if (filep->f_flags & O_NONBLOCK) {
343 result = -EAGAIN;
344 break;
345 }
346 if (signal_pending(current)) {
347 result = -ERESTARTSYS;
348 break;
349 }
350 schedule();
351 set_current_state(TASK_INTERRUPTIBLE);
352 }
353 }
354 remove_wait_queue(&lirc_wait, &wait);
355 set_current_state(TASK_RUNNING);
356 return count ? count : result;
357}
358
359static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n,
360 loff_t *ppos)
361{
362 int count;
363 unsigned int i;
364 unsigned int level, newlevel;
365 unsigned long flags;
366 int counttimer;
367 int *wbuf;
368 ssize_t ret;
369
370 if (!is_claimed)
371 return -EBUSY;
372
373 count = n / sizeof(int);
374
375 if (n % sizeof(int) || count % 2 == 0)
376 return -EINVAL;
377
378 wbuf = memdup_user(buf, n);
379 if (IS_ERR(wbuf))
380 return PTR_ERR(wbuf);
381
382#ifdef LIRC_TIMER
383 if (timer == 0) {
384
385 timer = init_lirc_timer();
386 if (timer == 0) {
387 ret = -EIO;
388 goto out;
389 }
390 }
391
392
393 for (i = 0; i < count; i++) {
394 __u64 helper;
395
396 helper = ((__u64)wbuf[i]) * timer;
397 do_div(helper, 1000000);
398 wbuf[i] = (int)helper;
399 }
400
401 local_irq_save(flags);
402 i = 0;
403 while (i < count) {
404 level = lirc_get_timer();
405 counttimer = 0;
406 lirc_on();
407 do {
408 newlevel = lirc_get_timer();
409 if (level == 0 && newlevel != 0)
410 counttimer++;
411 level = newlevel;
412 if (check_pselecd && (in(1) & LP_PSELECD)) {
413 lirc_off();
414 local_irq_restore(flags);
415 ret = -EIO;
416 goto out;
417 }
418 } while (counttimer < wbuf[i]);
419 i++;
420
421 lirc_off();
422 if (i == count)
423 break;
424 counttimer = 0;
425 do {
426 newlevel = lirc_get_timer();
427 if (level == 0 && newlevel != 0)
428 counttimer++;
429 level = newlevel;
430 if (check_pselecd && (in(1) & LP_PSELECD)) {
431 local_irq_restore(flags);
432 ret = -EIO;
433 goto out;
434 }
435 } while (counttimer < wbuf[i]);
436 i++;
437 }
438 local_irq_restore(flags);
439#else
440
441#endif
442 ret = n;
443out:
444 kfree(wbuf);
445
446 return ret;
447}
448
449static unsigned int lirc_poll(struct file *file, poll_table *wait)
450{
451 poll_wait(file, &lirc_wait, wait);
452 if (rptr != wptr)
453 return POLLIN | POLLRDNORM;
454 return 0;
455}
456
457static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
458{
459 int result;
460 u32 __user *uptr = (u32 __user *)arg;
461 u32 features = LIRC_CAN_SET_TRANSMITTER_MASK |
462 LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
463 u32 mode;
464 u32 value;
465
466 switch (cmd) {
467 case LIRC_GET_FEATURES:
468 result = put_user(features, uptr);
469 if (result)
470 return result;
471 break;
472 case LIRC_GET_SEND_MODE:
473 result = put_user(LIRC_MODE_PULSE, uptr);
474 if (result)
475 return result;
476 break;
477 case LIRC_GET_REC_MODE:
478 result = put_user(LIRC_MODE_MODE2, uptr);
479 if (result)
480 return result;
481 break;
482 case LIRC_SET_SEND_MODE:
483 result = get_user(mode, uptr);
484 if (result)
485 return result;
486 if (mode != LIRC_MODE_PULSE)
487 return -EINVAL;
488 break;
489 case LIRC_SET_REC_MODE:
490 result = get_user(mode, uptr);
491 if (result)
492 return result;
493 if (mode != LIRC_MODE_MODE2)
494 return -ENOSYS;
495 break;
496 case LIRC_SET_TRANSMITTER_MASK:
497 result = get_user(value, uptr);
498 if (result)
499 return result;
500 if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value)
501 return LIRC_PARALLEL_MAX_TRANSMITTERS;
502 tx_mask = value;
503 break;
504 default:
505 return -ENOIOCTLCMD;
506 }
507 return 0;
508}
509
510static int lirc_open(struct inode *node, struct file *filep)
511{
512 if (is_open || !lirc_claim())
513 return -EBUSY;
514
515 parport_enable_irq(pport);
516
517
518 rptr = 0;
519 wptr = 0;
520 lost_irqs = 0;
521
522 is_open = 1;
523 return 0;
524}
525
526static int lirc_close(struct inode *node, struct file *filep)
527{
528 if (is_claimed) {
529 is_claimed = 0;
530 parport_release(ppdevice);
531 }
532 is_open = 0;
533 return 0;
534}
535
536static const struct file_operations lirc_fops = {
537 .owner = THIS_MODULE,
538 .llseek = lirc_lseek,
539 .read = lirc_read,
540 .write = lirc_write,
541 .poll = lirc_poll,
542 .unlocked_ioctl = lirc_ioctl,
543#ifdef CONFIG_COMPAT
544 .compat_ioctl = lirc_ioctl,
545#endif
546 .open = lirc_open,
547 .release = lirc_close
548};
549
550static int set_use_inc(void *data)
551{
552 return 0;
553}
554
555static void set_use_dec(void *data)
556{
557}
558
559static struct lirc_driver driver = {
560 .name = LIRC_DRIVER_NAME,
561 .minor = -1,
562 .code_length = 1,
563 .sample_rate = 0,
564 .data = NULL,
565 .add_to_buf = NULL,
566 .set_use_inc = set_use_inc,
567 .set_use_dec = set_use_dec,
568 .fops = &lirc_fops,
569 .dev = NULL,
570 .owner = THIS_MODULE,
571};
572
573static struct platform_device *lirc_parallel_dev;
574
575static int lirc_parallel_probe(struct platform_device *dev)
576{
577 return 0;
578}
579
580static int lirc_parallel_remove(struct platform_device *dev)
581{
582 return 0;
583}
584
585static int lirc_parallel_suspend(struct platform_device *dev,
586 pm_message_t state)
587{
588 return 0;
589}
590
591static int lirc_parallel_resume(struct platform_device *dev)
592{
593 return 0;
594}
595
596static struct platform_driver lirc_parallel_driver = {
597 .probe = lirc_parallel_probe,
598 .remove = lirc_parallel_remove,
599 .suspend = lirc_parallel_suspend,
600 .resume = lirc_parallel_resume,
601 .driver = {
602 .name = LIRC_DRIVER_NAME,
603 },
604};
605
606static int pf(void *handle)
607{
608 parport_disable_irq(pport);
609 is_claimed = 0;
610 return 0;
611}
612
613static void kf(void *handle)
614{
615 if (!is_open)
616 return;
617 if (!lirc_claim())
618 return;
619 parport_enable_irq(pport);
620 lirc_off();
621
622
623
624
625}
626
627
628
629static int __init lirc_parallel_init(void)
630{
631 int result;
632
633 result = platform_driver_register(&lirc_parallel_driver);
634 if (result) {
635 pr_notice("platform_driver_register returned %d\n", result);
636 return result;
637 }
638
639 lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
640 if (!lirc_parallel_dev) {
641 result = -ENOMEM;
642 goto exit_driver_unregister;
643 }
644
645 result = platform_device_add(lirc_parallel_dev);
646 if (result)
647 goto exit_device_put;
648
649 pport = parport_find_base(io);
650 if (!pport) {
651 pr_notice("no port at %x found\n", io);
652 result = -ENXIO;
653 goto exit_device_del;
654 }
655 ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
656 pf, kf, lirc_lirc_irq_handler, 0,
657 NULL);
658 parport_put_port(pport);
659 if (!ppdevice) {
660 pr_notice("parport_register_device() failed\n");
661 result = -ENXIO;
662 goto exit_device_del;
663 }
664 if (parport_claim(ppdevice) != 0)
665 goto skip_init;
666 is_claimed = 1;
667 out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP);
668
669#ifdef LIRC_TIMER
670 if (debug)
671 out(LIRC_PORT_DATA, tx_mask);
672
673 timer = init_lirc_timer();
674
675#if 0
676 if (timer == 0) {
677 is_claimed = 0;
678 parport_release(pport);
679 parport_unregister_device(ppdevice);
680 result = -EIO;
681 goto exit_device_del;
682 }
683
684#endif
685 if (debug)
686 out(LIRC_PORT_DATA, 0);
687#endif
688
689 is_claimed = 0;
690 parport_release(ppdevice);
691 skip_init:
692 driver.dev = &lirc_parallel_dev->dev;
693 driver.minor = lirc_register_driver(&driver);
694 if (driver.minor < 0) {
695 pr_notice("register_chrdev() failed\n");
696 parport_unregister_device(ppdevice);
697 result = -EIO;
698 goto exit_device_del;
699 }
700 pr_info("installed using port 0x%04x irq %d\n", io, irq);
701 return 0;
702
703exit_device_del:
704 platform_device_del(lirc_parallel_dev);
705exit_device_put:
706 platform_device_put(lirc_parallel_dev);
707exit_driver_unregister:
708 platform_driver_unregister(&lirc_parallel_driver);
709 return result;
710}
711
712static void __exit lirc_parallel_exit(void)
713{
714 parport_unregister_device(ppdevice);
715 lirc_unregister_driver(driver.minor);
716
717 platform_device_unregister(lirc_parallel_dev);
718 platform_driver_unregister(&lirc_parallel_driver);
719}
720
721module_init(lirc_parallel_init);
722module_exit(lirc_parallel_exit);
723
724MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
725MODULE_AUTHOR("Christoph Bartelmus");
726MODULE_LICENSE("GPL");
727
728module_param(io, int, S_IRUGO);
729MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
730
731module_param(irq, int, S_IRUGO);
732MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
733
734module_param(tx_mask, int, S_IRUGO);
735MODULE_PARM_DESC(tx_mask, "Transmitter mask (default: 0x01)");
736
737module_param(debug, bool, S_IRUGO | S_IWUSR);
738MODULE_PARM_DESC(debug, "Enable debugging messages");
739
740module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
741MODULE_PARM_DESC(check_pselecd, "Check for printer (default: 0)");
742