All of lore.kernel.org
 help / color / mirror / Atom feed
From: "David Härdeman" <david@hardeman.nu>
To: linux-media@vger.kernel.org
Cc: jwilson@redhat.com, mchehab@redhat.com, sean@mess.org
Subject: [PATCH 5/8] rc-core: use the full 32 bits for NEC scancodes
Date: Sat, 25 Aug 2012 23:47:14 +0200	[thread overview]
Message-ID: <20120825214713.22603.89806.stgit@localhost.localdomain> (raw)
In-Reply-To: <20120825214520.22603.37194.stgit@localhost.localdomain>

Using the full 32 bits for all kinds of NEC scancodes simplifies rc-core
and the nec decoder without any loss of functionality.

In order to maintain backwards compatibility, some heuristics are added
in rc-main.c to convert scancodes to NEC32 as necessary. No conversion
is made for the newer "rc_keymap_entry" based ioctls.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/ir-nec-decoder.c       |   28 +++---------------------
 drivers/media/rc/rc-main.c              |   36 ++++++++++++++++++++++++++++++-
 drivers/media/usb/dvb-usb-v2/af9015.c   |   22 +++++--------------
 drivers/media/usb/dvb-usb-v2/az6007.c   |   16 +++-----------
 drivers/media/usb/dvb-usb-v2/it913x.c   |   15 +++++--------
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c |   21 +++---------------
 include/media/rc-map.h                  |   11 ++++++++-
 7 files changed, 68 insertions(+), 81 deletions(-)

diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 61fa889..0b98f8f 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -50,7 +50,6 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct nec_dec *data = &dev->raw->nec;
 	u32 scancode;
 	u8 address, not_address, command, not_command;
-	bool send_32bits = false;
 
 	if (!(dev->enabled_protocols & RC_BIT_NEC))
 		return 0;
@@ -163,33 +162,14 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 		command	    = bitrev8((data->bits >>  8) & 0xff);
 		not_command = bitrev8((data->bits >>  0) & 0xff);
 
-		if ((command ^ not_command) != 0xff) {
-			IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
-				   data->bits);
-			send_32bits = true;
-		}
-
-		if (send_32bits) {
-			/* NEC transport, but modified protocol, used by at
-			 * least Apple and TiVo remotes */
-			scancode = data->bits;
-			IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode);
-		} else if ((address ^ not_address) != 0xff) {
-			/* Extended NEC */
-			scancode = address     << 16 |
-				   not_address <<  8 |
-				   command;
-			IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
-		} else {
-			/* Normal NEC */
-			scancode = address << 8 | command;
-			IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
-		}
+		scancode = address << 24 | not_address << 16 |
+			   command << 8  | not_command;
+		IR_dprintk(1, "NEC scancode 0x%08x\n", scancode);
 
 		if (data->is_nec_x)
 			data->necx_repeat = true;
 
-		rc_keydown(dev, RC_TYPE_NEC, scancode, 0);
+		rc_keydown(dev, RC_TYPE_NEC, RC_SCANCODE_NEC32(scancode), 0);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index b111500..d29818c 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -324,6 +324,30 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev,
 }
 
 /**
+ * to_nec32() - helper function to try to convert misc NEC scancodes to NEC32
+ * @orig:	original scancode
+ * @return:	NEC32 scancode
+ *
+ * This helper routine is used to provide backwards compatibility.
+ */
+static u64 to_nec32(u64 orig)
+{
+	u8 b3 = (u8)(orig >> 16);
+	u8 b2 = (u8)(orig >>  8);
+	u8 b1 = (u8)(orig >>  0);
+
+	if (orig <= 0xffff)
+		/* Plain old NEC */
+		return b2 << 24 | ((u8)~b2) << 16 |  b1 << 8 | ((u8)~b1);
+	else if (orig <= 0xffffff)
+		/* NEC extended */
+		return b3 << 24 | b2 << 16 |  b1 << 8 | ((u8)~b1);
+	else
+		/* NEC32 */
+		return orig;
+}
+
+/**
  * ir_setkeycode() - set a keycode in the scancode->keycode table
  * @idev:	the struct input_dev device descriptor
  * @scancode:	the desired scancode
@@ -371,6 +395,9 @@ static int ir_setkeycode(struct input_dev *idev,
 		else
 			entry.protocol = RC_TYPE_OTHER;
 
+		if (entry.protocol == RC_TYPE_NEC)
+			entry.scancode = to_nec32(entry.scancode);
+
 		index = ir_establish_scancode(rdev, rc_map, &entry, true);
 		if (index >= rc_map->len) {
 			retval = -ENOMEM;
@@ -430,8 +457,12 @@ static int ir_setkeytable(struct rc_dev *dev,
 		   rc_map->size, rc_map->alloc);
 
 	for (i = 0; i < from->size; i++) {
+		if (from->rc_type == RC_TYPE_NEC)
+			entry.scancode = to_nec32(from->scan[i].scancode);
+		else
+			entry.scancode = from->scan[i].scancode;
+
 		entry.protocol = from->rc_type;
-		entry.scancode = from->scan[i].scancode;
 		index = ir_establish_scancode(dev, rc_map, &entry, false);
 		if (index >= rc_map->len) {
 			rc = -ENOMEM;
@@ -527,6 +558,9 @@ static int ir_getkeycode(struct input_dev *idev,
 		else
 			protocol = RC_TYPE_OTHER;
 
+		if (protocol == RC_TYPE_NEC)
+			scancode = to_nec32(scancode);
+
 		index = ir_lookup_by_scancode(rc_map, protocol, scancode);
 
 	} else if (ke->len == sizeof(struct rc_scancode)) {
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c
index 6a32274..330ae5e 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -1192,7 +1192,8 @@ static int af9015_rc_query(struct dvb_usb_device *d)
 	if ((state->rc_repeat != buf[6] || buf[0]) &&
 			!memcmp(&buf[12], state->rc_last, 4)) {
 		deb_rc("%s: key repeated\n", __func__);
-		rc_keydown(d->rc_dev, RC_TYPE_NEC, state->rc_keycode, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC,
+			   RC_SCANCODE_NEC32(state->rc_keycode), 0);
 		state->rc_repeat = buf[6];
 		return ret;
 	}
@@ -1208,21 +1209,10 @@ static int af9015_rc_query(struct dvb_usb_device *d)
 
 		/* Remember this key */
 		memcpy(state->rc_last, &buf[12], 4);
-		if (buf[14] == (u8) ~buf[15]) {
-			if (buf[12] == (u8) ~buf[13]) {
-				/* NEC */
-				state->rc_keycode = buf[12] << 8 | buf[14];
-			} else {
-				/* NEC extended*/
-				state->rc_keycode = buf[12] << 16 |
-					buf[13] << 8 | buf[14];
-			}
-		} else {
-			/* 32 bit NEC */
-			state->rc_keycode = buf[12] << 24 | buf[13] << 16 |
-					buf[14] << 8 | buf[15];
-		}
-		rc_keydown(d->rc_dev, RC_TYPE_NEC, state->rc_keycode, 0);
+		state->rc_keycode = buf[12] << 24 | buf[13] << 16 |
+				    buf[14] << 8  | buf[15];
+		rc_keydown(d->rc_dev, RC_TYPE_NEC,
+			   RC_SCANCODE_NEC32(state->rc_keycode), 0);
 	} else {
 		deb_rc("%s: no key press\n", __func__);
 		/* Invalidate last keypress */
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
index d3e6922..488fe68 100644
--- a/drivers/media/usb/dvb-usb-v2/az6007.c
+++ b/drivers/media/usb/dvb-usb-v2/az6007.c
@@ -200,18 +200,10 @@ static int az6007_rc_query(struct dvb_usb_device *d)
 	if (st->data[1] == 0x44)
 		return 0;
 
-	if ((st->data[3] ^ st->data[4]) == 0xff) {
-		if ((st->data[1] ^ st->data[2]) == 0xff)
-			code = RC_SCANCODE_NEC(st->data[1], st->data[3]);
-		else
-			code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2],
-						st->data[3]);
-	} else {
-		code = RC_SCANCODE_NEC32(st->data[1] << 24 |
-					 st->data[2] << 16 |
-					 st->data[3] << 8  |
-					 st->data[4]);
-	}
+	code = RC_SCANCODE_NEC32(st->data[1] << 24 |
+				 st->data[2] << 16 |
+				 st->data[3] << 8  |
+				 st->data[4]);
 
 	rc_keydown(d->rc_dev, RC_TYPE_NEC, code, st->data[5]);
 
diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c
index f23c5b7..951d151 100644
--- a/drivers/media/usb/dvb-usb-v2/it913x.c
+++ b/drivers/media/usb/dvb-usb-v2/it913x.c
@@ -313,7 +313,6 @@ static int it913x_rc_query(struct dvb_usb_device *d)
 {
 	u8 ibuf[4];
 	int ret;
-	u16 device, command;
 	u64 scancode;
 
 	if (!d->rc_dev)
@@ -325,14 +324,12 @@ static int it913x_rc_query(struct dvb_usb_device *d)
 	ret = it913x_io(d, READ_LONG, PRO_LINK, CMD_IR_GET,
 		0, 0, &ibuf[0], sizeof(ibuf));
 
-	if ((ibuf[2] + ibuf[3]) == 0xff) {
-		command = ibuf[2];
-		device = (ibuf[0] << 8) | ibuf[1];
-		scancode = RC_SCANCODE_NECX(device, command);
-		deb_info(1, "NEC Extended Key = 0x%08llx",
-			 (unsigned long long)scancode);
-		rc_keydown(d->rc_dev, RC_TYPE_NEC, scancode, 0);
-	}
+	scancode = RC_SCANCODE_NEC32(ibuf[0] << 24 |
+				     ibuf[1] << 16 |
+				     ibuf[2] <<  8 |
+				     ibuf[3] <<  0);
+	deb_info(1, "NEC32 Key = 0x%08llx", (unsigned long long)scancode);
+	rc_keydown(d->rc_dev, RC_TYPE_NEC, scancode, 0);
 
 	mutex_unlock(&d->i2c_mutex);
 
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 887d0f5..7f80f61 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1062,23 +1062,10 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
 		goto err;
 
 	if (buf[4] & 0x01) {
-		if (buf[2] == (u8) ~buf[3]) {
-			if (buf[0] == (u8) ~buf[1]) {
-				/* NEC standard (16 bit) */
-				rc_code = RC_SCANCODE_NEC(buf[0], buf[2]);
-			} else {
-				/* NEC extended (24 bit) */
-				rc_code = RC_SCANCODE_NECX(buf[0] << 8 |
-							   buf[1],
-							   buf[2]);
-			}
-		} else {
-			/* NEC full (32 bit) */
-			rc_code = RC_SCANCODE_NEC32(buf[0] << 24 |
-						    buf[1] << 16 |
-						    buf[2] << 8  |
-						    buf[3]);
-		}
+		rc_code = RC_SCANCODE_NEC32(buf[0] << 24 |
+					    buf[1] << 16 |
+					    buf[2] << 8  |
+					    buf[3]);
 
 		rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0);
 
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 88a1c4e..b497608 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -62,8 +62,15 @@ enum rc_type {
 
 #define RC_SCANCODE_UNKNOWN(x) (x)
 #define RC_SCANCODE_OTHER(x) (x)
-#define RC_SCANCODE_NEC(addr, cmd) (((addr) << 8) | (cmd))
-#define RC_SCANCODE_NECX(addr, cmd) (((addr) << 8) | (cmd))
+#define RC_SCANCODE_NEC(addr, cmd)  \
+	((( (addr) & 0xff) << 24) | \
+	 ((~(addr) & 0xff) << 16) | \
+	 (( (cmd)  & 0xff) << 8 ) | \
+	 ((~(cmd)  & 0xff) << 0 ))
+#define RC_SCANCODE_NECX(addr, cmd)   \
+	((( (addr) & 0xffff) << 16) | \
+	 (( (cmd)  & 0x00ff) << 8)  | \
+	 ((~(cmd)  & 0x00ff) << 0))
 #define RC_SCANCODE_NEC32(data) ((data) & 0xffffffff)
 #define RC_SCANCODE_RC5(sys, cmd) (((sys) << 8) | (cmd))
 #define RC_SCANCODE_RC5_SZ(sys, cmd) (((sys) << 8) | (cmd))


  parent reply	other threads:[~2012-08-25 21:47 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
2012-08-25 21:46 ` [PATCH 1/8] winbond-cir: correctness fix David Härdeman
2012-08-25 21:46 ` [PATCH 2/8] winbond-cir: asynchronous tx David Härdeman
2012-08-25 21:47 ` [PATCH 3/8] rc-core: add separate defines for protocol bitmaps and numbers David Härdeman
2012-09-25 20:19   ` Mauro Carvalho Chehab
2012-08-25 21:47 ` [PATCH 4/8] rc-core: don't throw away protocol information David Härdeman
2012-09-25 18:40   ` Mauro Carvalho Chehab
2012-08-25 21:47 ` David Härdeman [this message]
2012-08-25 21:47 ` [PATCH 6/8] rc-core: merge rc5 and streamzap decoders David Härdeman
2012-08-25 21:47 ` [PATCH 7/8] rc-core: rename ir_input_class to rc_class David Härdeman
2012-08-25 21:47 ` [PATCH 8/8] rc-core: initialize rc-core earlier if built-in David Härdeman
2012-08-30 19:56 ` [PATCH 0/8] rc-core: patches for 3.7 Jarod Wilson
2012-09-03 21:55   ` David Härdeman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120825214713.22603.89806.stgit@localhost.localdomain \
    --to=david@hardeman.nu \
    --cc=jwilson@redhat.com \
    --cc=linux-media@vger.kernel.org \
    --cc=mchehab@redhat.com \
    --cc=sean@mess.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.