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