linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] rc-core: patches for 3.7
@ 2012-08-25 21:46 David Härdeman
  2012-08-25 21:46 ` [PATCH 1/8] winbond-cir: correctness fix David Härdeman
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:46 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

This is two minor winbond-cir fixes as well as the first six patches
from my previous patchbomb.

The latter have been modified so that backwards compatibility is retained
as much as possible (the format of the sysfs files do not change for
example).

---

David Härdeman (8):
      winbond-cir: correctness fix
      winbond-cir: asynchronous tx
      rc-core: add separate defines for protocol bitmaps and numbers
      rc-core: don't throw away protocol information
      rc-core: use the full 32 bits for NEC scancodes
      rc-core: merge rc5 and streamzap decoders
      rc-core: rename ir_input_class to rc_class
      rc-core: initialize rc-core earlier if built-in


 drivers/media/common/siano/smsir.c           |    2 
 drivers/media/i2c/ir-kbd-i2c.c               |   26 +-
 drivers/media/pci/bt8xx/bttv-input.c         |   15 +
 drivers/media/pci/cx18/cx18-i2c.c            |    2 
 drivers/media/pci/cx23885/cx23885-input.c    |    6 
 drivers/media/pci/cx88/cx88-input.c          |   18 +
 drivers/media/pci/dm1105/dm1105.c            |    3 
 drivers/media/pci/ivtv/ivtv-i2c.c            |    8 -
 drivers/media/pci/saa7134/saa7134-input.c    |    8 -
 drivers/media/pci/ttpci/budget-ci.c          |    7 -
 drivers/media/rc/Kconfig                     |   12 -
 drivers/media/rc/Makefile                    |    1 
 drivers/media/rc/ati_remote.c                |   15 +
 drivers/media/rc/ene_ir.c                    |    2 
 drivers/media/rc/fintek-cir.c                |    2 
 drivers/media/rc/gpio-ir-recv.c              |    2 
 drivers/media/rc/iguanair.c                  |    2 
 drivers/media/rc/imon.c                      |   50 ++--
 drivers/media/rc/ir-jvc-decoder.c            |    6 
 drivers/media/rc/ir-lirc-codec.c             |    4 
 drivers/media/rc/ir-mce_kbd-decoder.c        |    4 
 drivers/media/rc/ir-nec-decoder.c            |   32 --
 drivers/media/rc/ir-raw.c                    |    2 
 drivers/media/rc/ir-rc5-decoder.c            |   64 +++--
 drivers/media/rc/ir-rc5-sz-decoder.c         |  154 -----------
 drivers/media/rc/ir-rc6-decoder.c            |   54 ++--
 drivers/media/rc/ir-sanyo-decoder.c          |    6 
 drivers/media/rc/ir-sony-decoder.c           |   17 +
 drivers/media/rc/ite-cir.c                   |    2 
 drivers/media/rc/keymaps/rc-imon-mce.c       |    2 
 drivers/media/rc/keymaps/rc-rc6-mce.c        |    2 
 drivers/media/rc/keymaps/rc-streamzap.c      |    4 
 drivers/media/rc/mceusb.c                    |    2 
 drivers/media/rc/nuvoton-cir.c               |    2 
 drivers/media/rc/rc-core-priv.h              |    9 -
 drivers/media/rc/rc-loopback.c               |    2 
 drivers/media/rc/rc-main.c                   |  354 ++++++++++++++++++--------
 drivers/media/rc/redrat3.c                   |    2 
 drivers/media/rc/streamzap.c                 |   12 -
 drivers/media/rc/ttusbir.c                   |    2 
 drivers/media/rc/winbond-cir.c               |   51 +---
 drivers/media/usb/cx231xx/cx231xx-input.c    |    2 
 drivers/media/usb/dvb-usb-v2/af9015.c        |   24 +-
 drivers/media/usb/dvb-usb-v2/af9035.c        |    4 
 drivers/media/usb/dvb-usb-v2/anysee.c        |    5 
 drivers/media/usb/dvb-usb-v2/az6007.c        |   19 +
 drivers/media/usb/dvb-usb-v2/dvb_usb.h       |    2 
 drivers/media/usb/dvb-usb-v2/it913x.c        |   22 +-
 drivers/media/usb/dvb-usb-v2/lmedm04.c       |    4 
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c      |   26 +-
 drivers/media/usb/dvb-usb/dib0700.h          |    2 
 drivers/media/usb/dvb-usb/dib0700_core.c     |   18 +
 drivers/media/usb/dvb-usb/dib0700_devices.c  |  156 ++++++-----
 drivers/media/usb/dvb-usb/dvb-usb.h          |    4 
 drivers/media/usb/dvb-usb/pctv452e.c         |   15 +
 drivers/media/usb/dvb-usb/technisat-usb2.c   |    2 
 drivers/media/usb/dvb-usb/ttusb2.c           |    4 
 drivers/media/usb/em28xx/em28xx-cards.c      |   15 +
 drivers/media/usb/em28xx/em28xx-input.c      |   44 ++-
 drivers/media/usb/em28xx/em28xx.h            |    1 
 drivers/media/usb/hdpvr/hdpvr-i2c.c          |    2 
 drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c |    4 
 drivers/media/usb/tm6000/tm6000-cards.c      |    2 
 drivers/media/usb/tm6000/tm6000-input.c      |   80 ++++--
 include/media/ir-kbd-i2c.h                   |    2 
 include/media/rc-core.h                      |   32 ++
 include/media/rc-map.h                       |   86 +++++-
 67 files changed, 797 insertions(+), 750 deletions(-)
 delete mode 100644 drivers/media/rc/ir-rc5-sz-decoder.c

-- 
David Härdeman

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/8] winbond-cir: correctness fix
  2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
@ 2012-08-25 21:46 ` David Härdeman
  2012-08-25 21:46 ` [PATCH 2/8] winbond-cir: asynchronous tx David Härdeman
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:46 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

This is a minor correctness fix for the duration calculation in
winbond-cir (the read value should be incremented by one).

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/winbond-cir.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 54ee348..29e6769 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -358,7 +358,7 @@ wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device)
 		if (data->rxstate == WBCIR_RXSTATE_ERROR)
 			continue;
 		rawir.pulse = irdata & 0x80 ? false : true;
-		rawir.duration = US_TO_NS((irdata & 0x7F) * 10);
+		rawir.duration = US_TO_NS(((irdata & 0x7F) + 1) * 10);
 		ir_raw_event_store_with_filter(data->dev, &rawir);
 	}
 


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/8] winbond-cir: asynchronous tx
  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 ` David Härdeman
  2012-08-25 21:47 ` [PATCH 3/8] rc-core: add separate defines for protocol bitmaps and numbers David Härdeman
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:46 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

Change winbond-cir's tx support to be asynchronous and not to mess with
the TX buffer. Essentially the winbond-cir counterpart to the patch
Sean Young sent for iguanair.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/winbond-cir.c |   47 +++++++++++++++-------------------------
 1 file changed, 18 insertions(+), 29 deletions(-)

diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 29e6769..30ae1f2 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -180,7 +180,6 @@ enum wbcir_rxstate {
 enum wbcir_txstate {
 	WBCIR_TXSTATE_INACTIVE = 0,
 	WBCIR_TXSTATE_ACTIVE,
-	WBCIR_TXSTATE_DONE,
 	WBCIR_TXSTATE_ERROR
 };
 
@@ -216,7 +215,6 @@ struct wbcir_data {
 	u32 txlen;
 	u32 txoff;
 	u32 *txbuf;
-	wait_queue_head_t txwaitq;
 	u8 txmask;
 	u32 txcarrier;
 };
@@ -424,11 +422,11 @@ wbcir_irq_tx(struct wbcir_data *data)
 		if (data->txstate == WBCIR_TXSTATE_ERROR)
 			/* Clear TX underrun bit */
 			outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR);
-		else
-			data->txstate = WBCIR_TXSTATE_DONE;
 		wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR);
 		led_trigger_event(data->txtrigger, LED_OFF);
-		wake_up(&data->txwaitq);
+		kfree(data->txbuf);
+		data->txbuf = NULL;
+		data->txstate = WBCIR_TXSTATE_INACTIVE;
 	} else if (data->txoff == data->txlen) {
 		/* At the end of transmission, tell the hw before last byte */
 		outsb(data->sbase + WBCIR_REG_SP3_TXDATA, bytes, used - 1);
@@ -579,43 +577,37 @@ wbcir_txmask(struct rc_dev *dev, u32 mask)
 }
 
 static int
-wbcir_tx(struct rc_dev *dev, unsigned *buf, unsigned count)
+wbcir_tx(struct rc_dev *dev, unsigned *b, unsigned count)
 {
 	struct wbcir_data *data = dev->priv;
+	unsigned *buf;
 	unsigned i;
 	unsigned long flags;
 
+	buf = kmalloc(count * sizeof(*b), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Convert values to multiples of 10us */
+	for (i = 0; i < count; i++)
+		buf[i] = DIV_ROUND_CLOSEST(b[i], 10);
+
 	/* Not sure if this is possible, but better safe than sorry */
 	spin_lock_irqsave(&data->spinlock, flags);
 	if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
 		spin_unlock_irqrestore(&data->spinlock, flags);
+		kfree(buf);
 		return -EBUSY;
 	}
 
-	/* Convert values to multiples of 10us */
-	for (i = 0; i < count; i++)
-		buf[i] = DIV_ROUND_CLOSEST(buf[i], 10);
-
 	/* Fill the TX fifo once, the irq handler will do the rest */
 	data->txbuf = buf;
 	data->txlen = count;
 	data->txoff = 0;
 	wbcir_irq_tx(data);
 
-	/* Wait for the TX to complete */
-	while (data->txstate == WBCIR_TXSTATE_ACTIVE) {
-		spin_unlock_irqrestore(&data->spinlock, flags);
-		wait_event(data->txwaitq, data->txstate != WBCIR_TXSTATE_ACTIVE);
-		spin_lock_irqsave(&data->spinlock, flags);
-	}
-
 	/* We're done */
-	if (data->txstate == WBCIR_TXSTATE_ERROR)
-		count = -EAGAIN;
-	data->txstate = WBCIR_TXSTATE_INACTIVE;
-	data->txbuf = NULL;
 	spin_unlock_irqrestore(&data->spinlock, flags);
-
 	return count;
 }
 
@@ -927,13 +919,11 @@ wbcir_init_hw(struct wbcir_data *data)
 	ir_raw_event_reset(data->dev);
 	ir_raw_event_handle(data->dev);
 
-	/*
-	 * Check TX state, if we did a suspend/resume cycle while TX was
-	 * active, we will have a process waiting in txwaitq.
-	 */
+	/* Clear TX state */
 	if (data->txstate == WBCIR_TXSTATE_ACTIVE) {
-		data->txstate = WBCIR_TXSTATE_ERROR;
-		wake_up(&data->txwaitq);
+		kfree(data->txbuf);
+		data->txbuf = NULL;
+		data->txstate = WBCIR_TXSTATE_INACTIVE;
 	}
 
 	/* Enable interrupts */
@@ -974,7 +964,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	pnp_set_drvdata(device, data);
 
 	spin_lock_init(&data->spinlock);
-	init_waitqueue_head(&data->txwaitq);
 	data->ebase = pnp_port_start(device, 0);
 	data->wbase = pnp_port_start(device, 1);
 	data->sbase = pnp_port_start(device, 2);


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/8] rc-core: add separate defines for protocol bitmaps and numbers
  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 ` 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
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:47 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

The RC_TYPE_* defines are currently used both where a single protocol is
expected and where a bitmap of protocols is expected. This patch tries
to separate the two in preparation for the following patches.

The intended use is also clearer to anyone reading the code. Where a
single protocol is expected, enum rc_type is used, where one or more
protocol(s) are expected, something like u64 is used.

The patch has been rewritten so that the format of the sysfs "protocols"
file is no longer altered (at the loss of some detail). The file itself
should probably be deprecated in the future though.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/common/siano/smsir.c           |    2 
 drivers/media/i2c/ir-kbd-i2c.c               |   14 +-
 drivers/media/pci/cx18/cx18-i2c.c            |    2 
 drivers/media/pci/cx23885/cx23885-input.c    |    6 +
 drivers/media/pci/cx88/cx88-input.c          |    8 +
 drivers/media/pci/ivtv/ivtv-i2c.c            |    8 +
 drivers/media/pci/saa7134/saa7134-input.c    |    2 
 drivers/media/rc/ati_remote.c                |    2 
 drivers/media/rc/ene_ir.c                    |    2 
 drivers/media/rc/fintek-cir.c                |    2 
 drivers/media/rc/gpio-ir-recv.c              |    2 
 drivers/media/rc/iguanair.c                  |    2 
 drivers/media/rc/imon.c                      |   40 +++----
 drivers/media/rc/ir-jvc-decoder.c            |    4 -
 drivers/media/rc/ir-lirc-codec.c             |    4 -
 drivers/media/rc/ir-mce_kbd-decoder.c        |    4 -
 drivers/media/rc/ir-nec-decoder.c            |    4 -
 drivers/media/rc/ir-rc5-decoder.c            |   14 ++
 drivers/media/rc/ir-rc5-sz-decoder.c         |    6 +
 drivers/media/rc/ir-rc6-decoder.c            |    8 +
 drivers/media/rc/ir-sanyo-decoder.c          |    4 -
 drivers/media/rc/ir-sony-decoder.c           |   17 +++
 drivers/media/rc/ite-cir.c                   |    2 
 drivers/media/rc/keymaps/rc-imon-mce.c       |    2 
 drivers/media/rc/keymaps/rc-rc6-mce.c        |    2 
 drivers/media/rc/mceusb.c                    |    2 
 drivers/media/rc/nuvoton-cir.c               |    2 
 drivers/media/rc/rc-loopback.c               |    2 
 drivers/media/rc/rc-main.c                   |   73 +++++++------
 drivers/media/rc/redrat3.c                   |    2 
 drivers/media/rc/streamzap.c                 |    2 
 drivers/media/rc/ttusbir.c                   |    2 
 drivers/media/rc/winbond-cir.c               |    2 
 drivers/media/usb/cx231xx/cx231xx-input.c    |    2 
 drivers/media/usb/dvb-usb-v2/af9015.c        |    2 
 drivers/media/usb/dvb-usb-v2/af9035.c        |    4 -
 drivers/media/usb/dvb-usb-v2/anysee.c        |    2 
 drivers/media/usb/dvb-usb-v2/az6007.c        |    2 
 drivers/media/usb/dvb-usb-v2/dvb_usb.h       |    2 
 drivers/media/usb/dvb-usb-v2/it913x.c        |    2 
 drivers/media/usb/dvb-usb-v2/lmedm04.c       |    2 
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c      |    4 -
 drivers/media/usb/dvb-usb/dib0700.h          |    2 
 drivers/media/usb/dvb-usb/dib0700_core.c     |   16 ++-
 drivers/media/usb/dvb-usb/dib0700_devices.c  |  146 +++++++++++++-------------
 drivers/media/usb/dvb-usb/dvb-usb.h          |    2 
 drivers/media/usb/dvb-usb/pctv452e.c         |    4 -
 drivers/media/usb/dvb-usb/technisat-usb2.c   |    2 
 drivers/media/usb/dvb-usb/ttusb2.c           |    2 
 drivers/media/usb/em28xx/em28xx-input.c      |   16 ++-
 drivers/media/usb/hdpvr/hdpvr-i2c.c          |    2 
 drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c |    4 -
 drivers/media/usb/tm6000/tm6000-input.c      |   20 ++--
 include/media/ir-kbd-i2c.h                   |    2 
 include/media/rc-core.h                      |    4 -
 include/media/rc-map.h                       |   64 +++++++++--
 56 files changed, 314 insertions(+), 244 deletions(-)

diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index 37bc5c4..b8c5cad 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 
 	dev->priv = coredev;
 	dev->driver_type = RC_DRIVER_IR_RAW;
-	dev->allowed_protos = RC_TYPE_ALL;
+	dev->allowed_protos = RC_BIT_ALL;
 	dev->map_name = sms_get_board(board_id)->rc_codes;
 	dev->driver_name = MODULE_NAME;
 
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 04f192a..08ae067 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -284,7 +284,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	char *ir_codes = NULL;
 	const char *name = NULL;
-	u64 rc_type = RC_TYPE_UNKNOWN;
+	u64 rc_type = RC_BIT_UNKNOWN;
 	struct IR_i2c *ir;
 	struct rc_dev *rc = NULL;
 	struct i2c_adapter *adap = client->adapter;
@@ -303,7 +303,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	case 0x64:
 		name        = "Pixelview";
 		ir->get_key = get_key_pixelview;
-		rc_type     = RC_TYPE_OTHER;
+		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_EMPTY;
 		break;
 	case 0x18:
@@ -311,31 +311,31 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	case 0x1a:
 		name        = "Hauppauge";
 		ir->get_key = get_key_haup;
-		rc_type     = RC_TYPE_RC5;
+		rc_type     = RC_BIT_RC5;
 		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	case 0x30:
 		name        = "KNC One";
 		ir->get_key = get_key_knc1;
-		rc_type     = RC_TYPE_OTHER;
+		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_EMPTY;
 		break;
 	case 0x6b:
 		name        = "FusionHDTV";
 		ir->get_key = get_key_fusionhdtv;
-		rc_type     = RC_TYPE_RC5;
+		rc_type     = RC_BIT_RC5;
 		ir_codes    = RC_MAP_FUSIONHDTV_MCE;
 		break;
 	case 0x40:
 		name        = "AVerMedia Cardbus remote";
 		ir->get_key = get_key_avermedia_cardbus;
-		rc_type     = RC_TYPE_OTHER;
+		rc_type     = RC_BIT_OTHER;
 		ir_codes    = RC_MAP_AVERMEDIA_CARDBUS;
 		break;
 	case 0x71:
 		name        = "Hauppauge/Zilog Z8";
 		ir->get_key = get_key_haup_xvr;
-		rc_type     = RC_TYPE_RC5;
+		rc_type     = RC_BIT_RC5;
 		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	}
diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c
index 51609d5..4908eb7 100644
--- a/drivers/media/pci/cx18/cx18-i2c.c
+++ b/drivers/media/pci/cx18/cx18-i2c.c
@@ -98,7 +98,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
 	case CX18_HW_Z8F0811_IR_RX_HAUP:
 		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type = RC_TYPE_RC5;
+		init_data->type = RC_BIT_RC5;
 		init_data->name = cx->card_name;
 		info.platform_data = init_data;
 		break;
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
index 5606672..11a636b 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -270,21 +270,21 @@ int cx23885_input_init(struct cx23885_dev *dev)
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 		/* Integrated CX2388[58] IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_TYPE_ALL;
+		allowed_protos = RC_BIT_ALL;
 		/* The grey Hauppauge RC-5 remote */
 		rc_map = RC_MAP_HAUPPAUGE;
 		break;
 	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
 		/* Integrated CX23885 IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_TYPE_NEC;
+		allowed_protos = RC_BIT_NEC;
 		/* The grey Terratec remote with orange buttons */
 		rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS;
 		break;
 	case CX23885_BOARD_TEVII_S470:
 		/* Integrated CX23885 IR controller */
 		driver_type = RC_DRIVER_IR_RAW;
-		allowed_protos = RC_TYPE_ALL;
+		allowed_protos = RC_BIT_ALL;
 		/* A guess at the remote */
 		rc_map = RC_MAP_TEVII_NEC;
 		break;
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
index ebf448c..f29e18c 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -248,7 +248,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
 	struct cx88_IR *ir;
 	struct rc_dev *dev;
 	char *ir_codes = NULL;
-	u64 rc_type = RC_TYPE_OTHER;
+	u64 rc_type = RC_BIT_OTHER;
 	int err = -ENOMEM;
 	u32 hardware_mask = 0;	/* For devices with a hardware mask, when
 				 * used with a full-code IR table
@@ -416,7 +416,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
 		break;
 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
 		ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
-		rc_type          = RC_TYPE_NEC;
+		rc_type          = RC_BIT_NEC;
 		ir->sampling     = 0xff00; /* address */
 		break;
 	}
@@ -592,7 +592,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
 	case CX88_BOARD_LEADTEK_PVR2000:
 		addr_list = pvr2000_addr_list;
 		core->init_data.name = "cx88 Leadtek PVR 2000 remote";
-		core->init_data.type = RC_TYPE_UNKNOWN;
+		core->init_data.type = RC_BIT_UNKNOWN;
 		core->init_data.get_key = get_key_pvr2000;
 		core->init_data.ir_codes = RC_MAP_EMPTY;
 		break;
@@ -613,7 +613,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
 			/* Hauppauge XVR */
 			core->init_data.name = "cx88 Hauppauge XVR remote";
 			core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
-			core->init_data.type = RC_TYPE_RC5;
+			core->init_data.type = RC_BIT_RC5;
 			core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 
 			info.platform_data = &core->init_data;
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
index d47f41a..46e262b 100644
--- a/drivers/media/pci/ivtv/ivtv-i2c.c
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -200,21 +200,21 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
 		init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
 		init_data->internal_get_key_func =
 					IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
-		init_data->type = RC_TYPE_OTHER;
+		init_data->type = RC_BIT_OTHER;
 		init_data->name = "AVerMedia AVerTV card";
 		break;
 	case IVTV_HW_I2C_IR_RX_HAUP_EXT:
 	case IVTV_HW_I2C_IR_RX_HAUP_INT:
 		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-		init_data->type = RC_TYPE_RC5;
+		init_data->type = RC_BIT_RC5;
 		init_data->name = itv->card_name;
 		break;
 	case IVTV_HW_Z8F0811_IR_RX_HAUP:
 		/* Default to grey remote */
 		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type = RC_TYPE_RC5;
+		init_data->type = RC_BIT_RC5;
 		init_data->name = itv->card_name;
 		break;
 	case IVTV_HW_I2C_IR_RX_ADAPTEC:
@@ -222,7 +222,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
 		init_data->name = itv->card_name;
 		/* FIXME: The protocol and RC_MAP needs to be corrected */
 		init_data->ir_codes = RC_MAP_EMPTY;
-		init_data->type = RC_TYPE_UNKNOWN;
+		init_data->type = RC_BIT_UNKNOWN;
 		break;
 	}
 
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index 0f78f5e..e761262 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -990,7 +990,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 		dev->init_data.name = "BeholdTV";
 		dev->init_data.get_key = get_key_beholdm6xx;
 		dev->init_data.ir_codes = RC_MAP_BEHOLD;
-		dev->init_data.type = RC_TYPE_NEC;
+		dev->init_data.type = RC_BIT_NEC;
 		info.addr = 0x2d;
 		break;
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 08aede5..09d9e05 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -784,7 +784,7 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote)
 
 	rdev->priv = ati_remote;
 	rdev->driver_type = RC_DRIVER_SCANCODE;
-	rdev->allowed_protos = RC_TYPE_OTHER;
+	rdev->allowed_protos = RC_BIT_OTHER;
 	rdev->driver_name = "ati_remote";
 
 	rdev->open = ati_remote_rc_open;
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index 647dd95..07f7c38 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1043,7 +1043,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 		learning_mode_force = false;
 
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->priv = dev;
 	rdev->open = ene_open;
 	rdev->close = ene_close;
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index 52fd769..d2d93cb 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
 	/* Set up the rc device */
 	rdev->priv = fintek;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->open = fintek_open;
 	rdev->close = fintek_close;
 	rdev->input_name = FINTEK_DESCRIPTION;
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 04cb272..ba1a1eb 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -95,7 +95,7 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
 	if (pdata->allowed_protos)
 		rcdev->allowed_protos = pdata->allowed_protos;
 	else
-		rcdev->allowed_protos = RC_TYPE_ALL;
+		rcdev->allowed_protos = RC_BIT_ALL;
 	rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
 
 	gpio_dev->rcdev = rcdev;
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 1e4c68a..aca2242 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -503,7 +503,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
 	usb_to_input_id(ir->udev, &rc->input_id);
 	rc->dev.parent = &intf->dev;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->priv = ir;
 	rc->open = iguanair_open;
 	rc->close = iguanair_close;
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 5dd0386..8f6a289 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1001,7 +1001,7 @@ static void imon_touch_display_timeout(unsigned long data)
  * it is not, so we must acquire it prior to calling send_packet, which
  * requires that the lock is held.
  */
-static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
 	int retval;
 	struct imon_context *ictx = rc->priv;
@@ -1010,31 +1010,27 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 	unsigned char ir_proto_packet[] = {
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
-	if (rc_type && !(rc_type & rc->allowed_protos))
+	if (*rc_type && !(*rc_type & rc->allowed_protos))
 		dev_warn(dev, "Looks like you're trying to use an IR protocol "
 			 "this device does not support\n");
 
-	switch (rc_type) {
-	case RC_TYPE_RC6:
+	if (*rc_type & RC_BIT_RC6_MCE) {
 		dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
 		ir_proto_packet[0] = 0x01;
-		break;
-	case RC_TYPE_UNKNOWN:
-	case RC_TYPE_OTHER:
+		*rc_type = RC_BIT_RC6_MCE;
+	} else if (*rc_type & RC_BIT_OTHER) {
 		dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
 		if (!pad_stabilize)
 			dev_dbg(dev, "PAD stabilize functionality disabled\n");
 		/* ir_proto_packet[0] = 0x00; // already the default */
-		rc_type = RC_TYPE_OTHER;
-		break;
-	default:
+		*rc_type = RC_BIT_OTHER;
+	} else {
 		dev_warn(dev, "Unsupported IR protocol specified, overriding "
 			 "to iMON IR protocol\n");
 		if (!pad_stabilize)
 			dev_dbg(dev, "PAD stabilize functionality disabled\n");
 		/* ir_proto_packet[0] = 0x00; // already the default */
-		rc_type = RC_TYPE_OTHER;
-		break;
+		*rc_type = RC_BIT_OTHER;
 	}
 
 	memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
@@ -1048,7 +1044,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 	if (retval)
 		goto out;
 
-	ictx->rc_type = rc_type;
+	ictx->rc_type = *rc_type;
 	ictx->pad_mouse = false;
 
 out:
@@ -1323,7 +1319,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
 		rel_x = buf[2];
 		rel_y = buf[3];
 
-		if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+		if (ictx->rc_type == RC_BIT_OTHER && pad_stabilize) {
 			if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
 				dir = stabilize((int)rel_x, (int)rel_y,
 						timeout, threshold);
@@ -1390,7 +1386,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
 		buf[0] = 0x01;
 		buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
 
-		if (ictx->rc_type == RC_TYPE_OTHER && pad_stabilize) {
+		if (ictx->rc_type == RC_BIT_OTHER && pad_stabilize) {
 			dir = stabilize((int)rel_x, (int)rel_y,
 					timeout, threshold);
 			if (!dir) {
@@ -1511,7 +1507,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
 		kc = imon_panel_key_lookup(scancode);
 	} else {
 		scancode = be32_to_cpu(*((u32 *)buf));
-		if (ictx->rc_type == RC_TYPE_RC6) {
+		if (ictx->rc_type == RC_BIT_RC6_MCE) {
 			ktype = IMON_KEY_IMON;
 			if (buf[0] == 0x80)
 				ktype = IMON_KEY_MCE;
@@ -1744,7 +1740,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 {
 	u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
 	u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
-	u64 allowed_protos = RC_TYPE_OTHER;
+	u64 allowed_protos = RC_BIT_OTHER;
 
 	switch (ffdc_cfg_byte) {
 	/* iMON Knob, no display, iMON IR + vol knob */
@@ -1775,13 +1771,13 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 	case 0x9e:
 		dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
 		detected_display_type = IMON_DISPLAY_TYPE_VFD;
-		allowed_protos = RC_TYPE_RC6;
+		allowed_protos = RC_BIT_RC6_MCE;
 		break;
 	/* iMON LCD, MCE IR */
 	case 0x9f:
 		dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
 		detected_display_type = IMON_DISPLAY_TYPE_LCD;
-		allowed_protos = RC_TYPE_RC6;
+		allowed_protos = RC_BIT_RC6_MCE;
 		break;
 	default:
 		dev_info(ictx->dev, "Unknown 0xffdc device, "
@@ -1789,7 +1785,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 		detected_display_type = IMON_DISPLAY_TYPE_VFD;
 		/* We don't know which one it is, allow user to set the
 		 * RC6 one from userspace if OTHER wasn't correct. */
-		allowed_protos |= RC_TYPE_RC6;
+		allowed_protos |= RC_BIT_RC6_MCE;
 		break;
 	}
 
@@ -1875,7 +1871,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
 
 	rdev->priv = ictx;
 	rdev->driver_type = RC_DRIVER_SCANCODE;
-	rdev->allowed_protos = RC_TYPE_OTHER | RC_TYPE_RC6; /* iMON PAD or MCE */
+	rdev->allowed_protos = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
 	rdev->change_protocol = imon_ir_change_protocol;
 	rdev->driver_name = MOD_NAME;
 
@@ -1893,7 +1889,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
 
 	imon_set_display_type(ictx);
 
-	if (ictx->rc_type == RC_TYPE_RC6)
+	if (ictx->rc_type == RC_BIT_RC6_MCE)
 		rdev->map_name = RC_MAP_IMON_MCE;
 	else
 		rdev->map_name = RC_MAP_IMON_PAD;
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index 035668e..69edffb 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 {
 	struct jvc_dec *data = &dev->raw->jvc;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_JVC))
+	if (!(dev->raw->enabled_protocols & RC_BIT_JVC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -174,7 +174,7 @@ out:
 }
 
 static struct ir_raw_handler jvc_handler = {
-	.protocols	= RC_TYPE_JVC,
+	.protocols	= RC_BIT_JVC,
 	.decode		= ir_jvc_decode,
 };
 
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 6ad4a07..e6f22d5 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct lirc_codec *lirc = &dev->raw->lirc;
 	int sample;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_LIRC))
+	if (!(dev->raw->enabled_protocols & RC_BIT_LIRC))
 		return 0;
 
 	if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
@@ -408,7 +408,7 @@ static int ir_lirc_unregister(struct rc_dev *dev)
 }
 
 static struct ir_raw_handler lirc_handler = {
-	.protocols	= RC_TYPE_LIRC,
+	.protocols	= RC_BIT_LIRC,
 	.decode		= ir_lirc_decode,
 	.raw_register	= ir_lirc_register,
 	.raw_unregister	= ir_lirc_unregister,
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 3784ebf..33fafa4 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	unsigned long delay;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_MCE_KBD))
+	if (!(dev->raw->enabled_protocols & RC_BIT_MCE_KBD))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -422,7 +422,7 @@ static int ir_mce_kbd_unregister(struct rc_dev *dev)
 }
 
 static struct ir_raw_handler mce_kbd_handler = {
-	.protocols	= RC_TYPE_MCE_KBD,
+	.protocols	= RC_BIT_MCE_KBD,
 	.decode		= ir_mce_kbd_decode,
 	.raw_register	= ir_mce_kbd_register,
 	.raw_unregister	= ir_mce_kbd_unregister,
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 2ca509e..a47ee36 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 address, not_address, command, not_command;
 	bool send_32bits = false;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_NEC))
+	if (!(dev->raw->enabled_protocols & RC_BIT_NEC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -201,7 +201,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 }
 
 static struct ir_raw_handler nec_handler = {
-	.protocols	= RC_TYPE_NEC,
+	.protocols	= RC_BIT_NEC,
 	.decode		= ir_nec_decode,
 };
 
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 9ab663a..5b4d1dd 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -52,8 +52,8 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 toggle;
 	u32 scancode;
 
-        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5))
-                return 0;
+	if (!(dev->raw->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
+		return 0;
 
 	if (!is_timing_event(ev)) {
 		if (ev.reset)
@@ -128,6 +128,10 @@ again:
 		if (data->wanted_bits == RC5X_NBITS) {
 			/* RC5X */
 			u8 xdata, command, system;
+			if (!(dev->raw->enabled_protocols & RC_BIT_RC5X)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			xdata    = (data->bits & 0x0003F) >> 0;
 			command  = (data->bits & 0x00FC0) >> 6;
 			system   = (data->bits & 0x1F000) >> 12;
@@ -141,6 +145,10 @@ again:
 		} else {
 			/* RC5 */
 			u8 command, system;
+			if (!(dev->raw->enabled_protocols & RC_BIT_RC5)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			command  = (data->bits & 0x0003F) >> 0;
 			system   = (data->bits & 0x007C0) >> 6;
 			toggle   = (data->bits & 0x00800) ? 1 : 0;
@@ -164,7 +172,7 @@ out:
 }
 
 static struct ir_raw_handler rc5_handler = {
-	.protocols	= RC_TYPE_RC5,
+	.protocols	= RC_BIT_RC5 | RC_BIT_RC5X,
 	.decode		= ir_rc5_decode,
 };
 
diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
index ec8d4a2..fd807a8 100644
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ b/drivers/media/rc/ir-rc5-sz-decoder.c
@@ -48,8 +48,8 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 toggle, command, system;
 	u32 scancode;
 
-        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5_SZ))
-                return 0;
+	if (!(dev->raw->enabled_protocols & RC_BIT_RC5_SZ))
+		return 0;
 
 	if (!is_timing_event(ev)) {
 		if (ev.reset)
@@ -128,7 +128,7 @@ out:
 }
 
 static struct ir_raw_handler rc5_sz_handler = {
-	.protocols	= RC_TYPE_RC5_SZ,
+	.protocols	= RC_BIT_RC5_SZ,
 	.decode		= ir_rc5_sz_decode,
 };
 
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 4cfdd7f..e19072f 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -89,7 +89,9 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 toggle;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_RC6))
+	if (!(dev->raw->enabled_protocols &
+	      (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
+	       RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -271,7 +273,9 @@ out:
 }
 
 static struct ir_raw_handler rc6_handler = {
-	.protocols	= RC_TYPE_RC6,
+	.protocols	= RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
+			  RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
+			  RC_BIT_RC6_MCE,
 	.decode		= ir_rc6_decode,
 };
 
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 7e54ec5..7e69a3b 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 address, command, not_command;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO))
+	if (!(dev->raw->enabled_protocols & RC_BIT_SANYO))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -179,7 +179,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 }
 
 static struct ir_raw_handler sanyo_handler = {
-	.protocols	= RC_TYPE_SANYO,
+	.protocols	= RC_BIT_SANYO,
 	.decode		= ir_sanyo_decode,
 };
 
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index dab98b3..fb91434 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -45,7 +45,8 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 device, subdevice, function;
 
-	if (!(dev->raw->enabled_protocols & RC_TYPE_SONY))
+	if (!(dev->raw->enabled_protocols &
+	      (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -123,16 +124,28 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 
 		switch (data->count) {
 		case 12:
+			if (!(dev->raw->enabled_protocols & RC_BIT_SONY12)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			device    = bitrev8((data->bits <<  3) & 0xF8);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  4) & 0xFE);
 			break;
 		case 15:
+			if (!(dev->raw->enabled_protocols & RC_BIT_SONY15)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			device    = bitrev8((data->bits >>  0) & 0xFF);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  7) & 0xFE);
 			break;
 		case 20:
+			if (!(dev->raw->enabled_protocols & RC_BIT_SONY20)) {
+				data->state = STATE_INACTIVE;
+				return 0;
+			}
 			device    = bitrev8((data->bits >>  5) & 0xF8);
 			subdevice = bitrev8((data->bits >>  0) & 0xFF);
 			function  = bitrev8((data->bits >> 12) & 0xFE);
@@ -157,7 +170,7 @@ out:
 }
 
 static struct ir_raw_handler sony_handler = {
-	.protocols	= RC_TYPE_SONY,
+	.protocols	= RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
 	.decode		= ir_sony_decode,
 };
 
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 36fe5a3..494801e 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1562,7 +1562,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
 	/* set up ir-core props */
 	rdev->priv = itdev;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->open = ite_open;
 	rdev->close = ite_close;
 	rdev->s_idle = ite_s_idle;
diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c
index 124c722..f0da960 100644
--- a/drivers/media/rc/keymaps/rc-imon-mce.c
+++ b/drivers/media/rc/keymaps/rc-imon-mce.c
@@ -121,7 +121,7 @@ static struct rc_map_list imon_mce_map = {
 		.scan    = imon_mce,
 		.size    = ARRAY_SIZE(imon_mce),
 		/* its RC6, but w/a hardware decoder */
-		.rc_type = RC_TYPE_RC6,
+		.rc_type = RC_TYPE_RC6_MCE,
 		.name    = RC_MAP_IMON_MCE,
 	}
 };
diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c
index 753e43e..ef4006f 100644
--- a/drivers/media/rc/keymaps/rc-rc6-mce.c
+++ b/drivers/media/rc/keymaps/rc-rc6-mce.c
@@ -97,7 +97,7 @@ static struct rc_map_list rc6_mce_map = {
 	.map = {
 		.scan    = rc6_mce,
 		.size    = ARRAY_SIZE(rc6_mce),
-		.rc_type = RC_TYPE_RC6,
+		.rc_type = RC_TYPE_RC6_MCE,
 		.name    = RC_MAP_RC6_MCE,
 	}
 };
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index a5c6c1c..2e5172e 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1205,7 +1205,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
 	rc->dev.parent = dev;
 	rc->priv = ir;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->timeout = MS_TO_NS(100);
 	if (!ir->flags.no_tx) {
 		rc->s_tx_mask = mceusb_set_tx_mask;
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 699eef3..8e8a19c 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1042,7 +1042,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 	/* Set up the rc device */
 	rdev->priv = nvt;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->open = nvt_open;
 	rdev->close = nvt_close;
 	rdev->tx_ir = nvt_tx_ir;
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index f9be681..53d0282 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -195,7 +195,7 @@ static int __init loop_init(void)
 	rc->map_name		= RC_MAP_EMPTY;
 	rc->priv		= &loopdev;
 	rc->driver_type		= RC_DRIVER_IR_RAW;
-	rc->allowed_protos	= RC_TYPE_ALL;
+	rc->allowed_protos	= RC_BIT_ALL;
 	rc->timeout		= 100 * 1000 * 1000; /* 100 ms */
 	rc->min_timeout		= 1;
 	rc->max_timeout		= UINT_MAX;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index cabc19c..601d1ac1 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -725,25 +725,36 @@ static struct class ir_input_class = {
 	.devnode	= ir_devnode,
 };
 
+/*
+ * These are the protocol textual descriptions that are
+ * used by the sysfs protocols file. Note that the order
+ * of the entries is relevant.
+ */
 static struct {
 	u64	type;
 	char	*name;
 } proto_names[] = {
-	{ RC_TYPE_UNKNOWN,	"unknown"	},
-	{ RC_TYPE_RC5,		"rc-5"		},
-	{ RC_TYPE_NEC,		"nec"		},
-	{ RC_TYPE_RC6,		"rc-6"		},
-	{ RC_TYPE_JVC,		"jvc"		},
-	{ RC_TYPE_SONY,		"sony"		},
-	{ RC_TYPE_RC5_SZ,	"rc-5-sz"	},
-	{ RC_TYPE_SANYO,	"sanyo"		},
-	{ RC_TYPE_MCE_KBD,	"mce_kbd"	},
-	{ RC_TYPE_LIRC,		"lirc"		},
-	{ RC_TYPE_OTHER,	"other"		},
+	{ RC_BIT_NONE,		"none"		},
+	{ RC_BIT_OTHER,		"other"		},
+	{ RC_BIT_UNKNOWN,	"unknown"	},
+	{ RC_BIT_RC5 |
+	  RC_BIT_RC5X,		"rc-5"		},
+	{ RC_BIT_NEC,		"nec"		},
+	{ RC_BIT_RC6_0 |
+	  RC_BIT_RC6_6A_20 |
+	  RC_BIT_RC6_6A_24 |
+	  RC_BIT_RC6_6A_32 |
+	  RC_BIT_RC6_MCE,	"rc-6"		},
+	{ RC_BIT_JVC,		"jvc"		},
+	{ RC_BIT_SONY12 |
+	  RC_BIT_SONY15 |
+	  RC_BIT_SONY20,	"sony"		},
+	{ RC_BIT_RC5_SZ,	"rc-5-sz"	},
+	{ RC_BIT_SANYO,		"sanyo"		},
+	{ RC_BIT_MCE_KBD,	"mce_kbd"	},
+	{ RC_BIT_LIRC,		"lirc"		},
 };
 
-#define PROTO_NONE	"none"
-
 /**
  * show_protocols() - shows the current IR protocol(s)
  * @device:	the device descriptor
@@ -790,6 +801,9 @@ static ssize_t show_protocols(struct device *device,
 			tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
 		else if (allowed & proto_names[i].type)
 			tmp += sprintf(tmp, "%s ", proto_names[i].name);
+
+		if (allowed & proto_names[i].type)
+			allowed &= ~proto_names[i].type;
 	}
 
 	if (tmp != buf)
@@ -867,26 +881,20 @@ static ssize_t store_protocols(struct device *device,
 			disable = false;
 		}
 
-		if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
-			tmp += sizeof(PROTO_NONE);
-			mask = 0;
-			count++;
-		} else {
-			for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
-				if (!strcasecmp(tmp, proto_names[i].name)) {
-					tmp += strlen(proto_names[i].name);
-					mask = proto_names[i].type;
-					break;
-				}
-			}
-			if (i == ARRAY_SIZE(proto_names)) {
-				IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
-				ret = -EINVAL;
-				goto out;
+		for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+			if (!strcasecmp(tmp, proto_names[i].name)) {
+				mask = proto_names[i].type;
+				break;
 			}
-			count++;
 		}
 
+		if (i == ARRAY_SIZE(proto_names)) {
+			IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
+			return -EINVAL;
+		}
+
+		count++;
+
 		if (enable)
 			type |= mask;
 		else if (disable)
@@ -902,7 +910,7 @@ static ssize_t store_protocols(struct device *device,
 	}
 
 	if (dev->change_protocol) {
-		rc = dev->change_protocol(dev, type);
+		rc = dev->change_protocol(dev, &type);
 		if (rc < 0) {
 			IR_dprintk(1, "Error setting protocols to 0x%llx\n",
 				   (long long)type);
@@ -1117,7 +1125,8 @@ int rc_register_device(struct rc_dev *dev)
 	}
 
 	if (dev->change_protocol) {
-		rc = dev->change_protocol(dev, rc_map->rc_type);
+		u64 rc_type = (1 << rc_map->rc_type);
+		rc = dev->change_protocol(dev, &rc_type);
 		if (rc < 0)
 			goto out_raw;
 	}
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 2878b0e..13a679f 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -1079,7 +1079,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
 	rc->dev.parent = dev;
 	rc->priv = rr3;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->timeout = US_TO_NS(2750);
 	rc->tx_ir = redrat3_transmit_ir;
 	rc->s_tx_carrier = redrat3_set_tx_carrier;
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index d6f4bfe..c720f12 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -322,7 +322,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
 	rdev->dev.parent = dev;
 	rdev->priv = sz;
 	rdev->driver_type = RC_DRIVER_IR_RAW;
-	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->allowed_protos = RC_BIT_ALL;
 	rdev->driver_name = DRIVER_NAME;
 	rdev->map_name = RC_MAP_STREAMZAP;
 
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
index 1aee57f..2151927 100644
--- a/drivers/media/rc/ttusbir.c
+++ b/drivers/media/rc/ttusbir.c
@@ -316,7 +316,7 @@ static int __devinit ttusbir_probe(struct usb_interface *intf,
 	usb_to_input_id(tt->udev, &rc->input_id);
 	rc->dev.parent = &intf->dev;
 	rc->driver_type = RC_DRIVER_IR_RAW;
-	rc->allowed_protos = RC_TYPE_ALL;
+	rc->allowed_protos = RC_BIT_ALL;
 	rc->priv = tt;
 	rc->driver_name = DRIVER_NAME;
 	rc->map_name = RC_MAP_TT_1500;
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 30ae1f2..b1cb3a9 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1022,7 +1022,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	data->dev->priv = data;
 	data->dev->dev.parent = &device->dev;
 	data->dev->timeout = MS_TO_NS(100);
-	data->dev->allowed_protos = RC_TYPE_ALL;
+	data->dev->allowed_protos = RC_BIT_ALL;
 
 	if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
 		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c
index 96176e9..0f7b424 100644
--- a/drivers/media/usb/cx231xx/cx231xx-input.c
+++ b/drivers/media/usb/cx231xx/cx231xx-input.c
@@ -99,7 +99,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
 	/* The i2c micro-controller only outputs the cmd part of NEC protocol */
 	dev->init_data.rc_dev->scanmask = 0xff;
 	dev->init_data.rc_dev->driver_name = "cx231xx";
-	dev->init_data.type = RC_TYPE_NEC;
+	dev->init_data.type = RC_BIT_NEC;
 	info.addr = 0x30;
 
 	/* Load and bind ir-kbd-i2c */
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c
index 9afceed..8131416 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -1288,7 +1288,7 @@ static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 	if (!rc->map_name)
 		rc->map_name = RC_MAP_EMPTY;
 
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = af9015_rc_query;
 	rc->interval = 500;
 
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index b700444..c718ada 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -956,10 +956,10 @@ static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 		switch (tmp) {
 		case 0: /* NEC */
 		default:
-			rc->allowed_protos = RC_TYPE_NEC;
+			rc->allowed_protos = RC_BIT_NEC;
 			break;
 		case 1: /* RC6 */
-			rc->allowed_protos = RC_TYPE_RC6;
+			rc->allowed_protos = RC_BIT_RC6;
 			break;
 		}
 
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index b430bca..9ddb70f 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -1048,7 +1048,7 @@ static int anysee_rc_query(struct dvb_usb_device *d)
 
 static int anysee_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query          = anysee_rc_query;
 	rc->interval       = 250;  /* windows driver uses 500ms */
 
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
index 54f1221..d75dbf2 100644
--- a/drivers/media/usb/dvb-usb-v2/az6007.c
+++ b/drivers/media/usb/dvb-usb-v2/az6007.c
@@ -826,7 +826,7 @@ static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
 	pr_debug("Getting az6007 Remote Control properties\n");
 
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query          = az6007_rc_query;
 	rc->interval       = 400;
 
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
index 5a53c62..ae168f5 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
@@ -126,7 +126,7 @@ struct dvb_usb_driver_info {
 struct dvb_usb_rc {
 	const char *map_name;
 	u64 allowed_protos;
-	int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
 	int (*query) (struct dvb_usb_device *d);
 	unsigned int interval;
 	const enum rc_driver_type driver_type;
diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c
index 695f910..0b1ddc2 100644
--- a/drivers/media/usb/dvb-usb-v2/it913x.c
+++ b/drivers/media/usb/dvb-usb-v2/it913x.c
@@ -698,7 +698,7 @@ static int it913x_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 		return 0;
 	}
 
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = it913x_rc_query;
 	rc->interval = 250;
 
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index c41d9d9..6a2445b 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -1253,7 +1253,7 @@ static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
 static int lme2510_get_rc_config(struct dvb_usb_device *d,
 	struct dvb_usb_rc *rc)
 {
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	return 0;
 }
 
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index d2b1505..5c3c6df 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1099,7 +1099,7 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d,
 		struct dvb_usb_rc *rc)
 {
 	rc->map_name = RC_MAP_EMPTY;
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = rtl2831u_rc_query;
 	rc->interval = 400;
 
@@ -1171,7 +1171,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
 		struct dvb_usb_rc *rc)
 {
 	rc->map_name = RC_MAP_EMPTY;
-	rc->allowed_protos = RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_NEC;
 	rc->query = rtl2832u_rc_query;
 	rc->interval = 400;
 
diff --git a/drivers/media/usb/dvb-usb/dib0700.h b/drivers/media/usb/dvb-usb/dib0700.h
index 7de125c..637b612 100644
--- a/drivers/media/usb/dvb-usb/dib0700.h
+++ b/drivers/media/usb/dvb-usb/dib0700.h
@@ -64,7 +64,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
 extern struct i2c_algorithm dib0700_i2c_algo;
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
 			struct dvb_usb_device_description **desc, int *cold);
-extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
+extern int dib0700_change_protocol(struct rc_dev *dev, u64 *rc_type);
 extern int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz);
 
 extern int dib0700_device_count;
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
index ef87229..19b5ed2 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -605,7 +605,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 	return ret;
 }
 
-int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
+int dib0700_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
 	struct dvb_usb_device *d = rc->priv;
 	struct dib0700_state *st = d->priv;
@@ -621,17 +621,19 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 	st->buf[2] = 0;
 
 	/* Set the IR mode */
-	if (rc_type == RC_TYPE_RC5)
+	if (*rc_type & RC_BIT_RC5) {
 		new_proto = 1;
-	else if (rc_type == RC_TYPE_NEC)
+		*rc_type = RC_BIT_RC5;
+	} else if (*rc_type & RC_BIT_NEC) {
 		new_proto = 0;
-	else if (rc_type == RC_TYPE_RC6) {
+		*rc_type = RC_BIT_NEC;
+	} else if (*rc_type & RC_BIT_RC6_MCE) {
 		if (st->fw_version < 0x10200) {
 			ret = -EINVAL;
 			goto out;
 		}
-
 		new_proto = 2;
+		*rc_type = RC_BIT_RC6_MCE;
 	} else {
 		ret = -EINVAL;
 		goto out;
@@ -645,7 +647,7 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
 		goto out;
 	}
 
-	d->props.rc.core.protocol = rc_type;
+	d->props.rc.core.protocol = *rc_type;
 
 out:
 	mutex_unlock(&d->usb_mutex);
@@ -707,7 +709,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
 		 purb->actual_length);
 
 	switch (d->props.rc.core.protocol) {
-	case RC_TYPE_NEC:
+	case RC_BIT_NEC:
 		toggle = 0;
 
 		/* NEC protocol sends repeat code as 0 0 0 FF */
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index 510001d..1179842 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -518,7 +518,7 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 
 	d->last_event = 0;
 	switch (d->props.rc.core.protocol) {
-	case RC_TYPE_NEC:
+	case RC_BIT_NEC:
 		/* NEC protocol sends repeat code as 0 0 0 FF */
 		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
 		    (key[3] == 0xff))
@@ -3658,9 +3658,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3698,9 +3698,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3763,9 +3763,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_interval      = DEFAULT_RC_INTERVAL,
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3808,9 +3808,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3890,9 +3890,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3936,9 +3936,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -3987,9 +3987,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4055,9 +4055,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4106,9 +4106,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4177,9 +4177,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4215,9 +4215,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4295,9 +4295,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4341,9 +4341,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4394,9 +4394,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4433,9 +4433,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4472,9 +4472,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4511,9 +4511,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4550,9 +4550,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4589,9 +4589,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4644,9 +4644,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4681,9 +4681,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4721,9 +4721,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4761,9 +4761,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
@@ -4802,9 +4802,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
 			.module_name	  = "dib0700",
 			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
+			.allowed_protos   = RC_BIT_RC5 |
+					    RC_BIT_RC6_MCE |
+					    RC_BIT_NEC,
 			.change_protocol  = dib0700_change_protocol,
 		},
 	},
diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h
index aab0f99..ce4c4e3 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb.h
+++ b/drivers/media/usb/dvb-usb/dvb-usb.h
@@ -202,7 +202,7 @@ struct dvb_rc {
 	u64 protocol;
 	u64 allowed_protos;
 	enum rc_driver_type driver_type;
-	int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+	int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
 	char *module_name;
 	int (*rc_query) (struct dvb_usb_device *d);
 	int rc_interval;
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c
index 02e8785..d1ddfa1 100644
--- a/drivers/media/usb/dvb-usb/pctv452e.c
+++ b/drivers/media/usb/dvb-usb/pctv452e.c
@@ -927,7 +927,7 @@ static struct dvb_usb_device_properties pctv452e_properties = {
 
 	.rc.core = {
 		.rc_codes	= RC_MAP_DIB0700_RC5_TABLE,
-		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.allowed_protos	= RC_BIT_UNKNOWN,
 		.rc_query	= pctv452e_rc_query,
 		.rc_interval	= 100,
 	},
@@ -980,7 +980,7 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
 
 	.rc.core = {
 		.rc_codes	= RC_MAP_TT_1500,
-		.allowed_protos	= RC_TYPE_UNKNOWN,
+		.allowed_protos	= RC_BIT_UNKNOWN,
 		.rc_query	= pctv452e_rc_query,
 		.rc_interval	= 100,
 	},
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index acefaa8..3b8752a 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -731,7 +731,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
 		.rc_codes    = RC_MAP_TECHNISAT_USB2,
 		.module_name = "technisat-usb2",
 		.rc_query    = technisat_usb2_rc_query,
-		.allowed_protos = RC_TYPE_ALL,
+		.allowed_protos = RC_BIT_ALL,
 		.driver_type    = RC_DRIVER_IR_RAW,
 	}
 };
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c
index e53a106..c5be462 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.c
+++ b/drivers/media/usb/dvb-usb/ttusb2.c
@@ -741,7 +741,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
 		.rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
 		.rc_codes         = RC_MAP_TT_1500,
 		.rc_query         = tt3650_rc_query,
-		.allowed_protos   = RC_TYPE_UNKNOWN,
+		.allowed_protos   = RC_BIT_UNKNOWN,
 	},
 
 	.num_adapters = 1,
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 97d36b4..660bf80 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -345,7 +345,7 @@ static void em28xx_ir_stop(struct rc_dev *rc)
 	cancel_delayed_work_sync(&ir->work);
 }
 
-static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
+static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
 {
 	int rc = 0;
 	struct em28xx_IR *ir = rc_dev->priv;
@@ -354,14 +354,16 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
 
 	/* Adjust xclk based o IR table for RC5/NEC tables */
 
-	if (rc_type == RC_TYPE_RC5) {
+	if (*rc_type & RC_BIT_RC5) {
 		dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
 		ir->full_code = 1;
-	} else if (rc_type == RC_TYPE_NEC) {
+		*rc_type = RC_BIT_RC5;
+	} else if (*rc_type & RC_BIT_NEC) {
 		dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
 		ir_config = EM2874_IR_NEC;
 		ir->full_code = 1;
-	} else if (rc_type != RC_TYPE_UNKNOWN)
+		*rc_type = RC_BIT_NEC;
+	} else if (*rc_type != RC_BIT_UNKNOWN)
 		rc = -EINVAL;
 
 	em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
@@ -524,6 +526,7 @@ static int em28xx_ir_init(struct em28xx *dev)
 	struct em28xx_IR *ir;
 	struct rc_dev *rc;
 	int err = -ENOMEM;
+	u64 rc_type;
 
 	if (dev->board.ir_codes == NULL) {
 		/* No remote control support */
@@ -546,14 +549,15 @@ static int em28xx_ir_init(struct em28xx *dev)
 	 * em2874 supports more protocols. For now, let's just announce
 	 * the two protocols that were already tested
 	 */
-	rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
 	rc->priv = ir;
 	rc->change_protocol = em28xx_ir_change_protocol;
 	rc->open = em28xx_ir_start;
 	rc->close = em28xx_ir_stop;
 
 	/* By default, keep protocol field untouched */
-	err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+	rc_type = RC_BIT_UNKNOWN;
+	err = em28xx_ir_change_protocol(rc, &rc_type);
 	if (err)
 		goto err_out_free;
 
diff --git a/drivers/media/usb/hdpvr/hdpvr-i2c.c b/drivers/media/usb/hdpvr/hdpvr-i2c.c
index 82e819f..031cf02 100644
--- a/drivers/media/usb/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/usb/hdpvr/hdpvr-i2c.c
@@ -55,7 +55,7 @@ struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
 	/* Our default information for ir-kbd-i2c.c to use */
 	init_data->ir_codes = RC_MAP_HAUPPAUGE;
 	init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-	init_data->type = RC_TYPE_RC5;
+	init_data->type = RC_BIT_RC5;
 	init_data->name = "HD-PVR";
 	init_data->polling_interval = 405; /* ms, duplicated from Windows */
 	hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
index 885ce11..9ab596c 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
@@ -581,7 +581,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
 	case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
 		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-		init_data->type                  = RC_TYPE_RC5;
+		init_data->type                  = RC_BIT_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
 		init_data->polling_interval      = 100; /* ms From ir-kbd-i2c */
 		/* IR Receiver */
@@ -596,7 +596,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
 	case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
 		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-		init_data->type                  = RC_TYPE_RC5;
+		init_data->type                  = RC_BIT_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
 		/* IR Receiver */
 		info.addr          = 0x71;
diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c
index dffbd4b..8a6bbf1 100644
--- a/drivers/media/usb/tm6000/tm6000-input.c
+++ b/drivers/media/usb/tm6000/tm6000-input.c
@@ -109,12 +109,12 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
 	 */
 
 	switch (ir->rc_type) {
-	case RC_TYPE_NEC:
+	case RC_BIT_NEC:
 		leader = 900;	/* ms */
 		pulse  = 700;	/* ms - the actual value would be 562 */
 		break;
 	default:
-	case RC_TYPE_RC5:
+	case RC_BIT_RC5:
 		leader = 900;	/* ms - from the NEC decoding */
 		pulse  = 1780;	/* ms - The actual value would be 1776 */
 		break;
@@ -122,12 +122,12 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
 
 	pulse = ir_clock_mhz * pulse;
 	leader = ir_clock_mhz * leader;
-	if (ir->rc_type == RC_TYPE_NEC)
+	if (ir->rc_type == RC_BIT_NEC)
 		leader = leader | 0x8000;
 
 	dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
 		__func__,
-		(ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
+		(ir->rc_type == RC_BIT_NEC) ? "NEC" : "RC-5",
 		ir_clock_mhz, leader, pulse);
 
 	/* Remote WAKEUP = enable, normal mode, from IR decoder output */
@@ -297,7 +297,7 @@ static void tm6000_ir_stop(struct rc_dev *rc)
 	cancel_delayed_work_sync(&ir->work);
 }
 
-static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
 {
 	struct tm6000_IR *ir = rc->priv;
 
@@ -306,10 +306,10 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 
 	dprintk(2, "%s\n",__func__);
 
-	if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
+	if ((rc->rc_map.scan) && (*rc_type == RC_BIT_NEC))
 		ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
 
-	ir->rc_type = rc_type;
+	ir->rc_type = *rc_type;
 
 	tm6000_ir_config(ir);
 	/* TODO */
@@ -398,6 +398,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
 	struct tm6000_IR *ir;
 	struct rc_dev *rc;
 	int err = -ENOMEM;
+	u64 rc_type;
 
 	if (!enable_ir)
 		return -ENODEV;
@@ -421,7 +422,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
 	ir->rc = rc;
 
 	/* input setup */
-	rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+	rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
 	/* Neded, in order to support NEC remotes with 24 or 32 bits */
 	rc->scanmask = 0xffff;
 	rc->priv = ir;
@@ -444,7 +445,8 @@ int tm6000_ir_init(struct tm6000_core *dev)
 	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
 	strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
-	tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+	rc_type = RC_BIT_UNKNOWN;
+	tm6000_ir_change_protocol(rc, &rc_type);
 
 	rc->input_name = ir->name;
 	rc->input_phys = ir->phys;
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h
index 768aa77..e221bc7 100644
--- a/include/media/ir-kbd-i2c.h
+++ b/include/media/ir-kbd-i2c.h
@@ -37,7 +37,7 @@ enum ir_kbd_get_key_fn {
 struct IR_i2c_init_data {
 	char			*ir_codes;
 	const char		*name;
-	u64			type; /* RC_TYPE_RC5, etc */
+	u64			type; /* RC_BIT_RC5, etc */
 	u32			polling_interval; /* 0 means DEFAULT_POLLING_INTERVAL */
 
 	/*
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index b0c494a..f03445f 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -50,7 +50,7 @@ enum rc_driver_type {
  * @input_dev: the input child device used to communicate events to userspace
  * @driver_type: specifies if protocol decoding is done in hardware or software
  * @idle: used to keep track of RX state
- * @allowed_protos: bitmask with the supported RC_TYPE_* protocols
+ * @allowed_protos: bitmask with the supported RC_BIT_* protocols
  * @scanmask: some hardware decoders are not capable of providing the full
  *	scancode to the application. As this is a hardware limit, we can't do
  *	anything with it. Yet, as the same keycode table can be used with other
@@ -113,7 +113,7 @@ struct rc_dev {
 	u32				max_timeout;
 	u32				rx_resolution;
 	u32				tx_resolution;
-	int				(*change_protocol)(struct rc_dev *dev, u64 rc_type);
+	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_type);
 	int				(*open)(struct rc_dev *dev);
 	void				(*close)(struct rc_dev *dev);
 	int				(*s_tx_mask)(struct rc_dev *dev, u32 mask);
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index cfd5163..74f55a3 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -11,22 +11,54 @@
 
 #include <linux/input.h>
 
-#define RC_TYPE_UNKNOWN	0
-#define RC_TYPE_RC5	(1  << 0)	/* Philips RC5 protocol */
-#define RC_TYPE_NEC	(1  << 1)
-#define RC_TYPE_RC6	(1  << 2)	/* Philips RC6 protocol */
-#define RC_TYPE_JVC	(1  << 3)	/* JVC protocol */
-#define RC_TYPE_SONY	(1  << 4)	/* Sony12/15/20 protocol */
-#define RC_TYPE_RC5_SZ	(1  << 5)	/* RC5 variant used by Streamzap */
-#define RC_TYPE_SANYO   (1  << 6)	/* Sanyo protocol */
-#define RC_TYPE_MCE_KBD	(1  << 29)	/* RC6-ish MCE keyboard/mouse */
-#define RC_TYPE_LIRC	(1  << 30)	/* Pass raw IR to lirc userspace */
-#define RC_TYPE_OTHER	(1u << 31)
+enum rc_type {
+	RC_TYPE_UNKNOWN		= 0,	/* Protocol not known */
+	RC_TYPE_OTHER		= 1,	/* Protocol known but proprietary */
+	RC_TYPE_LIRC		= 2,	/* Pass raw IR to lirc userspace */
+	RC_TYPE_RC5		= 3,	/* Philips RC5 protocol */
+	RC_TYPE_RC5X		= 4,	/* Philips RC5x protocol */
+	RC_TYPE_RC5_SZ		= 5,	/* StreamZap variant of RC5 */
+	RC_TYPE_JVC		= 6,	/* JVC protocol */
+	RC_TYPE_SONY12		= 7,	/* Sony 12 bit protocol */
+	RC_TYPE_SONY15		= 8,	/* Sony 15 bit protocol */
+	RC_TYPE_SONY20		= 9,	/* Sony 20 bit protocol */
+	RC_TYPE_NEC		= 10,	/* NEC protocol */
+	RC_TYPE_SANYO		= 11,	/* Sanyo protocol */
+	RC_TYPE_MCE_KBD		= 12,	/* RC6-ish MCE keyboard/mouse */
+	RC_TYPE_RC6_0		= 13,	/* Philips RC6-0-16 protocol */
+	RC_TYPE_RC6_6A_20	= 14,	/* Philips RC6-6A-20 protocol */
+	RC_TYPE_RC6_6A_24	= 15,	/* Philips RC6-6A-24 protocol */
+	RC_TYPE_RC6_6A_32	= 16,	/* Philips RC6-6A-32 protocol */
+	RC_TYPE_RC6_MCE		= 17,	/* MCE (Philips RC6-6A-32 subtype) protocol */
+};
+
+#define RC_BIT_NONE		0
+#define RC_BIT_UNKNOWN		(1 << RC_TYPE_UNKNOWN)
+#define RC_BIT_OTHER		(1 << RC_TYPE_OTHER)
+#define RC_BIT_LIRC		(1 << RC_TYPE_LIRC)
+#define RC_BIT_RC5		(1 << RC_TYPE_RC5)
+#define RC_BIT_RC5X		(1 << RC_TYPE_RC5X)
+#define RC_BIT_RC5_SZ		(1 << RC_TYPE_RC5_SZ)
+#define RC_BIT_JVC		(1 << RC_TYPE_JVC)
+#define RC_BIT_SONY12		(1 << RC_TYPE_SONY12)
+#define RC_BIT_SONY15		(1 << RC_TYPE_SONY15)
+#define RC_BIT_SONY20		(1 << RC_TYPE_SONY20)
+#define RC_BIT_NEC		(1 << RC_TYPE_NEC)
+#define RC_BIT_SANYO		(1 << RC_TYPE_SANYO)
+#define RC_BIT_MCE_KBD		(1 << RC_TYPE_MCE_KBD)
+#define RC_BIT_RC6_0		(1 << RC_TYPE_RC6_0)
+#define RC_BIT_RC6_6A_20	(1 << RC_TYPE_RC6_6A_20)
+#define RC_BIT_RC6_6A_24	(1 << RC_TYPE_RC6_6A_24)
+#define RC_BIT_RC6_6A_32	(1 << RC_TYPE_RC6_6A_32)
+#define RC_BIT_RC6_MCE		(1 << RC_TYPE_RC6_MCE)
 
-#define RC_TYPE_ALL (RC_TYPE_RC5    | RC_TYPE_NEC   | RC_TYPE_RC6     | \
-		     RC_TYPE_JVC    | RC_TYPE_SONY  | RC_TYPE_LIRC    | \
-		     RC_TYPE_RC5_SZ | RC_TYPE_SANYO | RC_TYPE_MCE_KBD | \
-		     RC_TYPE_OTHER)
+#define RC_BIT_ALL	(RC_BIT_UNKNOWN | RC_BIT_OTHER | RC_BIT_LIRC | \
+			 RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \
+			 RC_BIT_JVC | \
+			 RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20 | \
+			 RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \
+			 RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \
+			 RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)
 
 struct rc_map_table {
 	u32	scancode;
@@ -38,7 +70,7 @@ struct rc_map {
 	unsigned int		size;	/* Max number of entries */
 	unsigned int		len;	/* Used number of entries */
 	unsigned int		alloc;	/* Size of *scan in bytes */
-	u64			rc_type;
+	enum rc_type		rc_type;
 	const char		*name;
 	spinlock_t		lock;
 };


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/8] rc-core: don't throw away protocol information
  2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
                   ` (2 preceding siblings ...)
  2012-08-25 21:47 ` [PATCH 3/8] rc-core: add separate defines for protocol bitmaps and numbers David Härdeman
@ 2012-08-25 21:47 ` David Härdeman
  2012-09-25 18:40   ` Mauro Carvalho Chehab
  2012-08-25 21:47 ` [PATCH 5/8] rc-core: use the full 32 bits for NEC scancodes David Härdeman
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:47 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

Setting and getting keycodes in the input subsystem used to be done via
the EVIOC[GS]KEYCODE ioctl and "unsigned int[2]" (one int for scancode
and one for the keycode).

The interface has now been extended to use the EVIOC[GS]KEYCODE_V2 ioctl
which uses the following struct:

struct input_keymap_entry {
	__u8  flags;
	__u8  len;
	__u16 index;
	__u32 keycode;
	__u8  scancode[32];
};

(scancode can of course be even bigger, thanks to the len member).

This patch changes how the "input_keymap_entry" struct is interpreted
by rc-core by casting it to "rc_keymap_entry":

struct rc_scancode {
	__u16 protocol;
	__u16 reserved[3];
	__u64 scancode;
}

struct rc_keymap_entry {
	__u8  flags;
	__u8  len;
	__u16 index;
	__u32 keycode;
	union {
		struct rc_scancode rc;
		__u8 raw[32];
	};
};

The u64 scancode member is large enough for all current protocols and it
would be possible to extend it in the future should it be necessary for
some exotic protocol.

The main advantage with this change is that the protocol is made explicit,
which means that we're not throwing away data (the protocol type) and that
it'll be easier to support multiple protocols with one decoder (think rc5
and rc5-streamzap).

Heuristics are also added to hopefully do the right thing with older
ioctls in order to preserve backwards compatibility.

Further patches will also add the ability to communicate the protocol to
userspace.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/i2c/ir-kbd-i2c.c              |   12 +
 drivers/media/pci/bt8xx/bttv-input.c        |   15 +-
 drivers/media/pci/cx88/cx88-input.c         |   10 +
 drivers/media/pci/dm1105/dm1105.c           |    3 
 drivers/media/pci/saa7134/saa7134-input.c   |    6 -
 drivers/media/pci/ttpci/budget-ci.c         |    7 -
 drivers/media/rc/ati_remote.c               |   13 +
 drivers/media/rc/imon.c                     |   10 +
 drivers/media/rc/ir-jvc-decoder.c           |    4 
 drivers/media/rc/ir-lirc-codec.c            |    2 
 drivers/media/rc/ir-mce_kbd-decoder.c       |    2 
 drivers/media/rc/ir-nec-decoder.c           |    4 
 drivers/media/rc/ir-raw.c                   |    2 
 drivers/media/rc/ir-rc5-decoder.c           |   23 +--
 drivers/media/rc/ir-rc5-sz-decoder.c        |    4 
 drivers/media/rc/ir-rc6-decoder.c           |   48 +++--
 drivers/media/rc/ir-sanyo-decoder.c         |    4 
 drivers/media/rc/ir-sony-decoder.c          |   26 +--
 drivers/media/rc/rc-core-priv.h             |    1 
 drivers/media/rc/rc-main.c                  |  237 +++++++++++++++++++--------
 drivers/media/usb/dvb-usb-v2/af9015.c       |    4 
 drivers/media/usb/dvb-usb-v2/anysee.c       |    3 
 drivers/media/usb/dvb-usb-v2/az6007.c       |   25 ++-
 drivers/media/usb/dvb-usb-v2/it913x.c       |   19 +-
 drivers/media/usb/dvb-usb-v2/lmedm04.c      |    2 
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c     |   17 +-
 drivers/media/usb/dvb-usb/dib0700_core.c    |    2 
 drivers/media/usb/dvb-usb/dib0700_devices.c |   10 +
 drivers/media/usb/dvb-usb/dvb-usb.h         |    2 
 drivers/media/usb/dvb-usb/pctv452e.c        |   11 +
 drivers/media/usb/dvb-usb/ttusb2.c          |    2 
 drivers/media/usb/em28xx/em28xx-cards.c     |   15 ++
 drivers/media/usb/em28xx/em28xx-input.c     |   30 ++-
 drivers/media/usb/em28xx/em28xx.h           |    1 
 drivers/media/usb/tm6000/tm6000-cards.c     |    2 
 drivers/media/usb/tm6000/tm6000-input.c     |   60 ++++---
 include/media/rc-core.h                     |   28 +++
 include/media/rc-map.h                      |   17 ++
 38 files changed, 431 insertions(+), 252 deletions(-)

diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 08ae067..86c53fa 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -108,7 +108,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
 		start, range, toggle, dev, code);
 
 	/* return key */
-	*ir_key = (dev << 8) | code;
+	*ir_key = RC_SCANCODE_RC5(dev, code);
 	*ir_raw = ircode;
 	return 1;
 }
@@ -258,7 +258,14 @@ static int ir_key_poll(struct IR_i2c *ir)
 
 	if (rc) {
 		dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
-		rc_keydown(ir->rc, ir_key, 0);
+		switch (ir->rc->enabled_protocols) {
+		case RC_BIT_RC5:
+			rc_keydown(ir->rc, RC_TYPE_RC5, ir_key, 0);
+			break;
+		default:
+			rc_keydown(ir->rc, RC_TYPE_UNKNOWN, ir_key, 0);
+			break;
+		}
 	}
 	return 0;
 }
@@ -423,6 +430,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	 */
 	rc->map_name       = ir->ir_codes;
 	rc->allowed_protos = rc_type;
+	rc->enabled_protocols = rc_type;
 	if (!rc->driver_name)
 		rc->driver_name = MODULE_NAME;
 
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
index ef4c7cd..210568f 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -73,12 +73,12 @@ static void ir_handle_key(struct bttv *btv)
 
 	if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
 	    (ir->mask_keyup   && !(gpio & ir->mask_keyup))) {
-		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 	} else {
 		/* HACK: Probably, ir->mask_keydown is missing
 		   for this board */
 		if (btv->c.type == BTTV_BOARD_WINFAST2000)
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 
 		rc_keyup(ir->dev);
 	}
@@ -103,7 +103,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
 			gpio, data,
 			(gpio & ir->mask_keyup) ? " up" : "up/down");
 
-		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		if (keyup)
 			rc_keyup(ir->dev);
 	} else {
@@ -117,7 +117,7 @@ static void ir_enltv_handle_key(struct bttv *btv)
 		if (keyup)
 			rc_keyup(ir->dev);
 		else
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 	}
 
 	ir->last_gpio = data | keyup;
@@ -235,10 +235,9 @@ static void bttv_rc5_timer_end(unsigned long data)
 			u32 toggle = RC5_TOGGLE(rc5);
 			u32 instr = RC5_INSTR(rc5);
 
-			/* Good code */
-			rc_keydown(ir->dev, instr, toggle);
-			dprintk("instruction %x, toggle %x\n",
-				instr, toggle);
+			/* Good code - UNKNOWN, while using legacy code */
+			rc_keydown(ir->dev, RC_TYPE_UNKNOWN, instr, toggle);
+			dprintk("instruction %x, toggle %x\n", instr, toggle);
 		}
 	}
 }
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
index f29e18c..b1922f0 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -130,25 +130,27 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
 
 		data = (data << 4) | ((gpio_key & 0xf0) >> 4);
 
-		rc_keydown(ir->dev, data, 0);
+		rc_keydown(ir->dev, ir->dev->allowed_protos, data, 0);
 
 	} else if (ir->mask_keydown) {
 		/* bit set on keydown */
 		if (gpio & ir->mask_keydown)
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, ir->dev->allowed_protos,
+					     data, 0);
 		else
 			rc_keyup(ir->dev);
 
 	} else if (ir->mask_keyup) {
 		/* bit cleared on keydown */
 		if (0 == (gpio & ir->mask_keyup))
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, ir->dev->allowed_protos,
+					     data, 0);
 		else
 			rc_keyup(ir->dev);
 
 	} else {
 		/* can't distinguish keydown/up :-/ */
-		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keydown_notimeout(ir->dev, ir->dev->allowed_protos, data, 0);
 		rc_keyup(ir->dev);
 	}
 }
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
index a609b3a..04a02ba 100644
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -677,7 +677,8 @@ static void dm1105_emit_key(struct work_struct *work)
 
 	data = (ircom >> 8) & 0x7f;
 
-	rc_keydown(ir->dev, data, 0);
+	/* Yes, UNKNOWN because we don't generate a full NEC scancode (yet?) */
+	rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 }
 
 /* work handler */
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index e761262..9bc6ed8 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -83,14 +83,14 @@ static int build_key(struct saa7134_dev *dev)
 		if (data == ir->mask_keycode)
 			rc_keyup(ir->dev);
 		else
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		return 0;
 	}
 
 	if (ir->polling) {
 		if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 		    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 		} else {
 			rc_keyup(ir->dev);
 		}
@@ -98,7 +98,7 @@ static int build_key(struct saa7134_dev *dev)
 	else {	/* IRQ driven mode - handle key press and release in one go */
 		if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
 		    (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-			rc_keydown_notimeout(ir->dev, data, 0);
+			rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
 			rc_keyup(ir->dev);
 		}
 	}
diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c
index 98e5241..2ee6b57 100644
--- a/drivers/media/pci/ttpci/budget-ci.c
+++ b/drivers/media/pci/ttpci/budget-ci.c
@@ -161,14 +161,15 @@ static void msp430_ir_interrupt(unsigned long data)
 		return;
 
 	if (budget_ci->ir.full_rc5) {
-		rc_keydown(dev,
-			   budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,
+		rc_keydown(dev, RC_TYPE_RC5,
+			   RC_SCANCODE_RC5(budget_ci->ir.rc5_device,
+					   budget_ci->ir.ir_key),
 			   (command & 0x20) ? 1 : 0);
 		return;
 	}
 
 	/* FIXME: We should generate complete scancodes for all devices */
-	rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
+	rc_keydown(dev, RC_TYPE_UNKNOWN, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
 }
 
 static int msp430_ir_init(struct budget_ci *budget_ci)
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 09d9e05..93d2ecc 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -548,6 +548,7 @@ static void ati_remote_input_report(struct urb *urb)
 		 * set, assume this is a scrollwheel up/down event.
 		 */
 		wheel_keycode = rc_g_keycode_from_table(ati_remote->rdev,
+							RC_TYPE_OTHER,
 							scancode & 0x78);
 
 		if (wheel_keycode == KEY_RESERVED) {
@@ -618,12 +619,12 @@ static void ati_remote_input_report(struct urb *urb)
 
 			while (count--) {
 				/*
-				* We don't use the rc-core repeat handling yet as
-				* it would cause ghost repeats which would be a
-				* regression for this driver.
-				*/
-				rc_keydown_notimeout(ati_remote->rdev, scancode,
-						     data[2]);
+				 * We don't use the rc-core repeat handling yet as
+				 * it would cause ghost repeats which would be a
+				 * regression for this driver.
+				 */
+				rc_keydown_notimeout(ati_remote->rdev, RC_TYPE_OTHER,
+						     scancode, data[2]);
 				rc_keyup(ati_remote->rdev);
 			}
 			return;
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 8f6a289..2e81a80 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1159,14 +1159,15 @@ static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode)
 	bool is_release_code = false;
 
 	/* Look for the initial press of a button */
-	keycode = rc_g_keycode_from_table(ictx->rdev, scancode);
+	keycode = rc_g_keycode_from_table(ictx->rdev, ictx->rc_type, scancode);
 	ictx->rc_toggle = 0x0;
 	ictx->rc_scancode = scancode;
 
 	/* Look for the release of a button */
 	if (keycode == KEY_RESERVED) {
 		release = scancode & ~0x4000;
-		keycode = rc_g_keycode_from_table(ictx->rdev, release);
+		keycode = rc_g_keycode_from_table(ictx->rdev, ictx->rc_type,
+						  release);
 		if (keycode != KEY_RESERVED)
 			is_release_code = true;
 	}
@@ -1195,7 +1196,7 @@ static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode)
 		scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
 
 	ictx->rc_scancode = scancode;
-	keycode = rc_g_keycode_from_table(ictx->rdev, scancode);
+	keycode = rc_g_keycode_from_table(ictx->rdev, ictx->rc_type, scancode);
 
 	/* not used in mce mode, but make sure we know its false */
 	ictx->release_code = false;
@@ -1577,7 +1578,8 @@ static void imon_incoming_packet(struct imon_context *ictx,
 		if (press_type == 0)
 			rc_keyup(ictx->rdev);
 		else {
-			rc_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle);
+			rc_keydown(ictx->rdev, ictx->rc_type,
+				   ictx->rc_scancode, ictx->rc_toggle);
 			spin_lock_irqsave(&ictx->kc_lock, flags);
 			ictx->last_keycode = ictx->kc;
 			spin_unlock_irqrestore(&ictx->kc_lock, flags);
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index 69edffb..30bcf18 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 {
 	struct jvc_dec *data = &dev->raw->jvc;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_JVC))
+	if (!(dev->enabled_protocols & RC_BIT_JVC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -140,7 +140,7 @@ again:
 			scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
 				   (bitrev8((data->bits >> 0) & 0xff) << 0);
 			IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
-			rc_keydown(dev, scancode, data->toggle);
+			rc_keydown(dev, RC_TYPE_JVC, scancode, data->toggle);
 			data->first = false;
 			data->old_bits = data->bits;
 		} else if (data->bits == data->old_bits) {
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index e6f22d5..f91aafb 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct lirc_codec *lirc = &dev->raw->lirc;
 	int sample;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_LIRC))
+	if (!(dev->enabled_protocols & RC_BIT_LIRC))
 		return 0;
 
 	if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
index 33fafa4..9f3c9b5 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	unsigned long delay;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_MCE_KBD))
+	if (!(dev->enabled_protocols & RC_BIT_MCE_KBD))
 		return 0;
 
 	if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index a47ee36..61fa889 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 address, not_address, command, not_command;
 	bool send_32bits = false;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_NEC))
+	if (!(dev->enabled_protocols & RC_BIT_NEC))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -189,7 +189,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 		if (data->is_nec_x)
 			data->necx_repeat = true;
 
-		rc_keydown(dev, scancode, 0);
+		rc_keydown(dev, RC_TYPE_NEC, scancode, 0);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
index 97dc8d1..db5c0ae 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
@@ -261,7 +261,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 		return -ENOMEM;
 
 	dev->raw->dev = dev;
-	dev->raw->enabled_protocols = ~0;
+	dev->enabled_protocols = ~0;
 	rc = kfifo_alloc(&dev->raw->kfifo,
 			 sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
 			 GFP_KERNEL);
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 5b4d1dd..ddbf9bf 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -51,8 +51,9 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct rc5_dec *data = &dev->raw->rc5;
 	u8 toggle;
 	u32 scancode;
+	enum rc_type protocol;
 
-	if (!(dev->raw->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
+	if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -128,38 +129,30 @@ again:
 		if (data->wanted_bits == RC5X_NBITS) {
 			/* RC5X */
 			u8 xdata, command, system;
-			if (!(dev->raw->enabled_protocols & RC_BIT_RC5X)) {
-				data->state = STATE_INACTIVE;
-				return 0;
-			}
 			xdata    = (data->bits & 0x0003F) >> 0;
 			command  = (data->bits & 0x00FC0) >> 6;
 			system   = (data->bits & 0x1F000) >> 12;
 			toggle   = (data->bits & 0x20000) ? 1 : 0;
 			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 16 | command << 8 | xdata;
-
-			IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
-				   scancode, toggle);
-
+			protocol = RC_TYPE_RC5X;
 		} else {
 			/* RC5 */
 			u8 command, system;
-			if (!(dev->raw->enabled_protocols & RC_BIT_RC5)) {
-				data->state = STATE_INACTIVE;
-				return 0;
-			}
 			command  = (data->bits & 0x0003F) >> 0;
 			system   = (data->bits & 0x007C0) >> 6;
 			toggle   = (data->bits & 0x00800) ? 1 : 0;
 			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 8 | command;
+			protocol = RC_TYPE_RC5;
+		}
 
-			IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
+		if (dev->enabled_protocols & (1 << protocol)) {
+			IR_dprintk(1, "RC5(x) scancode 0x%06x (toggle: %u)\n",
 				   scancode, toggle);
+			rc_keydown(dev, protocol, scancode, toggle);
 		}
 
-		rc_keydown(dev, scancode, toggle);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
index fd807a8..8681b96 100644
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ b/drivers/media/rc/ir-rc5-sz-decoder.c
@@ -48,7 +48,7 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u8 toggle, command, system;
 	u32 scancode;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_RC5_SZ))
+	if (!(dev->enabled_protocols & RC_BIT_RC5_SZ))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -115,7 +115,7 @@ again:
 		IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
 			   scancode, toggle);
 
-		rc_keydown(dev, scancode, toggle);
+		rc_keydown(dev, RC_TYPE_RC5_SZ, scancode, toggle);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index e19072f..571107e 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -88,8 +88,9 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct rc6_dec *data = &dev->raw->rc6;
 	u32 scancode;
 	u8 toggle;
+	enum rc_type protocol;
 
-	if (!(dev->raw->enabled_protocols &
+	if (!(dev->enabled_protocols &
 	      (RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
 	       RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
 		return 0;
@@ -231,36 +232,45 @@ again:
 
 		switch (rc6_mode(data)) {
 		case RC6_MODE_0:
+			protocol = RC_TYPE_RC6_0;
 			scancode = data->body;
 			toggle = data->toggle;
-			IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
-				   scancode, toggle);
 			break;
-		case RC6_MODE_6A:
-			if (data->count > CHAR_BIT * sizeof data->body) {
-				IR_dprintk(1, "RC6 too many (%u) data bits\n",
-					data->count);
-				goto out;
-			}
 
+		case RC6_MODE_6A:
 			scancode = data->body;
-			if (data->count == RC6_6A_32_NBITS &&
-					(scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
-				/* MCE RC */
-				toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
-				scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
-			} else {
-				toggle = 0;
+			toggle = 0;
+			switch (data->count) {
+			case 20:
+				protocol = RC_TYPE_RC6_6A_20;
+				break;
+			case 24:
+				protocol = RC_TYPE_RC6_6A_24;
+				break;
+			case 32:
+				protocol = RC_TYPE_RC6_6A_32;
+				if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+					/* MCE RC */
+					toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
+					scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
+					protocol = RC_TYPE_RC6_MCE;
+				}
+				break;
+			default:
+				IR_dprintk(1, "RC6 invalid number of data bits (%u)\n",
+					   data->count);
+				goto out;
 			}
-			IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
-				   scancode, toggle);
 			break;
+
 		default:
 			IR_dprintk(1, "RC6 unknown mode\n");
 			goto out;
 		}
 
-		rc_keydown(dev, scancode, toggle);
+		IR_dprintk(1, "RC6(%u), scancode 0x%08x (toggle: %u)\n",
+			   protocol, scancode, toggle);
+		rc_keydown(dev, protocol, scancode, toggle);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 7e69a3b..a95c869 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	u32 scancode;
 	u8 address, command, not_command;
 
-	if (!(dev->raw->enabled_protocols & RC_BIT_SANYO))
+	if (!(dev->enabled_protocols & RC_BIT_SANYO))
 		return 0;
 
 	if (!is_timing_event(ev)) {
@@ -167,7 +167,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
 
 		scancode = address << 8 | command;
 		IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode);
-		rc_keydown(dev, scancode, 0);
+		rc_keydown(dev, RC_TYPE_SANYO, scancode, 0);
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
index fb91434..f360e40 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -44,8 +44,9 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct sony_dec *data = &dev->raw->sony;
 	u32 scancode;
 	u8 device, subdevice, function;
+	enum rc_type protocol;
 
-	if (!(dev->raw->enabled_protocols &
+	if (!(dev->enabled_protocols &
 	      (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
 		return 0;
 
@@ -124,40 +125,33 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 
 		switch (data->count) {
 		case 12:
-			if (!(dev->raw->enabled_protocols & RC_BIT_SONY12)) {
-				data->state = STATE_INACTIVE;
-				return 0;
-			}
 			device    = bitrev8((data->bits <<  3) & 0xF8);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  4) & 0xFE);
+			protocol  = RC_TYPE_SONY12;
 			break;
 		case 15:
-			if (!(dev->raw->enabled_protocols & RC_BIT_SONY15)) {
-				data->state = STATE_INACTIVE;
-				return 0;
-			}
 			device    = bitrev8((data->bits >>  0) & 0xFF);
 			subdevice = 0;
 			function  = bitrev8((data->bits >>  7) & 0xFE);
+			protocol  = RC_TYPE_SONY15;
 			break;
 		case 20:
-			if (!(dev->raw->enabled_protocols & RC_BIT_SONY20)) {
-				data->state = STATE_INACTIVE;
-				return 0;
-			}
 			device    = bitrev8((data->bits >>  5) & 0xF8);
 			subdevice = bitrev8((data->bits >>  0) & 0xFF);
 			function  = bitrev8((data->bits >> 12) & 0xFE);
+			protocol  = RC_TYPE_SONY20;
 			break;
 		default:
 			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
 			goto out;
 		}
 
-		scancode = device << 16 | subdevice << 8 | function;
-		IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
-		rc_keydown(dev, scancode, 0);
+		if (dev->enabled_protocols & (1 << protocol)) {
+			scancode = device << 16 | subdevice << 8 | function;
+			IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
+			rc_keydown(dev, protocol, scancode, 0);
+		}
 		data->state = STATE_INACTIVE;
 		return 0;
 	}
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 96f0a8b..4de2d47 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -39,7 +39,6 @@ struct ir_raw_event_ctrl {
 	ktime_t				last_event;	/* when last event occurred */
 	enum raw_event_type		last_type;	/* last event type */
 	struct rc_dev			*dev;		/* pointer to the parent rc_dev */
-	u64				enabled_protocols; /* enabled raw protocol decoders */
 
 	/* raw decoder state follows */
 	struct ir_raw_event prev_ev;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 601d1ac1..b111500 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -96,7 +96,7 @@ EXPORT_SYMBOL_GPL(rc_map_unregister);
 
 
 static struct rc_map_table empty[] = {
-	{ 0x2a, KEY_COFFEE },
+	{ RC_TYPE_OTHER, 0x2a, KEY_COFFEE },
 };
 
 static struct rc_map_list empty_map = {
@@ -112,7 +112,6 @@ static struct rc_map_list empty_map = {
  * ir_create_table() - initializes a scancode table
  * @rc_map:	the rc_map to initialize
  * @name:	name to assign to the table
- * @rc_type:	ir type to assign to the new table
  * @size:	initial size of the table
  * @return:	zero on success or a negative error code
  *
@@ -120,10 +119,9 @@ static struct rc_map_list empty_map = {
  * memory to hold at least the specified number of elements.
  */
 static int ir_create_table(struct rc_map *rc_map,
-			   const char *name, u64 rc_type, size_t size)
+			   const char *name, size_t size)
 {
 	rc_map->name = name;
-	rc_map->rc_type = rc_type;
 	rc_map->alloc = roundup_pow_of_two(size * sizeof(struct rc_map_table));
 	rc_map->size = rc_map->alloc / sizeof(struct rc_map_table);
 	rc_map->scan = kmalloc(rc_map->alloc, GFP_KERNEL);
@@ -218,16 +216,20 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
 
 	/* Did the user wish to remove the mapping? */
 	if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
-		IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
-			   index, rc_map->scan[index].scancode);
+		IR_dprintk(1, "#%d: Deleting proto 0x%04x, scan 0x%08llx\n",
+			   index, rc_map->scan[index].protocol,
+			   (unsigned long long)rc_map->scan[index].scancode);
 		rc_map->len--;
 		memmove(&rc_map->scan[index], &rc_map->scan[index+ 1],
 			(rc_map->len - index) * sizeof(struct rc_map_table));
 	} else {
-		IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
+		IR_dprintk(1, "#%d: %s proto 0x%04x, scan 0x%08llx "
+			   "with key 0x%04x\n",
 			   index,
 			   old_keycode == KEY_RESERVED ? "New" : "Replacing",
-			   rc_map->scan[index].scancode, new_keycode);
+			   rc_map->scan[index].protocol,
+			   (unsigned long long)rc_map->scan[index].scancode,
+			   new_keycode);
 		rc_map->scan[index].keycode = new_keycode;
 		__set_bit(new_keycode, dev->input_dev->keybit);
 	}
@@ -254,9 +256,9 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
  * ir_establish_scancode() - set a keycode in the scancode->keycode table
  * @dev:	the struct rc_dev device descriptor
  * @rc_map:	scancode table to be searched
- * @scancode:	the desired scancode
- * @resize:	controls whether we allowed to resize the table to
- *		accommodate not yet present scancodes
+ * @entry:	the entry to be added to the table
+ * @resize:	controls whether we are allowed to resize the table to
+ *		accomodate not yet present scancodes
  * @return:	index of the mapping containing scancode in question
  *		or -1U in case of failure.
  *
@@ -266,7 +268,7 @@ static unsigned int ir_update_mapping(struct rc_dev *dev,
  */
 static unsigned int ir_establish_scancode(struct rc_dev *dev,
 					  struct rc_map *rc_map,
-					  unsigned int scancode,
+					  struct rc_map_table *entry,
 					  bool resize)
 {
 	unsigned int i;
@@ -280,16 +282,27 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev,
 	 * indicate the valid bits of the scancodes.
 	 */
 	if (dev->scanmask)
-		scancode &= dev->scanmask;
+		entry->scancode &= dev->scanmask;
 
-	/* First check if we already have a mapping for this ir command */
+	/*
+	 * First check if we already have a mapping for this command.
+	 * Note that the keytable is sorted first on protocol and second
+	 * on scancode (lowest to highest).
+	 */
 	for (i = 0; i < rc_map->len; i++) {
-		if (rc_map->scan[i].scancode == scancode)
-			return i;
+		if (rc_map->scan[i].protocol < entry->protocol)
+			continue;
 
-		/* Keytable is sorted from lowest to highest scancode */
-		if (rc_map->scan[i].scancode >= scancode)
+		if (rc_map->scan[i].protocol > entry->protocol)
 			break;
+
+		if (rc_map->scan[i].scancode < entry->scancode)
+			continue;
+
+		if (rc_map->scan[i].scancode > entry->scancode)
+			break;
+
+		return i;
 	}
 
 	/* No previous mapping found, we might need to grow the table */
@@ -302,7 +315,8 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev,
 	if (i < rc_map->len)
 		memmove(&rc_map->scan[i + 1], &rc_map->scan[i],
 			(rc_map->len - i) * sizeof(struct rc_map_table));
-	rc_map->scan[i].scancode = scancode;
+	rc_map->scan[i].scancode = entry->scancode;
+	rc_map->scan[i].protocol = entry->protocol;
 	rc_map->scan[i].keycode = KEY_RESERVED;
 	rc_map->len++;
 
@@ -325,10 +339,12 @@ static int ir_setkeycode(struct input_dev *idev,
 	struct rc_dev *rdev = input_get_drvdata(idev);
 	struct rc_map *rc_map = &rdev->rc_map;
 	unsigned int index;
-	unsigned int scancode;
+	struct rc_map_table entry;
 	int retval = 0;
 	unsigned long flags;
 
+	entry.keycode = ke->keycode;
+
 	spin_lock_irqsave(&rc_map->lock, flags);
 
 	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
@@ -337,19 +353,52 @@ static int ir_setkeycode(struct input_dev *idev,
 			retval = -EINVAL;
 			goto out;
 		}
-	} else {
+	} else if (ke->len == sizeof(int)) {
+		/* Legacy EVIOCSKEYCODE ioctl */
+		u32 scancode;
 		retval = input_scancode_to_scalar(ke, &scancode);
 		if (retval)
 			goto out;
+		entry.scancode = scancode;
+
+		/* Some heuristics to guess the correct protocol */
+		if (hweight64(rdev->enabled_protocols) == 1)
+			entry.protocol = rdev->enabled_protocols;
+		else if (hweight64(rdev->allowed_protos) == 1)
+			entry.protocol = rdev->allowed_protos;
+		else if (rc_map->len > 0)
+			entry.protocol = rc_map->scan[0].protocol;
+		else
+			entry.protocol = RC_TYPE_OTHER;
+
+		index = ir_establish_scancode(rdev, rc_map, &entry, true);
+		if (index >= rc_map->len) {
+			retval = -ENOMEM;
+			goto out;
+		}
+	} else if (ke->len == sizeof(struct rc_scancode)) {
+		/* New EVIOCSKEYCODE_V2 ioctl */
+		const struct rc_keymap_entry *rke = (struct rc_keymap_entry *)ke;
+		entry.protocol = rke->rc.protocol;
+		entry.scancode = rke->rc.scancode;
 
-		index = ir_establish_scancode(rdev, rc_map, scancode, true);
+		if (rke->rc.reserved[0] || rke->rc.reserved[1] || rke->rc.reserved[1]) {
+			retval = -EINVAL;
+			goto out;
+		}
+
+		index = ir_establish_scancode(rdev, rc_map, &entry, true);
 		if (index >= rc_map->len) {
 			retval = -ENOMEM;
 			goto out;
 		}
+	} else {
+		retval = -EINVAL;
+		goto out;
 	}
 
-	*old_keycode = ir_update_mapping(rdev, rc_map, index, ke->keycode);
+	if (retval == 0)
+		*old_keycode = ir_update_mapping(rdev, rc_map, index, ke->keycode);
 
 out:
 	spin_unlock_irqrestore(&rc_map->lock, flags);
@@ -369,11 +418,11 @@ static int ir_setkeytable(struct rc_dev *dev,
 			  const struct rc_map *from)
 {
 	struct rc_map *rc_map = &dev->rc_map;
+	struct rc_map_table entry;
 	unsigned int i, index;
 	int rc;
 
-	rc = ir_create_table(rc_map, from->name,
-			     from->rc_type, from->size);
+	rc = ir_create_table(rc_map, from->name, from->size);
 	if (rc)
 		return rc;
 
@@ -381,15 +430,15 @@ static int ir_setkeytable(struct rc_dev *dev,
 		   rc_map->size, rc_map->alloc);
 
 	for (i = 0; i < from->size; i++) {
-		index = ir_establish_scancode(dev, rc_map,
-					      from->scan[i].scancode, false);
+		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;
 			break;
 		}
 
-		ir_update_mapping(dev, rc_map, index,
-				  from->scan[i].keycode);
+		ir_update_mapping(dev, rc_map, index, from->scan[i].keycode);
 	}
 
 	if (rc)
@@ -401,6 +450,7 @@ static int ir_setkeytable(struct rc_dev *dev,
 /**
  * ir_lookup_by_scancode() - locate mapping by scancode
  * @rc_map:	the struct rc_map to search
+ * @protocol:	protocol to look for in the table
  * @scancode:	scancode to look for in the table
  * @return:	index in the table, -1U if not found
  *
@@ -408,17 +458,24 @@ static int ir_setkeytable(struct rc_dev *dev,
  * given scancode.
  */
 static unsigned int ir_lookup_by_scancode(const struct rc_map *rc_map,
-					  unsigned int scancode)
+					  u16 protocol, u64 scancode)
 {
 	int start = 0;
 	int end = rc_map->len - 1;
 	int mid;
+	struct rc_map_table *m;
 
 	while (start <= end) {
 		mid = (start + end) / 2;
-		if (rc_map->scan[mid].scancode < scancode)
+		m = &rc_map->scan[mid];
+
+		if (m->protocol < protocol)
 			start = mid + 1;
-		else if (rc_map->scan[mid].scancode > scancode)
+		else if (m->protocol > protocol)
+			end = mid - 1;
+		else if (m->scancode < scancode)
+			start = mid + 1;
+		else if (m->scancode > scancode)
 			end = mid - 1;
 		else
 			return mid;
@@ -439,33 +496,66 @@ static unsigned int ir_lookup_by_scancode(const struct rc_map *rc_map,
 static int ir_getkeycode(struct input_dev *idev,
 			 struct input_keymap_entry *ke)
 {
+	struct rc_keymap_entry *rke = (struct rc_keymap_entry *)ke;
 	struct rc_dev *rdev = input_get_drvdata(idev);
 	struct rc_map *rc_map = &rdev->rc_map;
 	struct rc_map_table *entry;
 	unsigned long flags;
 	unsigned int index;
-	unsigned int scancode;
 	int retval;
 
 	spin_lock_irqsave(&rc_map->lock, flags);
 
 	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
 		index = ke->index;
-	} else {
+	} else if (ke->len == sizeof(int)) {
+		/* Legacy EVIOCGKEYCODE ioctl */
+		u32 scancode;
+		u16 protocol;
+
 		retval = input_scancode_to_scalar(ke, &scancode);
 		if (retval)
 			goto out;
 
-		index = ir_lookup_by_scancode(rc_map, scancode);
+		/* Some heuristics to guess the correct protocol */
+		if (hweight64(rdev->enabled_protocols) == 1)
+			protocol = rdev->enabled_protocols;
+		else if (hweight64(rdev->allowed_protos) == 1)
+			protocol = rdev->allowed_protos;
+		else if (rc_map->len > 0)
+			protocol = rc_map->scan[0].protocol;
+		else
+			protocol = RC_TYPE_OTHER;
+
+		index = ir_lookup_by_scancode(rc_map, protocol, scancode);
+
+	} else if (ke->len == sizeof(struct rc_scancode)) {
+		/* New EVIOCGKEYCODE_V2 ioctl */
+		if (rke->rc.reserved[0] || rke->rc.reserved[1] || rke->rc.reserved[1]) {
+			retval = -EINVAL;
+			goto out;
+		}
+
+		index = ir_lookup_by_scancode(rc_map,
+					      rke->rc.protocol, rke->rc.scancode);
+
+	} else {
+		retval = -EINVAL;
+		goto out;
 	}
 
 	if (index < rc_map->len) {
 		entry = &rc_map->scan[index];
-
 		ke->index = index;
 		ke->keycode = entry->keycode;
-		ke->len = sizeof(entry->scancode);
-		memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
+		if (ke->len == sizeof(int)) {
+			u32 scancode = entry->scancode;
+			memcpy(ke->scancode, &scancode, sizeof(scancode));
+		} else {
+			ke->len = sizeof(struct rc_scancode);
+			rke->rc.protocol = entry->protocol;
+			rke->rc.scancode = entry->scancode;
+		}
 
 	} else if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) {
 		/*
@@ -490,6 +580,7 @@ out:
 /**
  * rc_g_keycode_from_table() - gets the keycode that corresponds to a scancode
  * @dev:	the struct rc_dev descriptor of the device
+ * @protocol:	the protocol to look for
  * @scancode:	the scancode to look for
  * @return:	the corresponding keycode, or KEY_RESERVED
  *
@@ -497,7 +588,8 @@ out:
  * keycode. Normally it should not be used since drivers should have no
  * interest in keycodes.
  */
-u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode)
+u32 rc_g_keycode_from_table(struct rc_dev *dev,
+			    enum rc_type protocol, u64 scancode)
 {
 	struct rc_map *rc_map = &dev->rc_map;
 	unsigned int keycode;
@@ -506,15 +598,16 @@ u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode)
 
 	spin_lock_irqsave(&rc_map->lock, flags);
 
-	index = ir_lookup_by_scancode(rc_map, scancode);
+	index = ir_lookup_by_scancode(rc_map, protocol, scancode);
 	keycode = index < rc_map->len ?
 			rc_map->scan[index].keycode : KEY_RESERVED;
 
 	spin_unlock_irqrestore(&rc_map->lock, flags);
 
 	if (keycode != KEY_RESERVED)
-		IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
-			   dev->input_name, scancode, keycode);
+		IR_dprintk(1, "%s: protocol 0x%04x scancode 0x%08llx keycode 0x%02x\n",
+			   dev->input_name, protocol,
+			   (unsigned long long)scancode, keycode);
 
 	return keycode;
 }
@@ -616,6 +709,7 @@ EXPORT_SYMBOL_GPL(rc_repeat);
 /**
  * ir_do_keydown() - internal function to process a keypress
  * @dev:	the struct rc_dev descriptor of the device
+ * @protocol:	the protocol of the keypress
  * @scancode:   the scancode of the keypress
  * @keycode:    the keycode of the keypress
  * @toggle:     the toggle value of the keypress
@@ -623,10 +717,11 @@ EXPORT_SYMBOL_GPL(rc_repeat);
  * This function is used internally to register a keypress, it must be
  * called with keylock held.
  */
-static void ir_do_keydown(struct rc_dev *dev, int scancode,
-			  u32 keycode, u8 toggle)
+static void ir_do_keydown(struct rc_dev *dev, u16 protocol,
+			  u64 scancode, u32 keycode, u8 toggle)
 {
 	bool new_event = !dev->keypressed ||
+			 dev->last_protocol != protocol ||
 			 dev->last_scancode != scancode ||
 			 dev->last_toggle != toggle;
 
@@ -638,36 +733,39 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode,
 	if (new_event && keycode != KEY_RESERVED) {
 		/* Register a keypress */
 		dev->keypressed = true;
+		dev->last_protocol = protocol;
 		dev->last_scancode = scancode;
 		dev->last_toggle = toggle;
 		dev->last_keycode = keycode;
 
 		IR_dprintk(1, "%s: key down event, "
-			   "key 0x%04x, scancode 0x%04x\n",
-			   dev->input_name, keycode, scancode);
+			   "key 0x%04x, protocol 0x%04x, scancode 0x%08llx\n",
+			   dev->input_name, keycode, protocol,
+			   (long long unsigned)scancode);
 		input_report_key(dev->input_dev, keycode, 1);
 	}
-
 	input_sync(dev->input_dev);
 }
 
 /**
  * rc_keydown() - generates input event for a key press
  * @dev:	the struct rc_dev descriptor of the device
- * @scancode:   the scancode that we're seeking
+ * @protocol:	the protocol for the keypress
+ * @scancode:   the scancode for the keypress
  * @toggle:     the toggle value (protocol dependent, if the protocol doesn't
  *              support toggle values, this should be set to zero)
  *
  * This routine is used to signal that a key has been pressed on the
  * remote control.
  */
-void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle)
+void rc_keydown(struct rc_dev *dev, enum rc_type protocol,
+		u64 scancode, u8 toggle)
 {
 	unsigned long flags;
-	u32 keycode = rc_g_keycode_from_table(dev, scancode);
+	u32 keycode = rc_g_keycode_from_table(dev, protocol, scancode);
 
 	spin_lock_irqsave(&dev->keylock, flags);
-	ir_do_keydown(dev, scancode, keycode, toggle);
+	ir_do_keydown(dev, protocol, scancode, keycode, toggle);
 
 	if (dev->keypressed) {
 		dev->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT);
@@ -681,6 +779,7 @@ EXPORT_SYMBOL_GPL(rc_keydown);
  * rc_keydown_notimeout() - generates input event for a key press without
  *                          an automatic keyup event at a later time
  * @dev:	the struct rc_dev descriptor of the device
+ * @protocol:	the protocol for the keypress
  * @scancode:   the scancode that we're seeking
  * @toggle:     the toggle value (protocol dependent, if the protocol doesn't
  *              support toggle values, this should be set to zero)
@@ -688,13 +787,14 @@ EXPORT_SYMBOL_GPL(rc_keydown);
  * This routine is used to signal that a key has been pressed on the
  * remote control. The driver must manually call rc_keyup() at a later stage.
  */
-void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle)
+void rc_keydown_notimeout(struct rc_dev *dev, enum rc_type protocol,
+			  u64 scancode, u8 toggle)
 {
 	unsigned long flags;
-	u32 keycode = rc_g_keycode_from_table(dev, scancode);
+	u32 keycode = rc_g_keycode_from_table(dev, protocol, scancode);
 
 	spin_lock_irqsave(&dev->keylock, flags);
-	ir_do_keydown(dev, scancode, keycode, toggle);
+	ir_do_keydown(dev, protocol, scancode, keycode, toggle);
 	spin_unlock_irqrestore(&dev->keylock, flags);
 }
 EXPORT_SYMBOL_GPL(rc_keydown_notimeout);
@@ -783,13 +883,12 @@ static ssize_t show_protocols(struct device *device,
 
 	mutex_lock(&dev->lock);
 
-	if (dev->driver_type == RC_DRIVER_SCANCODE) {
-		enabled = dev->rc_map.rc_type;
+	enabled = dev->enabled_protocols;
+	if (dev->driver_type == RC_DRIVER_SCANCODE)
 		allowed = dev->allowed_protos;
-	} else if (dev->raw) {
-		enabled = dev->raw->enabled_protocols;
+	else if (dev->raw)
 		allowed = ir_raw_get_allowed_protocols();
-	} else
+	else
 		return -ENODEV;
 
 	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
@@ -845,7 +944,6 @@ static ssize_t store_protocols(struct device *device,
 	u64 type;
 	u64 mask;
 	int rc, i, count = 0;
-	unsigned long flags;
 	ssize_t ret;
 
 	/* Device is being removed */
@@ -854,16 +952,14 @@ static ssize_t store_protocols(struct device *device,
 
 	mutex_lock(&dev->lock);
 
-	if (dev->driver_type == RC_DRIVER_SCANCODE)
-		type = dev->rc_map.rc_type;
-	else if (dev->raw)
-		type = dev->raw->enabled_protocols;
-	else {
+	if (dev->driver_type != RC_DRIVER_SCANCODE && !dev->raw) {
 		IR_dprintk(1, "Protocol switching not supported\n");
 		ret = -EINVAL;
 		goto out;
 	}
 
+	type = dev->enabled_protocols;
+
 	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
 		if (!*tmp)
 			break;
@@ -919,13 +1015,7 @@ static ssize_t store_protocols(struct device *device,
 		}
 	}
 
-	if (dev->driver_type == RC_DRIVER_SCANCODE) {
-		spin_lock_irqsave(&dev->rc_map.lock, flags);
-		dev->rc_map.rc_type = type;
-		spin_unlock_irqrestore(&dev->rc_map.lock, flags);
-	} else {
-		dev->raw->enabled_protocols = type;
-	}
+	dev->enabled_protocols = type;
 
 	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
 		   (long long)type);
@@ -1125,8 +1215,7 @@ int rc_register_device(struct rc_dev *dev)
 	}
 
 	if (dev->change_protocol) {
-		u64 rc_type = (1 << rc_map->rc_type);
-		rc = dev->change_protocol(dev, &rc_type);
+		rc = dev->change_protocol(dev, &dev->enabled_protocols);
 		if (rc < 0)
 			goto out_raw;
 	}
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c
index 8131416..6a32274 100644
--- a/drivers/media/usb/dvb-usb-v2/af9015.c
+++ b/drivers/media/usb/dvb-usb-v2/af9015.c
@@ -1192,7 +1192,7 @@ 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, state->rc_keycode, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC, state->rc_keycode, 0);
 		state->rc_repeat = buf[6];
 		return ret;
 	}
@@ -1222,7 +1222,7 @@ static int af9015_rc_query(struct dvb_usb_device *d)
 			state->rc_keycode = buf[12] << 24 | buf[13] << 16 |
 					buf[14] << 8 | buf[15];
 		}
-		rc_keydown(d->rc_dev, state->rc_keycode, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC, 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/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index 9ddb70f..f9060fb 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -1040,7 +1040,8 @@ static int anysee_rc_query(struct dvb_usb_device *d)
 	if (ircode[0]) {
 		dev_dbg(&d->udev->dev, "%s: key pressed %02x\n", __func__,
 				ircode[1]);
-		rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC,
+			   RC_SCANCODE_NEC(0x08, ircode[1]), 0);
 	}
 
 	return 0;
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
index d75dbf2..d3e6922 100644
--- a/drivers/media/usb/dvb-usb-v2/az6007.c
+++ b/drivers/media/usb/dvb-usb-v2/az6007.c
@@ -193,24 +193,27 @@ static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff)
 static int az6007_rc_query(struct dvb_usb_device *d)
 {
 	struct az6007_device_state *st = d_to_priv(d);
-	unsigned code = 0;
+	u64 code;
 
 	az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
 
 	if (st->data[1] == 0x44)
 		return 0;
 
-	if ((st->data[1] ^ st->data[2]) == 0xff)
-		code = st->data[1];
-	else
-		code = st->data[1] << 8 | st->data[2];
-
-	if ((st->data[3] ^ st->data[4]) == 0xff)
-		code = code << 8 | st->data[3];
-	else
-		code = code << 16 | st->data[3] << 8 | st->data[4];
+	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]);
+	}
 
-	rc_keydown(d->rc_dev, code, st->data[5]);
+	rc_keydown(d->rc_dev, RC_TYPE_NEC, code, st->data[5]);
 
 	return 0;
 }
diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c
index 0b1ddc2..f23c5b7 100644
--- a/drivers/media/usb/dvb-usb-v2/it913x.c
+++ b/drivers/media/usb/dvb-usb-v2/it913x.c
@@ -313,7 +313,12 @@ static int it913x_rc_query(struct dvb_usb_device *d)
 {
 	u8 ibuf[4];
 	int ret;
-	u32 key;
+	u16 device, command;
+	u64 scancode;
+
+	if (!d->rc_dev)
+		return 0;
+
 	/* Avoid conflict with frontends*/
 	mutex_lock(&d->i2c_mutex);
 
@@ -321,12 +326,12 @@ static int it913x_rc_query(struct dvb_usb_device *d)
 		0, 0, &ibuf[0], sizeof(ibuf));
 
 	if ((ibuf[2] + ibuf[3]) == 0xff) {
-		key = ibuf[2];
-		key += ibuf[0] << 16;
-		key += ibuf[1] << 8;
-		deb_info(1, "NEC Extended Key =%08x", key);
-		if (d->rc_dev != NULL)
-			rc_keydown(d->rc_dev, key, 0);
+		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);
 	}
 
 	mutex_unlock(&d->i2c_mutex);
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index 6a2445b..61ba44c 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -293,7 +293,7 @@ static void lme2510_int_response(struct urb *lme_urb)
 				deb_info(1, "INT Key =%08x", key);
 				if (adap_to_d(adap)->rc_dev != NULL)
 					rc_keydown(adap_to_d(adap)->rc_dev,
-						key, 0);
+						   RC_TYPE_UNKNOWN, key, 0);
 			}
 			break;
 		case 0xbb:
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 5c3c6df..887d0f5 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1028,7 +1028,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
 	int ret, i;
 	struct rtl28xxu_priv *priv = d->priv;
 	u8 buf[5];
-	u32 rc_code;
+	u64 rc_code;
 	struct rtl28xxu_reg_val rc_nec_tab[] = {
 		{ 0x3033, 0x80 },
 		{ 0x3020, 0x43 },
@@ -1065,19 +1065,22 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
 		if (buf[2] == (u8) ~buf[3]) {
 			if (buf[0] == (u8) ~buf[1]) {
 				/* NEC standard (16 bit) */
-				rc_code = buf[0] << 8 | buf[2];
+				rc_code = RC_SCANCODE_NEC(buf[0], buf[2]);
 			} else {
 				/* NEC extended (24 bit) */
-				rc_code = buf[0] << 16 |
-						buf[1] << 8 | buf[2];
+				rc_code = RC_SCANCODE_NECX(buf[0] << 8 |
+							   buf[1],
+							   buf[2]);
 			}
 		} else {
 			/* NEC full (32 bit) */
-			rc_code = 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_code, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0);
 
 		ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
 		if (ret)
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
index 19b5ed2..2a97a99 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -747,7 +747,7 @@ static void dib0700_rc_urb_completion(struct urb *purb)
 		goto resubmit;
 	}
 
-	rc_keydown(d->rc_dev, keycode, toggle);
+	rc_keydown(d->rc_dev, d->props.rc.core.protocol, keycode, toggle);
 
 resubmit:
 	/* Clean the buffer before we requeue */
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index 1179842..b1b94f7 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -489,7 +489,7 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
 static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 {
 	u8 key[4];
-	u32 keycode;
+	u64 keycode;
 	u8 toggle;
 	int i;
 	struct dib0700_state *st = d->priv;
@@ -524,17 +524,17 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 		    (key[3] == 0xff))
 			keycode = d->last_event;
 		else {
-			keycode = key[3-2] << 8 | key[3-3];
+			keycode = RC_SCANCODE_NEC(key[3-2], key[3-3]);
 			d->last_event = keycode;
 		}
 
-		rc_keydown(d->rc_dev, keycode, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_NEC, keycode, 0);
 		break;
 	default:
 		/* RC-5 protocol changes toggle bit on new keypress */
-		keycode = key[3-2] << 8 | key[3-3];
+		keycode = RC_SCANCODE_RC5(key[3-2], key[3-3]);
 		toggle = key[3-1];
-		rc_keydown(d->rc_dev, keycode, toggle);
+		rc_keydown(d->rc_dev, RC_TYPE_RC5, keycode, toggle);
 
 		break;
 	}
diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h
index ce4c4e3..4c164d9 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb.h
+++ b/drivers/media/usb/dvb-usb/dvb-usb.h
@@ -447,7 +447,7 @@ struct dvb_usb_device {
 	struct input_dev *input_dev;
 	char rc_phys[64];
 	struct delayed_work rc_query_work;
-	u32 last_event;
+	u64 last_event;
 	int last_state;
 
 	struct module *owner;
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c
index d1ddfa1..b87f349 100644
--- a/drivers/media/usb/dvb-usb/pctv452e.c
+++ b/drivers/media/usb/dvb-usb/pctv452e.c
@@ -96,7 +96,7 @@ struct pctv452e_state {
 
 	u8 c;	   /* transaction counter, wraps around...  */
 	u8 initialized; /* set to 1 if 0x15 has been sent */
-	u16 last_rc_key;
+	u64 last_scancode;
 };
 
 static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
@@ -565,15 +565,14 @@ static int pctv452e_rc_query(struct dvb_usb_device *d)
 
 	if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
 		/* got a "press" event */
-		state->last_rc_key = (rx[7] << 8) | rx[6];
+		state->last_scancode = RC_SCANCODE_RC5(rx[7], rx[6]);
 		if (debug > 2)
 			info("%s: cmd=0x%02x sys=0x%02x\n",
 				__func__, rx[6], rx[7]);
-
-		rc_keydown(d->rc_dev, state->last_rc_key, 0);
-	} else if (state->last_rc_key) {
+		rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_scancode, 0);
+	} else if (state->last_scancode) {
 		rc_keyup(d->rc_dev);
-		state->last_rc_key = 0;
+		state->last_scancode = 0;
 	}
 
 	return 0;
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c
index c5be462..ad57689 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.c
+++ b/drivers/media/usb/dvb-usb/ttusb2.c
@@ -440,7 +440,7 @@ static int tt3650_rc_query(struct dvb_usb_device *d)
 		/* got a "press" event */
 		st->last_rc_key = (rx[3] << 8) | rx[2];
 		deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
-		rc_keydown(d->rc_dev, st->last_rc_key, 0);
+		rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, st->last_rc_key, 0);
 	} else if (st->last_rc_key) {
 		rc_keyup(d->rc_dev);
 		st->last_rc_key = 0;
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index ca62b99..a5fa566 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -756,6 +756,7 @@ struct em28xx_board em28xx_boards[] = {
 		.tuner_type   = TUNER_TNF_5335MF,
 		.tda9887_conf = TDA9887_PRESENT,
 		.ir_codes     = RC_MAP_GADMEI_RM008Z,
+		.ir_protocol  = RC_BIT_UNKNOWN,
 		.decoder      = EM28XX_SAA711X,
 		.xclk         = EM28XX_XCLK_FREQUENCY_12MHZ,
 		.input        = { {
@@ -989,6 +990,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb      = 1,
 		.dvb_gpio     = hauppauge_wintv_hvr_900_digital,
 		.ir_codes     = RC_MAP_HAUPPAUGE,
+		.ir_protocol  = RC_BIT_RC5,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1016,6 +1018,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb      = 1,
 		.dvb_gpio     = hauppauge_wintv_hvr_900R2_digital,
 		.ir_codes     = RC_MAP_HAUPPAUGE,
+		.ir_protocol  = RC_BIT_RC5,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1042,6 +1045,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
 		.ir_codes       = RC_MAP_HAUPPAUGE,
+		.ir_protocol    = RC_BIT_RC5,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1068,6 +1072,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
 		.ir_codes       = RC_MAP_HAUPPAUGE,
+		.ir_protocol    = RC_BIT_RC5,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1094,6 +1099,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
 		.ir_codes       = RC_MAP_PINNACLE_PCTV_HD,
+		.ir_protocol    = RC_BIT_UNKNOWN,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1120,6 +1126,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
 		.ir_codes       = RC_MAP_ATI_TV_WONDER_HD_600,
+		.ir_protocol    = RC_BIT_UNKNOWN,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1146,6 +1153,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb        = 1,
 		.dvb_gpio       = default_digital,
 		.ir_codes       = RC_MAP_TERRATEC_CINERGY_XS,
+		.ir_protocol	= RC_BIT_NEC,
 		.xclk           = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1508,6 +1516,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb	= 1,
 		.dvb_gpio	= em2882_kworld_315u_digital,
 		.ir_codes	= RC_MAP_KWORLD_315U,
+		.ir_protocol    = RC_BIT_NEC,
 		.xclk		= EM28XX_XCLK_FREQUENCY_12MHZ,
 		.i2c_speed	= EM28XX_I2C_CLK_WAIT_ENABLE,
 		/* Analog mode - still not ready */
@@ -1639,6 +1648,7 @@ struct em28xx_board em28xx_boards[] = {
 		.dvb_gpio     = kworld_330u_digital,
 		.xclk         = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
 		.ir_codes     = RC_MAP_KWORLD_315U,
+		.ir_protocol  = RC_BIT_NEC,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
@@ -1662,6 +1672,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb      = 1,
 		.dvb_gpio     = hauppauge_wintv_hvr_900_digital,
 		.ir_codes     = RC_MAP_TERRATEC_CINERGY_XS,
+		.ir_protocol  = RC_BIT_NEC,
 		.xclk         = EM28XX_XCLK_FREQUENCY_12MHZ,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -1755,6 +1766,7 @@ struct em28xx_board em28xx_boards[] = {
 		.decoder      = EM28XX_TVP5150,
 		.tuner_gpio   = default_tuner_gpio,
 		.ir_codes     = RC_MAP_KAIOMY,
+		.ir_protocol  = RC_BIT_UNKNOWN,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
@@ -1871,6 +1883,7 @@ struct em28xx_board em28xx_boards[] = {
 		.has_dvb      = 1,
 		.dvb_gpio     = evga_indtube_digital,
 		.ir_codes     = RC_MAP_EVGA_INDTUBE,
+		.ir_protocol  = RC_BIT_UNKNOWN,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
@@ -2659,7 +2672,7 @@ static int em28xx_hint_board(struct em28xx *dev)
 	return -1;
 }
 
-static void em28xx_card_setup(struct em28xx *dev)
+void em28xx_card_setup(struct em28xx *dev)
 {
 	/*
 	 * If the device can be a webcam, seek for a sensor.
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 660bf80..d9cc536 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -70,7 +70,6 @@ struct em28xx_IR {
 	/* poll external decoder */
 	int polling;
 	struct delayed_work work;
-	unsigned int full_code:1;
 	unsigned int last_readcount;
 
 	int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
@@ -297,15 +296,25 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
 		dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__,
 			poll_result.toggle_bit, poll_result.read_count,
 			poll_result.rc_address, poll_result.rc_data[0]);
-		if (ir->full_code)
-			rc_keydown(ir->rc,
-				   poll_result.rc_address << 8 |
-				   poll_result.rc_data[0],
+		switch (ir->rc->enabled_protocols) {
+		case RC_BIT_RC5:
+			rc_keydown(ir->rc, RC_TYPE_RC5,
+				   RC_SCANCODE_RC5(poll_result.rc_address,
+						   poll_result.rc_data[0]),
 				   poll_result.toggle_bit);
-		else
-			rc_keydown(ir->rc,
+			break;
+		case RC_BIT_NEC:
+			rc_keydown(ir->rc, RC_TYPE_NEC,
+				   RC_SCANCODE_NEC(poll_result.rc_address,
+						   poll_result.rc_data[0]),
+				   poll_result.toggle_bit);
+			break;
+		default:
+			rc_keydown(ir->rc, RC_TYPE_UNKNOWN,
 				   poll_result.rc_data[0],
 				   poll_result.toggle_bit);
+			break;
+		}
 
 		if (ir->dev->chip_id == CHIP_ID_EM2874 ||
 		    ir->dev->chip_id == CHIP_ID_EM2884)
@@ -356,12 +365,10 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_type)
 
 	if (*rc_type & RC_BIT_RC5) {
 		dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
-		ir->full_code = 1;
 		*rc_type = RC_BIT_RC5;
 	} else if (*rc_type & RC_BIT_NEC) {
 		dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
 		ir_config = EM2874_IR_NEC;
-		ir->full_code = 1;
 		*rc_type = RC_BIT_NEC;
 	} else if (*rc_type != RC_BIT_UNKNOWN)
 		rc = -EINVAL;
@@ -555,11 +562,12 @@ static int em28xx_ir_init(struct em28xx *dev)
 	rc->open = em28xx_ir_start;
 	rc->close = em28xx_ir_stop;
 
-	/* By default, keep protocol field untouched */
-	rc_type = RC_BIT_UNKNOWN;
+	/* Set default protocol */
+	rc_type = dev->board.ir_protocol;
 	err = em28xx_ir_change_protocol(rc, &rc_type);
 	if (err)
 		goto err_out_free;
+	rc->enabled_protocols = rc_type;
 
 	/* This is how often we ask the chip for IR information */
 	ir->polling = 100; /* ms */
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 8757523..745a24c 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -413,6 +413,7 @@ struct em28xx_board {
 	struct em28xx_input       input[MAX_EM28XX_INPUT];
 	struct em28xx_input	  radio;
 	char			  *ir_codes;
+	u64			  ir_protocol; /* default protocol */
 };
 
 struct em28xx_eeprom {
diff --git a/drivers/media/usb/tm6000/tm6000-cards.c b/drivers/media/usb/tm6000/tm6000-cards.c
index 034659b..e45c047 100644
--- a/drivers/media/usb/tm6000/tm6000-cards.c
+++ b/drivers/media/usb/tm6000/tm6000-cards.c
@@ -85,6 +85,7 @@ struct tm6000_board {
 	struct tm6000_input	rinput;
 
 	char		*ir_codes;
+	u64		ir_protocol;
 };
 
 static struct tm6000_board tm6000_boards[] = {
@@ -481,6 +482,7 @@ static struct tm6000_board tm6000_boards[] = {
 			.ir		= TM6010_GPIO_0,
 		},
 		.ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+		.ir_protocol = RC_BIT_UNKNOWN,
 		.vinput = { {
 			.type	= TM6000_INPUT_TV,
 			.vmux	= TM6000_VMUX_VIDEO_B,
diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c
index 8a6bbf1..e743be4 100644
--- a/drivers/media/usb/tm6000/tm6000-input.c
+++ b/drivers/media/usb/tm6000/tm6000-input.c
@@ -51,10 +51,6 @@ MODULE_PARM_DESC(enable_ir, "ir clock, in MHz");
 		printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
 	} while (0)
 
-struct tm6000_ir_poll_result {
-	u16 rc_data;
-};
-
 struct tm6000_IR {
 	struct tm6000_core	*dev;
 	struct rc_dev		*rc;
@@ -162,12 +158,42 @@ static int tm6000_ir_config(struct tm6000_IR *ir)
 	return 0;
 }
 
+static void tm6000_ir_keydown(struct tm6000_IR *ir,
+			      const char *buf, unsigned int len)
+{
+	u8 device, command;
+	u64 scancode;
+	enum rc_type protocol;
+
+	if (len < 1)
+		return;
+
+	command = buf[0];
+	device = (len > 1 ? buf[1] : 0x0);
+	switch (ir->rc_type) {
+	case RC_BIT_RC5:
+		protocol = RC_TYPE_RC5;
+		scancode = RC_SCANCODE_RC5(device, command);
+		break;
+	case RC_BIT_NEC:
+		protocol = RC_TYPE_NEC;
+		scancode = RC_SCANCODE_NEC(device, command);
+		break;
+	default:
+		protocol = RC_TYPE_OTHER;
+		scancode = RC_SCANCODE_OTHER(device << 8 | command);
+		break;
+	}
+
+	dprintk(1, "%s, protocol: 0x%04x, scancode: 0x%08llx\n",
+		__func__, protocol, (unsigned long long)scancode);
+	rc_keydown(ir->rc, protocol, scancode, 0);
+}
+
 static void tm6000_ir_urb_received(struct urb *urb)
 {
 	struct tm6000_core *dev = urb->context;
 	struct tm6000_IR *ir = dev->ir;
-	struct tm6000_ir_poll_result poll_result;
-	char *buf;
 
 	dprintk(2, "%s\n",__func__);
 	if (urb->status < 0 || urb->actual_length <= 0) {
@@ -177,19 +203,14 @@ static void tm6000_ir_urb_received(struct urb *urb)
 		schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
 		return;
 	}
-	buf = urb->transfer_buffer;
 
 	if (ir_debug)
 		print_hex_dump(KERN_DEBUG, "tm6000: IR data: ",
 			       DUMP_PREFIX_OFFSET,16, 1,
-			       buf, urb->actual_length, false);
-
-	poll_result.rc_data = buf[0];
-	if (urb->actual_length > 1)
-		poll_result.rc_data |= buf[1] << 8;
+			       urb->transfer_buffer, urb->actual_length,
+			       false);
 
-	dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
-	rc_keydown(ir->rc, poll_result.rc_data, 0);
+	tm6000_ir_keydown(ir, urb->transfer_buffer, urb->actual_length);
 
 	usb_submit_urb(urb, GFP_ATOMIC);
 	/*
@@ -204,7 +225,6 @@ static void tm6000_ir_handle_key(struct work_struct *work)
 {
 	struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
 	struct tm6000_core *dev = ir->dev;
-	struct tm6000_ir_poll_result poll_result;
 	int rc;
 	u8 buf[2];
 
@@ -219,13 +239,8 @@ static void tm6000_ir_handle_key(struct work_struct *work)
 	if (rc < 0)
 		return;
 
-	if (rc > 1)
-		poll_result.rc_data = buf[0] | buf[1] << 8;
-	else
-		poll_result.rc_data = buf[0];
-
 	/* Check if something was read */
-	if ((poll_result.rc_data & 0xff) == 0xff) {
+	if ((buf[0] & 0xff) == 0xff) {
 		if (!ir->pwled) {
 			tm6000_flash_led(dev, 1);
 			ir->pwled = 1;
@@ -233,8 +248,7 @@ static void tm6000_ir_handle_key(struct work_struct *work)
 		return;
 	}
 
-	dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
-	rc_keydown(ir->rc, poll_result.rc_data, 0);
+	tm6000_ir_keydown(ir, buf, rc);
 	tm6000_flash_led(dev, 0);
 	ir->pwled = 0;
 
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index f03445f..65ae99f 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -34,6 +34,24 @@ enum rc_driver_type {
 	RC_DRIVER_IR_RAW,	/* Needs a Infra-Red pulse/space decoder */
 };
 
+/* This is used for the input EVIOC[SG]KEYCODE_V2 ioctls */
+struct rc_scancode {
+	__u16 protocol;
+	__u16 reserved[3];
+	__u64 scancode;
+};
+
+struct rc_keymap_entry {
+	__u8  flags;
+	__u8  len;
+	__u16 index;
+	__u32 keycode;
+	union {
+		struct rc_scancode rc;
+		__u8 raw[32];
+	};
+};
+
 /**
  * struct rc_dev - represents a remote control device
  * @dev: driver model's view of this device
@@ -99,6 +117,7 @@ struct rc_dev {
 	enum rc_driver_type		driver_type;
 	bool				idle;
 	u64				allowed_protos;
+	u64				enabled_protocols;
 	u32				scanmask;
 	void				*priv;
 	spinlock_t			keylock;
@@ -106,7 +125,8 @@ struct rc_dev {
 	unsigned long			keyup_jiffies;
 	struct timer_list		timer_keyup;
 	u32				last_keycode;
-	u32				last_scancode;
+	enum rc_type			last_protocol;
+	u64				last_scancode;
 	u8				last_toggle;
 	u32				timeout;
 	u32				min_timeout;
@@ -141,10 +161,10 @@ int rc_register_device(struct rc_dev *dev);
 void rc_unregister_device(struct rc_dev *dev);
 
 void rc_repeat(struct rc_dev *dev);
-void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle);
-void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle);
+void rc_keydown(struct rc_dev *dev, enum rc_type protocol, u64 scancode, u8 toggle);
+void rc_keydown_notimeout(struct rc_dev *dev, enum rc_type protocol, u64 scancode, u8 toggle);
 void rc_keyup(struct rc_dev *dev);
-u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode);
+u32 rc_g_keycode_from_table(struct rc_dev *dev, enum rc_type protocol, u64 scancode);
 
 /*
  * From rc-raw.c
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 74f55a3..88a1c4e 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -60,9 +60,20 @@ enum rc_type {
 			 RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \
 			 RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)
 
+#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_NEC32(data) ((data) & 0xffffffff)
+#define RC_SCANCODE_RC5(sys, cmd) (((sys) << 8) | (cmd))
+#define RC_SCANCODE_RC5_SZ(sys, cmd) (((sys) << 8) | (cmd))
+#define RC_SCANCODE_RC6_0(sys, cmd) (((sys) << 8) | (cmd))
+#define RC_SCANCODE_RC6_6A(vendor, sys, cmd) (((vendor) << 16) | ((sys) << 8) | (cmd))
+
 struct rc_map_table {
-	u32	scancode;
-	u32	keycode;
+	u64		scancode;
+	u32		keycode;
+	enum rc_type	protocol;
 };
 
 struct rc_map {
@@ -70,7 +81,7 @@ struct rc_map {
 	unsigned int		size;	/* Max number of entries */
 	unsigned int		len;	/* Used number of entries */
 	unsigned int		alloc;	/* Size of *scan in bytes */
-	enum rc_type		rc_type;
+	enum rc_type		rc_type; /* For in-kernel keymaps */
 	const char		*name;
 	spinlock_t		lock;
 };


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 5/8] rc-core: use the full 32 bits for NEC scancodes
  2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
                   ` (3 preceding siblings ...)
  2012-08-25 21:47 ` [PATCH 4/8] rc-core: don't throw away protocol information David Härdeman
@ 2012-08-25 21:47 ` David Härdeman
  2012-08-25 21:47 ` [PATCH 6/8] rc-core: merge rc5 and streamzap decoders David Härdeman
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:47 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

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))


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 6/8] rc-core: merge rc5 and streamzap decoders
  2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
                   ` (4 preceding siblings ...)
  2012-08-25 21:47 ` [PATCH 5/8] rc-core: use the full 32 bits for NEC scancodes David Härdeman
@ 2012-08-25 21:47 ` David Härdeman
  2012-08-25 21:47 ` [PATCH 7/8] rc-core: rename ir_input_class to rc_class David Härdeman
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:47 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

Now that the protocol is part of the scancode, it is pretty easy to merge
the rc5 and streamzap decoders. An additional advantage is that the decoder
is now stricter as it waits for the trailing silence before determining that
a command is a valid rc5/streamzap command (which avoids collisions that I've
seen with e.g. Sony protocols).

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/Kconfig                |   12 --
 drivers/media/rc/Makefile               |    1 
 drivers/media/rc/ir-rc5-decoder.c       |   51 ++++++----
 drivers/media/rc/ir-rc5-sz-decoder.c    |  154 -------------------------------
 drivers/media/rc/keymaps/rc-streamzap.c |    4 -
 drivers/media/rc/rc-core-priv.h         |    8 --
 drivers/media/rc/streamzap.c            |   10 --
 7 files changed, 31 insertions(+), 209 deletions(-)
 delete mode 100644 drivers/media/rc/ir-rc5-sz-decoder.c

diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 4682a5a..d700b1d 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -84,18 +84,6 @@ config IR_SONY_DECODER
 	   Enable this option if you have an infrared remote control which
 	   uses the Sony protocol, and you need software decoding support.
 
-config IR_RC5_SZ_DECODER
-	tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
-	depends on RC_CORE
-	select BITREVERSE
-	default y
-
-	---help---
-	   Enable this option if you have IR with RC-5 (streamzap) protocol,
-	   and if the IR is decoded in software. (The Streamzap PC Remote
-	   uses an IR protocol that is almost standard RC-5, but not quite,
-	   as it uses an additional bit).
-
 config IR_SANYO_DECODER
 	tristate "Enable IR raw decoder for the Sanyo protocol"
 	depends on RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 56bacf0..9f56774 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
-obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
 obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
 obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index ddbf9bf..9594b8f 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -1,6 +1,7 @@
-/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
+/* ir-rc5-decoder.c - decoder for RC5(x) and StreamZap protocols
  *
  * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
  *
  * 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
@@ -13,23 +14,22 @@
  */
 
 /*
- * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
- * There are other variants that use a different number of bits.
- * This is currently unsupported.
- * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
- * the first two bits are start bits, and a third one is a filing bit
+ * This decoder handles the 14 bit RC5 protocol, 15 bit "StreamZap" protocol
+ * and 20 bit RC5x protocol.
  */
 
 #include "rc-core-priv.h"
 #include <linux/module.h>
 
 #define RC5_NBITS		14
+#define RC5_SZ_NBITS		15
 #define RC5X_NBITS		20
 #define CHECK_RC5X_NBITS	8
 #define RC5_UNIT		888888 /* ns */
 #define RC5_BIT_START		(1 * RC5_UNIT)
 #define RC5_BIT_END		(1 * RC5_UNIT)
 #define RC5X_SPACE		(4 * RC5_UNIT)
+#define RC5_TRAILER		(10 * RC5_UNIT) /* In reality, approx 100 */
 
 enum rc5_state {
 	STATE_INACTIVE,
@@ -80,12 +80,15 @@ again:
 
 		data->state = STATE_BIT_START;
 		data->count = 1;
-		/* We just need enough bits to get to STATE_CHECK_RC5X */
-		data->wanted_bits = RC5X_NBITS;
 		decrease_duration(&ev, RC5_BIT_START);
 		goto again;
 
 	case STATE_BIT_START:
+		if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT / 2)) {
+			data->state = STATE_FINISHED;
+			goto again;
+		}
+
 		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
 			break;
 
@@ -100,9 +103,7 @@ again:
 		if (!is_transition(&ev, &dev->raw->prev_ev))
 			break;
 
-		if (data->count == data->wanted_bits)
-			data->state = STATE_FINISHED;
-		else if (data->count == CHECK_RC5X_NBITS)
+		if (data->count == CHECK_RC5X_NBITS)
 			data->state = STATE_CHECK_RC5X;
 		else
 			data->state = STATE_BIT_START;
@@ -112,13 +113,10 @@ again:
 
 	case STATE_CHECK_RC5X:
 		if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
-			/* RC5X */
-			data->wanted_bits = RC5X_NBITS;
+			data->is_rc5x = true;
 			decrease_duration(&ev, RC5X_SPACE);
-		} else {
-			/* RC5 */
-			data->wanted_bits = RC5_NBITS;
-		}
+		} else
+			data->is_rc5x = false;
 		data->state = STATE_BIT_START;
 		goto again;
 
@@ -126,7 +124,7 @@ again:
 		if (ev.pulse)
 			break;
 
-		if (data->wanted_bits == RC5X_NBITS) {
+		if (data->is_rc5x && data->count == RC5X_NBITS) {
 			/* RC5X */
 			u8 xdata, command, system;
 			xdata    = (data->bits & 0x0003F) >> 0;
@@ -136,7 +134,7 @@ again:
 			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 16 | command << 8 | xdata;
 			protocol = RC_TYPE_RC5X;
-		} else {
+		} else if (!data->is_rc5x && data->count == RC5_NBITS) {
 			/* RC5 */
 			u8 command, system;
 			command  = (data->bits & 0x0003F) >> 0;
@@ -145,10 +143,19 @@ again:
 			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 8 | command;
 			protocol = RC_TYPE_RC5;
-		}
+		} else if (!data->is_rc5x && data->count == RC5_SZ_NBITS) {
+			/* RC5 StreamZap */
+			u8 command, system;
+			command  = (data->bits & 0x0003F) >> 0;
+			system   = (data->bits & 0x02FC0) >> 6;
+			toggle   = (data->bits & 0x01000) ? 1 : 0;
+			scancode = system << 6 | command;
+			protocol = RC_TYPE_RC5_SZ;
+		} else
+			break;
 
 		if (dev->enabled_protocols & (1 << protocol)) {
-			IR_dprintk(1, "RC5(x) scancode 0x%06x (toggle: %u)\n",
+			IR_dprintk(1, "RC5(x/sz) scancode 0x%06x (toggle: %u)\n",
 				   scancode, toggle);
 			rc_keydown(dev, protocol, scancode, toggle);
 		}
@@ -165,7 +172,7 @@ out:
 }
 
 static struct ir_raw_handler rc5_handler = {
-	.protocols	= RC_BIT_RC5 | RC_BIT_RC5X,
+	.protocols	= RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
 	.decode		= ir_rc5_decode,
 };
 
diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
deleted file mode 100644
index 8681b96..0000000
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
- *
- * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
- * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
- *
- * 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 version 2 of the License.
- *
- *  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.
- */
-
-/*
- * This code handles the 15 bit RC5-ish protocol used by the Streamzap
- * PC Remote.
- * It considers a carrier of 36 kHz, with a total of 15 bits, where
- * the first two bits are start bits, and a third one is a filing bit
- */
-
-#include "rc-core-priv.h"
-#include <linux/module.h>
-
-#define RC5_SZ_NBITS		15
-#define RC5_UNIT		888888 /* ns */
-#define RC5_BIT_START		(1 * RC5_UNIT)
-#define RC5_BIT_END		(1 * RC5_UNIT)
-
-enum rc5_sz_state {
-	STATE_INACTIVE,
-	STATE_BIT_START,
-	STATE_BIT_END,
-	STATE_FINISHED,
-};
-
-/**
- * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
- * @dev:	the struct rc_dev descriptor of the device
- * @ev:		the struct ir_raw_event descriptor of the pulse/space
- *
- * This function returns -EINVAL if the pulse violates the state machine
- */
-static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
-{
-	struct rc5_sz_dec *data = &dev->raw->rc5_sz;
-	u8 toggle, command, system;
-	u32 scancode;
-
-	if (!(dev->enabled_protocols & RC_BIT_RC5_SZ))
-		return 0;
-
-	if (!is_timing_event(ev)) {
-		if (ev.reset)
-			data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		goto out;
-
-again:
-	IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-
-	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
-		return 0;
-
-	switch (data->state) {
-
-	case STATE_INACTIVE:
-		if (!ev.pulse)
-			break;
-
-		data->state = STATE_BIT_START;
-		data->count = 1;
-		data->wanted_bits = RC5_SZ_NBITS;
-		decrease_duration(&ev, RC5_BIT_START);
-		goto again;
-
-	case STATE_BIT_START:
-		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
-			break;
-
-		data->bits <<= 1;
-		if (!ev.pulse)
-			data->bits |= 1;
-		data->count++;
-		data->state = STATE_BIT_END;
-		return 0;
-
-	case STATE_BIT_END:
-		if (!is_transition(&ev, &dev->raw->prev_ev))
-			break;
-
-		if (data->count == data->wanted_bits)
-			data->state = STATE_FINISHED;
-		else
-			data->state = STATE_BIT_START;
-
-		decrease_duration(&ev, RC5_BIT_END);
-		goto again;
-
-	case STATE_FINISHED:
-		if (ev.pulse)
-			break;
-
-		/* RC5-sz */
-		command  = (data->bits & 0x0003F) >> 0;
-		system   = (data->bits & 0x02FC0) >> 6;
-		toggle   = (data->bits & 0x01000) ? 1 : 0;
-		scancode = system << 6 | command;
-
-		IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
-			   scancode, toggle);
-
-		rc_keydown(dev, RC_TYPE_RC5_SZ, scancode, toggle);
-		data->state = STATE_INACTIVE;
-		return 0;
-	}
-
-out:
-	IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
-		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
-	data->state = STATE_INACTIVE;
-	return -EINVAL;
-}
-
-static struct ir_raw_handler rc5_sz_handler = {
-	.protocols	= RC_BIT_RC5_SZ,
-	.decode		= ir_rc5_sz_decode,
-};
-
-static int __init ir_rc5_sz_decode_init(void)
-{
-	ir_raw_handler_register(&rc5_sz_handler);
-
-	printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
-	return 0;
-}
-
-static void __exit ir_rc5_sz_decode_exit(void)
-{
-	ir_raw_handler_unregister(&rc5_sz_handler);
-}
-
-module_init(ir_rc5_sz_decode_init);
-module_exit(ir_rc5_sz_decode_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c
index f9a0757..23c0611 100644
--- a/drivers/media/rc/keymaps/rc-streamzap.c
+++ b/drivers/media/rc/keymaps/rc-streamzap.c
@@ -15,9 +15,7 @@
 static struct rc_map_table streamzap[] = {
 /*
  * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
- * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
- * an additional RC-5-sz decoder is being deployed to support it, but it
- * may be possible to merge it back with the standard RC-5 decoder.
+ * bit in it.
  */
 	{ 0x28c0, KEY_NUMERIC_0 },
 	{ 0x28c1, KEY_NUMERIC_1 },
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 4de2d47..6a40bc9 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -54,7 +54,7 @@ struct ir_raw_event_ctrl {
 		int state;
 		u32 bits;
 		unsigned count;
-		unsigned wanted_bits;
+		bool is_rc5x;
 	} rc5;
 	struct rc6_dec {
 		int state;
@@ -77,12 +77,6 @@ struct ir_raw_event_ctrl {
 		bool first;
 		bool toggle;
 	} jvc;
-	struct rc5_sz_dec {
-		int state;
-		u32 bits;
-		unsigned count;
-		unsigned wanted_bits;
-	} rc5_sz;
 	struct sanyo_dec {
 		int state;
 		unsigned count;
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index c720f12..fdfedc6 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -69,13 +69,6 @@ MODULE_DEVICE_TABLE(usb, streamzap_table);
 /* number of samples buffered */
 #define SZ_BUF_LEN 128
 
-/* from ir-rc5-sz-decoder.c */
-#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
-#define load_rc5_sz_decode()    request_module("ir-rc5-sz-decoder")
-#else
-#define load_rc5_sz_decode()    {}
-#endif
-
 enum StreamzapDecoderState {
 	PulseSpace,
 	FullPulse,
@@ -458,9 +451,6 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
 	dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
 		 usbdev->bus->busnum, usbdev->devnum);
 
-	/* Load the streamzap not-quite-rc5 decoder too */
-	load_rc5_sz_decode();
-
 	return 0;
 
 rc_dev_fail:


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 7/8] rc-core: rename ir_input_class to rc_class
  2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
                   ` (5 preceding siblings ...)
  2012-08-25 21:47 ` [PATCH 6/8] rc-core: merge rc5 and streamzap decoders David Härdeman
@ 2012-08-25 21:47 ` 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
  8 siblings, 0 replies; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:47 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

The name is already misleading and will be more so in the future as the
connection to the input subsystem is obscured away further.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/rc-main.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index d29818c..ec7311f 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -849,14 +849,14 @@ static void ir_close(struct input_dev *idev)
 }
 
 /* class for /sys/class/rc */
-static char *ir_devnode(struct device *dev, umode_t *mode)
+static char *rc_devnode(struct device *dev, umode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev));
 }
 
-static struct class ir_input_class = {
+static struct class rc_class = {
 	.name		= "rc",
-	.devnode	= ir_devnode,
+	.devnode	= rc_devnode,
 };
 
 /*
@@ -1137,7 +1137,7 @@ struct rc_dev *rc_allocate_device(void)
 	setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev);
 
 	dev->dev.type = &rc_dev_type;
-	dev->dev.class = &ir_input_class;
+	dev->dev.class = &rc_class;
 	device_initialize(&dev->dev);
 
 	__module_get(THIS_MODULE);
@@ -1310,7 +1310,7 @@ EXPORT_SYMBOL_GPL(rc_unregister_device);
 
 static int __init rc_core_init(void)
 {
-	int rc = class_register(&ir_input_class);
+	int rc = class_register(&rc_class);
 	if (rc) {
 		printk(KERN_ERR "rc_core: unable to register rc class\n");
 		return rc;
@@ -1323,7 +1323,7 @@ static int __init rc_core_init(void)
 
 static void __exit rc_core_exit(void)
 {
-	class_unregister(&ir_input_class);
+	class_unregister(&rc_class);
 	rc_map_unregister(&empty_map);
 }
 


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 8/8] rc-core: initialize rc-core earlier if built-in
  2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
                   ` (6 preceding siblings ...)
  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 ` David Härdeman
  2012-08-30 19:56 ` [PATCH 0/8] rc-core: patches for 3.7 Jarod Wilson
  8 siblings, 0 replies; 13+ messages in thread
From: David Härdeman @ 2012-08-25 21:47 UTC (permalink / raw)
  To: linux-media; +Cc: jwilson, mchehab, sean

rc-core is a subsystem so it should be registered earlier if built into the
kernel.

Signed-off-by: David Härdeman <david@hardeman.nu>
---
 drivers/media/rc/rc-main.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index ec7311f..8134bd8 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1327,7 +1327,7 @@ static void __exit rc_core_exit(void)
 	rc_map_unregister(&empty_map);
 }
 
-module_init(rc_core_init);
+subsys_initcall(rc_core_init);
 module_exit(rc_core_exit);
 
 int rc_core_debug;    /* ir_debug level (0,1,2) */


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/8] rc-core: patches for 3.7
  2012-08-25 21:46 [PATCH 0/8] rc-core: patches for 3.7 David Härdeman
                   ` (7 preceding siblings ...)
  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 ` Jarod Wilson
  2012-09-03 21:55   ` David Härdeman
  8 siblings, 1 reply; 13+ messages in thread
From: Jarod Wilson @ 2012-08-30 19:56 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, mchehab, sean

On Sat, Aug 25, 2012 at 11:46:47PM +0200, David Härdeman wrote:
> This is two minor winbond-cir fixes as well as the first six patches
> from my previous patchbomb.
> 
> The latter have been modified so that backwards compatibility is retained
> as much as possible (the format of the sysfs files do not change for
> example).

I've read through the set, and it all seems to make sense to me, but I
haven't actually tried it out with any of the hardware I've got. I assume
its been tested on various other hardware though.

Side note: my life has been turned a wee bit upside down, been busy
dealing with some fairly big changes, and that's still ongoing, thus the
relative lack of repsonsiveness on, well, anything, lately.


-- 
Jarod Wilson
jarod@redhat.com


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/8] rc-core: patches for 3.7
  2012-08-30 19:56 ` [PATCH 0/8] rc-core: patches for 3.7 Jarod Wilson
@ 2012-09-03 21:55   ` David Härdeman
  0 siblings, 0 replies; 13+ messages in thread
From: David Härdeman @ 2012-09-03 21:55 UTC (permalink / raw)
  To: Jarod Wilson; +Cc: linux-media, mchehab, sean

On Thu, Aug 30, 2012 at 03:56:12PM -0400, Jarod Wilson wrote:
>On Sat, Aug 25, 2012 at 11:46:47PM +0200, David Härdeman wrote:
>> This is two minor winbond-cir fixes as well as the first six patches
>> from my previous patchbomb.
>> 
>> The latter have been modified so that backwards compatibility is retained
>> as much as possible (the format of the sysfs files do not change for
>> example).
>
>I've read through the set, and it all seems to make sense to me, but I
>haven't actually tried it out with any of the hardware I've got. I assume
>its been tested on various other hardware though.

I've tested the patches on mceusb hardware (RX only) and using some
scripted TX/RX testing with rc-loopback. I haven't tested (this latest
version) on winbond-cir hardware yet as I'm travelling.

>Side note: my life has been turned a wee bit upside down, been busy
>dealing with some fairly big changes, and that's still ongoing, thus the
>relative lack of repsonsiveness on, well, anything, lately.

If you have limited time and bandwidth I'd suggest that you focus on the
API changes - in this particular patchset that would be the addition of
the "struct rc_keymap_entry" to the EVIOC[GS]KEYCODE_V2 ioctl (maybe we
should involve the input maintainer as well?).

Getting the API right would benefit from you cooperation, getting bugs
worked out is hopefully something which can be done with or without you.

Thanks,
David


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/8] rc-core: don't throw away protocol information
  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
  0 siblings, 0 replies; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2012-09-25 18:40 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, jwilson, sean

Em Sat, 25 Aug 2012 23:47:08 +0200
David Härdeman <david@hardeman.nu> escreveu:


Pathes 1 to 3 are OK. Applied, thanks!

...

> +#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_NEC32(data) ((data) & 0xffffffff)
> +#define RC_SCANCODE_RC5(sys, cmd) (((sys) << 8) | (cmd))
> +#define RC_SCANCODE_RC5_SZ(sys, cmd) (((sys) << 8) | (cmd))
> +#define RC_SCANCODE_RC6_0(sys, cmd) (((sys) << 8) | (cmd))
> +#define RC_SCANCODE_RC6_6A(vendor, sys, cmd) (((vendor) << 16) | ((sys) << 8) | (cmd))


Huh? You're defining the same code for NEC, NECX, RC5, ...

Why? It seems better to have one macro for (up to) 16 bit protocols,
and another one for the two 32 bit ones.

Btw, on several drivers, you're using the wrong macro name. It doesn't seem
fine to miss-use it.

For example, see the generic I2C driver: several of the remote controllers
there are NEC[1]. Yet, you're using there the RC5 variant.

[1] Currently, they're using "other" because we don't have that IR's or the
devices that use it here, in order to make it scan the full NEC (or NEC
variant) code.

-- 
Regards,
Mauro

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/8] rc-core: add separate defines for protocol bitmaps and numbers
  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
  0 siblings, 0 replies; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2012-09-25 20:19 UTC (permalink / raw)
  To: David Härdeman; +Cc: linux-media, jwilson, sean

Em Sat, 25 Aug 2012 23:47:03 +0200
David Härdeman <david@hardeman.nu> escreveu:

> The RC_TYPE_* defines are currently used both where a single protocol is
> expected and where a bitmap of protocols is expected. This patch tries
> to separate the two in preparation for the following patches.
> 
> The intended use is also clearer to anyone reading the code. Where a
> single protocol is expected, enum rc_type is used, where one or more
> protocol(s) are expected, something like u64 is used.
> 
> The patch has been rewritten so that the format of the sysfs "protocols"
> file is no longer altered (at the loss of some detail). The file itself
> should probably be deprecated in the future though.
> 
> Signed-off-by: David Härdeman <david@hardeman.nu>

Patch broke compilation. It seems you forgot to update RC6 meaning here:

  CC      drivers/media/usb/dvb-usb-v2/af9035.o
drivers/media/usb/dvb-usb-v2/af9035.c: In function 'af9035_get_rc_config':
drivers/media/usb/dvb-usb-v2/af9035.c:973:25: error: 'RC_BIT_RC6' undeclared (first use in this function)
drivers/media/usb/dvb-usb-v2/af9035.c:973:25: note: each undeclared identifier is reported only once for each function it appears in

-- 
Regards,
Mauro

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-09-25 20:19 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 5/8] rc-core: use the full 32 bits for NEC scancodes David Härdeman
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).