Re: Asus P7131 Remote Control (includes patch)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


Hi there,
It's been somedays out... but here it is, almost fully working and I
tried to get the bt8xx and saa7134 rc5 toghether.

In brief, what I did:
* Moved the rc5_decode and rc5_timer_end from bt8xx to ir-functions.c
to share it among others.
* moved structs bttv_ir and saa7134_ir to a unique card_ir under
ir-common.h (rc5_timer_end expects it)
* Tried to get it working again...

The only thing I'm sure isn't working are all the dprintk()'s in the
new functions in ir-functions.c so I changed them to printk()'s for
testing, but that makes a lot of noise on dmesg so if somebody know
how to put back the dprintk's... ;)

And! I have no bt8xx to make sure I didn't break something, so If
anybody with a bt8xx can try his rc5 remote I'd be glad.

For the rest I thing I didn't do anything bad... hope so! And if
somebody is bored.. (saa7134|bttv)_rc5_irq is still waitting for
somebody trying to get it into one... hehe. There's another driver
which uses the *_ir struct but seems harder to move.

The patch is agains current HG.

If needed.
Signed-off-by: Marc Fargas <telenieko@xxxxxxxxxxxxx>
(don't know how to add the signed-off-by to a patch, hehe).

Cheers,
Marc Fargas

On 9/3/06, hermann pitton <hermann-pitton@xxxxxxxx> wrote:
Hi Marc,

the same keys is fine!

With the toggle bit back in the recent version of the patch it is all
OK.

Yes, key timing is really quick, didn't change it yet.
What about it when loading saa7134 with "rc5_key_timeout=50" ?

Thanks for all!

Cheers,
Hermann


--
The probability of failure of a (computer) system is exponentially
proportional to the physical distance between it and the one who could
fix it. -- Martin F. Krafft
diff -r 12f0f1ce18b1 linux/drivers/media/common/ir-functions.c
--- a/linux/drivers/media/common/ir-functions.c	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/common/ir-functions.c	Thu Sep 28 22:28:14 2006 +0200
@@ -263,6 +263,114 @@ int ir_decode_biphase(u32 *samples, int 
 	return value;
 }
 
+/* RC5 decoding stuff, moved from bttv-input.c to share it with
+ * saa7134 */
+
+
+/* decode raw bit pattern to RC5 code */
+u32 ir_rc5_decode(unsigned int code)
+{
+	unsigned int org_code = code;
+	unsigned int pair;
+	unsigned int rc5 = 0;
+	int i;
+
+	for (i = 0; i < 14; ++i) {
+		pair = code & 0x3;
+		code >>= 2;
+
+		rc5 <<= 1;
+		switch (pair) {
+		case 0:
+		case 2:
+			break;
+		case 1:
+			rc5 |= 1;
+			break;
+		case 3:
+			printk("ir-common: ir_rc5_decode(%x) bad code\n", org_code);
+			return 0;
+		}
+	}
+	printk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+		"instr=%x\n", rc5, org_code, RC5_START(rc5),
+		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+	return rc5;
+}
+
+
+void ir_rc5_timer_end(unsigned long data)
+{
+	struct card_ir *ir = (struct card_ir *)data;
+	struct timeval tv;
+	unsigned long current_jiffies, timeout;
+	u32 gap;
+	u32 rc5 = 0;
+
+	/* get time */
+	current_jiffies = jiffies;
+	do_gettimeofday(&tv);
+
+	/* avoid overflow with gap >1s */
+	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+		gap = 200000;
+	} else {
+		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+		    tv.tv_usec - ir->base_time.tv_usec;
+	}
+
+	/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
+	if (gap < 28000) {
+		printk("spurious timer_end\n");
+		return;
+	}
+
+	ir->active = 0;
+	if (ir->last_bit < 20) {
+		/* ignore spurious codes (caused by light/other remotes) */
+		printk("short code: %x\n", ir->code);
+	} else {
+		ir->code = (ir->code << ir->shift_by) | 1;
+		rc5 = ir_rc5_decode(ir->code);
+
+		/* two start bits? */
+		if (RC5_START(rc5) != ir->start) {
+			printk("rc5 start bits invalid: %u\n", RC5_START(rc5));
+
+			/* right address? */
+		} else if (RC5_ADDR(rc5) == ir->addr) {
+			u32 toggle = RC5_TOGGLE(rc5);
+			u32 instr = RC5_INSTR(rc5);
+
+			/* Good code, decide if repeat/repress */
+			if (toggle != RC5_TOGGLE(ir->last_rc5) ||
+			    instr != RC5_INSTR(ir->last_rc5)) {
+				printk("instruction %x, toggle %x\n", instr,
+					toggle);
+				ir_input_nokey(ir->dev, &ir->ir);
+				ir_input_keydown(ir->dev, &ir->ir, instr,
+						 instr);
+			}
+
+			/* Set/reset key-up timer */
+			timeout = current_jiffies + (500 + ir->rc5_key_timeout
+						     * HZ) / 1000;
+			mod_timer(&ir->timer_keyup, timeout);
+
+			/* Save code for repeat test */
+			ir->last_rc5 = rc5;
+		}
+	}
+}
+
+void ir_rc5_timer_keyup(unsigned long data)
+{
+	struct card_ir *ir = (struct card_ir *)data;
+
+	printk("key released\n");
+	ir_input_nokey(ir->dev, &ir->ir);
+}
+
 EXPORT_SYMBOL_GPL(ir_input_init);
 EXPORT_SYMBOL_GPL(ir_input_nokey);
 EXPORT_SYMBOL_GPL(ir_input_keydown);
@@ -271,6 +379,10 @@ EXPORT_SYMBOL_GPL(ir_dump_samples);
 EXPORT_SYMBOL_GPL(ir_dump_samples);
 EXPORT_SYMBOL_GPL(ir_decode_biphase);
 EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
+
+EXPORT_SYMBOL_GPL(ir_rc5_decode);
+EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
+EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
 
 /*
  * Local variables:
diff -r 12f0f1ce18b1 linux/drivers/media/common/ir-keymaps.c
--- a/linux/drivers/media/common/ir-keymaps.c	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/common/ir-keymaps.c	Thu Sep 28 22:28:14 2006 +0200
@@ -1595,3 +1595,57 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTA
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_norwood);
+
+/*
+ * Marc Fargas <telenieko@xxxxxxxxxxxxx> 
+ * this is the remote control that comes with the asus p7131
+ * which has a label saying is "Model PC-39"
+ */
+IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = {
+ 	/* Keys 0 to 9 */
+ 	[ 0x15 ] = KEY_0,
+ 	[ 0x29 ] = KEY_1,
+ 	[ 0x2d ] = KEY_2,
+ 	[ 0x2b ] = KEY_3,
+ 	[ 0x09 ] = KEY_4,
+ 	[ 0x0d ] = KEY_5,
+ 	[ 0x0b ] = KEY_6,
+ 	[ 0x31 ] = KEY_7,
+ 	[ 0x35 ] = KEY_8,
+ 	[ 0x33 ] = KEY_9,
+ 
+ 	[ 0x3e ] = KEY_RADIO,		/* radio */
+ 	[ 0x03 ] = KEY_MENU,		/* dvd/menu */
+ 	[ 0x2a ] = KEY_VOLUMEUP,
+ 	[ 0x19 ] = KEY_VOLUMEDOWN,
+ 	[ 0x37 ] = KEY_UP,
+ 	[ 0x3b ] = KEY_DOWN,
+	[ 0x27 ] = KEY_LEFT,
+ 	[ 0x2f ] = KEY_RIGHT,
+ 	[ 0x25 ] = KEY_VIDEO,		/* video */
+ 	[ 0x39 ] = KEY_AUDIO,		/* music */
+ 
+ 	[ 0x21 ] = KEY_TV,		/* tv */
+ 	[ 0x1d ] = KEY_EXIT,		/* back */
+ 	[ 0x0a ] = KEY_CHANNELUP,	/* channel / program + */
+ 	[ 0x1b ] = KEY_CHANNELDOWN,	/* channel / program - */
+ 	[ 0x1a ] = KEY_ENTER,		/* enter */
+ 
+ 	[ 0x06 ] = KEY_PAUSE,		/* play/pause */
+ 	[ 0x1e ] = KEY_PREVIOUS,	/* rew */
+ 	[ 0x26 ] = KEY_NEXT,		/* forward */
+ 	[ 0x0e ] = KEY_REWIND,		/* backward << */
+ 	[ 0x3a ] = KEY_FASTFORWARD,	/* forward >> */
+ 	[ 0x36 ] = KEY_STOP,
+ 	[ 0x2e ] = KEY_RECORD,		/* recording */
+ 	[ 0x16 ] = KEY_POWER,		/* the button that reads "close" */
+ 
+ 	[ 0x11 ] = KEY_ZOOM,		/* full screen */
+ 	[ 0x13 ] = KEY_MACRO,		/* recall */
+ 	[ 0x23 ] = KEY_HOME,		/* home */
+ 	[ 0x05 ] = KEY_PVR,		/* picture */
+ 	[ 0x3d ] = KEY_MUTE,		/* mute */
+ 	[ 0x01 ] = KEY_DVD,		/* dvd */
+};
+ 
+EXPORT_SYMBOL_GPL(ir_codes_asus_pc39);
diff -r 12f0f1ce18b1 linux/drivers/media/video/bt8xx/bttv-input.c
--- a/linux/drivers/media/video/bt8xx/bttv-input.c	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/video/bt8xx/bttv-input.c	Thu Sep 28 22:28:14 2006 +0200
@@ -37,13 +37,18 @@ static int repeat_period = 33;
 static int repeat_period = 33;
 module_param(repeat_period, int, 0644);
 
+int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+int ir_rc5_key_timeout = 200;
+module_param(ir_rc5_key_timeout, int, 0644);
+
 #define DEVNAME "bttv-input"
 
 /* ---------------------------------------------------------------------- */
 
 static void ir_handle_key(struct bttv *btv)
 {
-	struct bttv_ir *ir = btv->remote;
+	struct card_ir *ir = btv->remote;
 	u32 gpio,data;
 
 	/* read gpio value */
@@ -73,7 +78,7 @@ static void ir_handle_key(struct bttv *b
 
 void bttv_input_irq(struct bttv *btv)
 {
-	struct bttv_ir *ir = btv->remote;
+	struct card_ir *ir = btv->remote;
 
 	if (!ir->polling)
 		ir_handle_key(btv);
@@ -82,7 +87,7 @@ static void bttv_input_timer(unsigned lo
 static void bttv_input_timer(unsigned long data)
 {
 	struct bttv *btv = (struct bttv*)data;
-	struct bttv_ir *ir = btv->remote;
+	struct card_ir *ir = btv->remote;
 	unsigned long timeout;
 
 	ir_handle_key(btv);
@@ -92,51 +97,9 @@ static void bttv_input_timer(unsigned lo
 
 /* ---------------------------------------------------------------*/
 
-static int rc5_remote_gap = 885;
-module_param(rc5_remote_gap, int, 0644);
-static int rc5_key_timeout = 200;
-module_param(rc5_key_timeout, int, 0644);
-
-#define RC5_START(x)	(((x)>>12)&3)
-#define RC5_TOGGLE(x)	(((x)>>11)&1)
-#define RC5_ADDR(x)	(((x)>>6)&31)
-#define RC5_INSTR(x)	((x)&63)
-
-/* decode raw bit pattern to RC5 code */
-static u32 rc5_decode(unsigned int code)
-{
-	unsigned int org_code = code;
-	unsigned int pair;
-	unsigned int rc5 = 0;
-	int i;
-
-	code = (code << 1) | 1;
-	for (i = 0; i < 14; ++i) {
-		pair = code & 0x3;
-		code >>= 2;
-
-		rc5 <<= 1;
-		switch (pair) {
-		case 0:
-		case 2:
-			break;
-		case 1:
-			rc5 |= 1;
-			break;
-		case 3:
-			dprintk(KERN_WARNING "bad code: %x\n", org_code);
-			return 0;
-		}
-	}
-	dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
-		"instr=%x\n", rc5, org_code, RC5_START(rc5),
-		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
-	return rc5;
-}
-
 static int bttv_rc5_irq(struct bttv *btv)
 {
-	struct bttv_ir *ir = btv->remote;
+	struct card_ir *ir = btv->remote;
 	struct timeval tv;
 	u32 gpio;
 	u32 gap;
@@ -166,8 +129,8 @@ static int bttv_rc5_irq(struct bttv *btv
 		/* only if in the code (otherwise spurious IRQ or timer
 		   late) */
 		if (ir->last_bit < 28) {
-			ir->last_bit = (gap - rc5_remote_gap / 2) /
-			    rc5_remote_gap;
+			ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+			    ir_rc5_remote_gap;
 			ir->code |= 1 << ir->last_bit;
 		}
 		/* starting new code */
@@ -187,82 +150,11 @@ static int bttv_rc5_irq(struct bttv *btv
 	return 1;
 }
 
-
-static void bttv_rc5_timer_end(unsigned long data)
-{
-	struct bttv_ir *ir = (struct bttv_ir *)data;
-	struct timeval tv;
-	unsigned long current_jiffies, timeout;
-	u32 gap;
-
-	/* get time */
-	current_jiffies = jiffies;
-	do_gettimeofday(&tv);
-
-	/* avoid overflow with gap >1s */
-	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
-		gap = 200000;
-	} else {
-		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
-		    tv.tv_usec - ir->base_time.tv_usec;
-	}
-
-	/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
-	if (gap < 28000) {
-		dprintk(KERN_WARNING "spurious timer_end\n");
-		return;
-	}
-
-	ir->active = 0;
-	if (ir->last_bit < 20) {
-		/* ignore spurious codes (caused by light/other remotes) */
-		dprintk(KERN_WARNING "short code: %x\n", ir->code);
-	} else {
-		u32 rc5 = rc5_decode(ir->code);
-
-		/* two start bits? */
-		if (RC5_START(rc5) != 3) {
-			dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5));
-
-			/* right address? */
-		} else if (RC5_ADDR(rc5) == 0x0) {
-			u32 toggle = RC5_TOGGLE(rc5);
-			u32 instr = RC5_INSTR(rc5);
-
-			/* Good code, decide if repeat/repress */
-			if (toggle != RC5_TOGGLE(ir->last_rc5) ||
-			    instr != RC5_INSTR(ir->last_rc5)) {
-				dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr,
-					toggle);
-				ir_input_nokey(ir->dev, &ir->ir);
-				ir_input_keydown(ir->dev, &ir->ir, instr,
-						 instr);
-			}
-
-			/* Set/reset key-up timer */
-			timeout = current_jiffies + (500 + rc5_key_timeout
-						     * HZ) / 1000;
-			mod_timer(&ir->timer_keyup, timeout);
-
-			/* Save code for repeat test */
-			ir->last_rc5 = rc5;
-		}
-	}
-}
-
-static void bttv_rc5_timer_keyup(unsigned long data)
-{
-	struct bttv_ir *ir = (struct bttv_ir *)data;
-
-	dprintk(KERN_DEBUG "key released\n");
-	ir_input_nokey(ir->dev, &ir->ir);
-}
-
 /* ---------------------------------------------------------------------- */
 
 int bttv_input_init(struct bttv *btv)
 {
-	struct bttv_ir *ir;
+	struct card_ir *ir;
 	IR_KEYTAB_TYPE *ir_codes = NULL;
 	struct input_dev *input_dev;
 	int ir_type = IR_TYPE_OTHER;
@@ -405,12 +297,17 @@ int bttv_input_init(struct bttv *btv)
 	} else if (ir->rc5_gpio) {
 		/* set timer_end for code completion */
 		init_timer(&ir->timer_end);
-		ir->timer_end.function = bttv_rc5_timer_end;
+		ir->timer_end.function = ir_rc5_timer_end;
 		ir->timer_end.data = (unsigned long)ir;
 
 		init_timer(&ir->timer_keyup);
-		ir->timer_keyup.function = bttv_rc5_timer_keyup;
+		ir->timer_keyup.function = ir_rc5_timer_keyup;
 		ir->timer_keyup.data = (unsigned long)ir;
+		ir->shift_by = 1;
+		ir->start = 3;
+		ir->addr = 0x0;
+		ir->rc5_key_timeout = ir_rc5_key_timeout;
+		ir->rc5_remote_gap = ir_rc5_remote_gap;
 	}
 
 	/* all done */
diff -r 12f0f1ce18b1 linux/drivers/media/video/bt8xx/bttv.h
--- a/linux/drivers/media/video/bt8xx/bttv.h	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/video/bt8xx/bttv.h	Thu Sep 28 22:28:14 2006 +0200
@@ -198,33 +198,6 @@ struct bttv;
 struct bttv;
 
 
-struct bttv_ir {
-	struct input_dev        *dev;
-	struct ir_input_state   ir;
-	char                    name[32];
-	char                    phys[32];
-
-	/* Usual gpio signalling */
-
-	u32                     mask_keycode;
-	u32                     mask_keydown;
-	u32                     mask_keyup;
-	u32                     polling;
-	u32                     last_gpio;
-	struct work_struct      work;
-	struct timer_list       timer;
-
-	/* RC5 gpio */
-	u32 rc5_gpio;
-	struct timer_list timer_end;	/* timer_end for code completion */
-	struct timer_list timer_keyup;	/* timer_end for key release */
-	u32 last_rc5;			/* last good rc5 code */
-	u32 last_bit;			/* last raw bit seen */
-	u32 code;			/* raw code under construction */
-	struct timeval base_time;	/* time of last seen code */
-	int active;			/* building raw code */
-};
-
 struct tvcard
 {
 	char *name;
diff -r 12f0f1ce18b1 linux/drivers/media/video/bt8xx/bttvp.h
--- a/linux/drivers/media/video/bt8xx/bttvp.h	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/video/bt8xx/bttvp.h	Thu Sep 28 22:28:14 2006 +0200
@@ -322,7 +322,7 @@ struct bttv {
 
 	/* infrared remote */
 	int has_remote;
-	struct bttv_ir *remote;
+	struct card_ir *remote;
 
 	/* locking */
 	spinlock_t s_lock;
diff -r 12f0f1ce18b1 linux/drivers/media/video/saa7134/saa7134-cards.c
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c	Thu Sep 28 22:28:14 2006 +0200
@@ -3775,6 +3775,7 @@ int saa7134_board_init1(struct saa7134_d
 	case SAA7134_BOARD_KWORLD_TERMINATOR:
 	case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
 	case SAA7134_BOARD_FLYDVBT_LR301:
+	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
 	case SAA7134_BOARD_FLYDVBTDUO:
 	case SAA7134_BOARD_PROTEUS_2309:
 		dev->has_remote = SAA7134_REMOTE_GPIO;
diff -r 12f0f1ce18b1 linux/drivers/media/video/saa7134/saa7134-input.c
--- a/linux/drivers/media/video/saa7134/saa7134-input.c	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/video/saa7134/saa7134-input.c	Thu Sep 28 22:28:14 2006 +0200
@@ -42,16 +42,24 @@ module_param(pinnacle_remote, int, 0644)
 module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
 MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
 
+int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+int ir_rc5_key_timeout = 50;
+module_param(ir_rc5_key_timeout, int, 0644);
+
 #define dprintk(fmt, arg...)	if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
 
+/** rc5 functions */
+static int saa7134_rc5_irq(struct saa7134_dev *btv);
+
 /* -------------------- GPIO generic keycode builder -------------------- */
 
 static int build_key(struct saa7134_dev *dev)
 {
-	struct saa7134_ir *ir = dev->remote;
+	struct card_ir *ir = dev->remote;
 	u32 gpio, data;
 
 	/* rising SAA7134_GPIO_GPRESCAN reads the status */
@@ -115,16 +123,19 @@ static int get_key_purpletv(struct IR_i2
 
 void saa7134_input_irq(struct saa7134_dev *dev)
 {
-	struct saa7134_ir *ir = dev->remote;
-
-	if (!ir->polling)
+	struct card_ir *ir = dev->remote;
+        
+	if (!ir->polling && !ir->rc5_gpio) {
 		build_key(dev);
+	} else if (ir->rc5_gpio) {
+		saa7134_rc5_irq(dev);
+	}
 }
 
 static void saa7134_input_timer(unsigned long data)
 {
 	struct saa7134_dev *dev = (struct saa7134_dev*)data;
-	struct saa7134_ir *ir = dev->remote;
+	struct card_ir *ir = dev->remote;
 	unsigned long timeout;
 
 	build_key(dev);
@@ -134,13 +145,14 @@ static void saa7134_input_timer(unsigned
 
 int saa7134_input_init1(struct saa7134_dev *dev)
 {
-	struct saa7134_ir *ir;
+	struct card_ir *ir;
 	struct input_dev *input_dev;
 	IR_KEYTAB_TYPE *ir_codes = NULL;
 	u32 mask_keycode = 0;
 	u32 mask_keydown = 0;
 	u32 mask_keyup   = 0;
 	int polling      = 0;
+	int rc5_gpio	 = 0;
 	int ir_type      = IR_TYPE_OTHER;
 
 	if (dev->has_remote != SAA7134_REMOTE_GPIO)
@@ -248,6 +260,11 @@ int saa7134_input_init1(struct saa7134_d
 		mask_keycode = 0x0001F00;
 		mask_keydown = 0x0040000;
 		break;
+	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+		ir_codes     = ir_codes_asus_pc39;
+		mask_keydown = 0x0040000;
+		rc5_gpio = 1;
+		break;
 	}
 	if (NULL == ir_codes) {
 		printk("%s: Oops: IR config error [card=%d]\n",
@@ -270,6 +287,7 @@ int saa7134_input_init1(struct saa7134_d
 	ir->mask_keydown = mask_keydown;
 	ir->mask_keyup   = mask_keyup;
 	ir->polling      = polling;
+	ir->rc5_gpio	 = rc5_gpio;
 
 	/* init input device */
 	snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
@@ -297,16 +315,31 @@ int saa7134_input_init1(struct saa7134_d
 #endif
 #endif
 
-	/* all done */
-	dev->remote = ir;
+
 	if (ir->polling) {
 		init_timer(&ir->timer);
 		ir->timer.function = saa7134_input_timer;
 		ir->timer.data     = (unsigned long)dev;
 		ir->timer.expires  = jiffies + HZ;
 		add_timer(&ir->timer);
-	}
-
+	} else if (ir->rc5_gpio) {
+		/* set timer_end for code completion */
+		init_timer(&ir->timer_end);
+		ir->timer_end.function = ir_rc5_timer_end;
+		ir->timer_end.data = (unsigned long)ir;
+		init_timer(&ir->timer_keyup);
+		ir->timer_keyup.function = ir_rc5_timer_keyup;
+		ir->timer_keyup.data = (unsigned long)ir;
+		ir->shift_by = 2;
+		ir->start = 0x2;
+		ir->addr = 0x17;
+		ir->rc5_key_timeout = ir_rc5_key_timeout;
+		ir->rc5_remote_gap = ir_rc5_remote_gap;
+	}
+
+	/* all done */
+	dev->remote = ir;
+	
 	input_register_device(ir->dev);
 	return 0;
 }
@@ -353,6 +386,49 @@ void saa7134_set_i2c_ir(struct saa7134_d
 	}
 
 }
+
+static int saa7134_rc5_irq(struct saa7134_dev *btv)
+{
+	struct card_ir *ir = btv->remote;
+	struct timeval tv;
+	u32 gap;
+	unsigned long current_jiffies, timeout;
+
+	/* get time of bit */
+	current_jiffies = jiffies;
+	do_gettimeofday(&tv);
+
+	/* avoid overflow with gap >1s */
+	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+		gap = 200000;
+	} else {
+		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+		    tv.tv_usec - ir->base_time.tv_usec;
+	}
+
+	/* active code => add bit */
+	if (ir->active) {
+		/* only if in the code (otherwise spurious IRQ or timer
+		   late) */
+		if (ir->last_bit < 28) {
+			ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+			    ir_rc5_remote_gap;
+			ir->code |= 1 << ir->last_bit;
+		}
+		/* starting new code */
+	} else {
+		ir->active = 1;
+		ir->code = 0;
+		ir->base_time = tv;
+		ir->last_bit = 0;
+
+		timeout = current_jiffies + (500 + 30 * HZ) / 1000;
+		mod_timer(&ir->timer_end, timeout);
+	}
+
+	return 1;
+}
+
 /* ----------------------------------------------------------------------
  * Local variables:
  * c-basic-offset: 8
diff -r 12f0f1ce18b1 linux/drivers/media/video/saa7134/saa7134.h
--- a/linux/drivers/media/video/saa7134/saa7134.h	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/drivers/media/video/saa7134/saa7134.h	Thu Sep 28 22:28:14 2006 +0200
@@ -425,20 +425,6 @@ struct saa7134_dmasound {
 #endif
 };
 
-/* IR input */
-struct saa7134_ir {
-	struct input_dev           *dev;
-	struct ir_input_state      ir;
-	char                       name[32];
-	char                       phys[32];
-	u32                        mask_keycode;
-	u32                        mask_keydown;
-	u32                        mask_keyup;
-	int                        polling;
-	u32                        last_gpio;
-	struct timer_list          timer;
-};
-
 /* ts/mpeg status */
 struct saa7134_ts {
 	/* TS capture */
@@ -478,7 +464,7 @@ struct saa7134_dev {
 
 	/* infrared remote */
 	int                        has_remote;
-	struct saa7134_ir          *remote;
+	struct card_ir	           *remote;
 
 	/* pci i/o */
 	char                       name[32];
@@ -715,6 +701,7 @@ void saa7134_input_irq(struct saa7134_de
 void saa7134_input_irq(struct saa7134_dev *dev);
 void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
 
+
 /*
  * Local variables:
  * c-basic-offset: 8
diff -r 12f0f1ce18b1 linux/include/media/ir-common.h
--- a/linux/include/media/ir-common.h	Thu Sep 28 14:03:26 2006 -0300
+++ b/linux/include/media/ir-common.h	Thu Sep 28 22:28:54 2006 +0200
@@ -35,6 +35,14 @@
 #define IR_KEYCODE(tab,code)	(((unsigned)code < IR_KEYTAB_SIZE) \
 				 ? tab[code] : KEY_RESERVED)
 
+extern int ir_rc5_remote_gap;
+extern int ir_rc5_key_timeout;
+
+#define RC5_START(x)	(((x)>>12)&3)
+#define RC5_TOGGLE(x)	(((x)>>11)&1)
+#define RC5_ADDR(x)	(((x)>>6)&31)
+#define RC5_INSTR(x)	((x)&63)
+
 struct ir_input_state {
 	/* configuration */
 	int                ir_type;
@@ -47,6 +55,40 @@ struct ir_input_state {
 	int                keypressed;  /* current state */
 };
 
+/* this was saa7134_ir and bttv_ir, moved here for 
+ * rc5 decoding. */
+struct card_ir {
+	struct input_dev        *dev;
+	struct ir_input_state   ir;
+	char                    name[32];
+	char                    phys[32];
+
+	/* Usual gpio signalling */
+
+	u32                     mask_keycode;
+	u32                     mask_keydown;
+	u32                     mask_keyup;
+	u32                     polling;
+	u32                     last_gpio;
+	int			shift_by;
+	int			start; // What should RC5_START() be
+	int			addr; // What RC5_ADDR() should be.
+	int			rc5_key_timeout; 
+	int			rc5_remote_gap; 
+	struct work_struct      work;
+	struct timer_list       timer;
+
+	/* RC5 gpio */
+	u32 rc5_gpio;
+	struct timer_list timer_end;	/* timer_end for code completion */
+	struct timer_list timer_keyup;	/* timer_end for key release */
+	u32 last_rc5;			/* last good rc5 code */
+	u32 last_bit;			/* last raw bit seen */
+	u32 code;			/* raw code under construction */
+	struct timeval base_time;	/* time of last seen code */
+	int active;			/* building raw code */
+};
+
 void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
 		   int ir_type, IR_KEYTAB_TYPE *ir_codes);
 void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir);
@@ -56,6 +98,10 @@ int  ir_dump_samples(u32 *samples, int c
 int  ir_dump_samples(u32 *samples, int count);
 int  ir_decode_biphase(u32 *samples, int count, int low, int high);
 int  ir_decode_pulsedistance(u32 *samples, int count, int low, int high);
+
+u32 ir_rc5_decode(unsigned int code);
+void ir_rc5_timer_end(unsigned long data);
+void ir_rc5_timer_keyup(unsigned long data);
 
 /* Keymaps to be used by other modules */
 
@@ -92,6 +138,7 @@ extern IR_KEYTAB_TYPE ir_codes_npgtech[I
 extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE];
 
 #endif
 
--
video4linux discussion
Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

[Linux Media]     [Older V4L]     [Linux DVB]     [Video Disk Recorder]     [Linux Kernel]     [Asterisk]     [Photo]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Free Photo Albums]     [Fedora Users]     [Fedora Women]     [ALSA Users]     [ALSA Devel]     [SSH]     [DVB Maintainers]     [Linux USB]     [Yosemite Information]

Add to Google Powered by Linux