linux/drivers/staging/media/lirc/lirc_parallel.c
<<
>>
Prefs
   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
  68static bool debug;
  69static bool check_pselecd;
  70
  71static unsigned int irq = LIRC_IRQ;
  72static unsigned int io = LIRC_PORT;
  73#ifdef LIRC_TIMER
  74static unsigned int timer;
  75static 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
  80static int rbuf[RBUF_SIZE];
  81
  82static DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
  83
  84static unsigned int rptr;
  85static unsigned int wptr;
  86static unsigned int lost_irqs;
  87static int is_open;
  88
  89static struct parport *pport;
  90static struct pardevice *ppdevice;
  91static int is_claimed;
  92
  93static unsigned int tx_mask = 1;
  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:
 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++;                     /* 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                }
 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                }
 181                pr_info("%u Hz timer detected\n", newtimer);
 182                return newtimer; /* use detected value */
 183        }
 184
 185        pr_notice("no timer detected\n");
 186        return 0;
 187}
 188
 189static int lirc_claim(void)
 190{
 191        if (parport_claim(ppdevice) != 0) {
 192                pr_warn("could not claim port\n");
 193                pr_warn("waiting for port becoming available\n");
 194                if (parport_claim_or_block(ppdevice) < 0) {
 195                        pr_notice("could not claim port, giving up\n");
 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++;
 214                pr_notice("buffer overrun\n");
 215                return;
 216        }
 217        rbuf[wptr] = signal;
 218        wptr = nwptr;
 219}
 220
 221static void lirc_lirc_irq_handler(void *blah)
 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
 231        if (!is_open)
 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;
 285                        pr_notice("timeout\n");
 286                        break;
 287                }
 288        } while (lirc_get_signal());
 289
 290        if (signal != 0) {
 291                /* adjust value to usecs */
 292                __u64 helper;
 293
 294                helper = ((__u64) signal)*1000000;
 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
 325static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n,
 326                         loff_t *ppos)
 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, &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
 364static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n,
 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;
 373        ssize_t ret;
 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();
 391                if (timer == 0) {
 392                        ret = -EIO;
 393                        goto out;
 394                }
 395        }
 396
 397        /* adjust values from usecs */
 398        for (i = 0; i < count; i++) {
 399                __u64 helper;
 400
 401                helper = ((__u64) wbuf[i])*timer;
 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);
 420                                ret = -EIO;
 421                                goto out;
 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);
 437                                ret = -EIO;
 438                                goto out;
 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
 447        ret = n;
 448out:
 449        kfree(wbuf);
 450
 451        return ret;
 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;
 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;
 470
 471        switch (cmd) {
 472        case LIRC_GET_FEATURES:
 473                result = put_user(features, uptr);
 474                if (result)
 475                        return result;
 476                break;
 477        case LIRC_GET_SEND_MODE:
 478                result = put_user(LIRC_MODE_PULSE, uptr);
 479                if (result)
 480                        return result;
 481                break;
 482        case LIRC_GET_REC_MODE:
 483                result = put_user(LIRC_MODE_MODE2, uptr);
 484                if (result)
 485                        return result;
 486                break;
 487        case LIRC_SET_SEND_MODE:
 488                result = get_user(mode, uptr);
 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, uptr);
 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, uptr);
 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        /* 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
 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        },
 609};
 610
 611static int pf(void *handle)
 612{
 613        parport_disable_irq(pport);
 614        is_claimed = 0;
 615        return 0;
 616}
 617
 618static void kf(void *handle)
 619{
 620        if (!is_open)
 621                return;
 622        if (!lirc_claim())
 623                return;
 624        parport_enable_irq(pport);
 625        lirc_off();
 626        /* this is a bit annoying when you actually print...*/
 627        /*
 628        printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
 629        */
 630}
 631
 632/*** module initialization and cleanup ***/
 633
 634static int __init lirc_parallel_init(void)
 635{
 636        int result;
 637
 638        result = platform_driver_register(&lirc_parallel_driver);
 639        if (result) {
 640                pr_notice("platform_driver_register returned %d\n", result);
 641                return result;
 642        }
 643
 644        lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
 645        if (!lirc_parallel_dev) {
 646                result = -ENOMEM;
 647                goto exit_driver_unregister;
 648        }
 649
 650        result = platform_device_add(lirc_parallel_dev);
 651        if (result)
 652                goto exit_device_put;
 653
 654        pport = parport_find_base(io);
 655        if (pport == NULL) {
 656                pr_notice("no port at %x found\n", io);
 657                result = -ENXIO;
 658                goto exit_device_put;
 659        }
 660        ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
 661                                           pf, kf, lirc_lirc_irq_handler, 0,
 662                                           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   /* continue even if device is offline */
 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