staging: media: lirc: Removed unnecessary else expression.
[deliverable/linux.git] / drivers / staging / media / lirc / lirc_parallel.c
CommitLineData
805a8966
JW
1/*
2 * lirc_parallel.c
3 *
4 * lirc_parallel - device driver for infra-red signal receiving and
5 * transmitting unit built by the author
6 *
7 * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
cc38b8e9
YT
25#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
805a8966
JW
27/*** Includes ***/
28
805a8966
JW
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>
805a8966
JW
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>
5d884b97 47#include <linux/platform_device.h>
805a8966
JW
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/*** Global Variables ***/
67
90ab5ee9
RR
68static bool debug;
69static bool check_pselecd;
805a8966 70
04ad3a64
EA
71static unsigned int irq = LIRC_IRQ;
72static unsigned int io = LIRC_PORT;
805a8966 73#ifdef LIRC_TIMER
04ad3a64
EA
74static unsigned int timer;
75static unsigned int default_timer = LIRC_TIMER;
805a8966
JW
76#endif
77
78#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */
79
80static int rbuf[RBUF_SIZE];
81
04ad3a64 82static DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
805a8966 83
04ad3a64
EA
84static unsigned int rptr;
85static unsigned int wptr;
86static unsigned int lost_irqs;
87static int is_open;
805a8966 88
04ad3a64
EA
89static struct parport *pport;
90static struct pardevice *ppdevice;
91static int is_claimed;
805a8966 92
04ad3a64 93static unsigned int tx_mask = 1;
805a8966
JW
94
95/*** Internal Functions ***/
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; /* make compiler happy */
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:
cc38b8e9 120 pr_info("attempt to write to status register\n");
805a8966
JW
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++; /* wait max. 1 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 /* autodetect timer */
169 newtimer = (1000000*count)/timeelapsed;
cc38b8e9 170 pr_info("%u Hz timer detected\n", newtimer);
805a8966 171 return newtimer;
805a8966 172 }
381d7f79
ZD
173 newtimer = (1000000*count)/timeelapsed;
174 if (abs(newtimer - default_timer) > default_timer/10) {
175 /* bad timer */
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;
381d7f79 180 }
fb67f445
GK
181 pr_info("%u Hz timer detected\n", newtimer);
182 return newtimer; /* use detected value */
805a8966 183 }
381d7f79
ZD
184
185 pr_notice("no timer detected\n");
186 return 0;
805a8966
JW
187}
188
189static int lirc_claim(void)
190{
191 if (parport_claim(ppdevice) != 0) {
cc38b8e9
YT
192 pr_warn("could not claim port\n");
193 pr_warn("waiting for port becoming available\n");
805a8966 194 if (parport_claim_or_block(ppdevice) < 0) {
cc38b8e9 195 pr_notice("could not claim port, giving up\n");
805a8966
JW
196 return 0;
197 }
198 }
199 out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
200 is_claimed = 1;
201 return 1;
202}
203
204/*** interrupt handler ***/
205
206static void rbuf_write(int signal)
207{
208 unsigned int nwptr;
209
210 nwptr = (wptr + 1) & (RBUF_SIZE - 1);
211 if (nwptr == rptr) {
212 /* no new signals will be accepted */
213 lost_irqs++;
cc38b8e9 214 pr_notice("buffer overrun\n");
805a8966
JW
215 return;
216 }
217 rbuf[wptr] = signal;
218 wptr = nwptr;
219}
220
986058e1 221static void lirc_lirc_irq_handler(void *blah)
805a8966
JW
222{
223 struct timeval tv;
224 static struct timeval lasttv;
225 static int init;
226 long signal;
227 int data;
228 unsigned int level, newlevel;
229 unsigned int timeout;
230
82ce67bf 231 if (!is_open)
805a8966
JW
232 return;
233
234 if (!is_claimed)
235 return;
236
237#if 0
238 /* disable interrupt */
239 disable_irq(irq);
240 out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN));
241#endif
242 if (check_pselecd && (in(1) & LP_PSELECD))
243 return;
244
245#ifdef LIRC_TIMER
246 if (init) {
247 do_gettimeofday(&tv);
248
249 signal = tv.tv_sec - lasttv.tv_sec;
250 if (signal > 15)
251 /* really long time */
252 data = PULSE_MASK;
253 else
254 data = (int) (signal*1000000 +
255 tv.tv_usec - lasttv.tv_usec +
256 LIRC_SFH506_DELAY);
257
258 rbuf_write(data); /* space */
259 } else {
260 if (timer == 0) {
261 /*
262 * wake up; we'll lose this signal, but it will be
263 * garbage if the device is turned on anyway
264 */
265 timer = init_lirc_timer();
266 /* enable_irq(irq); */
267 return;
268 }
269 init = 1;
270 }
271
272 timeout = timer/10; /* timeout after 1/10 sec. */
273 signal = 1;
274 level = lirc_get_timer();
275 do {
276 newlevel = lirc_get_timer();
277 if (level == 0 && newlevel != 0)
278 signal++;
279 level = newlevel;
280
281 /* giving up */
282 if (signal > timeout
283 || (check_pselecd && (in(1) & LP_PSELECD))) {
284 signal = 0;
cc38b8e9 285 pr_notice("timeout\n");
805a8966
JW
286 break;
287 }
288 } while (lirc_get_signal());
289
290 if (signal != 0) {
dca488b8 291 /* adjust value to usecs */
a1266818 292 __u64 helper;
805a8966 293
a1266818 294 helper = ((__u64) signal)*1000000;
805a8966
JW
295 do_div(helper, timer);
296 signal = (long) helper;
297
298 if (signal > LIRC_SFH506_DELAY)
299 data = signal - LIRC_SFH506_DELAY;
300 else
301 data = 1;
302 rbuf_write(PULSE_BIT|data); /* pulse */
303 }
304 do_gettimeofday(&lasttv);
305#else
306 /* add your code here */
307#endif
308
309 wake_up_interruptible(&lirc_wait);
310
311 /* enable interrupt */
312 /*
313 enable_irq(irq);
314 out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN);
315 */
316}
317
318/*** file operations ***/
319
320static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
321{
322 return -ESPIPE;
323}
324
465b8229
TT
325static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n,
326 loff_t *ppos)
805a8966
JW
327{
328 int result = 0;
329 int count = 0;
330 DECLARE_WAITQUEUE(wait, current);
331
332 if (n % sizeof(int))
333 return -EINVAL;
334
335 add_wait_queue(&lirc_wait, &wait);
336 set_current_state(TASK_INTERRUPTIBLE);
337 while (count < n) {
338 if (rptr != wptr) {
339 if (copy_to_user(buf+count, (char *) &rbuf[rptr],
340 sizeof(int))) {
341 result = -EFAULT;
342 break;
343 }
344 rptr = (rptr + 1) & (RBUF_SIZE - 1);
345 count += sizeof(int);
346 } else {
347 if (filep->f_flags & O_NONBLOCK) {
348 result = -EAGAIN;
349 break;
350 }
351 if (signal_pending(current)) {
352 result = -ERESTARTSYS;
353 break;
354 }
355 schedule();
356 set_current_state(TASK_INTERRUPTIBLE);
357 }
358 }
359 remove_wait_queue(&lirc_wait, &wait);
360 set_current_state(TASK_RUNNING);
361 return count ? count : result;
362}
363
465b8229 364static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n,
805a8966
JW
365 loff_t *ppos)
366{
367 int count;
368 unsigned int i;
369 unsigned int level, newlevel;
370 unsigned long flags;
371 int counttimer;
372 int *wbuf;
88914bdf 373 ssize_t ret;
805a8966
JW
374
375 if (!is_claimed)
376 return -EBUSY;
377
378 count = n / sizeof(int);
379
380 if (n % sizeof(int) || count % 2 == 0)
381 return -EINVAL;
382
383 wbuf = memdup_user(buf, n);
384 if (IS_ERR(wbuf))
385 return PTR_ERR(wbuf);
386
387#ifdef LIRC_TIMER
388 if (timer == 0) {
389 /* try again if device is ready */
390 timer = init_lirc_timer();
88914bdf
JW
391 if (timer == 0) {
392 ret = -EIO;
393 goto out;
394 }
805a8966
JW
395 }
396
397 /* adjust values from usecs */
398 for (i = 0; i < count; i++) {
a1266818 399 __u64 helper;
805a8966 400
a1266818 401 helper = ((__u64) wbuf[i])*timer;
805a8966
JW
402 do_div(helper, 1000000);
403 wbuf[i] = (int) helper;
404 }
405
406 local_irq_save(flags);
407 i = 0;
408 while (i < count) {
409 level = lirc_get_timer();
410 counttimer = 0;
411 lirc_on();
412 do {
413 newlevel = lirc_get_timer();
414 if (level == 0 && newlevel != 0)
415 counttimer++;
416 level = newlevel;
417 if (check_pselecd && (in(1) & LP_PSELECD)) {
418 lirc_off();
419 local_irq_restore(flags);
88914bdf
JW
420 ret = -EIO;
421 goto out;
805a8966
JW
422 }
423 } while (counttimer < wbuf[i]);
424 i++;
425
426 lirc_off();
427 if (i == count)
428 break;
429 counttimer = 0;
430 do {
431 newlevel = lirc_get_timer();
432 if (level == 0 && newlevel != 0)
433 counttimer++;
434 level = newlevel;
435 if (check_pselecd && (in(1) & LP_PSELECD)) {
436 local_irq_restore(flags);
88914bdf
JW
437 ret = -EIO;
438 goto out;
805a8966
JW
439 }
440 } while (counttimer < wbuf[i]);
441 i++;
442 }
443 local_irq_restore(flags);
444#else
445 /* place code that handles write without external timer here */
446#endif
88914bdf
JW
447 ret = n;
448out:
449 kfree(wbuf);
450
451 return ret;
805a8966
JW
452}
453
454static unsigned int lirc_poll(struct file *file, poll_table *wait)
455{
456 poll_wait(file, &lirc_wait, wait);
457 if (rptr != wptr)
458 return POLLIN | POLLRDNORM;
459 return 0;
460}
461
462static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
463{
464 int result;
465b8229
TT
465 u32 __user *uptr = (u32 __user *)arg;
466 u32 features = LIRC_CAN_SET_TRANSMITTER_MASK |
467 LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
468 u32 mode;
469 u32 value;
805a8966
JW
470
471 switch (cmd) {
472 case LIRC_GET_FEATURES:
465b8229 473 result = put_user(features, uptr);
805a8966
JW
474 if (result)
475 return result;
476 break;
477 case LIRC_GET_SEND_MODE:
465b8229 478 result = put_user(LIRC_MODE_PULSE, uptr);
805a8966
JW
479 if (result)
480 return result;
481 break;
482 case LIRC_GET_REC_MODE:
465b8229 483 result = put_user(LIRC_MODE_MODE2, uptr);
805a8966
JW
484 if (result)
485 return result;
486 break;
487 case LIRC_SET_SEND_MODE:
465b8229 488 result = get_user(mode, uptr);
805a8966
JW
489 if (result)
490 return result;
491 if (mode != LIRC_MODE_PULSE)
492 return -EINVAL;
493 break;
494 case LIRC_SET_REC_MODE:
465b8229 495 result = get_user(mode, uptr);
805a8966
JW
496 if (result)
497 return result;
498 if (mode != LIRC_MODE_MODE2)
499 return -ENOSYS;
500 break;
501 case LIRC_SET_TRANSMITTER_MASK:
465b8229 502 result = get_user(value, uptr);
805a8966
JW
503 if (result)
504 return result;
a1266818 505 if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value)
805a8966 506 return LIRC_PARALLEL_MAX_TRANSMITTERS;
a1266818 507 tx_mask = value;
805a8966
JW
508 break;
509 default:
510 return -ENOIOCTLCMD;
511 }
512 return 0;
513}
514
515static int lirc_open(struct inode *node, struct file *filep)
516{
82ce67bf 517 if (is_open || !lirc_claim())
805a8966
JW
518 return -EBUSY;
519
520 parport_enable_irq(pport);
521
522 /* init read ptr */
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
0f9313ad 541static const struct file_operations lirc_fops = {
805a8966
JW
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,
8be292cc
JW
548#ifdef CONFIG_COMPAT
549 .compat_ioctl = lirc_ioctl,
550#endif
805a8966
JW
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 = {
d713680f
GD
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,
805a8966
JW
576};
577
5d884b97
TV
578static struct platform_device *lirc_parallel_dev;
579
fd8413a2 580static int lirc_parallel_probe(struct platform_device *dev)
5d884b97
TV
581{
582 return 0;
583}
584
6dd11195 585static int lirc_parallel_remove(struct platform_device *dev)
5d884b97
TV
586{
587 return 0;
588}
589
590static int lirc_parallel_suspend(struct platform_device *dev,
d713680f 591 pm_message_t state)
5d884b97
TV
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,
01f6f49b 603 .remove = lirc_parallel_remove,
5d884b97
TV
604 .suspend = lirc_parallel_suspend,
605 .resume = lirc_parallel_resume,
606 .driver = {
607 .name = LIRC_DRIVER_NAME,
608 .owner = THIS_MODULE,
609 },
610};
611
805a8966
JW
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 /* this is a bit annoying when you actually print...*/
628 /*
629 printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
630 */
631}
632
633/*** module initialization and cleanup ***/
634
635static int __init lirc_parallel_init(void)
636{
5d884b97
TV
637 int result;
638
639 result = platform_driver_register(&lirc_parallel_driver);
640 if (result) {
cc38b8e9 641 pr_notice("platform_driver_register returned %d\n", result);
5d884b97
TV
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
805a8966
JW
655 pport = parport_find_base(io);
656 if (pport == NULL) {
cc38b8e9 657 pr_notice("no port at %x found\n", io);
5d884b97
TV
658 result = -ENXIO;
659 goto exit_device_put;
805a8966
JW
660 }
661 ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
381d7f79
ZD
662 pf, kf, lirc_lirc_irq_handler, 0,
663 NULL);
805a8966
JW
664 parport_put_port(pport);
665 if (ppdevice == NULL) {
cc38b8e9 666 pr_notice("parport_register_device() failed\n");
5d884b97
TV
667 result = -ENXIO;
668 goto exit_device_put;
805a8966
JW
669 }
670 if (parport_claim(ppdevice) != 0)
671 goto skip_init;
672 is_claimed = 1;
673 out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
674
675#ifdef LIRC_TIMER
676 if (debug)
677 out(LIRC_PORT_DATA, tx_mask);
678
679 timer = init_lirc_timer();
680
681#if 0 /* continue even if device is offline */
682 if (timer == 0) {
683 is_claimed = 0;
684 parport_release(pport);
685 parport_unregister_device(ppdevice);
5d884b97
TV
686 result = -EIO;
687 goto exit_device_put;
805a8966
JW
688 }
689
690#endif
691 if (debug)
692 out(LIRC_PORT_DATA, 0);
693#endif
694
695 is_claimed = 0;
696 parport_release(ppdevice);
697 skip_init:
5d884b97 698 driver.dev = &lirc_parallel_dev->dev;
805a8966
JW
699 driver.minor = lirc_register_driver(&driver);
700 if (driver.minor < 0) {
cc38b8e9 701 pr_notice("register_chrdev() failed\n");
805a8966 702 parport_unregister_device(ppdevice);
5d884b97
TV
703 result = -EIO;
704 goto exit_device_put;
805a8966 705 }
cc38b8e9 706 pr_info("installed using port 0x%04x irq %d\n", io, irq);
805a8966 707 return 0;
5d884b97
TV
708
709exit_device_put:
710 platform_device_put(lirc_parallel_dev);
711exit_driver_unregister:
712 platform_driver_unregister(&lirc_parallel_driver);
713 return result;
805a8966
JW
714}
715
716static void __exit lirc_parallel_exit(void)
717{
718 parport_unregister_device(ppdevice);
719 lirc_unregister_driver(driver.minor);
7cf131cb
DJ
720
721 platform_device_unregister(lirc_parallel_dev);
722 platform_driver_unregister(&lirc_parallel_driver);
805a8966
JW
723}
724
725module_init(lirc_parallel_init);
726module_exit(lirc_parallel_exit);
727
728MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
729MODULE_AUTHOR("Christoph Bartelmus");
730MODULE_LICENSE("GPL");
731
732module_param(io, int, S_IRUGO);
733MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
734
735module_param(irq, int, S_IRUGO);
736MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
737
738module_param(tx_mask, int, S_IRUGO);
739MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)");
740
741module_param(debug, bool, S_IRUGO | S_IWUSR);
742MODULE_PARM_DESC(debug, "Enable debugging messages");
743
744module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
f17dda94 745MODULE_PARM_DESC(check_pselecd, "Check for printer (default: 0)");
This page took 0.339914 seconds and 5 git commands to generate.