linux/drivers/staging/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/*** Includes ***/
  26
  27#include <linux/module.h>
  28#include <linux/sched.h>
  29#include <linux/errno.h>
  30#include <linux/signal.h>
  31#include <linux/fs.h>
  32#include <linux/kernel.h>
  33#include <linux/ioport.h>
  34#include <linux/time.h>
  35#include <linux/mm.h>
  36#include <linux/delay.h>
  37
  38#include <linux/io.h>
  39#include <linux/irq.h>
  40#include <linux/uaccess.h>
  41#include <asm/div64.h>
  42
  43#include <linux/poll.h>
  44#include <linux/parport.h>
  45
  46#include <media/lirc.h>
  47#include <media/lirc_dev.h>
  48
  49#include "lirc_parallel.h"
  50
  51#define LIRC_DRIVER_NAME "lirc_parallel"
  52
  53#ifndef LIRC_IRQ
  54#define LIRC_IRQ 7
  55#endif
  56#ifndef LIRC_PORT
  57#define LIRC_PORT 0x378
  58#endif
  59#ifndef LIRC_TIMER
  60#define LIRC_TIMER 65536
  61#endif
  62
  63/*** Global Variables ***/
  64
  65static int debug;
  66static int check_pselecd;
  67
  68unsigned int irq = LIRC_IRQ;
  69unsigned int io = LIRC_PORT;
  70#ifdef LIRC_TIMER
  71unsigned int timer;
  72unsigned int default_timer = LIRC_TIMER;
  73#endif
  74
  75#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */
  76
  77static int rbuf[RBUF_SIZE];
  78
  79DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
  80
  81unsigned int rptr;
  82unsigned int wptr;
  83unsigned int lost_irqs;
  84int is_open;
  85
  86struct parport *pport;
  87struct pardevice *ppdevice;
  88int is_claimed;
  89
  90unsigned int tx_mask = 1;
  91
  92/*** Internal Functions ***/
  93
  94static unsigned int in(int offset)
  95{
  96        switch (offset) {
  97        case LIRC_LP_BASE:
  98                return parport_read_data(pport);
  99        case LIRC_LP_STATUS:
 100                return parport_read_status(pport);
 101        case LIRC_LP_CONTROL:
 102                return parport_read_control(pport);
 103        }
 104        return 0; /* make compiler happy */
 105}
 106
 107static void out(int offset, int value)
 108{
 109        switch (offset) {
 110        case LIRC_LP_BASE:
 111                parport_write_data(pport, value);
 112                break;
 113        case LIRC_LP_CONTROL:
 114                parport_write_control(pport, value);
 115                break;
 116        case LIRC_LP_STATUS:
 117                printk(KERN_INFO "%s: attempt to write to status register\n",
 118                       LIRC_DRIVER_NAME);
 119                break;
 120        }
 121}
 122
 123static unsigned int lirc_get_timer(void)
 124{
 125        return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT;
 126}
 127
 128static unsigned int lirc_get_signal(void)
 129{
 130        return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT;
 131}
 132
 133static void lirc_on(void)
 134{
 135        out(LIRC_PORT_DATA, tx_mask);
 136}
 137
 138static void lirc_off(void)
 139{
 140        out(LIRC_PORT_DATA, 0);
 141}
 142
 143static unsigned int init_lirc_timer(void)
 144{
 145        struct timeval tv, now;
 146        unsigned int level, newlevel, timeelapsed, newtimer;
 147        int count = 0;
 148
 149        do_gettimeofday(&tv);
 150        tv.tv_sec++;                     /* wait max. 1 sec. */
 151        level = lirc_get_timer();
 152        do {
 153                newlevel = lirc_get_timer();
 154                if (level == 0 && newlevel != 0)
 155                        count++;
 156                level = newlevel;
 157                do_gettimeofday(&now);
 158        } while (count < 1000 && (now.tv_sec < tv.tv_sec
 159                             || (now.tv_sec == tv.tv_sec
 160                                 && now.tv_usec < tv.tv_usec)));
 161
 162        timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000
 163                     + (now.tv_usec - tv.tv_usec));
 164        if (count >= 1000 && timeelapsed > 0) {
 165                if (default_timer == 0) {
 166                        /* autodetect timer */
 167                        newtimer = (1000000*count)/timeelapsed;
 168                        printk(KERN_INFO "%s: %u Hz timer detected\n",
 169                               LIRC_DRIVER_NAME, newtimer);
 170                        return newtimer;
 171                }  else {
 172                        newtimer = (1000000*count)/timeelapsed;
 173                        if (abs(newtimer - default_timer) > default_timer/10) {
 174                                /* bad timer */
 175                                printk(KERN_NOTICE "%s: bad timer: %u Hz\n",
 176                                       LIRC_DRIVER_NAME, newtimer);
 177                                printk(KERN_NOTICE "%s: using default timer: "
 178                                       "%u Hz\n",
 179                                       LIRC_DRIVER_NAME, default_timer);
 180                                return default_timer;
 181                        } else {
 182                                printk(KERN_INFO "%s: %u Hz timer detected\n",
 183                                       LIRC_DRIVER_NAME, newtimer);
 184                                return newtimer; /* use detected value */
 185                        }
 186                }
 187        } else {
 188                printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME);
 189                return 0;
 190        }
 191}
 192
 193static int lirc_claim(void)
 194{
 195        if (parport_claim(ppdevice) != 0) {
 196                printk(KERN_WARNING "%s: could not claim port\n",
 197                       LIRC_DRIVER_NAME);
 198                printk(KERN_WARNING "%s: waiting for port becoming available"
 199                       "\n", LIRC_DRIVER_NAME);
 200                if (parport_claim_or_block(ppdevice) < 0) {
 201                        printk(KERN_NOTICE "%s: could not claim port, giving"
 202                               " up\n", LIRC_DRIVER_NAME);
 203                        return 0;
 204                }
 205        }
 206        out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
 207        is_claimed = 1;
 208        return 1;
 209}
 210
 211/*** interrupt handler ***/
 212
 213static void rbuf_write(int signal)
 214{
 215        unsigned int nwptr;
 216
 217        nwptr = (wptr + 1) & (RBUF_SIZE - 1);
 218        if (nwptr == rptr) {
 219                /* no new signals will be accepted */
 220                lost_irqs++;
 221                printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME);
 222                return;
 223        }
 224        rbuf[wptr] = signal;
 225        wptr = nwptr;
 226}
 227
 228static void irq_handler(void *blah)
 229{
 230        struct timeval tv;
 231        static struct timeval lasttv;
 232        static int init;
 233        long signal;
 234        int data;
 235        unsigned int level, newlevel;
 236        unsigned int timeout;
 237
 238        if (!is_open)
 239                return;
 240
 241        if (!is_claimed)
 242                return;
 243
 244#if 0
 245        /* disable interrupt */
 246          disable_irq(irq);
 247          out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN));
 248#endif
 249        if (check_pselecd && (in(1) & LP_PSELECD))
 250                return;
 251
 252#ifdef LIRC_TIMER
 253        if (init) {
 254                do_gettimeofday(&tv);
 255
 256                signal = tv.tv_sec - lasttv.tv_sec;
 257                if (signal > 15)
 258                        /* really long time */
 259                        data = PULSE_MASK;
 260                else
 261                        data = (int) (signal*1000000 +
 262                                         tv.tv_usec - lasttv.tv_usec +
 263                                         LIRC_SFH506_DELAY);
 264
 265                rbuf_write(data); /* space */
 266        } else {
 267                if (timer == 0) {
 268                        /*
 269                         * wake up; we'll lose this signal, but it will be
 270                         * garbage if the device is turned on anyway
 271                         */
 272                        timer = init_lirc_timer();
 273                        /* enable_irq(irq); */
 274                        return;
 275                }
 276                init = 1;
 277        }
 278
 279        timeout = timer/10;     /* timeout after 1/10 sec. */
 280        signal = 1;
 281        level = lirc_get_timer();
 282        do {
 283                newlevel = lirc_get_timer();
 284                if (level == 0 && newlevel != 0)
 285                        signal++;
 286                level = newlevel;
 287
 288                /* giving up */
 289                if (signal > timeout
 290                    || (check_pselecd && (in(1) & LP_PSELECD))) {
 291                        signal = 0;
 292                        printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME);
 293                        break;
 294                }
 295        } while (lirc_get_signal());
 296
 297        if (signal != 0) {
 298                /* ajust value to usecs */
 299                __u64 helper;
 300
 301                helper = ((__u64) signal)*1000000;
 302                do_div(helper, timer);
 303                signal = (long) helper;
 304
 305                if (signal > LIRC_SFH506_DELAY)
 306                        data = signal - LIRC_SFH506_DELAY;
 307                else
 308                        data = 1;
 309                rbuf_write(PULSE_BIT|data); /* pulse */
 310        }
 311        do_gettimeofday(&lasttv);
 312#else
 313        /* add your code here */
 314#endif
 315
 316        wake_up_interruptible(&lirc_wait);
 317
 318        /* enable interrupt */
 319        /*
 320          enable_irq(irq);
 321          out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN);
 322        */
 323}
 324
 325/*** file operations ***/
 326
 327static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
 328{
 329        return -ESPIPE;
 330}
 331
 332static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos)
 333{
 334        int result = 0;
 335        int count = 0;
 336        DECLARE_WAITQUEUE(wait, current);
 337
 338        if (n % sizeof(int))
 339                return -EINVAL;
 340
 341        add_wait_queue(&lirc_wait, &wait);
 342        set_current_state(TASK_INTERRUPTIBLE);
 343        while (count < n) {
 344                if (rptr != wptr) {
 345                        if (copy_to_user(buf+count, (char *) &rbuf[rptr],
 346                                         sizeof(int))) {
 347                                result = -EFAULT;
 348                                break;
 349                        }
 350                        rptr = (rptr + 1) & (RBUF_SIZE - 1);
 351                        count += sizeof(int);
 352                } else {
 353                        if (filep->f_flags & O_NONBLOCK) {
 354                                result = -EAGAIN;
 355                                break;
 356                        }
 357                        if (signal_pending(current)) {
 358                                result = -ERESTARTSYS;
 359                                break;
 360                        }
 361                        schedule();
 362                        set_current_state(TASK_INTERRUPTIBLE);
 363                }
 364        }
 365        remove_wait_queue(&lirc_wait, &wait);
 366        set_current_state(TASK_RUNNING);
 367        return count ? count : result;
 368}
 369
 370static ssize_t lirc_write(struct file *filep, const char *buf, size_t n,
 371                          loff_t *ppos)
 372{
 373        int count;
 374        unsigned int i;
 375        unsigned int level, newlevel;
 376        unsigned long flags;
 377        int counttimer;
 378        int *wbuf;
 379        ssize_t ret;
 380
 381        if (!is_claimed)
 382                return -EBUSY;
 383
 384        count = n / sizeof(int);
 385
 386        if (n % sizeof(int) || count % 2 == 0)
 387                return -EINVAL;
 388
 389        wbuf = memdup_user(buf, n);
 390        if (IS_ERR(wbuf))
 391                return PTR_ERR(wbuf);
 392
 393#ifdef LIRC_TIMER
 394        if (timer == 0) {
 395                /* try again if device is ready */
 396                timer = init_lirc_timer();
 397                if (timer == 0) {
 398                        ret = -EIO;
 399                        goto out;
 400                }
 401        }
 402
 403        /* adjust values from usecs */
 404        for (i = 0; i < count; i++) {
 405                __u64 helper;
 406
 407                helper = ((__u64) wbuf[i])*timer;
 408                do_div(helper, 1000000);
 409                wbuf[i] = (int) helper;
 410        }
 411
 412        local_irq_save(flags);
 413        i = 0;
 414        while (i < count) {
 415                level = lirc_get_timer();
 416                counttimer = 0;
 417                lirc_on();
 418                do {
 419                        newlevel = lirc_get_timer();
 420                        if (level == 0 && newlevel != 0)
 421                                counttimer++;
 422                        level = newlevel;
 423                        if (check_pselecd && (in(1) & LP_PSELECD)) {
 424                                lirc_off();
 425                                local_irq_restore(flags);
 426                                ret = -EIO;
 427                                goto out;
 428                        }
 429                } while (counttimer < wbuf[i]);
 430                i++;
 431
 432                lirc_off();
 433                if (i == count)
 434                        break;
 435                counttimer = 0;
 436                do {
 437                        newlevel = lirc_get_timer();
 438                        if (level == 0 && newlevel != 0)
 439                                counttimer++;
 440                        level = newlevel;
 441                        if (check_pselecd && (in(1) & LP_PSELECD)) {
 442                                local_irq_restore(flags);
 443                                ret = -EIO;
 444                                goto out;
 445                        }
 446                } while (counttimer < wbuf[i]);
 447                i++;
 448        }
 449        local_irq_restore(flags);
 450#else
 451        /* place code that handles write without external timer here */
 452#endif
 453        ret = n;
 454out:
 455        kfree(wbuf);
 456
 457        return ret;
 458}
 459
 460static unsigned int lirc_poll(struct file *file, poll_table *wait)
 461{
 462        poll_wait(file, &lirc_wait, wait);
 463        if (rptr != wptr)
 464                return POLLIN | POLLRDNORM;
 465        return 0;
 466}
 467
 468static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 469{
 470        int result;
 471        __u32 features = LIRC_CAN_SET_TRANSMITTER_MASK |
 472                         LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
 473        __u32 mode;
 474        __u32 value;
 475
 476        switch (cmd) {
 477        case LIRC_GET_FEATURES:
 478                result = put_user(features, (__u32 *) arg);
 479                if (result)
 480                        return result;
 481                break;
 482        case LIRC_GET_SEND_MODE:
 483                result = put_user(LIRC_MODE_PULSE, (__u32 *) arg);
 484                if (result)
 485                        return result;
 486                break;
 487        case LIRC_GET_REC_MODE:
 488                result = put_user(LIRC_MODE_MODE2, (__u32 *) arg);
 489                if (result)
 490                        return result;
 491                break;
 492        case LIRC_SET_SEND_MODE:
 493                result = get_user(mode, (__u32 *) arg);
 494                if (result)
 495                        return result;
 496                if (mode != LIRC_MODE_PULSE)
 497                        return -EINVAL;
 498                break;
 499        case LIRC_SET_REC_MODE:
 500                result = get_user(mode, (__u32 *) arg);
 501                if (result)
 502                        return result;
 503                if (mode != LIRC_MODE_MODE2)
 504                        return -ENOSYS;
 505                break;
 506        case LIRC_SET_TRANSMITTER_MASK:
 507                result = get_user(value, (__u32 *) arg);
 508                if (result)
 509                        return result;
 510                if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value)
 511                        return LIRC_PARALLEL_MAX_TRANSMITTERS;
 512                tx_mask = value;
 513                break;
 514        default:
 515                return -ENOIOCTLCMD;
 516        }
 517        return 0;
 518}
 519
 520static int lirc_open(struct inode *node, struct file *filep)
 521{
 522        if (is_open || !lirc_claim())
 523                return -EBUSY;
 524
 525        parport_enable_irq(pport);
 526
 527        /* init read ptr */
 528        rptr = 0;
 529        wptr = 0;
 530        lost_irqs = 0;
 531
 532        is_open = 1;
 533        return 0;
 534}
 535
 536static int lirc_close(struct inode *node, struct file *filep)
 537{
 538        if (is_claimed) {
 539                is_claimed = 0;
 540                parport_release(ppdevice);
 541        }
 542        is_open = 0;
 543        return 0;
 544}
 545
 546static const struct file_operations lirc_fops = {
 547        .owner          = THIS_MODULE,
 548        .llseek         = lirc_lseek,
 549        .read           = lirc_read,
 550        .write          = lirc_write,
 551        .poll           = lirc_poll,
 552        .unlocked_ioctl = lirc_ioctl,
 553#ifdef CONFIG_COMPAT
 554        .compat_ioctl   = lirc_ioctl,
 555#endif
 556        .open           = lirc_open,
 557        .release        = lirc_close
 558};
 559
 560static int set_use_inc(void *data)
 561{
 562        return 0;
 563}
 564
 565static void set_use_dec(void *data)
 566{
 567}
 568
 569static struct lirc_driver driver = {
 570       .name            = LIRC_DRIVER_NAME,
 571       .minor           = -1,
 572       .code_length     = 1,
 573       .sample_rate     = 0,
 574       .data            = NULL,
 575       .add_to_buf      = NULL,
 576       .set_use_inc     = set_use_inc,
 577       .set_use_dec     = set_use_dec,
 578       .fops            = &lirc_fops,
 579       .dev             = NULL,
 580       .owner           = THIS_MODULE,
 581};
 582
 583static int pf(void *handle);
 584static void kf(void *handle);
 585
 586static int pf(void *handle)
 587{
 588        parport_disable_irq(pport);
 589        is_claimed = 0;
 590        return 0;
 591}
 592
 593static void kf(void *handle)
 594{
 595        if (!is_open)
 596                return;
 597        if (!lirc_claim())
 598                return;
 599        parport_enable_irq(pport);
 600        lirc_off();
 601        /* this is a bit annoying when you actually print...*/
 602        /*
 603        printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
 604        */
 605}
 606
 607/*** module initialization and cleanup ***/
 608
 609static int __init lirc_parallel_init(void)
 610{
 611        pport = parport_find_base(io);
 612        if (pport == NULL) {
 613                printk(KERN_NOTICE "%s: no port at %x found\n",
 614                       LIRC_DRIVER_NAME, io);
 615                return -ENXIO;
 616        }
 617        ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
 618                                           pf, kf, irq_handler, 0, NULL);
 619        parport_put_port(pport);
 620        if (ppdevice == NULL) {
 621                printk(KERN_NOTICE "%s: parport_register_device() failed\n",
 622                       LIRC_DRIVER_NAME);
 623                return -ENXIO;
 624        }
 625        if (parport_claim(ppdevice) != 0)
 626                goto skip_init;
 627        is_claimed = 1;
 628        out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
 629
 630#ifdef LIRC_TIMER
 631        if (debug)
 632                out(LIRC_PORT_DATA, tx_mask);
 633
 634        timer = init_lirc_timer();
 635
 636#if 0   /* continue even if device is offline */
 637        if (timer == 0) {
 638                is_claimed = 0;
 639                parport_release(pport);
 640                parport_unregister_device(ppdevice);
 641                return -EIO;
 642        }
 643
 644#endif
 645        if (debug)
 646                out(LIRC_PORT_DATA, 0);
 647#endif
 648
 649        is_claimed = 0;
 650        parport_release(ppdevice);
 651 skip_init:
 652        driver.minor = lirc_register_driver(&driver);
 653        if (driver.minor < 0) {
 654                printk(KERN_NOTICE "%s: register_chrdev() failed\n",
 655                       LIRC_DRIVER_NAME);
 656                parport_unregister_device(ppdevice);
 657                return -EIO;
 658        }
 659        printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n",
 660               LIRC_DRIVER_NAME, io, irq);
 661        return 0;
 662}
 663
 664static void __exit lirc_parallel_exit(void)
 665{
 666        parport_unregister_device(ppdevice);
 667        lirc_unregister_driver(driver.minor);
 668}
 669
 670module_init(lirc_parallel_init);
 671module_exit(lirc_parallel_exit);
 672
 673MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
 674MODULE_AUTHOR("Christoph Bartelmus");
 675MODULE_LICENSE("GPL");
 676
 677module_param(io, int, S_IRUGO);
 678MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
 679
 680module_param(irq, int, S_IRUGO);
 681MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
 682
 683module_param(tx_mask, int, S_IRUGO);
 684MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)");
 685
 686module_param(debug, bool, S_IRUGO | S_IWUSR);
 687MODULE_PARM_DESC(debug, "Enable debugging messages");
 688
 689module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
 690MODULE_PARM_DESC(debug, "Check for printer (default: 0)");
 691