aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2010-08-07 12:31:40 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-20 23:04:47 -0400
commit7a569f524dd36806b995c844f29e28ff40c444b2 (patch)
treef771e5bd298089fe007a74d654c756fda4c39f3e /drivers/media
parent516c714c6c823e412dc485ca9c5307348cddd097 (diff)
V4L/DVB: IR/streamzap: functional in-kernel decoding
This patch makes in-kernel decoding with the stock Streamzap PC Remote work out of the box. There are quite a few things going on in this patch, all related to getting this working: 1) I had to enable reporting of a long space at the end of each signal, or I had weird buffering and keybounce issues. 2) The keymap has been reworked slightly to match actual decoded values, the first edition was missing the pre-data bits present in the lirc config file for this remote. 3) There's a whole new decoder included, specifically for the not-quite-RC5 15-bit protocol variant used by the Streamzap PC Remote. The decoder, while usable with other recievers (tested with an mceusb receiver), will only be loaded by the streamzap driver, as its likely not of use in almost all other situations. This can be revisited if/when all keytable loading (and disabling of unneeded protocol decoder engines) is moved to userspace, but for now, I think this makes the most sense. Note that I did try to enable handling the streamzap RC5-ish protocol in the current RC5 decoder, but there's no particularly easy way to tell if its 14-bit RC5 or 15-bit Streamzap until we see bit 14, and even then, in testing an attempted decoder merge, only 2/3 of the keys were properly recognized as being the 15-bit variant and decoded correctly, the rest were close enough to compliant with 14-bit that they were decoded as such (but they have overlap with one another, and thus we can't just shrug and use the 14-bit decoded values). Also of note in this patch is the removal of the streamzap driver's internal delay buffer. Per discussion w/Christoph, it shouldn't be needed by lirc any longer anyway, and it doesn't seem to make any difference to the in-kernel decoder engine. That being the case, I'm yanking it all out, as it greatly simplifies the driver code. Signed-off-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/IR/Kconfig12
-rw-r--r--drivers/media/IR/Makefile1
-rw-r--r--drivers/media/IR/ir-core-priv.h6
-rw-r--r--drivers/media/IR/ir-rc5-sz-decoder.c153
-rw-r--r--drivers/media/IR/ir-sysfs.c1
-rw-r--r--drivers/media/IR/keymaps/Makefile2
-rw-r--r--drivers/media/IR/keymaps/rc-rc5-streamzap.c81
-rw-r--r--drivers/media/IR/keymaps/rc-streamzap.c82
-rw-r--r--drivers/media/IR/streamzap.c358
9 files changed, 349 insertions, 347 deletions
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
index 490c57cc4cfe..152000db3526 100644
--- a/drivers/media/IR/Kconfig
+++ b/drivers/media/IR/Kconfig
@@ -79,6 +79,18 @@ config IR_SONY_DECODER
79 Enable this option if you have an infrared remote control which 79 Enable this option if you have an infrared remote control which
80 uses the Sony protocol, and you need software decoding support. 80 uses the Sony protocol, and you need software decoding support.
81 81
82config IR_RC5_SZ_DECODER
83 tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
84 depends on IR_CORE
85 select BITREVERSE
86 default y
87
88 ---help---
89 Enable this option if you have IR with RC-5 (streamzap) protocol,
90 and if the IR is decoded in software. (The Streamzap PC Remote
91 uses an IR protocol that is almost standard RC-5, but not quite,
92 as it uses an additional bit).
93
82config IR_LIRC_CODEC 94config IR_LIRC_CODEC
83 tristate "Enable IR to LIRC bridge" 95 tristate "Enable IR to LIRC bridge"
84 depends on IR_CORE 96 depends on IR_CORE
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
index 53676838fe97..953c6c44330a 100644
--- a/drivers/media/IR/Makefile
+++ b/drivers/media/IR/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
11obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o 11obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
12obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o 12obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
13obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o 13obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
14obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
14obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o 15obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
15 16
16# stand-alone IR receivers/transmitters 17# stand-alone IR receivers/transmitters
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index a85a8c7c905a..0ad8ea39b39e 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -76,6 +76,12 @@ struct ir_raw_event_ctrl {
76 bool first; 76 bool first;
77 bool toggle; 77 bool toggle;
78 } jvc; 78 } jvc;
79 struct rc5_sz_dec {
80 int state;
81 u32 bits;
82 unsigned count;
83 unsigned wanted_bits;
84 } rc5_sz;
79 struct lirc_codec { 85 struct lirc_codec {
80 struct ir_input_dev *ir_dev; 86 struct ir_input_dev *ir_dev;
81 struct lirc_driver *drv; 87 struct lirc_driver *drv;
diff --git a/drivers/media/IR/ir-rc5-sz-decoder.c b/drivers/media/IR/ir-rc5-sz-decoder.c
new file mode 100644
index 000000000000..68f11d6acd5b
--- /dev/null
+++ b/drivers/media/IR/ir-rc5-sz-decoder.c
@@ -0,0 +1,153 @@
1/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
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 "ir-core-priv.h"
24
25#define RC5_SZ_NBITS 15
26#define RC5_UNIT 888888 /* ns */
27#define RC5_BIT_START (1 * RC5_UNIT)
28#define RC5_BIT_END (1 * RC5_UNIT)
29
30enum rc5_sz_state {
31 STATE_INACTIVE,
32 STATE_BIT_START,
33 STATE_BIT_END,
34 STATE_FINISHED,
35};
36
37/**
38 * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
39 * @input_dev: the struct input_dev descriptor of the device
40 * @ev: the struct ir_raw_event descriptor of the pulse/space
41 *
42 * This function returns -EINVAL if the pulse violates the state machine
43 */
44static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
45{
46 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
47 struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz;
48 u8 toggle, command, system;
49 u32 scancode;
50
51 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
52 return 0;
53
54 if (IS_RESET(ev)) {
55 data->state = STATE_INACTIVE;
56 return 0;
57 }
58
59 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
60 goto out;
61
62again:
63 IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
64 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
65
66 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
67 return 0;
68
69 switch (data->state) {
70
71 case STATE_INACTIVE:
72 if (!ev.pulse)
73 break;
74
75 data->state = STATE_BIT_START;
76 data->count = 1;
77 data->wanted_bits = RC5_SZ_NBITS;
78 decrease_duration(&ev, RC5_BIT_START);
79 goto again;
80
81 case STATE_BIT_START:
82 if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
83 break;
84
85 data->bits <<= 1;
86 if (!ev.pulse)
87 data->bits |= 1;
88 data->count++;
89 data->state = STATE_BIT_END;
90 return 0;
91
92 case STATE_BIT_END:
93 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
94 break;
95
96 if (data->count == data->wanted_bits)
97 data->state = STATE_FINISHED;
98 else
99 data->state = STATE_BIT_START;
100
101 decrease_duration(&ev, RC5_BIT_END);
102 goto again;
103
104 case STATE_FINISHED:
105 if (ev.pulse)
106 break;
107
108 /* RC5-sz */
109 command = (data->bits & 0x0003F) >> 0;
110 system = (data->bits & 0x02FC0) >> 6;
111 toggle = (data->bits & 0x01000) ? 1 : 0;
112 scancode = system << 6 | command;
113
114 IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
115 scancode, toggle);
116
117 ir_keydown(input_dev, scancode, toggle);
118 data->state = STATE_INACTIVE;
119 return 0;
120 }
121
122out:
123 IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
124 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
125 data->state = STATE_INACTIVE;
126 return -EINVAL;
127}
128
129static struct ir_raw_handler rc5_sz_handler = {
130 .protocols = IR_TYPE_RC5_SZ,
131 .decode = ir_rc5_sz_decode,
132};
133
134static int __init ir_rc5_sz_decode_init(void)
135{
136 ir_raw_handler_register(&rc5_sz_handler);
137
138 printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
139 return 0;
140}
141
142static void __exit ir_rc5_sz_decode_exit(void)
143{
144 ir_raw_handler_unregister(&rc5_sz_handler);
145}
146
147module_init(ir_rc5_sz_decode_init);
148module_exit(ir_rc5_sz_decode_exit);
149
150MODULE_LICENSE("GPL");
151MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
152MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
153MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 46d42467f9b4..be09d1995b41 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -43,6 +43,7 @@ static struct {
43 { IR_TYPE_RC6, "rc-6" }, 43 { IR_TYPE_RC6, "rc-6" },
44 { IR_TYPE_JVC, "jvc" }, 44 { IR_TYPE_JVC, "jvc" },
45 { IR_TYPE_SONY, "sony" }, 45 { IR_TYPE_SONY, "sony" },
46 { IR_TYPE_RC5_SZ, "rc-5-sz" },
46 { IR_TYPE_LIRC, "lirc" }, 47 { IR_TYPE_LIRC, "lirc" },
47}; 48};
48 49
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile
index 950e5d953c6f..c032b9d2e51a 100644
--- a/drivers/media/IR/keymaps/Makefile
+++ b/drivers/media/IR/keymaps/Makefile
@@ -58,10 +58,10 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
58 rc-purpletv.o \ 58 rc-purpletv.o \
59 rc-pv951.o \ 59 rc-pv951.o \
60 rc-rc5-hauppauge-new.o \ 60 rc-rc5-hauppauge-new.o \
61 rc-rc5-streamzap.o \
62 rc-rc5-tv.o \ 61 rc-rc5-tv.o \
63 rc-rc6-mce.o \ 62 rc-rc6-mce.o \
64 rc-real-audio-220-32-keys.o \ 63 rc-real-audio-220-32-keys.o \
64 rc-streamzap.o \
65 rc-tbs-nec.o \ 65 rc-tbs-nec.o \
66 rc-terratec-cinergy-xs.o \ 66 rc-terratec-cinergy-xs.o \
67 rc-tevii-nec.o \ 67 rc-tevii-nec.o \
diff --git a/drivers/media/IR/keymaps/rc-rc5-streamzap.c b/drivers/media/IR/keymaps/rc-rc5-streamzap.c
deleted file mode 100644
index 4c19c58b46d8..000000000000
--- a/drivers/media/IR/keymaps/rc-rc5-streamzap.c
+++ /dev/null
@@ -1,81 +0,0 @@
1/* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use
2 * with the Streamzap PC Remote IR Receiver.
3 *
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; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14static struct ir_scancode rc5_streamzap[] = {
15/*
16 * FIXME: The Streamzap remote isn't actually true RC-5, it has an extra
17 * bit in it, which presently throws the in-kernel RC-5 decoder for a loop.
18 * We either have to enhance the decoder to support it, add a new decoder,
19 * or just rely on lirc userspace decoding.
20 */
21 { 0x00, KEY_NUMERIC_0 },
22 { 0x01, KEY_NUMERIC_1 },
23 { 0x02, KEY_NUMERIC_2 },
24 { 0x03, KEY_NUMERIC_3 },
25 { 0x04, KEY_NUMERIC_4 },
26 { 0x05, KEY_NUMERIC_5 },
27 { 0x06, KEY_NUMERIC_6 },
28 { 0x07, KEY_NUMERIC_7 },
29 { 0x08, KEY_NUMERIC_8 },
30 { 0x0a, KEY_POWER },
31 { 0x0b, KEY_MUTE },
32 { 0x0c, KEY_CHANNELUP },
33 { 0x0d, KEY_VOLUMEUP },
34 { 0x0e, KEY_CHANNELDOWN },
35 { 0x0f, KEY_VOLUMEDOWN },
36 { 0x10, KEY_UP },
37 { 0x11, KEY_LEFT },
38 { 0x12, KEY_OK },
39 { 0x13, KEY_RIGHT },
40 { 0x14, KEY_DOWN },
41 { 0x15, KEY_MENU },
42 { 0x16, KEY_EXIT },
43 { 0x17, KEY_PLAY },
44 { 0x18, KEY_PAUSE },
45 { 0x19, KEY_STOP },
46 { 0x1a, KEY_BACK },
47 { 0x1b, KEY_FORWARD },
48 { 0x1c, KEY_RECORD },
49 { 0x1d, KEY_REWIND },
50 { 0x1e, KEY_FASTFORWARD },
51 { 0x20, KEY_RED },
52 { 0x21, KEY_GREEN },
53 { 0x22, KEY_YELLOW },
54 { 0x23, KEY_BLUE },
55
56};
57
58static struct rc_keymap rc5_streamzap_map = {
59 .map = {
60 .scan = rc5_streamzap,
61 .size = ARRAY_SIZE(rc5_streamzap),
62 .ir_type = IR_TYPE_RC5,
63 .name = RC_MAP_RC5_STREAMZAP,
64 }
65};
66
67static int __init init_rc_map_rc5_streamzap(void)
68{
69 return ir_register_map(&rc5_streamzap_map);
70}
71
72static void __exit exit_rc_map_rc5_streamzap(void)
73{
74 ir_unregister_map(&rc5_streamzap_map);
75}
76
77module_init(init_rc_map_rc5_streamzap)
78module_exit(exit_rc_map_rc5_streamzap)
79
80MODULE_LICENSE("GPL");
81MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/IR/keymaps/rc-streamzap.c b/drivers/media/IR/keymaps/rc-streamzap.c
new file mode 100644
index 000000000000..df32013a321c
--- /dev/null
+++ b/drivers/media/IR/keymaps/rc-streamzap.c
@@ -0,0 +1,82 @@
1/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use
2 * with the Streamzap PC Remote IR Receiver.
3 *
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; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <media/rc-map.h>
13
14static struct ir_scancode streamzap[] = {
15/*
16 * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
17 * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
18 * an additional RC-5-sz decoder is being deployed to support it, but it
19 * may be possible to merge it back with the standard RC-5 decoder.
20 */
21 { 0x28c0, KEY_NUMERIC_0 },
22 { 0x28c1, KEY_NUMERIC_1 },
23 { 0x28c2, KEY_NUMERIC_2 },
24 { 0x28c3, KEY_NUMERIC_3 },
25 { 0x28c4, KEY_NUMERIC_4 },
26 { 0x28c5, KEY_NUMERIC_5 },
27 { 0x28c6, KEY_NUMERIC_6 },
28 { 0x28c7, KEY_NUMERIC_7 },
29 { 0x28c8, KEY_NUMERIC_8 },
30 { 0x28c9, KEY_NUMERIC_9 },
31 { 0x28ca, KEY_POWER },
32 { 0x28cb, KEY_MUTE },
33 { 0x28cc, KEY_CHANNELUP },
34 { 0x28cd, KEY_VOLUMEUP },
35 { 0x28ce, KEY_CHANNELDOWN },
36 { 0x28cf, KEY_VOLUMEDOWN },
37 { 0x28d0, KEY_UP },
38 { 0x28d1, KEY_LEFT },
39 { 0x28d2, KEY_OK },
40 { 0x28d3, KEY_RIGHT },
41 { 0x28d4, KEY_DOWN },
42 { 0x28d5, KEY_MENU },
43 { 0x28d6, KEY_EXIT },
44 { 0x28d7, KEY_PLAY },
45 { 0x28d8, KEY_PAUSE },
46 { 0x28d9, KEY_STOP },
47 { 0x28da, KEY_BACK },
48 { 0x28db, KEY_FORWARD },
49 { 0x28dc, KEY_RECORD },
50 { 0x28dd, KEY_REWIND },
51 { 0x28de, KEY_FASTFORWARD },
52 { 0x28e0, KEY_RED },
53 { 0x28e1, KEY_GREEN },
54 { 0x28e2, KEY_YELLOW },
55 { 0x28e3, KEY_BLUE },
56
57};
58
59static struct rc_keymap streamzap_map = {
60 .map = {
61 .scan = streamzap,
62 .size = ARRAY_SIZE(streamzap),
63 .ir_type = IR_TYPE_RC5_SZ,
64 .name = RC_MAP_STREAMZAP,
65 }
66};
67
68static int __init init_rc_map_streamzap(void)
69{
70 return ir_register_map(&streamzap_map);
71}
72
73static void __exit exit_rc_map_streamzap(void)
74{
75 ir_unregister_map(&streamzap_map);
76}
77
78module_init(init_rc_map_streamzap)
79module_exit(exit_rc_map_streamzap)
80
81MODULE_LICENSE("GPL");
82MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c
index 058e29fd478c..2cf57e64a80b 100644
--- a/drivers/media/IR/streamzap.c
+++ b/drivers/media/IR/streamzap.c
@@ -38,7 +38,7 @@
38#include <linux/input.h> 38#include <linux/input.h>
39#include <media/ir-core.h> 39#include <media/ir-core.h>
40 40
41#define DRIVER_VERSION "1.60" 41#define DRIVER_VERSION "1.61"
42#define DRIVER_NAME "streamzap" 42#define DRIVER_NAME "streamzap"
43#define DRIVER_DESC "Streamzap Remote Control driver" 43#define DRIVER_DESC "Streamzap Remote Control driver"
44 44
@@ -69,6 +69,13 @@ MODULE_DEVICE_TABLE(usb, streamzap_table);
69/* number of samples buffered */ 69/* number of samples buffered */
70#define SZ_BUF_LEN 128 70#define SZ_BUF_LEN 128
71 71
72/* from ir-rc5-sz-decoder.c */
73#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
74#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder")
75#else
76#define load_rc5_sz_decode() 0
77#endif
78
72enum StreamzapDecoderState { 79enum StreamzapDecoderState {
73 PulseSpace, 80 PulseSpace,
74 FullPulse, 81 FullPulse,
@@ -81,7 +88,6 @@ struct streamzap_ir {
81 88
82 /* ir-core */ 89 /* ir-core */
83 struct ir_dev_props *props; 90 struct ir_dev_props *props;
84 struct ir_raw_event rawir;
85 91
86 /* core device info */ 92 /* core device info */
87 struct device *dev; 93 struct device *dev;
@@ -98,17 +104,6 @@ struct streamzap_ir {
98 dma_addr_t dma_in; 104 dma_addr_t dma_in;
99 unsigned int buf_in_len; 105 unsigned int buf_in_len;
100 106
101 /* timer used to support delay buffering */
102 struct timer_list delay_timer;
103 bool timer_running;
104 spinlock_t timer_lock;
105 struct timer_list flush_timer;
106 bool flush;
107
108 /* delay buffer */
109 struct kfifo fifo;
110 bool fifo_initialized;
111
112 /* track what state we're in */ 107 /* track what state we're in */
113 enum StreamzapDecoderState decoder_state; 108 enum StreamzapDecoderState decoder_state;
114 /* tracks whether we are currently receiving some signal */ 109 /* tracks whether we are currently receiving some signal */
@@ -118,7 +113,7 @@ struct streamzap_ir {
118 /* start time of signal; necessary for gap tracking */ 113 /* start time of signal; necessary for gap tracking */
119 struct timeval signal_last; 114 struct timeval signal_last;
120 struct timeval signal_start; 115 struct timeval signal_start;
121 /* bool timeout_enabled; */ 116 bool timeout_enabled;
122 117
123 char name[128]; 118 char name[128];
124 char phys[64]; 119 char phys[64];
@@ -143,122 +138,16 @@ static struct usb_driver streamzap_driver = {
143 .id_table = streamzap_table, 138 .id_table = streamzap_table,
144}; 139};
145 140
146static void streamzap_stop_timer(struct streamzap_ir *sz) 141static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
147{
148 unsigned long flags;
149
150 spin_lock_irqsave(&sz->timer_lock, flags);
151 if (sz->timer_running) {
152 sz->timer_running = false;
153 spin_unlock_irqrestore(&sz->timer_lock, flags);
154 del_timer_sync(&sz->delay_timer);
155 } else {
156 spin_unlock_irqrestore(&sz->timer_lock, flags);
157 }
158}
159
160static void streamzap_flush_timeout(unsigned long arg)
161{
162 struct streamzap_ir *sz = (struct streamzap_ir *)arg;
163
164 dev_info(sz->dev, "%s: callback firing\n", __func__);
165
166 /* finally start accepting data */
167 sz->flush = false;
168}
169
170static void streamzap_delay_timeout(unsigned long arg)
171{
172 struct streamzap_ir *sz = (struct streamzap_ir *)arg;
173 struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
174 unsigned long flags;
175 int len, ret;
176 static unsigned long delay;
177 bool wake = false;
178
179 /* deliver data every 10 ms */
180 delay = msecs_to_jiffies(10);
181
182 spin_lock_irqsave(&sz->timer_lock, flags);
183
184 if (kfifo_len(&sz->fifo) > 0) {
185 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
186 if (ret != sizeof(rawir))
187 dev_err(sz->dev, "Problem w/kfifo_out...\n");
188 ir_raw_event_store(sz->idev, &rawir);
189 wake = true;
190 }
191
192 len = kfifo_len(&sz->fifo);
193 if (len > 0) {
194 while ((len < SZ_BUF_LEN / 2) &&
195 (len < SZ_BUF_LEN * sizeof(int))) {
196 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
197 if (ret != sizeof(rawir))
198 dev_err(sz->dev, "Problem w/kfifo_out...\n");
199 ir_raw_event_store(sz->idev, &rawir);
200 wake = true;
201 len = kfifo_len(&sz->fifo);
202 }
203 if (sz->timer_running)
204 mod_timer(&sz->delay_timer, jiffies + delay);
205
206 } else {
207 sz->timer_running = false;
208 }
209
210 if (wake)
211 ir_raw_event_handle(sz->idev);
212
213 spin_unlock_irqrestore(&sz->timer_lock, flags);
214}
215
216static void streamzap_flush_delay_buffer(struct streamzap_ir *sz)
217{ 142{
218 struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; 143 ir_raw_event_store(sz->idev, &rawir);
219 bool wake = false;
220 int ret;
221
222 while (kfifo_len(&sz->fifo) > 0) {
223 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
224 if (ret != sizeof(rawir))
225 dev_err(sz->dev, "Problem w/kfifo_out...\n");
226 ir_raw_event_store(sz->idev, &rawir);
227 wake = true;
228 }
229
230 if (wake)
231 ir_raw_event_handle(sz->idev);
232}
233
234static void sz_push(struct streamzap_ir *sz)
235{
236 struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
237 unsigned long flags;
238 int ret;
239
240 spin_lock_irqsave(&sz->timer_lock, flags);
241 if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) {
242 ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
243 if (ret != sizeof(rawir))
244 dev_err(sz->dev, "Problem w/kfifo_out...\n");
245 ir_raw_event_store(sz->idev, &rawir);
246 }
247
248 kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir));
249
250 if (!sz->timer_running) {
251 sz->delay_timer.expires = jiffies + (HZ / 10);
252 add_timer(&sz->delay_timer);
253 sz->timer_running = true;
254 }
255
256 spin_unlock_irqrestore(&sz->timer_lock, flags);
257} 144}
258 145
259static void sz_push_full_pulse(struct streamzap_ir *sz, 146static void sz_push_full_pulse(struct streamzap_ir *sz,
260 unsigned char value) 147 unsigned char value)
261{ 148{
149 struct ir_raw_event rawir;
150
262 if (sz->idle) { 151 if (sz->idle) {
263 long deltv; 152 long deltv;
264 153
@@ -266,33 +155,33 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,
266 do_gettimeofday(&sz->signal_start); 155 do_gettimeofday(&sz->signal_start);
267 156
268 deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec; 157 deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
269 sz->rawir.pulse = false; 158 rawir.pulse = false;
270 if (deltv > 15) { 159 if (deltv > 15) {
271 /* really long time */ 160 /* really long time */
272 sz->rawir.duration = IR_MAX_DURATION; 161 rawir.duration = IR_MAX_DURATION;
273 } else { 162 } else {
274 sz->rawir.duration = (int)(deltv * 1000000 + 163 rawir.duration = (int)(deltv * 1000000 +
275 sz->signal_start.tv_usec - 164 sz->signal_start.tv_usec -
276 sz->signal_last.tv_usec); 165 sz->signal_last.tv_usec);
277 sz->rawir.duration -= sz->sum; 166 rawir.duration -= sz->sum;
278 sz->rawir.duration *= 1000; 167 rawir.duration *= 1000;
279 sz->rawir.duration &= IR_MAX_DURATION; 168 rawir.duration &= IR_MAX_DURATION;
280 } 169 }
281 dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration); 170 dev_dbg(sz->dev, "ls %u\n", rawir.duration);
282 sz_push(sz); 171 sz_push(sz, rawir);
283 172
284 sz->idle = 0; 173 sz->idle = false;
285 sz->sum = 0; 174 sz->sum = 0;
286 } 175 }
287 176
288 sz->rawir.pulse = true; 177 rawir.pulse = true;
289 sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; 178 rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
290 sz->rawir.duration += STREAMZAP_RESOLUTION / 2; 179 rawir.duration += STREAMZAP_RESOLUTION / 2;
291 sz->sum += sz->rawir.duration; 180 sz->sum += rawir.duration;
292 sz->rawir.duration *= 1000; 181 rawir.duration *= 1000;
293 sz->rawir.duration &= IR_MAX_DURATION; 182 rawir.duration &= IR_MAX_DURATION;
294 dev_dbg(sz->dev, "p %u\n", sz->rawir.duration); 183 dev_dbg(sz->dev, "p %u\n", rawir.duration);
295 sz_push(sz); 184 sz_push(sz, rawir);
296} 185}
297 186
298static void sz_push_half_pulse(struct streamzap_ir *sz, 187static void sz_push_half_pulse(struct streamzap_ir *sz,
@@ -304,13 +193,15 @@ static void sz_push_half_pulse(struct streamzap_ir *sz,
304static void sz_push_full_space(struct streamzap_ir *sz, 193static void sz_push_full_space(struct streamzap_ir *sz,
305 unsigned char value) 194 unsigned char value)
306{ 195{
307 sz->rawir.pulse = false; 196 struct ir_raw_event rawir;
308 sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; 197
309 sz->rawir.duration += STREAMZAP_RESOLUTION / 2; 198 rawir.pulse = false;
310 sz->sum += sz->rawir.duration; 199 rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
311 sz->rawir.duration *= 1000; 200 rawir.duration += STREAMZAP_RESOLUTION / 2;
312 dev_dbg(sz->dev, "s %u\n", sz->rawir.duration); 201 sz->sum += rawir.duration;
313 sz_push(sz); 202 rawir.duration *= 1000;
203 dev_dbg(sz->dev, "s %u\n", rawir.duration);
204 sz_push(sz, rawir);
314} 205}
315 206
316static void sz_push_half_space(struct streamzap_ir *sz, 207static void sz_push_half_space(struct streamzap_ir *sz,
@@ -330,10 +221,8 @@ static void streamzap_callback(struct urb *urb)
330 struct streamzap_ir *sz; 221 struct streamzap_ir *sz;
331 unsigned int i; 222 unsigned int i;
332 int len; 223 int len;
333 #if 0
334 static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) & 224 static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) &
335 IR_MAX_DURATION) | 0x03000000); 225 IR_MAX_DURATION) | 0x03000000);
336 #endif
337 226
338 if (!urb) 227 if (!urb)
339 return; 228 return;
@@ -356,57 +245,53 @@ static void streamzap_callback(struct urb *urb)
356 } 245 }
357 246
358 dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); 247 dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
359 if (!sz->flush) { 248 for (i = 0; i < len; i++) {
360 for (i = 0; i < urb->actual_length; i++) { 249 dev_dbg(sz->dev, "sz idx %d: %x\n",
361 dev_dbg(sz->dev, "%d: %x\n", i, 250 i, (unsigned char)sz->buf_in[i]);
362 (unsigned char)sz->buf_in[i]); 251 switch (sz->decoder_state) {
363 switch (sz->decoder_state) { 252 case PulseSpace:
364 case PulseSpace: 253 if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) ==
365 if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) == 254 STREAMZAP_PULSE_MASK) {
366 STREAMZAP_PULSE_MASK) { 255 sz->decoder_state = FullPulse;
367 sz->decoder_state = FullPulse; 256 continue;
368 continue; 257 } else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK)
369 } else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK) 258 == STREAMZAP_SPACE_MASK) {
370 == STREAMZAP_SPACE_MASK) { 259 sz_push_half_pulse(sz, sz->buf_in[i]);
371 sz_push_half_pulse(sz, sz->buf_in[i]); 260 sz->decoder_state = FullSpace;
372 sz->decoder_state = FullSpace; 261 continue;
373 continue; 262 } else {
374 } else { 263 sz_push_half_pulse(sz, sz->buf_in[i]);
375 sz_push_half_pulse(sz, sz->buf_in[i]);
376 sz_push_half_space(sz, sz->buf_in[i]);
377 }
378 break;
379 case FullPulse:
380 sz_push_full_pulse(sz, sz->buf_in[i]);
381 sz->decoder_state = IgnorePulse;
382 break;
383 case FullSpace:
384 if (sz->buf_in[i] == STREAMZAP_TIMEOUT) {
385 sz->idle = 1;
386 streamzap_stop_timer(sz);
387 #if 0
388 if (sz->timeout_enabled) {
389 sz->rawir.pulse = false;
390 sz->rawir.duration = timeout;
391 sz->rawir.duration *= 1000;
392 sz_push(sz);
393 }
394 #endif
395 streamzap_flush_delay_buffer(sz);
396 } else
397 sz_push_full_space(sz, sz->buf_in[i]);
398 sz->decoder_state = PulseSpace;
399 break;
400 case IgnorePulse:
401 if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) ==
402 STREAMZAP_SPACE_MASK) {
403 sz->decoder_state = FullSpace;
404 continue;
405 }
406 sz_push_half_space(sz, sz->buf_in[i]); 264 sz_push_half_space(sz, sz->buf_in[i]);
407 sz->decoder_state = PulseSpace;
408 break;
409 } 265 }
266 break;
267 case FullPulse:
268 sz_push_full_pulse(sz, sz->buf_in[i]);
269 sz->decoder_state = IgnorePulse;
270 break;
271 case FullSpace:
272 if (sz->buf_in[i] == STREAMZAP_TIMEOUT) {
273 struct ir_raw_event rawir;
274
275 rawir.pulse = false;
276 rawir.duration = timeout * 1000;
277 sz->idle = true;
278 if (sz->timeout_enabled)
279 sz_push(sz, rawir);
280 ir_raw_event_handle(sz->idev);
281 } else {
282 sz_push_full_space(sz, sz->buf_in[i]);
283 }
284 sz->decoder_state = PulseSpace;
285 break;
286 case IgnorePulse:
287 if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK) ==
288 STREAMZAP_SPACE_MASK) {
289 sz->decoder_state = FullSpace;
290 continue;
291 }
292 sz_push_half_space(sz, sz->buf_in[i]);
293 sz->decoder_state = PulseSpace;
294 break;
410 } 295 }
411 } 296 }
412 297
@@ -446,12 +331,11 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
446 331
447 props->priv = sz; 332 props->priv = sz;
448 props->driver_type = RC_DRIVER_IR_RAW; 333 props->driver_type = RC_DRIVER_IR_RAW;
449 /* FIXME: not sure about supported protocols, check on this */ 334 props->allowed_protos = IR_TYPE_ALL;
450 props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6;
451 335
452 sz->props = props; 336 sz->props = props;
453 337
454 ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME); 338 ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
455 if (ret < 0) { 339 if (ret < 0) {
456 dev_err(dev, "remote input device register failed\n"); 340 dev_err(dev, "remote input device register failed\n");
457 goto irdev_failed; 341 goto irdev_failed;
@@ -467,29 +351,6 @@ idev_alloc_failed:
467 return NULL; 351 return NULL;
468} 352}
469 353
470static int streamzap_delay_buf_init(struct streamzap_ir *sz)
471{
472 int ret;
473
474 ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN,
475 GFP_KERNEL);
476 if (ret == 0)
477 sz->fifo_initialized = 1;
478
479 return ret;
480}
481
482static void streamzap_start_flush_timer(struct streamzap_ir *sz)
483{
484 sz->flush_timer.expires = jiffies + HZ;
485 sz->flush = true;
486 add_timer(&sz->flush_timer);
487
488 sz->urb_in->dev = sz->usbdev;
489 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
490 dev_err(sz->dev, "urb submit failed\n");
491}
492
493/** 354/**
494 * streamzap_probe 355 * streamzap_probe
495 * 356 *
@@ -575,35 +436,21 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
575 snprintf(name + strlen(name), sizeof(name) - strlen(name), 436 snprintf(name + strlen(name), sizeof(name) - strlen(name),
576 " %s", buf); 437 " %s", buf);
577 438
578 retval = streamzap_delay_buf_init(sz);
579 if (retval) {
580 dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__);
581 goto free_urb_in;
582 }
583
584 sz->idev = streamzap_init_input_dev(sz); 439 sz->idev = streamzap_init_input_dev(sz);
585 if (!sz->idev) 440 if (!sz->idev)
586 goto input_dev_fail; 441 goto input_dev_fail;
587 442
588 sz->idle = true; 443 sz->idle = true;
589 sz->decoder_state = PulseSpace; 444 sz->decoder_state = PulseSpace;
445 /* FIXME: don't yet have a way to set this */
446 sz->timeout_enabled = true;
590 #if 0 447 #if 0
591 /* not yet supported, depends on patches from maxim */ 448 /* not yet supported, depends on patches from maxim */
592 /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ 449 /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
593 sz->timeout_enabled = false;
594 sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; 450 sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
595 sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; 451 sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
596 #endif 452 #endif
597 453
598 init_timer(&sz->delay_timer);
599 sz->delay_timer.function = streamzap_delay_timeout;
600 sz->delay_timer.data = (unsigned long)sz;
601 spin_lock_init(&sz->timer_lock);
602
603 init_timer(&sz->flush_timer);
604 sz->flush_timer.function = streamzap_flush_timeout;
605 sz->flush_timer.data = (unsigned long)sz;
606
607 do_gettimeofday(&sz->signal_start); 454 do_gettimeofday(&sz->signal_start);
608 455
609 /* Complete final initialisations */ 456 /* Complete final initialisations */
@@ -615,16 +462,18 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
615 462
616 usb_set_intfdata(intf, sz); 463 usb_set_intfdata(intf, sz);
617 464
618 streamzap_start_flush_timer(sz); 465 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
466 dev_err(sz->dev, "urb submit failed\n");
619 467
620 dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, 468 dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
621 usbdev->bus->busnum, usbdev->devnum); 469 usbdev->bus->busnum, usbdev->devnum);
622 470
471 /* Load the streamzap not-quite-rc5 decoder too */
472 load_rc5_sz_decode();
473
623 return 0; 474 return 0;
624 475
625input_dev_fail: 476input_dev_fail:
626 kfifo_free(&sz->fifo);
627free_urb_in:
628 usb_free_urb(sz->urb_in); 477 usb_free_urb(sz->urb_in);
629free_buf_in: 478free_buf_in:
630 usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in); 479 usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
@@ -654,13 +503,6 @@ static void streamzap_disconnect(struct usb_interface *interface)
654 if (!sz) 503 if (!sz)
655 return; 504 return;
656 505
657 if (sz->flush) {
658 sz->flush = false;
659 del_timer_sync(&sz->flush_timer);
660 }
661
662 streamzap_stop_timer(sz);
663
664 sz->usbdev = NULL; 506 sz->usbdev = NULL;
665 ir_input_unregister(sz->idev); 507 ir_input_unregister(sz->idev);
666 usb_kill_urb(sz->urb_in); 508 usb_kill_urb(sz->urb_in);
@@ -674,13 +516,6 @@ static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
674{ 516{
675 struct streamzap_ir *sz = usb_get_intfdata(intf); 517 struct streamzap_ir *sz = usb_get_intfdata(intf);
676 518
677 if (sz->flush) {
678 sz->flush = false;
679 del_timer_sync(&sz->flush_timer);
680 }
681
682 streamzap_stop_timer(sz);
683
684 usb_kill_urb(sz->urb_in); 519 usb_kill_urb(sz->urb_in);
685 520
686 return 0; 521 return 0;
@@ -690,13 +525,6 @@ static int streamzap_resume(struct usb_interface *intf)
690{ 525{
691 struct streamzap_ir *sz = usb_get_intfdata(intf); 526 struct streamzap_ir *sz = usb_get_intfdata(intf);
692 527
693 if (sz->fifo_initialized)
694 kfifo_reset(&sz->fifo);
695
696 sz->flush_timer.expires = jiffies + HZ;
697 sz->flush = true;
698 add_timer(&sz->flush_timer);
699
700 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { 528 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
701 dev_err(sz->dev, "Error sumbiting urb\n"); 529 dev_err(sz->dev, "Error sumbiting urb\n");
702 return -EIO; 530 return -EIO;