aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2014-04-03 19:32:31 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-25 18:10:44 -0400
commite87b540be2dd02552fb9244d50ae8b4e4619a34b (patch)
tree4440e341a8b937890c7a772fa709a1063ade3ef9 /drivers/media/rc
parent9d2f1d3cdedd4d3efff8d14f1f49cf73e2f5cc36 (diff)
[media] rc-core: merge rc5 and streamzap decoders
Now that the protocol is part of the scancode, it is pretty easy to merge the rc5 and streamzap decoders. An additional advantage is that the decoder is now stricter as it waits for the trailing silence before determining that a command is a valid rc5/streamzap command (which avoids collisions that I've seen with e.g. Sony protocols). Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/Kconfig12
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/ir-rc5-decoder.c72
-rw-r--r--drivers/media/rc/ir-rc5-sz-decoder.c154
-rw-r--r--drivers/media/rc/keymaps/rc-streamzap.c4
-rw-r--r--drivers/media/rc/rc-core-priv.h8
-rw-r--r--drivers/media/rc/streamzap.c10
7 files changed, 43 insertions, 218 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 9427faddce32..9d15a57ac590 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -84,18 +84,6 @@ config IR_SONY_DECODER
84 Enable this option if you have an infrared remote control which 84 Enable this option if you have an infrared remote control which
85 uses the Sony protocol, and you need software decoding support. 85 uses the Sony protocol, and you need software decoding support.
86 86
87config IR_RC5_SZ_DECODER
88 tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
89 depends on RC_CORE
90 select BITREVERSE
91 default y
92
93 ---help---
94 Enable this option if you have IR with RC-5 (streamzap) protocol,
95 and if the IR is decoded in software. (The Streamzap PC Remote
96 uses an IR protocol that is almost standard RC-5, but not quite,
97 as it uses an additional bit).
98
99config IR_SANYO_DECODER 87config IR_SANYO_DECODER
100 tristate "Enable IR raw decoder for the Sanyo protocol" 88 tristate "Enable IR raw decoder for the Sanyo protocol"
101 depends on RC_CORE 89 depends on RC_CORE
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 9ee9ee75ae8d..d07576f417dc 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
9obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o 9obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
10obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o 10obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
11obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o 11obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
12obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
13obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o 12obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
14obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o 13obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
15obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o 14obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 04ce42fa9eec..93168daf82eb 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -1,6 +1,7 @@
1/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol 1/* ir-rc5-decoder.c - decoder for RC5(x) and StreamZap protocols
2 * 2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab 3 * Copyright (C) 2010 by Mauro Carvalho Chehab
4 * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -13,23 +14,22 @@
13 */ 14 */
14 15
15/* 16/*
16 * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols. 17 * This decoder handles the 14 bit RC5 protocol, 15 bit "StreamZap" protocol
17 * There are other variants that use a different number of bits. 18 * and 20 bit RC5x protocol.
18 * This is currently unsupported.
19 * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
20 * the first two bits are start bits, and a third one is a filing bit
21 */ 19 */
22 20
23#include "rc-core-priv.h" 21#include "rc-core-priv.h"
24#include <linux/module.h> 22#include <linux/module.h>
25 23
26#define RC5_NBITS 14 24#define RC5_NBITS 14
25#define RC5_SZ_NBITS 15
27#define RC5X_NBITS 20 26#define RC5X_NBITS 20
28#define CHECK_RC5X_NBITS 8 27#define CHECK_RC5X_NBITS 8
29#define RC5_UNIT 888888 /* ns */ 28#define RC5_UNIT 888888 /* ns */
30#define RC5_BIT_START (1 * RC5_UNIT) 29#define RC5_BIT_START (1 * RC5_UNIT)
31#define RC5_BIT_END (1 * RC5_UNIT) 30#define RC5_BIT_END (1 * RC5_UNIT)
32#define RC5X_SPACE (4 * RC5_UNIT) 31#define RC5X_SPACE (4 * RC5_UNIT)
32#define RC5_TRAILER (10 * RC5_UNIT) /* In reality, approx 100 */
33 33
34enum rc5_state { 34enum rc5_state {
35 STATE_INACTIVE, 35 STATE_INACTIVE,
@@ -66,7 +66,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
66 goto out; 66 goto out;
67 67
68again: 68again:
69 IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n", 69 IR_dprintk(2, "RC5(x/sz) decode started at state %i (%uus %s)\n",
70 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 70 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
71 71
72 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) 72 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
@@ -80,12 +80,15 @@ again:
80 80
81 data->state = STATE_BIT_START; 81 data->state = STATE_BIT_START;
82 data->count = 1; 82 data->count = 1;
83 /* We just need enough bits to get to STATE_CHECK_RC5X */
84 data->wanted_bits = RC5X_NBITS;
85 decrease_duration(&ev, RC5_BIT_START); 83 decrease_duration(&ev, RC5_BIT_START);
86 goto again; 84 goto again;
87 85
88 case STATE_BIT_START: 86 case STATE_BIT_START:
87 if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT / 2)) {
88 data->state = STATE_FINISHED;
89 goto again;
90 }
91
89 if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) 92 if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
90 break; 93 break;
91 94
@@ -100,9 +103,7 @@ again:
100 if (!is_transition(&ev, &dev->raw->prev_ev)) 103 if (!is_transition(&ev, &dev->raw->prev_ev))
101 break; 104 break;
102 105
103 if (data->count == data->wanted_bits) 106 if (data->count == CHECK_RC5X_NBITS)
104 data->state = STATE_FINISHED;
105 else if (data->count == CHECK_RC5X_NBITS)
106 data->state = STATE_CHECK_RC5X; 107 data->state = STATE_CHECK_RC5X;
107 else 108 else
108 data->state = STATE_BIT_START; 109 data->state = STATE_BIT_START;
@@ -112,13 +113,10 @@ again:
112 113
113 case STATE_CHECK_RC5X: 114 case STATE_CHECK_RC5X:
114 if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) { 115 if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
115 /* RC5X */ 116 data->is_rc5x = true;
116 data->wanted_bits = RC5X_NBITS;
117 decrease_duration(&ev, RC5X_SPACE); 117 decrease_duration(&ev, RC5X_SPACE);
118 } else { 118 } else
119 /* RC5 */ 119 data->is_rc5x = false;
120 data->wanted_bits = RC5_NBITS;
121 }
122 data->state = STATE_BIT_START; 120 data->state = STATE_BIT_START;
123 goto again; 121 goto again;
124 122
@@ -126,7 +124,7 @@ again:
126 if (ev.pulse) 124 if (ev.pulse)
127 break; 125 break;
128 126
129 if (data->wanted_bits == RC5X_NBITS) { 127 if (data->is_rc5x && data->count == RC5X_NBITS) {
130 /* RC5X */ 128 /* RC5X */
131 u8 xdata, command, system; 129 u8 xdata, command, system;
132 if (!(dev->enabled_protocols & RC_BIT_RC5X)) { 130 if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
@@ -141,10 +139,7 @@ again:
141 scancode = system << 16 | command << 8 | xdata; 139 scancode = system << 16 | command << 8 | xdata;
142 protocol = RC_TYPE_RC5X; 140 protocol = RC_TYPE_RC5X;
143 141
144 IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n", 142 } else if (!data->is_rc5x && data->count == RC5_NBITS) {
145 scancode, toggle);
146
147 } else {
148 /* RC5 */ 143 /* RC5 */
149 u8 command, system; 144 u8 command, system;
150 if (!(dev->enabled_protocols & RC_BIT_RC5)) { 145 if (!(dev->enabled_protocols & RC_BIT_RC5)) {
@@ -158,9 +153,24 @@ again:
158 scancode = system << 8 | command; 153 scancode = system << 8 | command;
159 protocol = RC_TYPE_RC5; 154 protocol = RC_TYPE_RC5;
160 155
161 IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", 156 } else if (!data->is_rc5x && data->count == RC5_SZ_NBITS) {
162 scancode, toggle); 157 /* RC5 StreamZap */
163 } 158 u8 command, system;
159 if (!(dev->enabled_protocols & RC_BIT_RC5_SZ)) {
160 data->state = STATE_INACTIVE;
161 return 0;
162 }
163 command = (data->bits & 0x0003F) >> 0;
164 system = (data->bits & 0x02FC0) >> 6;
165 toggle = (data->bits & 0x01000) ? 1 : 0;
166 scancode = system << 6 | command;
167 protocol = RC_TYPE_RC5_SZ;
168
169 } else
170 break;
171
172 IR_dprintk(1, "RC5(x/sz) scancode 0x%06x (p: %u, t: %u)\n",
173 scancode, protocol, toggle);
164 174
165 rc_keydown(dev, protocol, scancode, toggle); 175 rc_keydown(dev, protocol, scancode, toggle);
166 data->state = STATE_INACTIVE; 176 data->state = STATE_INACTIVE;
@@ -168,14 +178,14 @@ again:
168 } 178 }
169 179
170out: 180out:
171 IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n", 181 IR_dprintk(1, "RC5(x/sz) decode failed at state %i (%uus %s)\n",
172 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 182 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
173 data->state = STATE_INACTIVE; 183 data->state = STATE_INACTIVE;
174 return -EINVAL; 184 return -EINVAL;
175} 185}
176 186
177static struct ir_raw_handler rc5_handler = { 187static struct ir_raw_handler rc5_handler = {
178 .protocols = RC_BIT_RC5 | RC_BIT_RC5X, 188 .protocols = RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
179 .decode = ir_rc5_decode, 189 .decode = ir_rc5_decode,
180}; 190};
181 191
@@ -183,7 +193,7 @@ static int __init ir_rc5_decode_init(void)
183{ 193{
184 ir_raw_handler_register(&rc5_handler); 194 ir_raw_handler_register(&rc5_handler);
185 195
186 printk(KERN_INFO "IR RC5(x) protocol handler initialized\n"); 196 printk(KERN_INFO "IR RC5(x/sz) protocol handler initialized\n");
187 return 0; 197 return 0;
188} 198}
189 199
@@ -196,6 +206,6 @@ module_init(ir_rc5_decode_init);
196module_exit(ir_rc5_decode_exit); 206module_exit(ir_rc5_decode_exit);
197 207
198MODULE_LICENSE("GPL"); 208MODULE_LICENSE("GPL");
199MODULE_AUTHOR("Mauro Carvalho Chehab"); 209MODULE_AUTHOR("Mauro Carvalho Chehab and Jarod Wilson");
200MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); 210MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
201MODULE_DESCRIPTION("RC5(x) IR protocol decoder"); 211MODULE_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 771e9fcbd770..000000000000
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab
4 * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16/*
17 * This code handles the 15 bit RC5-ish protocol used by the Streamzap
18 * PC Remote.
19 * It considers a carrier of 36 kHz, with a total of 15 bits, where
20 * the first two bits are start bits, and a third one is a filing bit
21 */
22
23#include "rc-core-priv.h"
24#include <linux/module.h>
25
26#define RC5_SZ_NBITS 15
27#define RC5_UNIT 888888 /* ns */
28#define RC5_BIT_START (1 * RC5_UNIT)
29#define RC5_BIT_END (1 * RC5_UNIT)
30
31enum rc5_sz_state {
32 STATE_INACTIVE,
33 STATE_BIT_START,
34 STATE_BIT_END,
35 STATE_FINISHED,
36};
37
38/**
39 * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
40 * @dev: the struct rc_dev descriptor of the device
41 * @ev: the struct ir_raw_event descriptor of the pulse/space
42 *
43 * This function returns -EINVAL if the pulse violates the state machine
44 */
45static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
46{
47 struct rc5_sz_dec *data = &dev->raw->rc5_sz;
48 u8 toggle, command, system;
49 u32 scancode;
50
51 if (!(dev->enabled_protocols & RC_BIT_RC5_SZ))
52 return 0;
53
54 if (!is_timing_event(ev)) {
55 if (ev.reset)
56 data->state = STATE_INACTIVE;
57 return 0;
58 }
59
60 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
61 goto out;
62
63again:
64 IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
65 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
66
67 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
68 return 0;
69
70 switch (data->state) {
71
72 case STATE_INACTIVE:
73 if (!ev.pulse)
74 break;
75
76 data->state = STATE_BIT_START;
77 data->count = 1;
78 data->wanted_bits = RC5_SZ_NBITS;
79 decrease_duration(&ev, RC5_BIT_START);
80 goto again;
81
82 case STATE_BIT_START:
83 if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
84 break;
85
86 data->bits <<= 1;
87 if (!ev.pulse)
88 data->bits |= 1;
89 data->count++;
90 data->state = STATE_BIT_END;
91 return 0;
92
93 case STATE_BIT_END:
94 if (!is_transition(&ev, &dev->raw->prev_ev))
95 break;
96
97 if (data->count == data->wanted_bits)
98 data->state = STATE_FINISHED;
99 else
100 data->state = STATE_BIT_START;
101
102 decrease_duration(&ev, RC5_BIT_END);
103 goto again;
104
105 case STATE_FINISHED:
106 if (ev.pulse)
107 break;
108
109 /* RC5-sz */
110 command = (data->bits & 0x0003F) >> 0;
111 system = (data->bits & 0x02FC0) >> 6;
112 toggle = (data->bits & 0x01000) ? 1 : 0;
113 scancode = system << 6 | command;
114
115 IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
116 scancode, toggle);
117
118 rc_keydown(dev, RC_TYPE_RC5_SZ, scancode, toggle);
119 data->state = STATE_INACTIVE;
120 return 0;
121 }
122
123out:
124 IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
125 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
126 data->state = STATE_INACTIVE;
127 return -EINVAL;
128}
129
130static struct ir_raw_handler rc5_sz_handler = {
131 .protocols = RC_BIT_RC5_SZ,
132 .decode = ir_rc5_sz_decode,
133};
134
135static int __init ir_rc5_sz_decode_init(void)
136{
137 ir_raw_handler_register(&rc5_sz_handler);
138
139 printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
140 return 0;
141}
142
143static void __exit ir_rc5_sz_decode_exit(void)
144{
145 ir_raw_handler_unregister(&rc5_sz_handler);
146}
147
148module_init(ir_rc5_sz_decode_init);
149module_exit(ir_rc5_sz_decode_exit);
150
151MODULE_LICENSE("GPL");
152MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
153MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
154MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff --git a/drivers/media/rc/keymaps/rc-streamzap.c b/drivers/media/rc/keymaps/rc-streamzap.c
index f9a07578d985..23c061174ed7 100644
--- a/drivers/media/rc/keymaps/rc-streamzap.c
+++ b/drivers/media/rc/keymaps/rc-streamzap.c
@@ -15,9 +15,7 @@
15static struct rc_map_table streamzap[] = { 15static struct rc_map_table streamzap[] = {
16/* 16/*
17 * The Streamzap remote is almost, but not quite, RC-5, as it has an extra 17 * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
18 * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently, 18 * bit in it.
19 * an additional RC-5-sz decoder is being deployed to support it, but it
20 * may be possible to merge it back with the standard RC-5 decoder.
21 */ 19 */
22 { 0x28c0, KEY_NUMERIC_0 }, 20 { 0x28c0, KEY_NUMERIC_0 },
23 { 0x28c1, KEY_NUMERIC_1 }, 21 { 0x28c1, KEY_NUMERIC_1 },
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index da536c93c978..dea7aff15a35 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 {
54 int state; 54 int state;
55 u32 bits; 55 u32 bits;
56 unsigned count; 56 unsigned count;
57 unsigned wanted_bits; 57 bool is_rc5x;
58 } rc5; 58 } rc5;
59 struct rc6_dec { 59 struct rc6_dec {
60 int state; 60 int state;
@@ -77,12 +77,6 @@ struct ir_raw_event_ctrl {
77 bool first; 77 bool first;
78 bool toggle; 78 bool toggle;
79 } jvc; 79 } jvc;
80 struct rc5_sz_dec {
81 int state;
82 u32 bits;
83 unsigned count;
84 unsigned wanted_bits;
85 } rc5_sz;
86 struct sanyo_dec { 80 struct sanyo_dec {
87 int state; 81 int state;
88 unsigned count; 82 unsigned count;
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index 828bbb886882..80c4feeb01ea 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -63,13 +63,6 @@ MODULE_DEVICE_TABLE(usb, streamzap_table);
63/* number of samples buffered */ 63/* number of samples buffered */
64#define SZ_BUF_LEN 128 64#define SZ_BUF_LEN 128
65 65
66/* from ir-rc5-sz-decoder.c */
67#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
68#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder")
69#else
70#define load_rc5_sz_decode() {}
71#endif
72
73enum StreamzapDecoderState { 66enum StreamzapDecoderState {
74 PulseSpace, 67 PulseSpace,
75 FullPulse, 68 FullPulse,
@@ -452,9 +445,6 @@ static int streamzap_probe(struct usb_interface *intf,
452 dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, 445 dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
453 usbdev->bus->busnum, usbdev->devnum); 446 usbdev->bus->busnum, usbdev->devnum);
454 447
455 /* Load the streamzap not-quite-rc5 decoder too */
456 load_rc5_sz_decode();
457
458 return 0; 448 return 0;
459 449
460rc_dev_fail: 450rc_dev_fail: