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