Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

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/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 /*** 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         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;
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                                 /* 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;
180                         } else {
181                                 pr_info("%u Hz timer detected\n", newtimer);
182                                 return newtimer; /* use detected value */
183                         }
184                 }
185         } else {
186                 pr_notice("no timer detected\n");
187                 return 0;
188         }
189 }
190 
191 static 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 /*** interrupt handler ***/
207 
208 static void rbuf_write(int signal)
209 {
210         unsigned int nwptr;
211 
212         nwptr = (wptr + 1) & (RBUF_SIZE - 1);
213         if (nwptr == rptr) {
214                 /* no new signals will be accepted */
215                 lost_irqs++;
216                 pr_notice("buffer overrun\n");
217                 return;
218         }
219         rbuf[wptr] = signal;
220         wptr = nwptr;
221 }
222 
223 static void lirc_lirc_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         /* disable interrupt */
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                         /* really long time */
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); /* space */
261         } else {
262                 if (timer == 0) {
263                         /*
264                          * wake up; we'll lose this signal, but it will be
265                          * garbage if the device is turned on anyway
266                          */
267                         timer = init_lirc_timer();
268                         /* enable_irq(irq); */
269                         return;
270                 }
271                 init = 1;
272         }
273 
274         timeout = timer/10;     /* timeout after 1/10 sec. */
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                 /* giving up */
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                 /* adjust value to usecs */
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); /* pulse */
305         }
306         do_gettimeofday(&lasttv);
307 #else
308         /* add your code here */
309 #endif
310 
311         wake_up_interruptible(&lirc_wait);
312 
313         /* enable interrupt */
314         /*
315           enable_irq(irq);
316           out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN);
317         */
318 }
319 
320 /*** file operations ***/
321 
322 static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
323 {
324         return -ESPIPE;
325 }
326 
327 static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n,
328                          loff_t *ppos)
329 {
330         int result = 0;
331         int count = 0;
332         DECLARE_WAITQUEUE(wait, current);
333 
334         if (n % sizeof(int))
335                 return -EINVAL;
336 
337         add_wait_queue(&lirc_wait, &wait);
338         set_current_state(TASK_INTERRUPTIBLE);
339         while (count < n) {
340                 if (rptr != wptr) {
341                         if (copy_to_user(buf+count, (char *) &rbuf[rptr],
342                                          sizeof(int))) {
343                                 result = -EFAULT;
344                                 break;
345                         }
346                         rptr = (rptr + 1) & (RBUF_SIZE - 1);
347                         count += sizeof(int);
348                 } else {
349                         if (filep->f_flags & O_NONBLOCK) {
350                                 result = -EAGAIN;
351                                 break;
352                         }
353                         if (signal_pending(current)) {
354                                 result = -ERESTARTSYS;
355                                 break;
356                         }
357                         schedule();
358                         set_current_state(TASK_INTERRUPTIBLE);
359                 }
360         }
361         remove_wait_queue(&lirc_wait, &wait);
362         set_current_state(TASK_RUNNING);
363         return count ? count : result;
364 }
365 
366 static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n,
367                           loff_t *ppos)
368 {
369         int count;
370         unsigned int i;
371         unsigned int level, newlevel;
372         unsigned long flags;
373         int counttimer;
374         int *wbuf;
375         ssize_t ret;
376 
377         if (!is_claimed)
378                 return -EBUSY;
379 
380         count = n / sizeof(int);
381 
382         if (n % sizeof(int) || count % 2 == 0)
383                 return -EINVAL;
384 
385         wbuf = memdup_user(buf, n);
386         if (IS_ERR(wbuf))
387                 return PTR_ERR(wbuf);
388 
389 #ifdef LIRC_TIMER
390         if (timer == 0) {
391                 /* try again if device is ready */
392                 timer = init_lirc_timer();
393                 if (timer == 0) {
394                         ret = -EIO;
395                         goto out;
396                 }
397         }
398 
399         /* adjust values from usecs */
400         for (i = 0; i < count; i++) {
401                 __u64 helper;
402 
403                 helper = ((__u64) wbuf[i])*timer;
404                 do_div(helper, 1000000);
405                 wbuf[i] = (int) helper;
406         }
407 
408         local_irq_save(flags);
409         i = 0;
410         while (i < count) {
411                 level = lirc_get_timer();
412                 counttimer = 0;
413                 lirc_on();
414                 do {
415                         newlevel = lirc_get_timer();
416                         if (level == 0 && newlevel != 0)
417                                 counttimer++;
418                         level = newlevel;
419                         if (check_pselecd && (in(1) & LP_PSELECD)) {
420                                 lirc_off();
421                                 local_irq_restore(flags);
422                                 ret = -EIO;
423                                 goto out;
424                         }
425                 } while (counttimer < wbuf[i]);
426                 i++;
427 
428                 lirc_off();
429                 if (i == count)
430                         break;
431                 counttimer = 0;
432                 do {
433                         newlevel = lirc_get_timer();
434                         if (level == 0 && newlevel != 0)
435                                 counttimer++;
436                         level = newlevel;
437                         if (check_pselecd && (in(1) & LP_PSELECD)) {
438                                 local_irq_restore(flags);
439                                 ret = -EIO;
440                                 goto out;
441                         }
442                 } while (counttimer < wbuf[i]);
443                 i++;
444         }
445         local_irq_restore(flags);
446 #else
447         /* place code that handles write without external timer here */
448 #endif
449         ret = n;
450 out:
451         kfree(wbuf);
452 
453         return ret;
454 }
455 
456 static unsigned int lirc_poll(struct file *file, poll_table *wait)
457 {
458         poll_wait(file, &lirc_wait, wait);
459         if (rptr != wptr)
460                 return POLLIN | POLLRDNORM;
461         return 0;
462 }
463 
464 static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
465 {
466         int result;
467         u32 __user *uptr = (u32 __user *)arg;
468         u32 features = LIRC_CAN_SET_TRANSMITTER_MASK |
469                        LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
470         u32 mode;
471         u32 value;
472 
473         switch (cmd) {
474         case LIRC_GET_FEATURES:
475                 result = put_user(features, uptr);
476                 if (result)
477                         return result;
478                 break;
479         case LIRC_GET_SEND_MODE:
480                 result = put_user(LIRC_MODE_PULSE, uptr);
481                 if (result)
482                         return result;
483                 break;
484         case LIRC_GET_REC_MODE:
485                 result = put_user(LIRC_MODE_MODE2, uptr);
486                 if (result)
487                         return result;
488                 break;
489         case LIRC_SET_SEND_MODE:
490                 result = get_user(mode, uptr);
491                 if (result)
492                         return result;
493                 if (mode != LIRC_MODE_PULSE)
494                         return -EINVAL;
495                 break;
496         case LIRC_SET_REC_MODE:
497                 result = get_user(mode, uptr);
498                 if (result)
499                         return result;
500                 if (mode != LIRC_MODE_MODE2)
501                         return -ENOSYS;
502                 break;
503         case LIRC_SET_TRANSMITTER_MASK:
504                 result = get_user(value, uptr);
505                 if (result)
506                         return result;
507                 if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value)
508                         return LIRC_PARALLEL_MAX_TRANSMITTERS;
509                 tx_mask = value;
510                 break;
511         default:
512                 return -ENOIOCTLCMD;
513         }
514         return 0;
515 }
516 
517 static int lirc_open(struct inode *node, struct file *filep)
518 {
519         if (is_open || !lirc_claim())
520                 return -EBUSY;
521 
522         parport_enable_irq(pport);
523 
524         /* init read ptr */
525         rptr = 0;
526         wptr = 0;
527         lost_irqs = 0;
528 
529         is_open = 1;
530         return 0;
531 }
532 
533 static int lirc_close(struct inode *node, struct file *filep)
534 {
535         if (is_claimed) {
536                 is_claimed = 0;
537                 parport_release(ppdevice);
538         }
539         is_open = 0;
540         return 0;
541 }
542 
543 static const struct file_operations lirc_fops = {
544         .owner          = THIS_MODULE,
545         .llseek         = lirc_lseek,
546         .read           = lirc_read,
547         .write          = lirc_write,
548         .poll           = lirc_poll,
549         .unlocked_ioctl = lirc_ioctl,
550 #ifdef CONFIG_COMPAT
551         .compat_ioctl   = lirc_ioctl,
552 #endif
553         .open           = lirc_open,
554         .release        = lirc_close
555 };
556 
557 static int set_use_inc(void *data)
558 {
559         return 0;
560 }
561 
562 static void set_use_dec(void *data)
563 {
564 }
565 
566 static struct lirc_driver driver = {
567         .name           = LIRC_DRIVER_NAME,
568         .minor          = -1,
569         .code_length    = 1,
570         .sample_rate    = 0,
571         .data           = NULL,
572         .add_to_buf     = NULL,
573         .set_use_inc    = set_use_inc,
574         .set_use_dec    = set_use_dec,
575         .fops           = &lirc_fops,
576         .dev            = NULL,
577         .owner          = THIS_MODULE,
578 };
579 
580 static struct platform_device *lirc_parallel_dev;
581 
582 static int lirc_parallel_probe(struct platform_device *dev)
583 {
584         return 0;
585 }
586 
587 static int lirc_parallel_remove(struct platform_device *dev)
588 {
589         return 0;
590 }
591 
592 static int lirc_parallel_suspend(struct platform_device *dev,
593                                         pm_message_t state)
594 {
595         return 0;
596 }
597 
598 static int lirc_parallel_resume(struct platform_device *dev)
599 {
600         return 0;
601 }
602 
603 static struct platform_driver lirc_parallel_driver = {
604         .probe  = lirc_parallel_probe,
605         .remove = lirc_parallel_remove,
606         .suspend        = lirc_parallel_suspend,
607         .resume = lirc_parallel_resume,
608         .driver = {
609                 .name   = LIRC_DRIVER_NAME,
610                 .owner  = THIS_MODULE,
611         },
612 };
613 
614 static int pf(void *handle)
615 {
616         parport_disable_irq(pport);
617         is_claimed = 0;
618         return 0;
619 }
620 
621 static void kf(void *handle)
622 {
623         if (!is_open)
624                 return;
625         if (!lirc_claim())
626                 return;
627         parport_enable_irq(pport);
628         lirc_off();
629         /* this is a bit annoying when you actually print...*/
630         /*
631         printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
632         */
633 }
634 
635 /*** module initialization and cleanup ***/
636 
637 static int __init lirc_parallel_init(void)
638 {
639         int result;
640 
641         result = platform_driver_register(&lirc_parallel_driver);
642         if (result) {
643                 pr_notice("platform_driver_register returned %d\n", result);
644                 return result;
645         }
646 
647         lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
648         if (!lirc_parallel_dev) {
649                 result = -ENOMEM;
650                 goto exit_driver_unregister;
651         }
652 
653         result = platform_device_add(lirc_parallel_dev);
654         if (result)
655                 goto exit_device_put;
656 
657         pport = parport_find_base(io);
658         if (pport == NULL) {
659                 pr_notice("no port at %x found\n", io);
660                 result = -ENXIO;
661                 goto exit_device_put;
662         }
663         ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
664                                            pf, kf, lirc_lirc_irq_handler, 0, NULL);
665         parport_put_port(pport);
666         if (ppdevice == NULL) {
667                 pr_notice("parport_register_device() failed\n");
668                 result = -ENXIO;
669                 goto exit_device_put;
670         }
671         if (parport_claim(ppdevice) != 0)
672                 goto skip_init;
673         is_claimed = 1;
674         out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
675 
676 #ifdef LIRC_TIMER
677         if (debug)
678                 out(LIRC_PORT_DATA, tx_mask);
679 
680         timer = init_lirc_timer();
681 
682 #if 0   /* continue even if device is offline */
683         if (timer == 0) {
684                 is_claimed = 0;
685                 parport_release(pport);
686                 parport_unregister_device(ppdevice);
687                 result = -EIO;
688                 goto exit_device_put;
689         }
690 
691 #endif
692         if (debug)
693                 out(LIRC_PORT_DATA, 0);
694 #endif
695 
696         is_claimed = 0;
697         parport_release(ppdevice);
698  skip_init:
699         driver.dev = &lirc_parallel_dev->dev;
700         driver.minor = lirc_register_driver(&driver);
701         if (driver.minor < 0) {
702                 pr_notice("register_chrdev() failed\n");
703                 parport_unregister_device(ppdevice);
704                 result = -EIO;
705                 goto exit_device_put;
706         }
707         pr_info("installed using port 0x%04x irq %d\n", io, irq);
708         return 0;
709 
710 exit_device_put:
711         platform_device_put(lirc_parallel_dev);
712 exit_driver_unregister:
713         platform_driver_unregister(&lirc_parallel_driver);
714         return result;
715 }
716 
717 static void __exit lirc_parallel_exit(void)
718 {
719         parport_unregister_device(ppdevice);
720         lirc_unregister_driver(driver.minor);
721 
722         platform_device_unregister(lirc_parallel_dev);
723         platform_driver_unregister(&lirc_parallel_driver);
724 }
725 
726 module_init(lirc_parallel_init);
727 module_exit(lirc_parallel_exit);
728 
729 MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
730 MODULE_AUTHOR("Christoph Bartelmus");
731 MODULE_LICENSE("GPL");
732 
733 module_param(io, int, S_IRUGO);
734 MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
735 
736 module_param(irq, int, S_IRUGO);
737 MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
738 
739 module_param(tx_mask, int, S_IRUGO);
740 MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)");
741 
742 module_param(debug, bool, S_IRUGO | S_IWUSR);
743 MODULE_PARM_DESC(debug, "Enable debugging messages");
744 
745 module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
746 MODULE_PARM_DESC(check_pselecd, "Check for printer (default: 0)");
747 

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