1805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson/* 2805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * lirc_parallel.c 3805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * 4805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * lirc_parallel - device driver for infra-red signal receiving and 5805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * transmitting unit built by the author 6805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * 7805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de> 8805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * 9805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * This program is free software; you can redistribute it and/or modify 10805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * it under the terms of the GNU General Public License as published by 11805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * the Free Software Foundation; either version 2 of the License, or 12805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * (at your option) any later version. 13805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * 14805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * This program is distributed in the hope that it will be useful, 15805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * but WITHOUT ANY WARRANTY; without even the implied warranty of 16805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * GNU General Public License for more details. 18805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * 19805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * You should have received a copy of the GNU General Public License 20805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * along with this program; if not, write to the Free Software 21805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * 23805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson */ 24805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 25805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson/*** Includes ***/ 26805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 27805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/module.h> 28805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/sched.h> 29805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/errno.h> 30805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/signal.h> 31805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/fs.h> 32805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/kernel.h> 33805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/ioport.h> 34805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/time.h> 35805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/mm.h> 36805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/delay.h> 37805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 38805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/io.h> 39805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/irq.h> 40805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/uaccess.h> 41805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <asm/div64.h> 42805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 43805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/poll.h> 44805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <linux/parport.h> 455d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger#include <linux/platform_device.h> 46805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 47805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <media/lirc.h> 48805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include <media/lirc_dev.h> 49805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 50805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#include "lirc_parallel.h" 51805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 52805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#define LIRC_DRIVER_NAME "lirc_parallel" 53805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 54805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#ifndef LIRC_IRQ 55805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#define LIRC_IRQ 7 56805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 57805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#ifndef LIRC_PORT 58805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#define LIRC_PORT 0x378 59805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 60805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#ifndef LIRC_TIMER 61805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#define LIRC_TIMER 65536 62805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 63805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 64805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson/*** Global Variables ***/ 65805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 6690ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool debug; 6790ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool check_pselecd; 68805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 69805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int irq = LIRC_IRQ; 70805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int io = LIRC_PORT; 71805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#ifdef LIRC_TIMER 72805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int timer; 73805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int default_timer = LIRC_TIMER; 74805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 75805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 76805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */ 77805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 78805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic int rbuf[RBUF_SIZE]; 79805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 80805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonDECLARE_WAIT_QUEUE_HEAD(lirc_wait); 81805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 82805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int rptr; 83805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int wptr; 84805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int lost_irqs; 85805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonint is_open; 86805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 87805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstruct parport *pport; 88805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstruct pardevice *ppdevice; 89805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonint is_claimed; 90805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 91805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonunsigned int tx_mask = 1; 92805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 93805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson/*** Internal Functions ***/ 94805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 95805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic unsigned int in(int offset) 96805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 97805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson switch (offset) { 98805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_LP_BASE: 99805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return parport_read_data(pport); 100805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_LP_STATUS: 101805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return parport_read_status(pport); 102805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_LP_CONTROL: 103805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return parport_read_control(pport); 104805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 105805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; /* make compiler happy */ 106805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 107805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 108805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void out(int offset, int value) 109805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 110805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson switch (offset) { 111805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_LP_BASE: 112805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_write_data(pport, value); 113805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 114805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_LP_CONTROL: 115805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_write_control(pport, value); 116805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 117805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_LP_STATUS: 118805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_INFO "%s: attempt to write to status register\n", 119805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME); 120805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 121805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 122805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 123805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 124805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic unsigned int lirc_get_timer(void) 125805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 126805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT; 127805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 128805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 129805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic unsigned int lirc_get_signal(void) 130805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 131805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT; 132805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 133805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 134805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void lirc_on(void) 135805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 136805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_PORT_DATA, tx_mask); 137805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 138805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 139805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void lirc_off(void) 140805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 141805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_PORT_DATA, 0); 142805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 143805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 144805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic unsigned int init_lirc_timer(void) 145805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 146805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson struct timeval tv, now; 147805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson unsigned int level, newlevel, timeelapsed, newtimer; 148805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int count = 0; 149805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 150805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do_gettimeofday(&tv); 151805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson tv.tv_sec++; /* wait max. 1 sec. */ 152805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson level = lirc_get_timer(); 153805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do { 154805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson newlevel = lirc_get_timer(); 155805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (level == 0 && newlevel != 0) 156805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson count++; 157805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson level = newlevel; 158805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do_gettimeofday(&now); 159805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } while (count < 1000 && (now.tv_sec < tv.tv_sec 160805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson || (now.tv_sec == tv.tv_sec 161805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson && now.tv_usec < tv.tv_usec))); 162805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 163805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000 164805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson + (now.tv_usec - tv.tv_usec)); 165805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (count >= 1000 && timeelapsed > 0) { 166805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (default_timer == 0) { 167805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* autodetect timer */ 168805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson newtimer = (1000000*count)/timeelapsed; 169805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_INFO "%s: %u Hz timer detected\n", 170805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME, newtimer); 171805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return newtimer; 172805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } else { 173805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson newtimer = (1000000*count)/timeelapsed; 174805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (abs(newtimer - default_timer) > default_timer/10) { 175805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* bad timer */ 176805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: bad timer: %u Hz\n", 177805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME, newtimer); 178805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: using default timer: " 179805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson "%u Hz\n", 180805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME, default_timer); 181805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return default_timer; 182805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } else { 183805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_INFO "%s: %u Hz timer detected\n", 184805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME, newtimer); 185805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return newtimer; /* use detected value */ 186805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 187805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 188805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } else { 189805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME); 190805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 191805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 192805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 193805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 194805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic int lirc_claim(void) 195805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 196805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (parport_claim(ppdevice) != 0) { 197805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_WARNING "%s: could not claim port\n", 198805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME); 199805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_WARNING "%s: waiting for port becoming available" 200805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson "\n", LIRC_DRIVER_NAME); 201805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (parport_claim_or_block(ppdevice) < 0) { 202805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: could not claim port, giving" 203805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson " up\n", LIRC_DRIVER_NAME); 204805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 205805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 206805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 207805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); 208805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_claimed = 1; 209805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 1; 210805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 211805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 212805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson/*** interrupt handler ***/ 213805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 214805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void rbuf_write(int signal) 215805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 216805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson unsigned int nwptr; 217805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 218805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson nwptr = (wptr + 1) & (RBUF_SIZE - 1); 219805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (nwptr == rptr) { 220805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* no new signals will be accepted */ 221805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson lost_irqs++; 222805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME); 223805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return; 224805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 225805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson rbuf[wptr] = signal; 226805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson wptr = nwptr; 227805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 228805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 229805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void irq_handler(void *blah) 230805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 231805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson struct timeval tv; 232805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson static struct timeval lasttv; 233805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson static int init; 234805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson long signal; 235805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int data; 236805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson unsigned int level, newlevel; 237805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson unsigned int timeout; 238805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 23982ce67bf262b3f47ecb5a0ca31cace8ac72b7c98Jarod Wilson if (!is_open) 240805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return; 241805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 242805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (!is_claimed) 243805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return; 244805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 245805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#if 0 246805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* disable interrupt */ 247805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson disable_irq(irq); 248805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN)); 249805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 250805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (check_pselecd && (in(1) & LP_PSELECD)) 251805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return; 252805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 253805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#ifdef LIRC_TIMER 254805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (init) { 255805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do_gettimeofday(&tv); 256805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 257805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson signal = tv.tv_sec - lasttv.tv_sec; 258805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (signal > 15) 259805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* really long time */ 260805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson data = PULSE_MASK; 261805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson else 262805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson data = (int) (signal*1000000 + 263805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson tv.tv_usec - lasttv.tv_usec + 264805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_SFH506_DELAY); 265805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 266805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson rbuf_write(data); /* space */ 267805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } else { 268805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (timer == 0) { 269805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* 270805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * wake up; we'll lose this signal, but it will be 271805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson * garbage if the device is turned on anyway 272805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson */ 273805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson timer = init_lirc_timer(); 274805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* enable_irq(irq); */ 275805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return; 276805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 277805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson init = 1; 278805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 279805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 280805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson timeout = timer/10; /* timeout after 1/10 sec. */ 281805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson signal = 1; 282805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson level = lirc_get_timer(); 283805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do { 284805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson newlevel = lirc_get_timer(); 285805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (level == 0 && newlevel != 0) 286805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson signal++; 287805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson level = newlevel; 288805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 289805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* giving up */ 290805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (signal > timeout 291805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson || (check_pselecd && (in(1) & LP_PSELECD))) { 292805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson signal = 0; 293805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME); 294805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 295805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 296805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } while (lirc_get_signal()); 297805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 298805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (signal != 0) { 299dca488b87efcae6f2b21ebe61922289b6093db2cUwe Kleine-König /* adjust value to usecs */ 300a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson __u64 helper; 301805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 302a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson helper = ((__u64) signal)*1000000; 303805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do_div(helper, timer); 304805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson signal = (long) helper; 305805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 306805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (signal > LIRC_SFH506_DELAY) 307805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson data = signal - LIRC_SFH506_DELAY; 308805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson else 309805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson data = 1; 310805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson rbuf_write(PULSE_BIT|data); /* pulse */ 311805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 312805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do_gettimeofday(&lasttv); 313805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#else 314805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* add your code here */ 315805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 316805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 317805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson wake_up_interruptible(&lirc_wait); 318805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 319805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* enable interrupt */ 320805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* 321805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson enable_irq(irq); 322805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN); 323805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson */ 324805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 325805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 326805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson/*** file operations ***/ 327805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 328805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic loff_t lirc_lseek(struct file *filep, loff_t offset, int orig) 329805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 330805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -ESPIPE; 331805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 332805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 333805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos) 334805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 335805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int result = 0; 336805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int count = 0; 337805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson DECLARE_WAITQUEUE(wait, current); 338805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 339805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (n % sizeof(int)) 340805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -EINVAL; 341805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 342805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson add_wait_queue(&lirc_wait, &wait); 343805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson set_current_state(TASK_INTERRUPTIBLE); 344805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson while (count < n) { 345805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (rptr != wptr) { 346805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (copy_to_user(buf+count, (char *) &rbuf[rptr], 347805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson sizeof(int))) { 348805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson result = -EFAULT; 349805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 350805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 351805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson rptr = (rptr + 1) & (RBUF_SIZE - 1); 352805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson count += sizeof(int); 353805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } else { 354805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (filep->f_flags & O_NONBLOCK) { 355805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson result = -EAGAIN; 356805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 357805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 358805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (signal_pending(current)) { 359805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson result = -ERESTARTSYS; 360805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 361805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 362805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson schedule(); 363805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson set_current_state(TASK_INTERRUPTIBLE); 364805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 365805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 366805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson remove_wait_queue(&lirc_wait, &wait); 367805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson set_current_state(TASK_RUNNING); 368805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return count ? count : result; 369805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 370805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 371805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic ssize_t lirc_write(struct file *filep, const char *buf, size_t n, 372805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson loff_t *ppos) 373805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 374805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int count; 375805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson unsigned int i; 376805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson unsigned int level, newlevel; 377805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson unsigned long flags; 378805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int counttimer; 379805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int *wbuf; 38088914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson ssize_t ret; 381805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 382805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (!is_claimed) 383805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -EBUSY; 384805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 385805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson count = n / sizeof(int); 386805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 387805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (n % sizeof(int) || count % 2 == 0) 388805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -EINVAL; 389805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 390805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson wbuf = memdup_user(buf, n); 391805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (IS_ERR(wbuf)) 392805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return PTR_ERR(wbuf); 393805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 394805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#ifdef LIRC_TIMER 395805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (timer == 0) { 396805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* try again if device is ready */ 397805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson timer = init_lirc_timer(); 39888914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson if (timer == 0) { 39988914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson ret = -EIO; 40088914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson goto out; 40188914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson } 402805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 403805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 404805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* adjust values from usecs */ 405805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson for (i = 0; i < count; i++) { 406a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson __u64 helper; 407805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 408a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson helper = ((__u64) wbuf[i])*timer; 409805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do_div(helper, 1000000); 410805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson wbuf[i] = (int) helper; 411805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 412805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 413805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson local_irq_save(flags); 414805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson i = 0; 415805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson while (i < count) { 416805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson level = lirc_get_timer(); 417805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson counttimer = 0; 418805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson lirc_on(); 419805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do { 420805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson newlevel = lirc_get_timer(); 421805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (level == 0 && newlevel != 0) 422805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson counttimer++; 423805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson level = newlevel; 424805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (check_pselecd && (in(1) & LP_PSELECD)) { 425805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson lirc_off(); 426805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson local_irq_restore(flags); 42788914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson ret = -EIO; 42888914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson goto out; 429805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 430805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } while (counttimer < wbuf[i]); 431805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson i++; 432805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 433805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson lirc_off(); 434805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (i == count) 435805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 436805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson counttimer = 0; 437805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson do { 438805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson newlevel = lirc_get_timer(); 439805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (level == 0 && newlevel != 0) 440805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson counttimer++; 441805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson level = newlevel; 442805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (check_pselecd && (in(1) & LP_PSELECD)) { 443805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson local_irq_restore(flags); 44488914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson ret = -EIO; 44588914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson goto out; 446805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 447805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } while (counttimer < wbuf[i]); 448805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson i++; 449805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 450805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson local_irq_restore(flags); 451805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#else 452805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* place code that handles write without external timer here */ 453805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 45488914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson ret = n; 45588914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilsonout: 45688914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson kfree(wbuf); 45788914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson 45888914bdf8c677ebd7e797adac05e47303fd6ac77Jarod Wilson return ret; 459805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 460805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 461805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic unsigned int lirc_poll(struct file *file, poll_table *wait) 462805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 463805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson poll_wait(file, &lirc_wait, wait); 464805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (rptr != wptr) 465805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return POLLIN | POLLRDNORM; 466805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 467805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 468805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 469805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) 470805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 471805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson int result; 472a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson __u32 features = LIRC_CAN_SET_TRANSMITTER_MASK | 473a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; 474a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson __u32 mode; 475a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson __u32 value; 476805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 477805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson switch (cmd) { 478805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_GET_FEATURES: 479a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson result = put_user(features, (__u32 *) arg); 480805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (result) 481805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return result; 482805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 483805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_GET_SEND_MODE: 484a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson result = put_user(LIRC_MODE_PULSE, (__u32 *) arg); 485805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (result) 486805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return result; 487805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 488805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_GET_REC_MODE: 489a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson result = put_user(LIRC_MODE_MODE2, (__u32 *) arg); 490805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (result) 491805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return result; 492805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 493805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_SET_SEND_MODE: 494a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson result = get_user(mode, (__u32 *) arg); 495805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (result) 496805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return result; 497805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (mode != LIRC_MODE_PULSE) 498805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -EINVAL; 499805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 500805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_SET_REC_MODE: 501a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson result = get_user(mode, (__u32 *) arg); 502805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (result) 503805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return result; 504805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (mode != LIRC_MODE_MODE2) 505805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -ENOSYS; 506805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 507805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson case LIRC_SET_TRANSMITTER_MASK: 508a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson result = get_user(value, (__u32 *) arg); 509805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (result) 510805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return result; 511a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value) 512805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return LIRC_PARALLEL_MAX_TRANSMITTERS; 513a126681810a327bee60a58ac5ad77f4518cf7a5fJarod Wilson tx_mask = value; 514805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson break; 515805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson default: 516805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -ENOIOCTLCMD; 517805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 518805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 519805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 520805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 521805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic int lirc_open(struct inode *node, struct file *filep) 522805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 52382ce67bf262b3f47ecb5a0ca31cace8ac72b7c98Jarod Wilson if (is_open || !lirc_claim()) 524805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return -EBUSY; 525805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 526805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_enable_irq(pport); 527805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 528805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* init read ptr */ 529805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson rptr = 0; 530805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson wptr = 0; 531805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson lost_irqs = 0; 532805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 533805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_open = 1; 534805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 535805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 536805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 537805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic int lirc_close(struct inode *node, struct file *filep) 538805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 539805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (is_claimed) { 540805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_claimed = 0; 541805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_release(ppdevice); 542805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 543805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_open = 0; 544805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 545805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 546805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 5470f9313ad068af4156109661fb8e94ee7fcb79001Mauro Carvalho Chehabstatic const struct file_operations lirc_fops = { 548805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .owner = THIS_MODULE, 549805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .llseek = lirc_lseek, 550805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .read = lirc_read, 551805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .write = lirc_write, 552805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .poll = lirc_poll, 553805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .unlocked_ioctl = lirc_ioctl, 5548be292cc035ebc3422f08e84682626dd8ed8334bJarod Wilson#ifdef CONFIG_COMPAT 5558be292cc035ebc3422f08e84682626dd8ed8334bJarod Wilson .compat_ioctl = lirc_ioctl, 5568be292cc035ebc3422f08e84682626dd8ed8334bJarod Wilson#endif 557805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .open = lirc_open, 558805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson .release = lirc_close 559805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson}; 560805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 561805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic int set_use_inc(void *data) 562805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 563805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 564805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 565805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 566805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void set_use_dec(void *data) 567805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 568805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 569805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 570805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic struct lirc_driver driver = { 571d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .name = LIRC_DRIVER_NAME, 572d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .minor = -1, 573d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .code_length = 1, 574d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .sample_rate = 0, 575d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .data = NULL, 576d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .add_to_buf = NULL, 577d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .set_use_inc = set_use_inc, 578d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .set_use_dec = set_use_dec, 579d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .fops = &lirc_fops, 580d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .dev = NULL, 581d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche .owner = THIS_MODULE, 582805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson}; 583805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 5845d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerstatic struct platform_device *lirc_parallel_dev; 5855d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 5865d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerstatic int __devinit lirc_parallel_probe(struct platform_device *dev) 5875d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger{ 5885d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger return 0; 5895d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger} 5905d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 5915d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerstatic int __devexit lirc_parallel_remove(struct platform_device *dev) 5925d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger{ 5935d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger return 0; 5945d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger} 5955d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 5965d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerstatic int lirc_parallel_suspend(struct platform_device *dev, 597d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche pm_message_t state) 5985d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger{ 5995d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger return 0; 6005d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger} 6015d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 6025d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerstatic int lirc_parallel_resume(struct platform_device *dev) 6035d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger{ 6045d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger return 0; 6055d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger} 6065d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 6075d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerstatic struct platform_driver lirc_parallel_driver = { 6085d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger .probe = lirc_parallel_probe, 6095d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger .remove = __devexit_p(lirc_parallel_remove), 6105d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger .suspend = lirc_parallel_suspend, 6115d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger .resume = lirc_parallel_resume, 6125d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger .driver = { 6135d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger .name = LIRC_DRIVER_NAME, 6145d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger .owner = THIS_MODULE, 6155d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger }, 6165d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger}; 6175d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 618805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic int pf(void *handle) 619805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 620805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_disable_irq(pport); 621805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_claimed = 0; 622805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 623805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 624805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 625805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void kf(void *handle) 626805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 627805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (!is_open) 628805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return; 629805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (!lirc_claim()) 630805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return; 631805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_enable_irq(pport); 632805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson lirc_off(); 633805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* this is a bit annoying when you actually print...*/ 634805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson /* 635805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME); 636805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson */ 637805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 638805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 639805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson/*** module initialization and cleanup ***/ 640805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 641805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic int __init lirc_parallel_init(void) 642805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 6435d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger int result; 6445d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 6455d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger result = platform_driver_register(&lirc_parallel_driver); 6465d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger if (result) { 647d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche printk(KERN_NOTICE "platform_driver_register" 648d713680f2a7a91864e3722420222952f30a0346eGreg Dietsche " returned %d\n", result); 6495d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger return result; 6505d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger } 6515d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 6525d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); 6535d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger if (!lirc_parallel_dev) { 6545d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger result = -ENOMEM; 6555d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger goto exit_driver_unregister; 6565d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger } 6575d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 6585d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger result = platform_device_add(lirc_parallel_dev); 6595d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger if (result) 6605d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger goto exit_device_put; 6615d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 662805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson pport = parport_find_base(io); 663805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (pport == NULL) { 664805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: no port at %x found\n", 665805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME, io); 6665d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger result = -ENXIO; 6675d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger goto exit_device_put; 668805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 669805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME, 670805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson pf, kf, irq_handler, 0, NULL); 671805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_put_port(pport); 672805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (ppdevice == NULL) { 673805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: parport_register_device() failed\n", 674805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME); 6755d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger result = -ENXIO; 6765d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger goto exit_device_put; 677805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 678805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (parport_claim(ppdevice) != 0) 679805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson goto skip_init; 680805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_claimed = 1; 681805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); 682805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 683805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#ifdef LIRC_TIMER 684805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (debug) 685805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_PORT_DATA, tx_mask); 686805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 687805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson timer = init_lirc_timer(); 688805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 689805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#if 0 /* continue even if device is offline */ 690805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (timer == 0) { 691805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_claimed = 0; 692805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_release(pport); 693805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_unregister_device(ppdevice); 6945d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger result = -EIO; 6955d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger goto exit_device_put; 696805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 697805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 698805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 699805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (debug) 700805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson out(LIRC_PORT_DATA, 0); 701805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson#endif 702805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 703805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson is_claimed = 0; 704805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_release(ppdevice); 705805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson skip_init: 7065d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger driver.dev = &lirc_parallel_dev->dev; 707805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson driver.minor = lirc_register_driver(&driver); 708805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson if (driver.minor < 0) { 709805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_NOTICE "%s: register_chrdev() failed\n", 710805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME); 711805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_unregister_device(ppdevice); 7125d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger result = -EIO; 7135d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger goto exit_device_put; 714805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson } 715805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n", 716805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson LIRC_DRIVER_NAME, io, irq); 717805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson return 0; 7185d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger 7195d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerexit_device_put: 7205d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger platform_device_put(lirc_parallel_dev); 7215d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehwegerexit_driver_unregister: 7225d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger platform_driver_unregister(&lirc_parallel_driver); 7235d884b97c5143f0d4097cefefbf9f7f755fd54faThomas Viehweger return result; 724805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 725805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 726805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonstatic void __exit lirc_parallel_exit(void) 727805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson{ 728805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson parport_unregister_device(ppdevice); 729805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson lirc_unregister_driver(driver.minor); 7307cf131cb240fb0959f3b56155781f4d4de4608d1Dave Jones 7317cf131cb240fb0959f3b56155781f4d4de4608d1Dave Jones platform_device_unregister(lirc_parallel_dev); 7327cf131cb240fb0959f3b56155781f4d4de4608d1Dave Jones platform_driver_unregister(&lirc_parallel_driver); 733805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson} 734805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 735805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonmodule_init(lirc_parallel_init); 736805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonmodule_exit(lirc_parallel_exit); 737805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 738805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonMODULE_DESCRIPTION("Infrared receiver driver for parallel ports."); 739805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonMODULE_AUTHOR("Christoph Bartelmus"); 740805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonMODULE_LICENSE("GPL"); 741805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 742805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonmodule_param(io, int, S_IRUGO); 743805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonMODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)"); 744805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 745805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonmodule_param(irq, int, S_IRUGO); 746805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonMODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); 747805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 748805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonmodule_param(tx_mask, int, S_IRUGO); 749805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonMODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); 750805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 751805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonmodule_param(debug, bool, S_IRUGO | S_IWUSR); 752805a8966659563df68ea7bbd94241dafd645c725Jarod WilsonMODULE_PARM_DESC(debug, "Enable debugging messages"); 753805a8966659563df68ea7bbd94241dafd645c725Jarod Wilson 754805a8966659563df68ea7bbd94241dafd645c725Jarod Wilsonmodule_param(check_pselecd, bool, S_IRUGO | S_IWUSR); 755f17dda94d48b654c793da6632f65654476291ba5Rusty RussellMODULE_PARM_DESC(check_pselecd, "Check for printer (default: 0)"); 756