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