Version:  2.0.40 2.2.26 2.4.37 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8

Linux/drivers/staging/media/lirc/lirc_parallel.c

  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 
 25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 26 
 27 /*** Includes ***/
 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 /*** Global Variables ***/
 67 
 68 static bool debug;
 69 static bool check_pselecd;
 70 
 71 static unsigned int irq = LIRC_IRQ;
 72 static unsigned int io = LIRC_PORT;
 73 #ifdef LIRC_TIMER
 74 static unsigned int timer;
 75 static unsigned int default_timer = LIRC_TIMER;
 76 #endif
 77 
 78 #define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */
 79 
 80 static int rbuf[RBUF_SIZE];
 81 
 82 static DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
 83 
 84 static unsigned int rptr;
 85 static unsigned int wptr;
 86 static unsigned int lost_irqs;
 87 static int is_open;
 88 
 89 static struct parport *pport;
 90 static struct pardevice *ppdevice;
 91 static int is_claimed;
 92 
 93 static unsigned int tx_mask = 1;
 94 
 95 /*** Internal Functions ***/
 96 
 97 static 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 
110 static 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 
125 static unsigned int lirc_get_timer(void)
126 {
127         return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT;
128 }
129 
130 static unsigned int lirc_get_signal(void)
131 {
132         return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT;
133 }
134 
135 static void lirc_on(void)
136 {
137         out(LIRC_PORT_DATA, tx_mask);
138 }
139 
140 static void lirc_off(void)
141 {
142         out(LIRC_PORT_DATA, 0);
143 }
144 
145 static 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         /* wait max. 1 sec. */
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                         /* autodetect timer */
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                         /* bad timer */
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; /* use detected value */
180         }
181 
182         pr_notice("no timer detected\n");
183         return 0;
184 }
185 
186 static 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 /*** interrupt handler ***/
202 
203 static void rbuf_write(int signal)
204 {
205         unsigned int nwptr;
206 
207         nwptr = (wptr + 1) & (RBUF_SIZE - 1);
208         if (nwptr == rptr) {
209                 /* no new signals will be accepted */
210                 lost_irqs++;
211                 pr_notice("buffer overrun\n");
212                 return;
213         }
214         rbuf[wptr] = signal;
215         wptr = nwptr;
216 }
217 
218 static 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         /* disable interrupt */
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                         /* really long time */
249                         data = PULSE_MASK;
250                 else
251                         data = (int)(ktime_to_us(delkt) + LIRC_SFH506_DELAY);
252 
253                 rbuf_write(data); /* space */
254         } else {
255                 if (timer == 0) {
256                         /*
257                          * wake up; we'll lose this signal, but it will be
258                          * garbage if the device is turned on anyway
259                          */
260                         timer = init_lirc_timer();
261                         /* enable_irq(irq); */
262                         return;
263                 }
264                 init = 1;
265         }
266 
267         timeout = timer / 10;   /* timeout after 1/10 sec. */
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                 /* giving up */
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                 /* adjust value to usecs */
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); /* pulse */
298         }
299         lastkt = ktime_get();
300 #else
301         /* add your code here */
302 #endif
303 
304         wake_up_interruptible(&lirc_wait);
305 
306         /* enable interrupt */
307         /*
308          * enable_irq(irq);
309          * out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN);
310          */
311 }
312 
313 /*** file operations ***/
314 
315 static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
316 {
317         return -ESPIPE;
318 }
319 
320 static 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 
359 static 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                 /* try again if device is ready */
385                 timer = init_lirc_timer();
386                 if (timer == 0) {
387                         ret = -EIO;
388                         goto out;
389                 }
390         }
391 
392         /* adjust values from usecs */
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         /* place code that handles write without external timer here */
441 #endif
442         ret = n;
443 out:
444         kfree(wbuf);
445 
446         return ret;
447 }
448 
449 static 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 
457 static 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 
510 static 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         /* init read ptr */
518         rptr = 0;
519         wptr = 0;
520         lost_irqs = 0;
521 
522         is_open = 1;
523         return 0;
524 }
525 
526 static 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 
536 static 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 
550 static int set_use_inc(void *data)
551 {
552         return 0;
553 }
554 
555 static void set_use_dec(void *data)
556 {
557 }
558 
559 static 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 
573 static struct platform_device *lirc_parallel_dev;
574 
575 static int lirc_parallel_probe(struct platform_device *dev)
576 {
577         return 0;
578 }
579 
580 static int lirc_parallel_remove(struct platform_device *dev)
581 {
582         return 0;
583 }
584 
585 static int lirc_parallel_suspend(struct platform_device *dev,
586                                         pm_message_t state)
587 {
588         return 0;
589 }
590 
591 static int lirc_parallel_resume(struct platform_device *dev)
592 {
593         return 0;
594 }
595 
596 static 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 
606 static int pf(void *handle)
607 {
608         parport_disable_irq(pport);
609         is_claimed = 0;
610         return 0;
611 }
612 
613 static 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         /* this is a bit annoying when you actually print...*/
622         /*
623          * printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
624         */
625 }
626 
627 /*** module initialization and cleanup ***/
628 
629 static 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_put;
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_put;
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   /* continue even if device is offline */
676         if (timer == 0) {
677                 is_claimed = 0;
678                 parport_release(pport);
679                 parport_unregister_device(ppdevice);
680                 result = -EIO;
681                 goto exit_device_put;
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_put;
699         }
700         pr_info("installed using port 0x%04x irq %d\n", io, irq);
701         return 0;
702 
703 exit_device_put:
704         platform_device_put(lirc_parallel_dev);
705 exit_driver_unregister:
706         platform_driver_unregister(&lirc_parallel_driver);
707         return result;
708 }
709 
710 static void __exit lirc_parallel_exit(void)
711 {
712         parport_unregister_device(ppdevice);
713         lirc_unregister_driver(driver.minor);
714 
715         platform_device_unregister(lirc_parallel_dev);
716         platform_driver_unregister(&lirc_parallel_driver);
717 }
718 
719 module_init(lirc_parallel_init);
720 module_exit(lirc_parallel_exit);
721 
722 MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
723 MODULE_AUTHOR("Christoph Bartelmus");
724 MODULE_LICENSE("GPL");
725 
726 module_param(io, int, S_IRUGO);
727 MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
728 
729 module_param(irq, int, S_IRUGO);
730 MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
731 
732 module_param(tx_mask, int, S_IRUGO);
733 MODULE_PARM_DESC(tx_mask, "Transmitter mask (default: 0x01)");
734 
735 module_param(debug, bool, S_IRUGO | S_IWUSR);
736 MODULE_PARM_DESC(debug, "Enable debugging messages");
737 
738 module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
739 MODULE_PARM_DESC(check_pselecd, "Check for printer (default: 0)");
740 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us