aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/Kconfig32
-rw-r--r--drivers/media/rc/Makefile5
-rw-r--r--drivers/media/rc/ati_remote.c159
-rw-r--r--drivers/media/rc/ene_ir.c2
-rw-r--r--drivers/media/rc/fintek-cir.c6
-rw-r--r--drivers/media/rc/gpio-ir-recv.c4
-rw-r--r--drivers/media/rc/iguanair.c2
-rw-r--r--drivers/media/rc/img-ir/img-ir-core.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.c31
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.h8
-rw-r--r--drivers/media/rc/img-ir/img-ir-jvc.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-nec.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-raw.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-raw.h5
-rw-r--r--drivers/media/rc/img-ir/img-ir-sanyo.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-sharp.c9
-rw-r--r--drivers/media/rc/img-ir/img-ir-sony.c17
-rw-r--r--drivers/media/rc/img-ir/img-ir.h5
-rw-r--r--drivers/media/rc/imon.c20
-rw-r--r--drivers/media/rc/ir-jvc-decoder.c4
-rw-r--r--drivers/media/rc/ir-lirc-codec.c2
-rw-r--r--drivers/media/rc/ir-mce_kbd-decoder.c2
-rw-r--r--drivers/media/rc/ir-nec-decoder.c4
-rw-r--r--drivers/media/rc/ir-rc5-decoder.c85
-rw-r--r--drivers/media/rc/ir-rc5-sz-decoder.c154
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c43
-rw-r--r--drivers/media/rc/ir-sanyo-decoder.c4
-rw-r--r--drivers/media/rc/ir-sharp-decoder.c4
-rw-r--r--drivers/media/rc/ir-sony-decoder.c16
-rw-r--r--drivers/media/rc/ir-xmp-decoder.c225
-rw-r--r--drivers/media/rc/ite-cir.c6
-rw-r--r--drivers/media/rc/keymaps/rc-ati-x10.c92
-rw-r--r--drivers/media/rc/keymaps/rc-behold.c68
-rw-r--r--drivers/media/rc/keymaps/rc-nebula.c112
-rw-r--r--drivers/media/rc/keymaps/rc-streamzap.c4
-rw-r--r--drivers/media/rc/mceusb.c33
-rw-r--r--drivers/media/rc/nuvoton-cir.c6
-rw-r--r--drivers/media/rc/rc-core-priv.h20
-rw-r--r--drivers/media/rc/rc-ir-raw.c (renamed from drivers/media/rc/ir-raw.c)12
-rw-r--r--drivers/media/rc/rc-loopback.c2
-rw-r--r--drivers/media/rc/rc-main.c301
-rw-r--r--drivers/media/rc/redrat3.c2
-rw-r--r--drivers/media/rc/st_rc.c2
-rw-r--r--drivers/media/rc/streamzap.c12
-rw-r--r--drivers/media/rc/sunxi-cir.c318
-rw-r--r--drivers/media/rc/ttusbir.c2
-rw-r--r--drivers/media/rc/winbond-cir.c2
47 files changed, 1222 insertions, 657 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 8fbd377e6311..5e626af8e313 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
@@ -125,6 +113,16 @@ config IR_MCE_KBD_DECODER
Enable this option if you have a Microsoft Remote Keyboard for
Windows Media Center Edition, which you would like to use with
a raw IR receiver in your system.
+
+config IR_XMP_DECODER
+ tristate "Enable IR raw decoder for the XMP protocol"
+ depends on RC_CORE
+ select BITREVERSE
+ default y
+
+ ---help---
+ Enable this option if you have IR with XMP protocol, and
+ if the IR is decoded in software
endif #RC_DECODERS
menuconfig RC_DEVICES
@@ -343,4 +341,14 @@ config RC_ST
If you're not sure, select N here.
+config IR_SUNXI
+ tristate "SUNXI IR remote control"
+ depends on RC_CORE
+ depends on ARCH_SUNXI
+ ---help---
+ Say Y if you want to use sunXi internal IR Controller
+
+ To compile this driver as a module, choose M here: the module will
+ be called sunxi-ir.
+
endif #RC_DEVICES
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index f8b54ff46601..9f9843a1af5f 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -1,4 +1,4 @@
-rc-core-objs := rc-main.o ir-raw.o
+rc-core-objs := rc-main.o rc-ir-raw.o
obj-y += keymaps/
@@ -9,11 +9,11 @@ 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_SHARP_DECODER) += ir-sharp-decoder.o
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
+obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o
# stand-alone IR receivers/transmitters
obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
@@ -32,4 +32,5 @@ obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
obj-$(CONFIG_IR_IGUANA) += iguanair.o
obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
obj-$(CONFIG_RC_ST) += st_rc.o
+obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
obj-$(CONFIG_IR_IMG) += img-ir/
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 2df7c5516013..a35631891cc0 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -279,46 +279,42 @@ struct ati_remote {
/* "Kinds" of messages sent from the hardware to the driver. */
#define KIND_END 0
-#define KIND_LITERAL 1 /* Simply pass to input system */
+#define KIND_LITERAL 1 /* Simply pass to input system as EV_KEY */
#define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */
-#define KIND_LU 3 /* Directional keypad diagonals - left up, */
-#define KIND_RU 4 /* right up, */
-#define KIND_LD 5 /* left down, */
-#define KIND_RD 6 /* right down */
-#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/
+#define KIND_ACCEL 3 /* Translate to EV_REL mouse-move events */
/* Translation table from hardware messages to input events. */
static const struct {
- short kind;
- unsigned char data;
- int type;
- unsigned int code;
- int value;
+ unsigned char kind;
+ unsigned char data; /* Raw key code from remote */
+ unsigned short code; /* Input layer translation */
} ati_remote_tbl[] = {
- /* Directional control pad axes */
- {KIND_ACCEL, 0x70, EV_REL, REL_X, -1}, /* left */
- {KIND_ACCEL, 0x71, EV_REL, REL_X, 1}, /* right */
- {KIND_ACCEL, 0x72, EV_REL, REL_Y, -1}, /* up */
- {KIND_ACCEL, 0x73, EV_REL, REL_Y, 1}, /* down */
- /* Directional control pad diagonals */
- {KIND_LU, 0x74, EV_REL, 0, 0}, /* left up */
- {KIND_RU, 0x75, EV_REL, 0, 0}, /* right up */
- {KIND_LD, 0x77, EV_REL, 0, 0}, /* left down */
- {KIND_RD, 0x76, EV_REL, 0, 0}, /* right down */
+ /* Directional control pad axes. Code is xxyy */
+ {KIND_ACCEL, 0x70, 0xff00}, /* left */
+ {KIND_ACCEL, 0x71, 0x0100}, /* right */
+ {KIND_ACCEL, 0x72, 0x00ff}, /* up */
+ {KIND_ACCEL, 0x73, 0x0001}, /* down */
- /* "Mouse button" buttons */
- {KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
- {KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
- {KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
- {KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
+ /* Directional control pad diagonals */
+ {KIND_ACCEL, 0x74, 0xffff}, /* left up */
+ {KIND_ACCEL, 0x75, 0x01ff}, /* right up */
+ {KIND_ACCEL, 0x77, 0xff01}, /* left down */
+ {KIND_ACCEL, 0x76, 0x0101}, /* right down */
+
+ /* "Mouse button" buttons. The code below uses the fact that the
+ * lsbit of the raw code is a down/up indicator. */
+ {KIND_LITERAL, 0x78, BTN_LEFT}, /* left btn down */
+ {KIND_LITERAL, 0x79, BTN_LEFT}, /* left btn up */
+ {KIND_LITERAL, 0x7c, BTN_RIGHT},/* right btn down */
+ {KIND_LITERAL, 0x7d, BTN_RIGHT},/* right btn up */
/* Artificial "doubleclick" events are generated by the hardware.
* They are mapped to the "side" and "extra" mouse buttons here. */
- {KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
- {KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
+ {KIND_FILTERED, 0x7a, BTN_SIDE}, /* left dblclick */
+ {KIND_FILTERED, 0x7e, BTN_EXTRA},/* right dblclick */
/* Non-mouse events are handled by rc-core */
- {KIND_END, 0x00, EV_MAX + 1, 0, 0}
+ {KIND_END, 0x00, 0}
};
/*
@@ -493,7 +489,6 @@ static void ati_remote_input_report(struct urb *urb)
unsigned char *data= ati_remote->inbuf;
struct input_dev *dev = ati_remote->idev;
int index = -1;
- int acc;
int remote_num;
unsigned char scancode;
u32 wheel_keycode = KEY_RESERVED;
@@ -507,8 +502,9 @@ static void ati_remote_input_report(struct urb *urb)
*/
/* Deal with strange looking inputs */
- if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
- ((data[3] & 0x0f) != 0x00) ) {
+ if ( urb->actual_length != 4 || data[0] != 0x14 ||
+ data[1] != (unsigned char)(data[2] + data[3] + 0xD5) ||
+ (data[3] & 0x0f) != 0x00) {
ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
return;
}
@@ -524,9 +520,9 @@ static void ati_remote_input_report(struct urb *urb)
remote_num = (data[3] >> 4) & 0x0f;
if (channel_mask & (1 << (remote_num + 1))) {
dbginfo(&ati_remote->interface->dev,
- "Masked input from channel 0x%02x: data %02x,%02x, "
+ "Masked input from channel 0x%02x: data %02x, "
"mask= 0x%02lx\n",
- remote_num, data[1], data[2], channel_mask);
+ remote_num, data[2], channel_mask);
return;
}
@@ -566,16 +562,16 @@ static void ati_remote_input_report(struct urb *urb)
}
if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code,
- ati_remote_tbl[index].value);
- input_sync(dev);
+ /*
+ * The lsbit of the raw key code is a down/up flag.
+ * Invert it to match the input layer's conventions.
+ */
+ input_event(dev, EV_KEY, ati_remote_tbl[index].code,
+ !(data[2] & 1));
ati_remote->old_jiffies = jiffies;
- return;
- }
- if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
+ } else if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
unsigned long now = jiffies;
/* Filter duplicate events which happen "too close" together. */
@@ -588,12 +584,11 @@ static void ati_remote_input_report(struct urb *urb)
ati_remote->first_jiffies = now;
}
- ati_remote->old_data = data[2];
ati_remote->old_jiffies = now;
- /* Ensure we skip at least the 4 first duplicate events (generated
- * by a single keypress), and continue skipping until repeat_delay
- * msecs have passed
+ /* Ensure we skip at least the 4 first duplicate events
+ * (generated by a single keypress), and continue skipping
+ * until repeat_delay msecs have passed.
*/
if (ati_remote->repeat_count > 0 &&
(ati_remote->repeat_count < 5 ||
@@ -601,7 +596,10 @@ static void ati_remote_input_report(struct urb *urb)
msecs_to_jiffies(repeat_delay))))
return;
- if (index < 0) {
+ if (index >= 0) {
+ input_event(dev, EV_KEY, ati_remote_tbl[index].code, 1);
+ input_event(dev, EV_KEY, ati_remote_tbl[index].code, 0);
+ } else {
/* Not a mouse event, hand it to rc-core. */
int count = 1;
@@ -622,61 +620,37 @@ static void ati_remote_input_report(struct urb *urb)
* it would cause ghost repeats which would be a
* regression for this driver.
*/
- rc_keydown_notimeout(ati_remote->rdev, scancode,
- data[2]);
+ rc_keydown_notimeout(ati_remote->rdev, RC_TYPE_OTHER,
+ scancode, data[2]);
rc_keyup(ati_remote->rdev);
}
- return;
+ goto nosync;
}
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code, 1);
- input_sync(dev);
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code, 0);
- input_sync(dev);
-
- } else {
+ } else if (ati_remote_tbl[index].kind == KIND_ACCEL) {
+ signed char dx = ati_remote_tbl[index].code >> 8;
+ signed char dy = ati_remote_tbl[index].code & 255;
/*
* Other event kinds are from the directional control pad, and
* have an acceleration factor applied to them. Without this
* acceleration, the control pad is mostly unusable.
*/
- acc = ati_remote_compute_accel(ati_remote);
-
- switch (ati_remote_tbl[index].kind) {
- case KIND_ACCEL:
- input_event(dev, ati_remote_tbl[index].type,
- ati_remote_tbl[index].code,
- ati_remote_tbl[index].value * acc);
- break;
- case KIND_LU:
- input_report_rel(dev, REL_X, -acc);
- input_report_rel(dev, REL_Y, -acc);
- break;
- case KIND_RU:
- input_report_rel(dev, REL_X, acc);
- input_report_rel(dev, REL_Y, -acc);
- break;
- case KIND_LD:
- input_report_rel(dev, REL_X, -acc);
- input_report_rel(dev, REL_Y, acc);
- break;
- case KIND_RD:
- input_report_rel(dev, REL_X, acc);
- input_report_rel(dev, REL_Y, acc);
- break;
- default:
- dev_dbg(&ati_remote->interface->dev,
- "ati_remote kind=%d\n",
- ati_remote_tbl[index].kind);
- }
- input_sync(dev);
-
+ int acc = ati_remote_compute_accel(ati_remote);
+ if (dx)
+ input_report_rel(dev, REL_X, dx * acc);
+ if (dy)
+ input_report_rel(dev, REL_Y, dy * acc);
ati_remote->old_jiffies = jiffies;
- ati_remote->old_data = data[2];
+
+ } else {
+ dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
+ ati_remote_tbl[index].kind);
+ return;
}
+ input_sync(dev);
+nosync:
+ ati_remote->old_data = data[2];
}
/*
@@ -763,8 +737,9 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
- if (ati_remote_tbl[i].type == EV_KEY)
- set_bit(ati_remote_tbl[i].code, idev->keybit);
+ if (ati_remote_tbl[i].kind == KIND_LITERAL ||
+ ati_remote_tbl[i].kind == KIND_FILTERED)
+ __set_bit(ati_remote_tbl[i].code, idev->keybit);
input_set_drvdata(idev, ati_remote);
@@ -784,7 +759,7 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote)
rdev->priv = ati_remote;
rdev->driver_type = RC_DRIVER_SCANCODE;
- rc_set_allowed_protocols(rdev, RC_BIT_OTHER);
+ rdev->allowed_protocols = 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 fc9d23f2ed3f..d16d9b496b92 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1059,7 +1059,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;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = 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 46b66e59438f..f0a1f7d31ee6 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;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = fintek_open;
rdev->close = fintek_close;
rdev->input_name = FINTEK_DESCRIPTION;
@@ -686,12 +686,12 @@ static struct pnp_driver fintek_driver = {
.shutdown = fintek_shutdown,
};
-static int fintek_init(void)
+static int __init fintek_init(void)
{
return pnp_register_driver(&fintek_driver);
}
-static void fintek_exit(void)
+static void __exit fintek_exit(void)
{
pnp_unregister_driver(&fintek_driver);
}
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 29b5f89813b4..59853085bc88 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -145,9 +145,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
rcdev->dev.parent = &pdev->dev;
rcdev->driver_name = GPIO_IR_DRIVER_NAME;
if (pdata->allowed_protos)
- rc_set_allowed_protocols(rcdev, pdata->allowed_protos);
+ rcdev->allowed_protocols = pdata->allowed_protos;
else
- rc_set_allowed_protocols(rcdev, RC_BIT_ALL);
+ rcdev->allowed_protocols = 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 627ddfd61980..ee60e17fba05 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -495,7 +495,7 @@ static int 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_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = RC_BIT_ALL;
rc->priv = ir;
rc->open = iguanair_open;
rc->close = iguanair_close;
diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c
index 6b7834834fb8..a0cac2f09109 100644
--- a/drivers/media/rc/img-ir/img-ir-core.c
+++ b/drivers/media/rc/img-ir/img-ir-core.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This contains core img-ir code for setting up the driver. The two interfaces
* (raw and hardware decode) are handled separately.
*/
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 0127dd257a57..bfb282a714e8 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This ties into the input subsystem using the RC-core. Protocol support is
* provided in separate modules which provide the parameters and scancode
* translation functions to set up the hardware decoder and interpret the
@@ -507,7 +512,7 @@ unlock:
static int img_ir_set_normal_filter(struct rc_dev *dev,
struct rc_scancode_filter *sc_filter)
{
- return img_ir_set_filter(dev, RC_FILTER_NORMAL, sc_filter);
+ return img_ir_set_filter(dev, RC_FILTER_NORMAL, sc_filter);
}
static int img_ir_set_wakeup_filter(struct rc_dev *dev,
@@ -551,8 +556,8 @@ static void img_ir_set_decoder(struct img_ir_priv *priv,
hw->mode = IMG_IR_M_NORMAL;
/* clear the wakeup scancode filter */
- rdev->scancode_filters[RC_FILTER_WAKEUP].data = 0;
- rdev->scancode_filters[RC_FILTER_WAKEUP].mask = 0;
+ rdev->scancode_wakeup_filter.data = 0;
+ rdev->scancode_wakeup_filter.mask = 0;
/* clear raw filters */
_img_ir_set_filter(priv, NULL);
@@ -656,8 +661,8 @@ success:
wakeup_protocols = *ir_type;
if (!hw->decoder || !hw->decoder->filter)
wakeup_protocols = 0;
- rc_set_allowed_wakeup_protocols(rdev, wakeup_protocols);
- rc_set_enabled_wakeup_protocols(rdev, wakeup_protocols);
+ rdev->allowed_wakeup_protocols = wakeup_protocols;
+ rdev->enabled_wakeup_protocols = wakeup_protocols;
return 0;
}
@@ -671,9 +676,9 @@ static void img_ir_set_protocol(struct img_ir_priv *priv, u64 proto)
spin_unlock_irq(&rdev->rc_map.lock);
mutex_lock(&rdev->lock);
- rc_set_enabled_protocols(rdev, proto);
- rc_set_allowed_wakeup_protocols(rdev, proto);
- rc_set_enabled_wakeup_protocols(rdev, proto);
+ rdev->enabled_protocols = proto;
+ rdev->allowed_wakeup_protocols = proto;
+ rdev->enabled_wakeup_protocols = proto;
mutex_unlock(&rdev->lock);
}
@@ -790,9 +795,11 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw)
struct img_ir_priv_hw *hw = &priv->hw;
const struct img_ir_decoder *dec = hw->decoder;
int ret = IMG_IR_SCANCODE;
- int scancode;
+ u32 scancode;
+ enum rc_type protocol = RC_TYPE_UNKNOWN;
+
if (dec->scancode)
- ret = dec->scancode(len, raw, &scancode, hw->enabled_protocols);
+ ret = dec->scancode(len, raw, &protocol, &scancode, hw->enabled_protocols);
else if (len >= 32)
scancode = (u32)raw;
else if (len < 32)
@@ -801,7 +808,7 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw)
len, (unsigned long long)raw);
if (ret == IMG_IR_SCANCODE) {
dev_dbg(priv->dev, "decoded scan code %#x\n", scancode);
- rc_keydown(hw->rdev, scancode, 0);
+ rc_keydown(hw->rdev, protocol, scancode, 0);
img_ir_end_repeat(priv);
} else if (ret == IMG_IR_REPEATCODE) {
if (hw->mode == IMG_IR_M_REPEATING) {
@@ -996,7 +1003,7 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
}
rdev->priv = priv;
rdev->map_name = RC_MAP_EMPTY;
- rc_set_allowed_protocols(rdev, img_ir_allowed_protos(priv));
+ rdev->allowed_protocols = img_ir_allowed_protos(priv);
rdev->input_name = "IMG Infrared Decoder";
rdev->s_filter = img_ir_set_normal_filter;
rdev->s_wakeup_filter = img_ir_set_wakeup_filter;
diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
index 6c9a94a81190..3e40ce87b898 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.h
+++ b/drivers/media/rc/img-ir/img-ir-hw.h
@@ -2,6 +2,11 @@
* ImgTec IR Hardware Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_HW_H_
@@ -157,7 +162,8 @@ struct img_ir_decoder {
struct img_ir_control control;
/* scancode logic */
- int (*scancode)(int len, u64 raw, int *scancode, u64 protocols);
+ int (*scancode)(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols);
int (*filter)(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols);
};
diff --git a/drivers/media/rc/img-ir/img-ir-jvc.c b/drivers/media/rc/img-ir/img-ir-jvc.c
index 10209d200efb..a60dda8bf706 100644
--- a/drivers/media/rc/img-ir/img-ir-jvc.c
+++ b/drivers/media/rc/img-ir/img-ir-jvc.c
@@ -2,12 +2,18 @@
* ImgTec IR Decoder setup for JVC protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
/* Convert JVC data to a scancode */
-static int img_ir_jvc_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int cust, data;
@@ -17,6 +23,7 @@ static int img_ir_jvc_scancode(int len, u64 raw, int *scancode, u64 protocols)
cust = (raw >> 0) & 0xff;
data = (raw >> 8) & 0xff;
+ *protocol = RC_TYPE_JVC;
*scancode = cust << 8 | data;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-nec.c b/drivers/media/rc/img-ir/img-ir-nec.c
index 751d9d945269..739897549b5b 100644
--- a/drivers/media/rc/img-ir/img-ir-nec.c
+++ b/drivers/media/rc/img-ir/img-ir-nec.c
@@ -2,13 +2,19 @@
* ImgTec IR Decoder setup for NEC protocol.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
#include <linux/bitrev.h>
/* Convert NEC data to a scancode */
-static int img_ir_nec_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
@@ -40,6 +46,7 @@ static int img_ir_nec_scancode(int len, u64 raw, int *scancode, u64 protocols)
*scancode = addr << 8 |
data;
}
+ *protocol = RC_TYPE_NEC;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c
index cfb01d9e571a..33f37ed87ad2 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.c
+++ b/drivers/media/rc/img-ir/img-ir-raw.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This ties into the input subsystem using the RC-core in raw mode. Raw IR
* signal edges are reported and decoded by generic software decoders.
*/
diff --git a/drivers/media/rc/img-ir/img-ir-raw.h b/drivers/media/rc/img-ir/img-ir-raw.h
index 9802ffd51b9a..4c9b7676e6fc 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.h
+++ b/drivers/media/rc/img-ir/img-ir-raw.h
@@ -2,6 +2,11 @@
* ImgTec IR Raw Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_RAW_H_
diff --git a/drivers/media/rc/img-ir/img-ir-sanyo.c b/drivers/media/rc/img-ir/img-ir-sanyo.c
index c2c763e08a41..6b0653ecdf5a 100644
--- a/drivers/media/rc/img-ir/img-ir-sanyo.c
+++ b/drivers/media/rc/img-ir/img-ir-sanyo.c
@@ -3,6 +3,11 @@
*
* Copyright 2012-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* From ir-sanyo-decoder.c:
*
* This protocol uses the NEC protocol timings. However, data is formatted as:
@@ -18,7 +23,8 @@
#include "img-ir-hw.h"
/* Convert Sanyo data to a scancode */
-static int img_ir_sanyo_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
@@ -38,6 +44,7 @@ static int img_ir_sanyo_scancode(int len, u64 raw, int *scancode, u64 protocols)
return -EINVAL;
/* Normal Sanyo */
+ *protocol = RC_TYPE_SANYO;
*scancode = addr << 8 | data;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-sharp.c b/drivers/media/rc/img-ir/img-ir-sharp.c
index 3397cc5a6794..3300a38802ac 100644
--- a/drivers/media/rc/img-ir/img-ir-sharp.c
+++ b/drivers/media/rc/img-ir/img-ir-sharp.c
@@ -2,12 +2,18 @@
* ImgTec IR Decoder setup for Sharp protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
/* Convert Sharp data to a scancode */
-static int img_ir_sharp_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, cmd, exp, chk;
@@ -26,6 +32,7 @@ static int img_ir_sharp_scancode(int len, u64 raw, int *scancode, u64 protocols)
/* probably the second half of the message */
return -EINVAL;
+ *protocol = RC_TYPE_SHARP;
*scancode = addr << 8 | cmd;
return IMG_IR_SCANCODE;
}
diff --git a/drivers/media/rc/img-ir/img-ir-sony.c b/drivers/media/rc/img-ir/img-ir-sony.c
index 993409a51a71..3a0f17b0752c 100644
--- a/drivers/media/rc/img-ir/img-ir-sony.c
+++ b/drivers/media/rc/img-ir/img-ir-sony.c
@@ -2,40 +2,49 @@
* ImgTec IR Decoder setup for Sony (SIRC) protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
/* Convert Sony data to a scancode */
-static int img_ir_sony_scancode(int len, u64 raw, int *scancode, u64 protocols)
+static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
+ u32 *scancode, u64 enabled_protocols)
{
unsigned int dev, subdev, func;
switch (len) {
case 12:
- if (!(protocols & RC_BIT_SONY12))
+ if (!(enabled_protocols & RC_BIT_SONY12))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0x1f; /* next 5 bits */
subdev = 0;
+ *protocol = RC_TYPE_SONY12;
break;
case 15:
- if (!(protocols & RC_BIT_SONY15))
+ if (!(enabled_protocols & RC_BIT_SONY15))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0xff; /* next 8 bits */
subdev = 0;
+ *protocol = RC_TYPE_SONY15;
break;
case 20:
- if (!(protocols & RC_BIT_SONY20))
+ if (!(enabled_protocols & RC_BIT_SONY20))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0x1f; /* next 5 bits */
raw >>= 5;
subdev = raw & 0xff; /* next 8 bits */
+ *protocol = RC_TYPE_SONY20;
break;
default:
return -EINVAL;
diff --git a/drivers/media/rc/img-ir/img-ir.h b/drivers/media/rc/img-ir/img-ir.h
index afb189394af9..2ddf56083182 100644
--- a/drivers/media/rc/img-ir/img-ir.h
+++ b/drivers/media/rc/img-ir/img-ir.h
@@ -2,6 +2,11 @@
* ImgTec IR Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_H_
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 6f24e77b1488..7115e68ba697 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -78,11 +78,11 @@ static int display_open(struct inode *inode, struct file *file);
static int display_close(struct inode *inode, struct file *file);
/* VFD write operation */
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos);
/* LCD file_operations override function prototypes */
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos);
/*** G L O B A L S ***/
@@ -825,7 +825,7 @@ static struct attribute_group imon_rf_attr_group = {
* than 32 bytes are provided spaces will be appended to
* generate a full screen.
*/
-static ssize_t vfd_write(struct file *file, const char *buf,
+static ssize_t vfd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos)
{
int i;
@@ -912,7 +912,7 @@ exit:
* display whatever diacritics you need, and so on), but it's also
* a lot more complicated than most LCDs...
*/
-static ssize_t lcd_write(struct file *file, const char *buf,
+static ssize_t lcd_write(struct file *file, const char __user *buf,
size_t n_bytes, loff_t *pos)
{
int retval = 0;
@@ -1017,7 +1017,7 @@ 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_protocols_allowed(rc, *rc_type))
+ if (*rc_type && !(*rc_type & rc->allowed_protocols))
dev_warn(dev, "Looks like you're trying to use an IR protocol "
"this device does not support\n");
@@ -1579,7 +1579,10 @@ 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);
+ if (ictx->rc_type == RC_BIT_RC6_MCE)
+ rc_keydown(ictx->rdev,
+ ictx->rc_type == RC_BIT_RC6_MCE ? RC_TYPE_RC6_MCE : RC_TYPE_OTHER,
+ 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);
@@ -1867,8 +1870,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
rdev->priv = ictx;
rdev->driver_type = RC_DRIVER_SCANCODE;
- /* iMON PAD or MCE */
- rc_set_allowed_protocols(rdev, RC_BIT_OTHER | RC_BIT_RC6_MCE);
+ rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
rdev->change_protocol = imon_ir_change_protocol;
rdev->driver_name = MOD_NAME;
@@ -1881,7 +1883,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
if (ictx->product == 0xffdc) {
imon_get_ffdc_type(ictx);
- rc_set_allowed_protocols(rdev, ictx->rc_type);
+ rdev->allowed_protocols = ictx->rc_type;
}
imon_set_display_type(ictx);
diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
index 4ea62a1dcfda..30bcf188d377 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 (!rc_protocols_enabled(dev, 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 d731da6c414d..ed2c8a1ed8ca 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 (!rc_protocols_enabled(dev, 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 0c55f794c8cf..9f3c9b59f30c 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 (!rc_protocols_enabled(dev, 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 35c42e5e270b..7b81fec0820f 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 (!rc_protocols_enabled(dev, 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-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 4295d9b250c8..2ef763928ca4 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
+ * 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,
@@ -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 (!rc_protocols_enabled(dev, RC_BIT_RC5 | RC_BIT_RC5X))
+ if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
return 0;
if (!is_timing_event(ev)) {
@@ -65,7 +66,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
goto out;
again:
- IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
+ IR_dprintk(2, "RC5(x/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))
@@ -79,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;
@@ -99,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;
@@ -111,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;
@@ -125,10 +124,10 @@ again:
if (ev.pulse)
break;
- if (data->wanted_bits == RC5X_NBITS) {
+ if (data->is_rc5x && data->count == RC5X_NBITS) {
/* RC5X */
u8 xdata, command, system;
- if (!rc_protocols_enabled(dev, RC_BIT_RC5X)) {
+ if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
data->state = STATE_INACTIVE;
return 0;
}
@@ -138,14 +137,12 @@ again:
toggle = (data->bits & 0x20000) ? 1 : 0;
command += (data->bits & 0x01000) ? 0 : 0x40;
scancode = system << 16 | command << 8 | xdata;
+ protocol = RC_TYPE_RC5X;
- IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
- scancode, toggle);
-
- } else {
+ } else if (!data->is_rc5x && data->count == RC5_NBITS) {
/* RC5 */
u8 command, system;
- if (!rc_protocols_enabled(dev, RC_BIT_RC5)) {
+ if (!(dev->enabled_protocols & RC_BIT_RC5)) {
data->state = STATE_INACTIVE;
return 0;
}
@@ -154,25 +151,41 @@ again:
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",
- scancode, toggle);
- }
+ } else if (!data->is_rc5x && data->count == RC5_SZ_NBITS) {
+ /* RC5 StreamZap */
+ u8 command, system;
+ if (!(dev->enabled_protocols & RC_BIT_RC5_SZ)) {
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+ 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;
- rc_keydown(dev, scancode, toggle);
+ } else
+ break;
+
+ IR_dprintk(1, "RC5(x/sz) scancode 0x%06x (p: %u, t: %u)\n",
+ scancode, protocol, toggle);
+
+ rc_keydown(dev, protocol, scancode, toggle);
data->state = STATE_INACTIVE;
return 0;
}
out:
- IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
- data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ IR_dprintk(1, "RC5(x/sz) decode failed at state %i count %d (%uus %s)\n",
+ data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
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,
};
@@ -180,7 +193,7 @@ static int __init ir_rc5_decode_init(void)
{
ir_raw_handler_register(&rc5_handler);
- printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
+ printk(KERN_INFO "IR RC5(x/sz) protocol handler initialized\n");
return 0;
}
@@ -193,6 +206,6 @@ module_init(ir_rc5_decode_init);
module_exit(ir_rc5_decode_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_AUTHOR("Mauro Carvalho Chehab and Jarod Wilson");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
+MODULE_DESCRIPTION("RC5(x/sz) IR protocol decoder");
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 dc18b7434db8..000000000000
--- 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
- * 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 (!rc_protocols_enabled(dev, 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, 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/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index cfbd64e3999c..f1f098e22f7e 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -88,10 +88,11 @@ 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 (!rc_protocols_enabled(dev, RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
- RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
- RC_BIT_RC6_MCE))
+ 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;
if (!is_timing_event(ev)) {
@@ -233,9 +234,11 @@ again:
case RC6_MODE_0:
scancode = data->body;
toggle = data->toggle;
+ protocol = RC_TYPE_RC6_0;
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",
@@ -244,23 +247,39 @@ again:
}
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 {
+ switch (data->count) {
+ case 20:
+ protocol = RC_TYPE_RC6_6A_20;
+ toggle = 0;
+ break;
+ case 24:
+ protocol = RC_BIT_RC6_6A_24;
toggle = 0;
+ break;
+ case 32:
+ if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
+ protocol = RC_TYPE_RC6_MCE;
+ scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
+ toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
+ } else {
+ protocol = RC_BIT_RC6_6A_32;
+ toggle = 0;
+ }
+ break;
+ default:
+ IR_dprintk(1, "RC6(6A) unsupported length\n");
+ goto out;
}
- IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
- scancode, toggle);
+
+ IR_dprintk(1, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
+ protocol, scancode, toggle);
break;
default:
IR_dprintk(1, "RC6 unknown mode\n");
goto out;
}
- rc_keydown(dev, 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 eb715f04dc27..ad1dc6ae21fc 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 (!rc_protocols_enabled(dev, 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-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
index 66d20394ceaa..b7acdbae8159 100644
--- a/drivers/media/rc/ir-sharp-decoder.c
+++ b/drivers/media/rc/ir-sharp-decoder.c
@@ -48,7 +48,7 @@ static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
struct sharp_dec *data = &dev->raw->sharp;
u32 msg, echo, address, command, scancode;
- if (!rc_protocols_enabled(dev, RC_BIT_SHARP))
+ if (!(dev->enabled_protocols & RC_BIT_SHARP))
return 0;
if (!is_timing_event(ev)) {
@@ -162,7 +162,7 @@ static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
scancode = address << 8 | command;
IR_dprintk(1, "Sharp scancode 0x%04x\n", scancode);
- rc_keydown(dev, scancode, 0);
+ rc_keydown(dev, RC_TYPE_SHARP, 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 599c19a73360..d12dc3da5931 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
@@ -42,11 +42,12 @@ enum sony_state {
static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct sony_dec *data = &dev->raw->sony;
+ enum rc_type protocol;
u32 scancode;
u8 device, subdevice, function;
- if (!rc_protocols_enabled(dev, RC_BIT_SONY12 | RC_BIT_SONY15 |
- RC_BIT_SONY20))
+ if (!(dev->enabled_protocols &
+ (RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
return 0;
if (!is_timing_event(ev)) {
@@ -124,31 +125,34 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
switch (data->count) {
case 12:
- if (!rc_protocols_enabled(dev, RC_BIT_SONY12)) {
+ if (!(dev->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 (!rc_protocols_enabled(dev, RC_BIT_SONY15)) {
+ if (!(dev->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 (!rc_protocols_enabled(dev, RC_BIT_SONY20)) {
+ if (!(dev->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);
@@ -157,7 +161,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
scancode = device << 16 | subdevice << 8 | function;
IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
- rc_keydown(dev, scancode, 0);
+ rc_keydown(dev, protocol, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
diff --git a/drivers/media/rc/ir-xmp-decoder.c b/drivers/media/rc/ir-xmp-decoder.c
new file mode 100644
index 000000000000..1017d4816e8d
--- /dev/null
+++ b/drivers/media/rc/ir-xmp-decoder.c
@@ -0,0 +1,225 @@
+/* ir-xmp-decoder.c - handle XMP IR Pulse/Space protocol
+ *
+ * Copyright (C) 2014 by Marcel Mol
+ *
+ * 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.
+ *
+ * - Based on info from http://www.hifi-remote.com
+ * - Ignore Toggle=9 frames
+ * - Ignore XMP-1 XMP-2 difference, always store 16 bit OBC
+ */
+
+#include <linux/bitrev.h>
+#include <linux/module.h>
+#include "rc-core-priv.h"
+
+#define XMP_UNIT 136000 /* ns */
+#define XMP_LEADER 210000 /* ns */
+#define XMP_NIBBLE_PREFIX 760000 /* ns */
+#define XMP_HALFFRAME_SPACE 13800000 /* ns */
+#define XMP_TRAILER_SPACE 20000000 /* should be 80ms but not all dureation supliers can go that high */
+
+enum xmp_state {
+ STATE_INACTIVE,
+ STATE_LEADER_PULSE,
+ STATE_NIBBLE_SPACE,
+};
+
+/**
+ * ir_xmp_decode() - Decode one XMP pulse or space
+ * @dev: the struct rc_dev descriptor of the device
+ * @duration: the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
+{
+ struct xmp_dec *data = &dev->raw->xmp;
+
+ if (!(dev->enabled_protocols & RC_BIT_XMP))
+ return 0;
+
+ if (!is_timing_event(ev)) {
+ if (ev.reset)
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ IR_dprintk(2, "XMP decode started at state %d %d (%uus %s)\n",
+ data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
+
+ switch (data->state) {
+
+ case STATE_INACTIVE:
+ if (!ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2)) {
+ data->count = 0;
+ data->state = STATE_NIBBLE_SPACE;
+ }
+
+ return 0;
+
+ case STATE_LEADER_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2))
+ data->state = STATE_NIBBLE_SPACE;
+
+ return 0;
+
+ case STATE_NIBBLE_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (geq_margin(ev.duration, XMP_TRAILER_SPACE, XMP_NIBBLE_PREFIX)) {
+ int divider, i;
+ u8 addr, subaddr, subaddr2, toggle, oem, obc1, obc2, sum1, sum2;
+ u32 *n;
+ u32 scancode;
+
+ if (data->count != 16) {
+ IR_dprintk(2, "received TRAILER period at index %d: %u\n",
+ data->count, ev.duration);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+
+ n = data->durations;
+ /*
+ * the 4th nibble should be 15 so base the divider on this
+ * to transform durations into nibbles. Substract 2000 from
+ * the divider to compensate for fluctuations in the signal
+ */
+ divider = (n[3] - XMP_NIBBLE_PREFIX) / 15 - 2000;
+ if (divider < 50) {
+ IR_dprintk(2, "divider to small %d.\n", divider);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+
+ /* convert to nibbles and do some sanity checks */
+ for (i = 0; i < 16; i++)
+ n[i] = (n[i] - XMP_NIBBLE_PREFIX) / divider;
+ sum1 = (15 + n[0] + n[1] + n[2] + n[3] +
+ n[4] + n[5] + n[6] + n[7]) % 16;
+ sum2 = (15 + n[8] + n[9] + n[10] + n[11] +
+ n[12] + n[13] + n[14] + n[15]) % 16;
+
+ if (sum1 != 15 || sum2 != 15) {
+ IR_dprintk(2, "checksum errors sum1=0x%X sum2=0x%X\n",
+ sum1, sum2);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+
+ subaddr = n[0] << 4 | n[2];
+ subaddr2 = n[8] << 4 | n[11];
+ oem = n[4] << 4 | n[5];
+ addr = n[6] << 4 | n[7];
+ toggle = n[10];
+ obc1 = n[12] << 4 | n[13];
+ obc2 = n[14] << 4 | n[15];
+ if (subaddr != subaddr2) {
+ IR_dprintk(2, "subaddress nibbles mismatch 0x%02X != 0x%02X\n",
+ subaddr, subaddr2);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+ if (oem != 0x44)
+ IR_dprintk(1, "Warning: OEM nibbles 0x%02X. Expected 0x44\n",
+ oem);
+
+ scancode = addr << 24 | subaddr << 16 |
+ obc1 << 8 | obc2;
+ IR_dprintk(1, "XMP scancode 0x%06x\n", scancode);
+
+ if (toggle == 0) {
+ rc_keydown(dev, RC_TYPE_XMP, scancode, 0);
+ } else {
+ rc_repeat(dev);
+ IR_dprintk(1, "Repeat last key\n");
+ }
+ data->state = STATE_INACTIVE;
+
+ return 0;
+
+ } else if (geq_margin(ev.duration, XMP_HALFFRAME_SPACE, XMP_NIBBLE_PREFIX)) {
+ /* Expect 8 or 16 nibble pulses. 16 in case of 'final' frame */
+ if (data->count == 16) {
+ IR_dprintk(2, "received half frame pulse at index %d. Probably a final frame key-up event: %u\n",
+ data->count, ev.duration);
+ /*
+ * TODO: for now go back to half frame position
+ * so trailer can be found and key press
+ * can be handled.
+ */
+ data->count = 8;
+ }
+
+ else if (data->count != 8)
+ IR_dprintk(2, "received half frame pulse at index %d: %u\n",
+ data->count, ev.duration);
+ data->state = STATE_LEADER_PULSE;
+
+ return 0;
+
+ } else if (geq_margin(ev.duration, XMP_NIBBLE_PREFIX, XMP_UNIT)) {
+ /* store nibble raw data, decode after trailer */
+ if (data->count == 16) {
+ IR_dprintk(2, "to many pulses (%d) ignoring: %u\n",
+ data->count, ev.duration);
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+ }
+ data->durations[data->count] = ev.duration;
+ data->count++;
+ data->state = STATE_LEADER_PULSE;
+
+ return 0;
+
+ }
+
+ break;
+ }
+
+ IR_dprintk(1, "XMP decode failed at count %d state %d (%uus %s)\n",
+ data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+}
+
+static struct ir_raw_handler xmp_handler = {
+ .protocols = RC_BIT_XMP,
+ .decode = ir_xmp_decode,
+};
+
+static int __init ir_xmp_decode_init(void)
+{
+ ir_raw_handler_register(&xmp_handler);
+
+ printk(KERN_INFO "IR XMP protocol handler initialized\n");
+ return 0;
+}
+
+static void __exit ir_xmp_decode_exit(void)
+{
+ ir_raw_handler_unregister(&xmp_handler);
+}
+
+module_init(ir_xmp_decode_init);
+module_exit(ir_xmp_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marcel Mol <marcel@mesa.nl>");
+MODULE_AUTHOR("MESA Consulting (http://www.mesa.nl)");
+MODULE_DESCRIPTION("XMP IR protocol decoder");
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index ab24cc6d3655..447fe35862dc 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1563,7 +1563,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;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = ite_open;
rdev->close = ite_close;
rdev->s_idle = ite_s_idle;
@@ -1709,12 +1709,12 @@ static struct pnp_driver ite_driver = {
.shutdown = ite_shutdown,
};
-static int ite_init(void)
+static int __init ite_init(void)
{
return pnp_register_driver(&ite_driver);
}
-static void ite_exit(void)
+static void __exit ite_exit(void)
{
pnp_unregister_driver(&ite_driver);
}
diff --git a/drivers/media/rc/keymaps/rc-ati-x10.c b/drivers/media/rc/keymaps/rc-ati-x10.c
index 81506440eded..4bdc709ec54d 100644
--- a/drivers/media/rc/keymaps/rc-ati-x10.c
+++ b/drivers/media/rc/keymaps/rc-ati-x10.c
@@ -26,7 +26,42 @@
#include <linux/module.h>
#include <media/rc-map.h>
+/*
+ * Intended usage comments below are from vendor-supplied
+ * Source: ATI REMOTE WONDERâ„¢ Installation Guide
+ * http://www2.ati.com/manuals/remctrl.pdf
+ *
+ * Scancodes were in strict left-right, top-bottom order on the
+ * original ATI Remote Wonder, but were moved on later models.
+ *
+ * Keys A-F are intended to be user-programmable.
+ */
+
static struct rc_map_table ati_x10[] = {
+ /* keyboard - Above the cursor pad */
+ { 0x00, KEY_A },
+ { 0x01, KEY_B },
+ { 0x02, KEY_POWER }, /* Power */
+
+ { 0x03, KEY_TV }, /* TV */
+ { 0x04, KEY_DVD }, /* DVD */
+ { 0x05, KEY_WWW }, /* WEB */
+ { 0x06, KEY_BOOKMARKS }, /* "book": Open Media Library */
+ { 0x07, KEY_EDIT }, /* "hand": Toggle left mouse button (grab) */
+
+ /* Mouse emulation pad goes here, handled by driver separately */
+
+ { 0x09, KEY_VOLUMEDOWN }, /* VOL + */
+ { 0x08, KEY_VOLUMEUP }, /* VOL - */
+ { 0x0a, KEY_MUTE }, /* MUTE */
+ { 0x0b, KEY_CHANNELUP }, /* CH + */
+ { 0x0c, KEY_CHANNELDOWN },/* CH - */
+
+ /*
+ * We could use KEY_NUMERIC_x for these, but the X11 protocol
+ * has problems with keycodes greater than 255, so avoid those high
+ * keycodes in default maps.
+ */
{ 0x0d, KEY_1 },
{ 0x0e, KEY_2 },
{ 0x0f, KEY_3 },
@@ -36,46 +71,45 @@ static struct rc_map_table ati_x10[] = {
{ 0x13, KEY_7 },
{ 0x14, KEY_8 },
{ 0x15, KEY_9 },
+ { 0x16, KEY_MENU }, /* "menu": DVD root menu */
+ /* KEY_NUMERIC_STAR? */
{ 0x17, KEY_0 },
- { 0x00, KEY_A },
- { 0x01, KEY_B },
+ { 0x18, KEY_SETUP }, /* "check": DVD setup menu */
+ /* KEY_NUMERIC_POUND? */
+
+ /* DVD navigation buttons */
{ 0x19, KEY_C },
+ { 0x1a, KEY_UP }, /* up */
{ 0x1b, KEY_D },
- { 0x21, KEY_E },
- { 0x23, KEY_F },
- { 0x18, KEY_KPENTER }, /* "check" */
- { 0x16, KEY_MENU }, /* "menu" */
- { 0x02, KEY_POWER }, /* Power */
- { 0x03, KEY_TV }, /* TV */
- { 0x04, KEY_DVD }, /* DVD */
- { 0x05, KEY_WWW }, /* WEB */
- { 0x06, KEY_BOOKMARKS }, /* "book" */
- { 0x07, KEY_EDIT }, /* "hand" */
- { 0x1c, KEY_COFFEE }, /* "timer" */
- { 0x20, KEY_FRONT }, /* "max" */
+ { 0x1c, KEY_PROPS }, /* "timer" Should be Data On Screen */
+ /* Symbol is "circle nailed to box" */
{ 0x1d, KEY_LEFT }, /* left */
+ { 0x1e, KEY_OK }, /* "OK" */
{ 0x1f, KEY_RIGHT }, /* right */
+ { 0x20, KEY_SCREEN }, /* "max" (X11 warning: 0x177) */
+ /* Should be AC View Toggle, but
+ that's not in <input/input.h>.
+ KEY_ZOOM (0x174)? */
+ { 0x21, KEY_E },
{ 0x22, KEY_DOWN }, /* down */
- { 0x1a, KEY_UP }, /* up */
- { 0x1e, KEY_OK }, /* "OK" */
- { 0x09, KEY_VOLUMEDOWN }, /* VOL + */
- { 0x08, KEY_VOLUMEUP }, /* VOL - */
- { 0x0a, KEY_MUTE }, /* MUTE */
- { 0x0b, KEY_CHANNELUP }, /* CH + */
- { 0x0c, KEY_CHANNELDOWN },/* CH - */
+ { 0x23, KEY_F },
+ /* Play/stop/pause buttons */
+ { 0x24, KEY_REWIND }, /* (<<) Rewind */
+ { 0x25, KEY_PLAY }, /* ( >) Play (KEY_PLAYCD?) */
+ { 0x26, KEY_FASTFORWARD }, /* (>>) Fast forward */
+
{ 0x27, KEY_RECORD }, /* ( o) red */
- { 0x25, KEY_PLAY }, /* ( >) */
- { 0x24, KEY_REWIND }, /* (<<) */
- { 0x26, KEY_FORWARD }, /* (>>) */
- { 0x28, KEY_STOP }, /* ([]) */
- { 0x29, KEY_PAUSE }, /* ('') */
- { 0x2b, KEY_PREVIOUS }, /* (<-) */
+ { 0x28, KEY_STOPCD }, /* ([]) Stop (KEY_STOP is something else!) */
+ { 0x29, KEY_PAUSE }, /* ('') Pause (KEY_PAUSECD?) */
+
+ /* Extra keys, not on the original ATI remote */
{ 0x2a, KEY_NEXT }, /* (>+) */
- { 0x2d, KEY_INFO }, /* PLAYING */
+ { 0x2b, KEY_PREVIOUS }, /* (<-) */
+ { 0x2d, KEY_INFO }, /* PLAYING (X11 warning: 0x166) */
{ 0x2e, KEY_HOME }, /* TOP */
{ 0x2f, KEY_END }, /* END */
- { 0x30, KEY_SELECT }, /* SELECT */
+ { 0x30, KEY_SELECT }, /* SELECT (X11 warning: 0x161) */
};
static struct rc_map_list ati_x10_map = {
diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c
index d6519f8ac95a..520a96f2ff86 100644
--- a/drivers/media/rc/keymaps/rc-behold.c
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -30,8 +30,8 @@ static struct rc_map_table behold[] = {
/* 0x1c 0x12 *
* TV/FM POWER *
* */
- { 0x6b861c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */
- { 0x6b8612, KEY_POWER },
+ { 0x866b1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */
+ { 0x866b12, KEY_POWER },
/* 0x01 0x02 0x03 *
* 1 2 3 *
@@ -42,28 +42,28 @@ static struct rc_map_table behold[] = {
* 0x07 0x08 0x09 *
* 7 8 9 *
* */
- { 0x6b8601, KEY_1 },
- { 0x6b8602, KEY_2 },
- { 0x6b8603, KEY_3 },
- { 0x6b8604, KEY_4 },
- { 0x6b8605, KEY_5 },
- { 0x6b8606, KEY_6 },
- { 0x6b8607, KEY_7 },
- { 0x6b8608, KEY_8 },
- { 0x6b8609, KEY_9 },
+ { 0x866b01, KEY_1 },
+ { 0x866b02, KEY_2 },
+ { 0x866b03, KEY_3 },
+ { 0x866b04, KEY_4 },
+ { 0x866b05, KEY_5 },
+ { 0x866b06, KEY_6 },
+ { 0x866b07, KEY_7 },
+ { 0x866b08, KEY_8 },
+ { 0x866b09, KEY_9 },
/* 0x0a 0x00 0x17 *
* RECALL 0 MODE *
* */
- { 0x6b860a, KEY_AGAIN },
- { 0x6b8600, KEY_0 },
- { 0x6b8617, KEY_MODE },
+ { 0x866b0a, KEY_AGAIN },
+ { 0x866b00, KEY_0 },
+ { 0x866b17, KEY_MODE },
/* 0x14 0x10 *
* ASPECT FULLSCREEN *
* */
- { 0x6b8614, KEY_SCREEN },
- { 0x6b8610, KEY_ZOOM },
+ { 0x866b14, KEY_SCREEN },
+ { 0x866b10, KEY_ZOOM },
/* 0x0b *
* Up *
@@ -74,17 +74,17 @@ static struct rc_map_table behold[] = {
* 0x015 *
* Down *
* */
- { 0x6b860b, KEY_CHANNELUP },
- { 0x6b8618, KEY_VOLUMEDOWN },
- { 0x6b8616, KEY_OK }, /* XXX KEY_ENTER */
- { 0x6b860c, KEY_VOLUMEUP },
- { 0x6b8615, KEY_CHANNELDOWN },
+ { 0x866b0b, KEY_CHANNELUP },
+ { 0x866b18, KEY_VOLUMEDOWN },
+ { 0x866b16, KEY_OK }, /* XXX KEY_ENTER */
+ { 0x866b0c, KEY_VOLUMEUP },
+ { 0x866b15, KEY_CHANNELDOWN },
/* 0x11 0x0d *
* MUTE INFO *
* */
- { 0x6b8611, KEY_MUTE },
- { 0x6b860d, KEY_INFO },
+ { 0x866b11, KEY_MUTE },
+ { 0x866b0d, KEY_INFO },
/* 0x0f 0x1b 0x1a *
* RECORD PLAY/PAUSE STOP *
@@ -93,26 +93,26 @@ static struct rc_map_table behold[] = {
*TELETEXT AUDIO SOURCE *
* RED YELLOW *
* */
- { 0x6b860f, KEY_RECORD },
- { 0x6b861b, KEY_PLAYPAUSE },
- { 0x6b861a, KEY_STOP },
- { 0x6b860e, KEY_TEXT },
- { 0x6b861f, KEY_RED }, /*XXX KEY_AUDIO */
- { 0x6b861e, KEY_VIDEO },
+ { 0x866b0f, KEY_RECORD },
+ { 0x866b1b, KEY_PLAYPAUSE },
+ { 0x866b1a, KEY_STOP },
+ { 0x866b0e, KEY_TEXT },
+ { 0x866b1f, KEY_RED }, /*XXX KEY_AUDIO */
+ { 0x866b1e, KEY_VIDEO },
/* 0x1d 0x13 0x19 *
* SLEEP PREVIEW DVB *
* GREEN BLUE *
* */
- { 0x6b861d, KEY_SLEEP },
- { 0x6b8613, KEY_GREEN },
- { 0x6b8619, KEY_BLUE }, /* XXX KEY_SAT */
+ { 0x866b1d, KEY_SLEEP },
+ { 0x866b13, KEY_GREEN },
+ { 0x866b19, KEY_BLUE }, /* XXX KEY_SAT */
/* 0x58 0x5c *
* FREEZE SNAPSHOT *
* */
- { 0x6b8658, KEY_SLOW },
- { 0x6b865c, KEY_CAMERA },
+ { 0x866b58, KEY_SLOW },
+ { 0x866b5c, KEY_CAMERA },
};
diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c
index 8ec881adb7cf..4c50f33c7c41 100644
--- a/drivers/media/rc/keymaps/rc-nebula.c
+++ b/drivers/media/rc/keymaps/rc-nebula.c
@@ -14,68 +14,68 @@
#include <linux/module.h>
static struct rc_map_table nebula[] = {
- { 0x00, KEY_0 },
- { 0x01, KEY_1 },
- { 0x02, KEY_2 },
- { 0x03, KEY_3 },
- { 0x04, KEY_4 },
- { 0x05, KEY_5 },
- { 0x06, KEY_6 },
- { 0x07, KEY_7 },
- { 0x08, KEY_8 },
- { 0x09, KEY_9 },
- { 0x0a, KEY_TV },
- { 0x0b, KEY_AUX },
- { 0x0c, KEY_DVD },
- { 0x0d, KEY_POWER },
- { 0x0e, KEY_CAMERA }, /* labelled 'Picture' */
- { 0x0f, KEY_AUDIO },
- { 0x10, KEY_INFO },
- { 0x11, KEY_F13 }, /* 16:9 */
- { 0x12, KEY_F14 }, /* 14:9 */
- { 0x13, KEY_EPG },
- { 0x14, KEY_EXIT },
- { 0x15, KEY_MENU },
- { 0x16, KEY_UP },
- { 0x17, KEY_DOWN },
- { 0x18, KEY_LEFT },
- { 0x19, KEY_RIGHT },
- { 0x1a, KEY_ENTER },
- { 0x1b, KEY_CHANNELUP },
- { 0x1c, KEY_CHANNELDOWN },
- { 0x1d, KEY_VOLUMEUP },
- { 0x1e, KEY_VOLUMEDOWN },
- { 0x1f, KEY_RED },
- { 0x20, KEY_GREEN },
- { 0x21, KEY_YELLOW },
- { 0x22, KEY_BLUE },
- { 0x23, KEY_SUBTITLE },
- { 0x24, KEY_F15 }, /* AD */
- { 0x25, KEY_TEXT },
- { 0x26, KEY_MUTE },
- { 0x27, KEY_REWIND },
- { 0x28, KEY_STOP },
- { 0x29, KEY_PLAY },
- { 0x2a, KEY_FASTFORWARD },
- { 0x2b, KEY_F16 }, /* chapter */
- { 0x2c, KEY_PAUSE },
- { 0x2d, KEY_PLAY },
- { 0x2e, KEY_RECORD },
- { 0x2f, KEY_F17 }, /* picture in picture */
- { 0x30, KEY_KPPLUS }, /* zoom in */
- { 0x31, KEY_KPMINUS }, /* zoom out */
- { 0x32, KEY_F18 }, /* capture */
- { 0x33, KEY_F19 }, /* web */
- { 0x34, KEY_EMAIL },
- { 0x35, KEY_PHONE },
- { 0x36, KEY_PC },
+ { 0x0000, KEY_0 },
+ { 0x0001, KEY_1 },
+ { 0x0002, KEY_2 },
+ { 0x0003, KEY_3 },
+ { 0x0004, KEY_4 },
+ { 0x0005, KEY_5 },
+ { 0x0006, KEY_6 },
+ { 0x0007, KEY_7 },
+ { 0x0008, KEY_8 },
+ { 0x0009, KEY_9 },
+ { 0x000a, KEY_TV },
+ { 0x000b, KEY_AUX },
+ { 0x000c, KEY_DVD },
+ { 0x000d, KEY_POWER },
+ { 0x000e, KEY_CAMERA }, /* labelled 'Picture' */
+ { 0x000f, KEY_AUDIO },
+ { 0x0010, KEY_INFO },
+ { 0x0011, KEY_F13 }, /* 16:9 */
+ { 0x0012, KEY_F14 }, /* 14:9 */
+ { 0x0013, KEY_EPG },
+ { 0x0014, KEY_EXIT },
+ { 0x0015, KEY_MENU },
+ { 0x0016, KEY_UP },
+ { 0x0017, KEY_DOWN },
+ { 0x0018, KEY_LEFT },
+ { 0x0019, KEY_RIGHT },
+ { 0x001a, KEY_ENTER },
+ { 0x001b, KEY_CHANNELUP },
+ { 0x001c, KEY_CHANNELDOWN },
+ { 0x001d, KEY_VOLUMEUP },
+ { 0x001e, KEY_VOLUMEDOWN },
+ { 0x001f, KEY_RED },
+ { 0x0020, KEY_GREEN },
+ { 0x0021, KEY_YELLOW },
+ { 0x0022, KEY_BLUE },
+ { 0x0023, KEY_SUBTITLE },
+ { 0x0024, KEY_F15 }, /* AD */
+ { 0x0025, KEY_TEXT },
+ { 0x0026, KEY_MUTE },
+ { 0x0027, KEY_REWIND },
+ { 0x0028, KEY_STOP },
+ { 0x0029, KEY_PLAY },
+ { 0x002a, KEY_FASTFORWARD },
+ { 0x002b, KEY_F16 }, /* chapter */
+ { 0x002c, KEY_PAUSE },
+ { 0x002d, KEY_PLAY },
+ { 0x002e, KEY_RECORD },
+ { 0x002f, KEY_F17 }, /* picture in picture */
+ { 0x0030, KEY_KPPLUS }, /* zoom in */
+ { 0x0031, KEY_KPMINUS }, /* zoom out */
+ { 0x0032, KEY_F18 }, /* capture */
+ { 0x0033, KEY_F19 }, /* web */
+ { 0x0034, KEY_EMAIL },
+ { 0x0035, KEY_PHONE },
+ { 0x0036, KEY_PC },
};
static struct rc_map_list nebula_map = {
.map = {
.scan = nebula,
.size = ARRAY_SIZE(nebula),
- .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
+ .rc_type = RC_TYPE_RC5,
.name = RC_MAP_NEBULA,
}
};
diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c
index f9a07578d985..23c061174ed7 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/mceusb.c b/drivers/media/rc/mceusb.c
index d5c1df3c9db1..45b0894288e5 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -187,6 +187,7 @@
#define VENDOR_CONEXANT 0x0572
#define VENDOR_TWISTEDMELON 0x2596
#define VENDOR_HAUPPAUGE 0x2040
+#define VENDOR_PCTV 0x2013
enum mceusb_model_type {
MCE_GEN2 = 0, /* Most boards */
@@ -240,7 +241,6 @@ static const struct mceusb_model mceusb_model[] = {
* remotes, but we should have something handy,
* to allow testing it
*/
- .rc_map = RC_MAP_HAUPPAUGE,
.name = "Conexant Hybrid TV (cx231xx) MCE IR",
},
[CX_HYBRID_TV] = {
@@ -248,7 +248,6 @@ static const struct mceusb_model mceusb_model[] = {
.name = "Conexant Hybrid TV (cx231xx) MCE IR",
},
[HAUPPAUGE_CX_HYBRID_TV] = {
- .rc_map = RC_MAP_HAUPPAUGE,
.no_tx = 1, /* eeprom says it has no tx */
.name = "Conexant Hybrid TV (cx231xx) MCE IR no TX",
},
@@ -396,6 +395,13 @@ static struct usb_device_id mceusb_dev_table[] = {
/* Hauppauge WINTV-HVR-HVR 930C-HD - based on cx231xx */
{ USB_DEVICE(VENDOR_HAUPPAUGE, 0xb130),
.driver_info = HAUPPAUGE_CX_HYBRID_TV },
+ { USB_DEVICE(VENDOR_HAUPPAUGE, 0xb131),
+ .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+ { USB_DEVICE(VENDOR_PCTV, 0x0259),
+ .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+ { USB_DEVICE(VENDOR_PCTV, 0x025e),
+ .driver_info = HAUPPAUGE_CX_HYBRID_TV },
+
/* Terminating entry */
{ }
};
@@ -1192,8 +1198,10 @@ static void mceusb_flash_led(struct mceusb_dev *ir)
mce_async_out(ir, FLASH_LED, sizeof(FLASH_LED));
}
-static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
+static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir,
+ struct usb_interface *intf)
{
+ struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf));
struct device *dev = ir->dev;
struct rc_dev *rc;
int ret;
@@ -1219,7 +1227,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_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = RC_BIT_ALL;
rc->timeout = MS_TO_NS(100);
if (!ir->flags.no_tx) {
rc->s_tx_mask = mceusb_set_tx_mask;
@@ -1227,8 +1235,19 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
rc->tx_ir = mceusb_tx_ir;
}
rc->driver_name = DRIVER_NAME;
- rc->map_name = mceusb_model[ir->model].rc_map ?
- mceusb_model[ir->model].rc_map : RC_MAP_RC6_MCE;
+
+ switch (le16_to_cpu(udev->descriptor.idVendor)) {
+ case VENDOR_HAUPPAUGE:
+ rc->map_name = RC_MAP_HAUPPAUGE;
+ break;
+ case VENDOR_PCTV:
+ rc->map_name = RC_MAP_PINNACLE_PCTV_HD;
+ break;
+ default:
+ rc->map_name = RC_MAP_RC6_MCE;
+ }
+ if (mceusb_model[ir->model].rc_map)
+ rc->map_name = mceusb_model[ir->model].rc_map;
ret = rc_register_device(rc);
if (ret < 0) {
@@ -1343,7 +1362,7 @@ static int mceusb_dev_probe(struct usb_interface *intf,
snprintf(name + strlen(name), sizeof(name) - strlen(name),
" %s", buf);
- ir->rc = mceusb_init_rc_dev(ir);
+ ir->rc = mceusb_init_rc_dev(ir, intf);
if (!ir->rc)
goto rc_dev_fail;
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index d244e1a83f43..7f4fd859bba5 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1044,7 +1044,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;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = nvt_open;
rdev->close = nvt_close;
rdev->tx_ir = nvt_tx_ir;
@@ -1221,12 +1221,12 @@ static struct pnp_driver nvt_driver = {
.shutdown = nvt_shutdown,
};
-static int nvt_init(void)
+static int __init nvt_init(void)
{
return pnp_register_driver(&nvt_driver);
}
-static void nvt_exit(void)
+static void __exit nvt_exit(void)
{
pnp_unregister_driver(&nvt_driver);
}
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index da536c93c978..b68d4f762734 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;
@@ -116,6 +110,11 @@ struct ir_raw_event_ctrl {
bool send_timeout_reports;
} lirc;
+ struct xmp_dec {
+ int state;
+ unsigned count;
+ u32 durations[16];
+ } xmp;
};
/* macros for IR decoders */
@@ -231,5 +230,12 @@ static inline void load_mce_kbd_decode(void) { }
static inline void load_lirc_codec(void) { }
#endif
+/* from ir-xmp-decoder.c */
+#ifdef CONFIG_IR_XMP_DECODER_MODULE
+#define load_xmp_decode() request_module_nowait("ir-xmp-decoder")
+#else
+static inline void load_xmp_decode(void) { }
+#endif
+
#endif /* _RC_CORE_PRIV */
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 763c9d131d0f..e8fff2add265 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -1,4 +1,4 @@
-/* ir-raw.c - handle IR pulse/space events
+/* rc-ir-raw.c - handle IR pulse/space events
*
* Copyright (C) 2010 by Mauro Carvalho Chehab
*
@@ -240,6 +240,12 @@ ir_raw_get_allowed_protocols(void)
return protocols;
}
+static int change_protocol(struct rc_dev *dev, u64 *rc_type)
+{
+ /* the caller will update dev->enabled_protocols */
+ return 0;
+}
+
/*
* Used to (un)register raw event clients
*/
@@ -256,7 +262,8 @@ int ir_raw_event_register(struct rc_dev *dev)
return -ENOMEM;
dev->raw->dev = dev;
- rc_set_enabled_protocols(dev, ~0);
+ dev->enabled_protocols = ~0;
+ dev->change_protocol = change_protocol;
rc = kfifo_alloc(&dev->raw->kfifo,
sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
GFP_KERNEL);
@@ -355,6 +362,7 @@ void ir_raw_init(void)
load_sharp_decode();
load_mce_kbd_decode();
load_lirc_codec();
+ load_xmp_decode();
/* If needed, we may later add some init code. In this case,
it is needed to change the CONFIG_MODULE test at rc-core.h
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 0a88e0cf964f..63dace8198b0 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_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = 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 970b93d6f399..a7991c7d010a 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -285,8 +285,8 @@ static unsigned int ir_establish_scancode(struct rc_dev *dev,
* IR tables from other remotes. So, we support specifying a mask to
* indicate the valid bits of the scancodes.
*/
- if (dev->scanmask)
- scancode &= dev->scanmask;
+ if (dev->scancode_mask)
+ scancode &= dev->scancode_mask;
/* First check if we already have a mapping for this ir command */
for (i = 0; i < rc_map->len; i++) {
@@ -623,6 +623,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
@@ -630,12 +631,13 @@ 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, enum rc_type protocol,
+ u32 scancode, u32 keycode, u8 toggle)
{
bool new_event = (!dev->keypressed ||
+ dev->last_protocol != protocol ||
dev->last_scancode != scancode ||
- dev->last_toggle != toggle);
+ dev->last_toggle != toggle);
if (new_event && dev->keypressed)
ir_do_keyup(dev, false);
@@ -645,13 +647,14 @@ 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%08x\n",
+ dev->input_name, keycode, protocol, scancode);
input_report_key(dev->input_dev, keycode, 1);
led_trigger_event(led_feedback, LED_FULL);
@@ -663,20 +666,21 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode,
/**
* 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, u32 scancode, u8 toggle)
{
unsigned long flags;
u32 keycode = rc_g_keycode_from_table(dev, 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);
@@ -690,20 +694,22 @@ 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
- * @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. 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,
+ u32 scancode, u8 toggle)
{
unsigned long flags;
u32 keycode = rc_g_keycode_from_table(dev, 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);
@@ -794,6 +800,7 @@ static struct {
{ RC_BIT_SHARP, "sharp" },
{ RC_BIT_MCE_KBD, "mce_kbd" },
{ RC_BIT_LIRC, "lirc" },
+ { RC_BIT_XMP, "xmp" },
};
/**
@@ -824,7 +831,7 @@ struct rc_filter_attribute {
/**
* show_protocols() - shows the current/wakeup IR protocol(s)
* @device: the device descriptor
- * @mattr: the device attribute struct (unused)
+ * @mattr: the device attribute struct
* @buf: a pointer to the output buffer
*
* This routine is a callback routine for input read the IR protocol type(s).
@@ -850,20 +857,20 @@ static ssize_t show_protocols(struct device *device,
mutex_lock(&dev->lock);
- enabled = dev->enabled_protocols[fattr->type];
- if (dev->driver_type == RC_DRIVER_SCANCODE ||
- fattr->type == RC_FILTER_WAKEUP)
- allowed = dev->allowed_protocols[fattr->type];
- else if (dev->raw)
- allowed = ir_raw_get_allowed_protocols();
- else {
- mutex_unlock(&dev->lock);
- return -ENODEV;
+ if (fattr->type == RC_FILTER_NORMAL) {
+ enabled = dev->enabled_protocols;
+ allowed = dev->allowed_protocols;
+ if (dev->raw && !allowed)
+ allowed = ir_raw_get_allowed_protocols();
+ } else {
+ enabled = dev->enabled_wakeup_protocols;
+ allowed = dev->allowed_wakeup_protocols;
}
- IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
- (long long)allowed,
- (long long)enabled);
+ mutex_unlock(&dev->lock);
+
+ IR_dprintk(1, "%s: allowed - 0x%llx, enabled - 0x%llx\n",
+ __func__, (long long)allowed, (long long)enabled);
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
if (allowed & enabled & proto_names[i].type)
@@ -879,62 +886,29 @@ static ssize_t show_protocols(struct device *device,
tmp--;
*tmp = '\n';
- mutex_unlock(&dev->lock);
-
return tmp + 1 - buf;
}
/**
- * store_protocols() - changes the current/wakeup IR protocol(s)
- * @device: the device descriptor
- * @mattr: the device attribute struct (unused)
- * @buf: a pointer to the input buffer
- * @len: length of the input buffer
+ * parse_protocol_change() - parses a protocol change request
+ * @protocols: pointer to the bitmask of current protocols
+ * @buf: pointer to the buffer with a list of changes
*
- * This routine is for changing the IR protocol type.
- * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
- * Writing "+proto" will add a protocol to the list of enabled protocols.
- * Writing "-proto" will remove a protocol from the list of enabled protocols.
+ * Writing "+proto" will add a protocol to the protocol mask.
+ * Writing "-proto" will remove a protocol from protocol mask.
* Writing "proto" will enable only "proto".
* Writing "none" will disable all protocols.
- * Returns -EINVAL if an invalid protocol combination or unknown protocol name
- * is used, otherwise @len.
- *
- * dev->lock is taken to guard against races between device
- * registration, store_protocols and show_protocols.
+ * Returns the number of changes performed or a negative error code.
*/
-static ssize_t store_protocols(struct device *device,
- struct device_attribute *mattr,
- const char *data,
- size_t len)
+static int parse_protocol_change(u64 *protocols, const char *buf)
{
- struct rc_dev *dev = to_rc_dev(device);
- struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
- bool enable, disable;
const char *tmp;
- u64 old_type, type;
+ unsigned count = 0;
+ bool enable, disable;
u64 mask;
- int rc, i, count = 0;
- ssize_t ret;
- int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
- int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
- struct rc_scancode_filter local_filter, *filter;
-
- /* Device is being removed */
- if (!dev)
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-
- if (dev->driver_type != RC_DRIVER_SCANCODE && !dev->raw) {
- IR_dprintk(1, "Protocol switching not supported\n");
- ret = -EINVAL;
- goto out;
- }
- old_type = dev->enabled_protocols[fattr->type];
- type = old_type;
+ int i;
- while ((tmp = strsep((char **) &data, " \n")) != NULL) {
+ while ((tmp = strsep((char **)&buf, " \n")) != NULL) {
if (!*tmp)
break;
@@ -960,76 +934,124 @@ static ssize_t store_protocols(struct device *device,
if (i == ARRAY_SIZE(proto_names)) {
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
count++;
if (enable)
- type |= mask;
+ *protocols |= mask;
else if (disable)
- type &= ~mask;
+ *protocols &= ~mask;
else
- type = mask;
+ *protocols = mask;
}
if (!count) {
IR_dprintk(1, "Protocol not specified\n");
- ret = -EINVAL;
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+/**
+ * store_protocols() - changes the current/wakeup IR protocol(s)
+ * @device: the device descriptor
+ * @mattr: the device attribute struct
+ * @buf: a pointer to the input buffer
+ * @len: length of the input buffer
+ *
+ * This routine is for changing the IR protocol type.
+ * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]protocols.
+ * See parse_protocol_change() for the valid commands.
+ * Returns @len on success or a negative error code.
+ *
+ * dev->lock is taken to guard against races between device
+ * registration, store_protocols and show_protocols.
+ */
+static ssize_t store_protocols(struct device *device,
+ struct device_attribute *mattr,
+ const char *buf, size_t len)
+{
+ struct rc_dev *dev = to_rc_dev(device);
+ struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
+ u64 *current_protocols;
+ int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
+ struct rc_scancode_filter *filter;
+ int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
+ u64 old_protocols, new_protocols;
+ ssize_t rc;
+
+ /* Device is being removed */
+ if (!dev)
+ return -EINVAL;
+
+ if (fattr->type == RC_FILTER_NORMAL) {
+ IR_dprintk(1, "Normal protocol change requested\n");
+ current_protocols = &dev->enabled_protocols;
+ change_protocol = dev->change_protocol;
+ filter = &dev->scancode_filter;
+ set_filter = dev->s_filter;
+ } else {
+ IR_dprintk(1, "Wakeup protocol change requested\n");
+ current_protocols = &dev->enabled_wakeup_protocols;
+ change_protocol = dev->change_wakeup_protocol;
+ filter = &dev->scancode_wakeup_filter;
+ set_filter = dev->s_wakeup_filter;
+ }
+
+ if (!change_protocol) {
+ IR_dprintk(1, "Protocol switching not supported\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&dev->lock);
+
+ old_protocols = *current_protocols;
+ new_protocols = old_protocols;
+ rc = parse_protocol_change(&new_protocols, buf);
+ if (rc < 0)
+ goto out;
+
+ rc = change_protocol(dev, &new_protocols);
+ if (rc < 0) {
+ IR_dprintk(1, "Error setting protocols to 0x%llx\n",
+ (long long)new_protocols);
goto out;
}
- change_protocol = (fattr->type == RC_FILTER_NORMAL)
- ? dev->change_protocol : dev->change_wakeup_protocol;
- if (change_protocol) {
- rc = change_protocol(dev, &type);
- if (rc < 0) {
- IR_dprintk(1, "Error setting protocols to 0x%llx\n",
- (long long)type);
- ret = -EINVAL;
- goto out;
- }
+ if (new_protocols == old_protocols) {
+ rc = len;
+ goto out;
}
- dev->enabled_protocols[fattr->type] = type;
- IR_dprintk(1, "Current protocol(s): 0x%llx\n",
- (long long)type);
+ *current_protocols = new_protocols;
+ IR_dprintk(1, "Protocols changed to 0x%llx\n", (long long)new_protocols);
/*
* If the protocol is changed the filter needs updating.
* Try setting the same filter with the new protocol (if any).
* Fall back to clearing the filter.
*/
- filter = &dev->scancode_filters[fattr->type];
- set_filter = (fattr->type == RC_FILTER_NORMAL)
- ? dev->s_filter : dev->s_wakeup_filter;
-
- if (set_filter && old_type != type && filter->mask) {
- local_filter = *filter;
- if (!type) {
- /* no protocol => clear filter */
- ret = -1;
- } else {
- /* hardware filtering => try setting, otherwise clear */
- ret = set_filter(dev, &local_filter);
- }
- if (ret < 0) {
- /* clear the filter */
- local_filter.data = 0;
- local_filter.mask = 0;
- set_filter(dev, &local_filter);
- }
+ if (set_filter && filter->mask) {
+ if (new_protocols)
+ rc = set_filter(dev, filter);
+ else
+ rc = -1;
- /* commit the new filter */
- *filter = local_filter;
+ if (rc < 0) {
+ filter->data = 0;
+ filter->mask = 0;
+ set_filter(dev, filter);
+ }
}
- ret = len;
+ rc = len;
out:
mutex_unlock(&dev->lock);
- return ret;
+ return rc;
}
/**
@@ -1055,20 +1077,23 @@ static ssize_t show_filter(struct device *device,
{
struct rc_dev *dev = to_rc_dev(device);
struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
+ struct rc_scancode_filter *filter;
u32 val;
/* Device is being removed */
if (!dev)
return -EINVAL;
+ if (fattr->type == RC_FILTER_NORMAL)
+ filter = &dev->scancode_filter;
+ else
+ filter = &dev->scancode_wakeup_filter;
+
mutex_lock(&dev->lock);
- if ((fattr->type == RC_FILTER_NORMAL && !dev->s_filter) ||
- (fattr->type == RC_FILTER_WAKEUP && !dev->s_wakeup_filter))
- val = 0;
- else if (fattr->mask)
- val = dev->scancode_filters[fattr->type].mask;
+ if (fattr->mask)
+ val = filter->mask;
else
- val = dev->scancode_filters[fattr->type].data;
+ val = filter->data;
mutex_unlock(&dev->lock);
return sprintf(buf, "%#x\n", val);
@@ -1095,15 +1120,15 @@ static ssize_t show_filter(struct device *device,
*/
static ssize_t store_filter(struct device *device,
struct device_attribute *attr,
- const char *buf,
- size_t count)
+ const char *buf, size_t len)
{
struct rc_dev *dev = to_rc_dev(device);
struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
- struct rc_scancode_filter local_filter, *filter;
+ struct rc_scancode_filter new_filter, *filter;
int ret;
unsigned long val;
int (*set_filter)(struct rc_dev *dev, struct rc_scancode_filter *filter);
+ u64 *enabled_protocols;
/* Device is being removed */
if (!dev)
@@ -1113,38 +1138,42 @@ static ssize_t store_filter(struct device *device,
if (ret < 0)
return ret;
- /* Can the scancode filter be set? */
- set_filter = (fattr->type == RC_FILTER_NORMAL) ? dev->s_filter :
- dev->s_wakeup_filter;
+ if (fattr->type == RC_FILTER_NORMAL) {
+ set_filter = dev->s_filter;
+ enabled_protocols = &dev->enabled_protocols;
+ filter = &dev->scancode_filter;
+ } else {
+ set_filter = dev->s_wakeup_filter;
+ enabled_protocols = &dev->enabled_wakeup_protocols;
+ filter = &dev->scancode_wakeup_filter;
+ }
+
if (!set_filter)
return -EINVAL;
mutex_lock(&dev->lock);
- /* Tell the driver about the new filter */
- filter = &dev->scancode_filters[fattr->type];
- local_filter = *filter;
+ new_filter = *filter;
if (fattr->mask)
- local_filter.mask = val;
+ new_filter.mask = val;
else
- local_filter.data = val;
+ new_filter.data = val;
- if (!dev->enabled_protocols[fattr->type] && local_filter.mask) {
+ if (!*enabled_protocols && val) {
/* refuse to set a filter unless a protocol is enabled */
ret = -EINVAL;
goto unlock;
}
- ret = set_filter(dev, &local_filter);
+ ret = set_filter(dev, &new_filter);
if (ret < 0)
goto unlock;
- /* Success, commit the new filter */
- *filter = local_filter;
+ *filter = new_filter;
unlock:
mutex_unlock(&dev->lock);
- return (ret < 0) ? ret : count;
+ return (ret < 0) ? ret : len;
}
static void rc_dev_release(struct device *device)
@@ -1315,7 +1344,7 @@ int rc_register_device(struct rc_dev *dev)
dev->dev.groups = dev->sysfs_groups;
dev->sysfs_groups[attr++] = &rc_dev_protocol_attr_grp;
if (dev->s_filter)
- dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp;
+ dev->sysfs_groups[attr++] = &rc_dev_filter_attr_grp;
if (dev->s_wakeup_filter)
dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp;
if (dev->change_wakeup_protocol)
@@ -1395,7 +1424,7 @@ int rc_register_device(struct rc_dev *dev)
rc = dev->change_protocol(dev, &rc_type);
if (rc < 0)
goto out_raw;
- dev->enabled_protocols[RC_FILTER_NORMAL] = rc_type;
+ dev->enabled_protocols = rc_type;
}
mutex_unlock(&dev->lock);
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 79abbc8d9600..795b394a5d84 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -878,7 +878,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_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = 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/st_rc.c b/drivers/media/rc/st_rc.c
index 22e4c1f28ab4..5c151351afa4 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -287,7 +287,7 @@ static int st_rc_probe(struct platform_device *pdev)
st_rc_hardware_init(rc_dev);
rdev->driver_type = RC_DRIVER_IR_RAW;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
/* rx sampling rate is 10Mhz */
rdev->rx_resolution = 100;
rdev->timeout = US_TO_NS(MAX_SYMB_TIME);
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index bd5e4ff9e0ba..80c4feeb01ea 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -63,13 +63,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,
@@ -316,7 +309,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;
- rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->allowed_protocols = RC_BIT_ALL;
rdev->driver_name = DRIVER_NAME;
rdev->map_name = RC_MAP_STREAMZAP;
@@ -452,9 +445,6 @@ static int 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:
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
new file mode 100644
index 000000000000..bcee8e1a4e9e
--- /dev/null
+++ b/drivers/media/rc/sunxi-cir.c
@@ -0,0 +1,318 @@
+/*
+ * Driver for Allwinner sunXi IR controller
+ *
+ * Copyright (C) 2014 Alexsey Shestacov <wingrime@linux-sunxi.org>
+ * Copyright (C) 2014 Alexander Bersenev <bay@hackerdom.ru>
+ *
+ * Based on sun5i-ir.c:
+ * Copyright (C) 2007-2012 Daniel Wang
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <media/rc-core.h>
+
+#define SUNXI_IR_DEV "sunxi-ir"
+
+/* Registers */
+/* IR Control */
+#define SUNXI_IR_CTL_REG 0x00
+/* Global Enable */
+#define REG_CTL_GEN BIT(0)
+/* RX block enable */
+#define REG_CTL_RXEN BIT(1)
+/* CIR mode */
+#define REG_CTL_MD (BIT(4) | BIT(5))
+
+/* Rx Config */
+#define SUNXI_IR_RXCTL_REG 0x10
+/* Pulse Polarity Invert flag */
+#define REG_RXCTL_RPPI BIT(2)
+
+/* Rx Data */
+#define SUNXI_IR_RXFIFO_REG 0x20
+
+/* Rx Interrupt Enable */
+#define SUNXI_IR_RXINT_REG 0x2C
+/* Rx FIFO Overflow */
+#define REG_RXINT_ROI_EN BIT(0)
+/* Rx Packet End */
+#define REG_RXINT_RPEI_EN BIT(1)
+/* Rx FIFO Data Available */
+#define REG_RXINT_RAI_EN BIT(4)
+
+/* Rx FIFO available byte level */
+#define REG_RXINT_RAL(val) (((val) << 8) & (GENMASK(11, 8)))
+
+/* Rx Interrupt Status */
+#define SUNXI_IR_RXSTA_REG 0x30
+/* RX FIFO Get Available Counter */
+#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (GENMASK(5, 0)))
+/* Clear all interrupt status value */
+#define REG_RXSTA_CLEARALL 0xff
+
+/* IR Sample Config */
+#define SUNXI_IR_CIR_REG 0x34
+/* CIR_REG register noise threshold */
+#define REG_CIR_NTHR(val) (((val) << 2) & (GENMASK(7, 2)))
+/* CIR_REG register idle threshold */
+#define REG_CIR_ITHR(val) (((val) << 8) & (GENMASK(15, 8)))
+
+/* Hardware supported fifo size */
+#define SUNXI_IR_FIFO_SIZE 16
+/* How many messages in FIFO trigger IRQ */
+#define TRIGGER_LEVEL 8
+/* Required frequency for IR0 or IR1 clock in CIR mode */
+#define SUNXI_IR_BASE_CLK 8000000
+/* Frequency after IR internal divider */
+#define SUNXI_IR_CLK (SUNXI_IR_BASE_CLK / 64)
+/* Sample period in ns */
+#define SUNXI_IR_SAMPLE (1000000000ul / SUNXI_IR_CLK)
+/* Noise threshold in samples */
+#define SUNXI_IR_RXNOISE 1
+/* Idle Threshold in samples */
+#define SUNXI_IR_RXIDLE 20
+/* Time after which device stops sending data in ms */
+#define SUNXI_IR_TIMEOUT 120
+
+struct sunxi_ir {
+ spinlock_t ir_lock;
+ struct rc_dev *rc;
+ void __iomem *base;
+ int irq;
+ struct clk *clk;
+ struct clk *apb_clk;
+ const char *map_name;
+};
+
+static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
+{
+ unsigned long status;
+ unsigned char dt;
+ unsigned int cnt, rc;
+ struct sunxi_ir *ir = dev_id;
+ DEFINE_IR_RAW_EVENT(rawir);
+
+ spin_lock(&ir->ir_lock);
+
+ status = readl(ir->base + SUNXI_IR_RXSTA_REG);
+
+ /* clean all pending statuses */
+ writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+ if (status & REG_RXINT_RAI_EN) {
+ /* How many messages in fifo */
+ rc = REG_RXSTA_GET_AC(status);
+ /* Sanity check */
+ rc = rc > SUNXI_IR_FIFO_SIZE ? SUNXI_IR_FIFO_SIZE : rc;
+ /* If we have data */
+ for (cnt = 0; cnt < rc; cnt++) {
+ /* for each bit in fifo */
+ dt = readb(ir->base + SUNXI_IR_RXFIFO_REG);
+ rawir.pulse = (dt & 0x80) != 0;
+ rawir.duration = ((dt & 0x7f) + 1) * SUNXI_IR_SAMPLE;
+ ir_raw_event_store_with_filter(ir->rc, &rawir);
+ }
+ }
+
+ if (status & REG_RXINT_ROI_EN) {
+ ir_raw_event_reset(ir->rc);
+ } else if (status & REG_RXINT_RPEI_EN) {
+ ir_raw_event_set_idle(ir->rc, true);
+ ir_raw_event_handle(ir->rc);
+ }
+
+ spin_unlock(&ir->ir_lock);
+
+ return IRQ_HANDLED;
+}
+
+static int sunxi_ir_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ unsigned long tmp = 0;
+
+ struct device *dev = &pdev->dev;
+ struct device_node *dn = dev->of_node;
+ struct resource *res;
+ struct sunxi_ir *ir;
+
+ ir = devm_kzalloc(dev, sizeof(struct sunxi_ir), GFP_KERNEL);
+ if (!ir)
+ return -ENOMEM;
+
+ /* Clock */
+ ir->apb_clk = devm_clk_get(dev, "apb");
+ if (IS_ERR(ir->apb_clk)) {
+ dev_err(dev, "failed to get a apb clock.\n");
+ return PTR_ERR(ir->apb_clk);
+ }
+ ir->clk = devm_clk_get(dev, "ir");
+ if (IS_ERR(ir->clk)) {
+ dev_err(dev, "failed to get a ir clock.\n");
+ return PTR_ERR(ir->clk);
+ }
+
+ ret = clk_set_rate(ir->clk, SUNXI_IR_BASE_CLK);
+ if (ret) {
+ dev_err(dev, "set ir base clock failed!\n");
+ return ret;
+ }
+
+ if (clk_prepare_enable(ir->apb_clk)) {
+ dev_err(dev, "try to enable apb_ir_clk failed\n");
+ return -EINVAL;
+ }
+
+ if (clk_prepare_enable(ir->clk)) {
+ dev_err(dev, "try to enable ir_clk failed\n");
+ ret = -EINVAL;
+ goto exit_clkdisable_apb_clk;
+ }
+
+ /* IO */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ir->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ir->base)) {
+ dev_err(dev, "failed to map registers\n");
+ ret = PTR_ERR(ir->base);
+ goto exit_clkdisable_clk;
+ }
+
+ ir->rc = rc_allocate_device();
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate device\n");
+ ret = -ENOMEM;
+ goto exit_clkdisable_clk;
+ }
+
+ ir->rc->priv = ir;
+ ir->rc->input_name = SUNXI_IR_DEV;
+ ir->rc->input_phys = "sunxi-ir/input0";
+ ir->rc->input_id.bustype = BUS_HOST;
+ ir->rc->input_id.vendor = 0x0001;
+ ir->rc->input_id.product = 0x0001;
+ ir->rc->input_id.version = 0x0100;
+ ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL);
+ ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY;
+ ir->rc->dev.parent = dev;
+ ir->rc->driver_type = RC_DRIVER_IR_RAW;
+ ir->rc->allowed_protocols = RC_BIT_ALL;
+ ir->rc->rx_resolution = SUNXI_IR_SAMPLE;
+ ir->rc->timeout = MS_TO_NS(SUNXI_IR_TIMEOUT);
+ ir->rc->driver_name = SUNXI_IR_DEV;
+
+ ret = rc_register_device(ir->rc);
+ if (ret) {
+ dev_err(dev, "failed to register rc device\n");
+ goto exit_free_dev;
+ }
+
+ platform_set_drvdata(pdev, ir);
+
+ /* IRQ */
+ ir->irq = platform_get_irq(pdev, 0);
+ if (ir->irq < 0) {
+ dev_err(dev, "no irq resource\n");
+ ret = ir->irq;
+ goto exit_free_dev;
+ }
+
+ ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir);
+ if (ret) {
+ dev_err(dev, "failed request irq\n");
+ goto exit_free_dev;
+ }
+
+ /* Enable CIR Mode */
+ writel(REG_CTL_MD, ir->base+SUNXI_IR_CTL_REG);
+
+ /* Set noise threshold and idle threshold */
+ writel(REG_CIR_NTHR(SUNXI_IR_RXNOISE)|REG_CIR_ITHR(SUNXI_IR_RXIDLE),
+ ir->base + SUNXI_IR_CIR_REG);
+
+ /* Invert Input Signal */
+ writel(REG_RXCTL_RPPI, ir->base + SUNXI_IR_RXCTL_REG);
+
+ /* Clear All Rx Interrupt Status */
+ writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+ /*
+ * Enable IRQ on overflow, packet end, FIFO available with trigger
+ * level
+ */
+ writel(REG_RXINT_ROI_EN | REG_RXINT_RPEI_EN |
+ REG_RXINT_RAI_EN | REG_RXINT_RAL(TRIGGER_LEVEL - 1),
+ ir->base + SUNXI_IR_RXINT_REG);
+
+ /* Enable IR Module */
+ tmp = readl(ir->base + SUNXI_IR_CTL_REG);
+ writel(tmp | REG_CTL_GEN | REG_CTL_RXEN, ir->base + SUNXI_IR_CTL_REG);
+
+ dev_info(dev, "initialized sunXi IR driver\n");
+ return 0;
+
+exit_free_dev:
+ rc_free_device(ir->rc);
+exit_clkdisable_clk:
+ clk_disable_unprepare(ir->clk);
+exit_clkdisable_apb_clk:
+ clk_disable_unprepare(ir->apb_clk);
+
+ return ret;
+}
+
+static int sunxi_ir_remove(struct platform_device *pdev)
+{
+ unsigned long flags;
+ struct sunxi_ir *ir = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(ir->clk);
+ clk_disable_unprepare(ir->apb_clk);
+
+ spin_lock_irqsave(&ir->ir_lock, flags);
+ /* disable IR IRQ */
+ writel(0, ir->base + SUNXI_IR_RXINT_REG);
+ /* clear All Rx Interrupt Status */
+ writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+ /* disable IR */
+ writel(0, ir->base + SUNXI_IR_CTL_REG);
+ spin_unlock_irqrestore(&ir->ir_lock, flags);
+
+ rc_unregister_device(ir->rc);
+ return 0;
+}
+
+static const struct of_device_id sunxi_ir_match[] = {
+ { .compatible = "allwinner,sun4i-a10-ir", },
+ {},
+};
+
+static struct platform_driver sunxi_ir_driver = {
+ .probe = sunxi_ir_probe,
+ .remove = sunxi_ir_remove,
+ .driver = {
+ .name = SUNXI_IR_DEV,
+ .owner = THIS_MODULE,
+ .of_match_table = sunxi_ir_match,
+ },
+};
+
+module_platform_driver(sunxi_ir_driver);
+
+MODULE_DESCRIPTION("Allwinner sunXi IR controller driver");
+MODULE_AUTHOR("Alexsey Shestacov <wingrime@linux-sunxi.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
index c5be38e2a2fe..bc214e2b3a36 100644
--- a/drivers/media/rc/ttusbir.c
+++ b/drivers/media/rc/ttusbir.c
@@ -318,7 +318,7 @@ static int 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_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->allowed_protocols = 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 a8b981f5ce2e..d839f73f6a05 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1082,7 +1082,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
data->dev->dev.parent = &device->dev;
data->dev->timeout = MS_TO_NS(100);
data->dev->rx_resolution = US_TO_NS(2);
- rc_set_allowed_protocols(data->dev, RC_BIT_ALL);
+ data->dev->allowed_protocols = RC_BIT_ALL;
err = rc_register_device(data->dev);
if (err)