1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
/*
* lirc_dvb.c: module for lirc support
*
* Copyright (C) 2001 Matthias Hilbig <hilbig@upb.de>
*
* based heavily (copy&paste) on
*
* LIRC Infrared handler by Christoph Martin <martin@uni-mainz.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*/
#include <linux/module.h>
#include <linux/kmod.h>
#include <dvb.h>
/* include lirc_dev headers */
#include <drivers/lirc_dev/lirc_dev.h>
#define SUCCESS 0
#define LOGHEAD "lirc_dvb: "
static int debug = 0;
#define dprintk if (debug) printk
DECLARE_WAIT_QUEUE_HEAD(gpioq);
static int minor = -1;
/* lirc definitions */
static unsigned char code_length = 32;
static unsigned char code_bytes = 1;
/* buffer definitions */
#define IR_BUF_LENGTH 20
#define IR_INC(x) x = (x + 1) % IR_BUF_LENGTH
#define IRB_USED ((irbeg <= irend)?irend-irbeg:IR_BUF_LENGTH-(irbeg-irend))
static u32 irbuf[IR_BUF_LENGTH];
static u8 irbeg, irend;
static spinlock_t irlock = SPIN_LOCK_UNLOCKED;
static inline void irb_enqueue(u32 value) {
u8 lookahead;
spin_lock(&irlock);
lookahead = irend;
IR_INC(lookahead);
if (lookahead != irbeg) { //if its full don't accept further keys
irbuf[irend] = value;
irend = lookahead;
}
spin_unlock(&irlock);
}
static inline u32 irb_dequeue(void) {
u32 value;
static u32 lastvalue = (1<<31);
spin_lock(&irlock);
if (irend == irbeg) {
spin_unlock(&irlock);
return lastvalue;
}
value = lastvalue = irbuf[irbeg];
IR_INC(irbeg);
dprintk(LOGHEAD "buffer used: %d\n",IRB_USED);
spin_unlock(&irlock);
return value;
}
static inline void irb_init(void) {
irbeg = irend = 0;
spin_lock_init(&irlock);
}
/* this function receives irevents from dvb-driver */
void irhandler (u32 ircom) {
dprintk(LOGHEAD "ircom=%08x\n",ircom);
irb_enqueue(ircom);
wake_up_interruptible(&gpioq);
}
static int get_key(void* data, unsigned char *key, int key_no)
{
u32 irdata;
static unsigned char codes[4];
int index = code_bytes - key_no - 1;
if (key_no > 0) {
if (code_bytes < 2 || key_no >= code_bytes) {
dprintk(LOGHEAD "something wrong in get_key\n");
return -EBADRQC;
}
*key = codes[index];
return SUCCESS;
}
irdata = irb_dequeue();
memcpy(codes, &irdata, code_bytes);
*key = codes[index];
return SUCCESS;
}
static wait_queue_head_t* get_queue(void* data)
{
printk(LOGHEAD "get_queue\n");
return &gpioq;
}
static void set_use_inc(void* data)
{
MOD_INC_USE_COUNT;
}
static void set_use_dec(void* data)
{
MOD_DEC_USE_COUNT;
}
static struct lirc_plugin
plugin = {
"lirc_dvb ",
0,
0,
0,
NULL,
get_key,
get_queue,
set_use_inc,
set_use_dec
};
int init_module(void)
{
int ret;
plugin.code_length = code_length;
plugin.minor = minor;
plugin.sample_rate = 10;
irb_init();
request_module("lirc_dev");
code_bytes = (plugin.code_length/8) + (plugin.code_length%8 ? 1 : 0);
init_waitqueue_head(&gpioq);
ret = lirc_register_plugin(&plugin);
if (0 > ret) {
printk (LOGHEAD "device registration failed with %d\n", ret);
return ret;
}
minor = ret;
printk(LOGHEAD "driver registered\n");
dvb_register_irc_handler(irhandler);
return SUCCESS;
}
void cleanup_module(void)
{
int ret;
dvb_unregister_irc_handler(irhandler);
ret = lirc_unregister_plugin(minor);
if (0 > ret) {
printk(LOGHEAD "error in lirc_unregister_minor: %d\n"
"Trying again...\n", ret);
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ);
ret = lirc_unregister_plugin(minor);
if (0 > ret) {
printk(LOGHEAD "error in lirc_unregister_minor: %d!!!\n", ret);
return;
}
}
wake_up(&gpioq);
dprintk("module successfully unloaded\n");
}
|