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
  71unsigned int irq = LIRC_IRQ;
  72unsigned int io = LIRC_PORT;
  73#ifdef LIRC_TIMER
  74unsigned int timer;
  75unsigned 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
  82DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
  83
  84unsigned int rptr;
  85unsigned int wptr;
  86unsigned int lost_irqs;
  87int is_open;
  88
  89struct parport *pport;
  90struct pardevice *ppdevice;
  91int is_claimed;
  92
  93unsigned 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                }  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
 191static 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
 208static 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
 223static void 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
 322static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
 323{
 324        return -ESPIPE;
 325}
 326
 327static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos)
 328{
 329        int result = 0;
 330        int count = 0;
 331        DECLARE_WAITQUEUE(wait, current);
 332
 333        if (n % sizeof(int))
 334                return -EINVAL;
 335
 336        add_wait_queue(&lirc_wait, &wait);
 337        set_current_state(TASK_INTERRUPTIBLE);
 338        while (count < n) {
 339                if (rptr != wptr) {
 340                        if (copy_to_user(buf+count, (char *) &rbuf[rptr],
 341                                         sizeof(int))) {
 342                                result = -EFAULT;
 343                                break;
 344                        }
 345                        rptr = (rptr + 1) & (RBUF_SIZE - 1);
 346                        count += sizeof(int);
 347                } else {
 348                        if (filep->f_flags & O_NONBLOCK) {
 349                                result = -EAGAIN;
 350                                break;
 351                        }
 352                        if (signal_pending(current)) {
 353                                result = -ERESTARTSYS;
 354                                break;
 355                        }
 356                        schedule();
 357                        set_current_state(TASK_INTERRUPTIBLE);
 358                }
 359        }
 360        remove_wait_queue(&lirc_wait, &wait);
 361        set_current_state(TASK_RUNNING);
 362        return count ? count : result;
 363}
 364
 365static ssize_t lirc_write(struct file *filep, const char *buf, size_t n,
 366                          loff_t *ppos)
 367{
 368        int count;
 369        unsigned int i;
 370        unsigned int level, newlevel;
 371        unsigned long flags;
 372        int counttimer;
 373        int *wbuf;
 374        ssize_t ret;
 375
 376        if (!is_claimed)
 377                return -EBUSY;
 378
 379        count = n / sizeof(int);
 380
 381        if (n % sizeof(int) || count % 2 == 0)
 382                return -EINVAL;
 383
 384        wbuf = memdup_user(buf, n);
 385        if (IS_ERR(wbuf))
 386                return PTR_ERR(wbuf);
 387
 388#ifdef LIRC_TIMER
 389        if (timer == 0) {
 390                /* try again if device is ready */
 391                timer = init_lirc_timer();
 392                if (timer == 0) {
 393                        ret = -EIO;
 394                        goto out;
 395                }
 396        }
 397
 398        /* adjust values from usecs */
 399        for (i = 0; i < count; i++) {
 400                __u64 helper;
 401
 402                helper = ((__u64) wbuf[i])*timer;
 403                do_div(helper, 1000000);
 404                wbuf[i] = (int) helper;
 405        }
 406
 407        local_irq_save(flags);
 408        i = 0;
 409        while (i < count) {
 410                level = lirc_get_timer();
 411                counttimer = 0;
 412                lirc_on();
 413                do {
 414                        newlevel = lirc_get_timer();
 415                        if (level == 0 && newlevel != 0)
 416                                counttimer++;
 417                        level = newlevel;
 418                        if (check_pselecd && (in(1) & LP_PSELECD)) {
 419                                lirc_off();
 420                                local_irq_restore(flags);
 421                                ret = -EIO;
 422                                goto out;
 423                        }
 424                } while (counttimer < wbuf[i]);
 425                i++;
 426
 427                lirc_off();
 428                if (i == count)
 429                        break;
 430                counttimer = 0;
 431                do {
 432                        newlevel = lirc_get_timer();
 433                        if (level == 0 && newlevel != 0)
 434                                counttimer++;
 435                        level = newlevel;
 436                        if (check_pselecd && (in(1) & LP_PSELECD)) {
 437                                local_irq_restore(flags);
 438                                ret = -EIO;
 439                                goto out;
 440                        }
 441                } while (counttimer < wbuf[i]);
 442                i++;
 443        }
 444        local_irq_restore(flags);
 445#else
 446        /* place code that handles write without external timer here */
 447#endif
 448        ret = n;
 449out:
 450        kfree(wbuf);
 451
 452        return ret;
 453}
 454
 455static unsigned int lirc_poll(struct file *file, poll_table *wait)
 456{
 457        poll_wait(file, &lirc_wait, wait);
 458        if (rptr != wptr)
 459                return POLLIN | POLLRDNORM;
 460        return 0;
 461}
 462
 463static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 464{
 465        int result;
 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, (__u32 *) arg);
 474                if (result)
 475                        return result;
 476                break;
 477        case LIRC_GET_SEND_MODE:
 478                result = put_user(LIRC_MODE_PULSE, (__u32 *) arg);
 479                if (result)
 480                        return result;
 481                break;
 482        case LIRC_GET_REC_MODE:
 483                result = put_user(LIRC_MODE_MODE2, (__u32 *) arg);
 484                if (result)
 485                        return result;
 486                break;
 487        case LIRC_SET_SEND_MODE:
 488                result = get_user(mode, (__u32 *) arg);
 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, (__u32 *) arg);
 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, (__u32 *) arg);
 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                .owner  = THIS_MODULE,
 609        },
 610};
 611
 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{
 637        int result;
 638
 639        result = platform_driver_register(&lirc_parallel_driver);
 640        if (result) {
 641                pr_notice("platform_driver_register returned %d\n", result);
 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
 655        pport = parport_find_base(io);
 656        if (pport == NULL) {
 657                pr_notice("no port at %x found\n", io);
 658                result = -ENXIO;
 659                goto exit_device_put;
 660        }
 661        ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
 662                                           pf, kf, irq_handler, 0, 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