aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-rc6-decoder.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 13:38:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 13:38:08 -0400
commitf63b759c44b0561c76a67894c734157df3313b42 (patch)
tree4e9638f6c1aa5c0faa62ad4213282cc7cb39772a /drivers/media/IR/ir-rc6-decoder.c
parent4a35cee066df1b1958e25e71595b3845d06b192e (diff)
parent844a9e93d7fcd910cd94f6eb262e2cc43cacbe56 (diff)
Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (243 commits) V4L/DVB: sms: Convert IR support to use the Remote Controller core V4L/DVB: sms: properly initialize IR phys and IR name V4L/DVB: standardize names at rc-dib0700 tables V4L/DVB: smsusb: enable IR port for Hauppauge WinTV MiniStick V4L/DVB: dib0700: Fix RC protocol logic to properly handle NEC/NECx and RC-5 V4L/DVB: dib0700: properly implement IR change_protocol V4L/DVB: dib0700: break keytable into NEC and RC-5 variants V4L/DVB: dib0700: avoid bad repeat V4L/DVB: Port dib0700 to rc-core V4L/DVB: Add a keymap file with dib0700 table V4L/DVB: dvb-usb: add support for rc-core mode V4L/DVB: dvb-usb: prepare drivers for using rc-core V4L/DVB: dvb-usb: get rid of struct dvb_usb_rc_key V4L/DVB: rj54n1cb0c: fix a comment in the driver V4L/DVB: V4L2: sh_vou: VOU does support the full PAL resolution too V4L/DVB: V4L2: sh_mobile_camera_ceu: add support for CSI2 V4L/DVB: V4L2: soc-camera: add a MIPI CSI-2 driver for SH-Mobile platforms V4L/DVB: V4L2: soc-camera: export soc-camera bus type for notifications V4L/DVB: V4L2: mediabus: add 12-bit Bayer and YUV420 pixel formats V4L/DVB: mediabus: fix ambiguous pixel code names ...
Diffstat (limited to 'drivers/media/IR/ir-rc6-decoder.c')
-rw-r--r--drivers/media/IR/ir-rc6-decoder.c153
1 files changed, 7 insertions, 146 deletions
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
index 2bf479f4f1bc..f1624b8279bc 100644
--- a/drivers/media/IR/ir-rc6-decoder.c
+++ b/drivers/media/IR/ir-rc6-decoder.c
@@ -36,10 +36,6 @@
36#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ 36#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
37#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ 37#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
38 38
39/* Used to register rc6_decoder clients */
40static LIST_HEAD(decoder_list);
41static DEFINE_SPINLOCK(decoder_lock);
42
43enum rc6_mode { 39enum rc6_mode {
44 RC6_MODE_0, 40 RC6_MODE_0,
45 RC6_MODE_6A, 41 RC6_MODE_6A,
@@ -58,89 +54,8 @@ enum rc6_state {
58 STATE_FINISHED, 54 STATE_FINISHED,
59}; 55};
60 56
61struct decoder_data { 57static enum rc6_mode rc6_mode(struct rc6_dec *data)
62 struct list_head list;
63 struct ir_input_dev *ir_dev;
64 int enabled:1;
65
66 /* State machine control */
67 enum rc6_state state;
68 u8 header;
69 u32 body;
70 struct ir_raw_event prev_ev;
71 bool toggle;
72 unsigned count;
73 unsigned wanted_bits;
74};
75
76
77/**
78 * get_decoder_data() - gets decoder data
79 * @input_dev: input device
80 *
81 * Returns the struct decoder_data that corresponds to a device
82 */
83static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
84{
85 struct decoder_data *data = NULL;
86
87 spin_lock(&decoder_lock);
88 list_for_each_entry(data, &decoder_list, list) {
89 if (data->ir_dev == ir_dev)
90 break;
91 }
92 spin_unlock(&decoder_lock);
93 return data;
94}
95
96static ssize_t store_enabled(struct device *d,
97 struct device_attribute *mattr,
98 const char *buf,
99 size_t len)
100{ 58{
101 unsigned long value;
102 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
103 struct decoder_data *data = get_decoder_data(ir_dev);
104
105 if (!data)
106 return -EINVAL;
107
108 if (strict_strtoul(buf, 10, &value) || value > 1)
109 return -EINVAL;
110
111 data->enabled = value;
112
113 return len;
114}
115
116static ssize_t show_enabled(struct device *d,
117 struct device_attribute *mattr, char *buf)
118{
119 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
120 struct decoder_data *data = get_decoder_data(ir_dev);
121
122 if (!data)
123 return -EINVAL;
124
125 if (data->enabled)
126 return sprintf(buf, "1\n");
127 else
128 return sprintf(buf, "0\n");
129}
130
131static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
132
133static struct attribute *decoder_attributes[] = {
134 &dev_attr_enabled.attr,
135 NULL
136};
137
138static struct attribute_group decoder_attribute_group = {
139 .name = "rc6_decoder",
140 .attrs = decoder_attributes,
141};
142
143static enum rc6_mode rc6_mode(struct decoder_data *data) {
144 switch (data->header & RC6_MODE_MASK) { 59 switch (data->header & RC6_MODE_MASK) {
145 case 0: 60 case 0:
146 return RC6_MODE_0; 61 return RC6_MODE_0;
@@ -162,16 +77,12 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
162 */ 77 */
163static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) 78static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
164{ 79{
165 struct decoder_data *data;
166 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 80 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
81 struct rc6_dec *data = &ir_dev->raw->rc6;
167 u32 scancode; 82 u32 scancode;
168 u8 toggle; 83 u8 toggle;
169 84
170 data = get_decoder_data(ir_dev); 85 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
171 if (!data)
172 return -EINVAL;
173
174 if (!data->enabled)
175 return 0; 86 return 0;
176 87
177 if (IS_RESET(ev)) { 88 if (IS_RESET(ev)) {
@@ -223,12 +134,11 @@ again:
223 if (ev.pulse) 134 if (ev.pulse)
224 data->header |= 1; 135 data->header |= 1;
225 data->count++; 136 data->count++;
226 data->prev_ev = ev;
227 data->state = STATE_HEADER_BIT_END; 137 data->state = STATE_HEADER_BIT_END;
228 return 0; 138 return 0;
229 139
230 case STATE_HEADER_BIT_END: 140 case STATE_HEADER_BIT_END:
231 if (!is_transition(&ev, &data->prev_ev)) 141 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
232 break; 142 break;
233 143
234 if (data->count == RC6_HEADER_NBITS) 144 if (data->count == RC6_HEADER_NBITS)
@@ -244,12 +154,11 @@ again:
244 break; 154 break;
245 155
246 data->toggle = ev.pulse; 156 data->toggle = ev.pulse;
247 data->prev_ev = ev;
248 data->state = STATE_TOGGLE_END; 157 data->state = STATE_TOGGLE_END;
249 return 0; 158 return 0;
250 159
251 case STATE_TOGGLE_END: 160 case STATE_TOGGLE_END:
252 if (!is_transition(&ev, &data->prev_ev) || 161 if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
253 !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) 162 !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
254 break; 163 break;
255 164
@@ -259,7 +168,6 @@ again:
259 } 168 }
260 169
261 data->state = STATE_BODY_BIT_START; 170 data->state = STATE_BODY_BIT_START;
262 data->prev_ev = ev;
263 decrease_duration(&ev, RC6_TOGGLE_END); 171 decrease_duration(&ev, RC6_TOGGLE_END);
264 data->count = 0; 172 data->count = 0;
265 173
@@ -291,13 +199,11 @@ again:
291 if (ev.pulse) 199 if (ev.pulse)
292 data->body |= 1; 200 data->body |= 1;
293 data->count++; 201 data->count++;
294 data->prev_ev = ev;
295
296 data->state = STATE_BODY_BIT_END; 202 data->state = STATE_BODY_BIT_END;
297 return 0; 203 return 0;
298 204
299 case STATE_BODY_BIT_END: 205 case STATE_BODY_BIT_END:
300 if (!is_transition(&ev, &data->prev_ev)) 206 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
301 break; 207 break;
302 208
303 if (data->count == data->wanted_bits) 209 if (data->count == data->wanted_bits)
@@ -348,54 +254,9 @@ out:
348 return -EINVAL; 254 return -EINVAL;
349} 255}
350 256
351static int ir_rc6_register(struct input_dev *input_dev)
352{
353 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
354 struct decoder_data *data;
355 int rc;
356
357 rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
358 if (rc < 0)
359 return rc;
360
361 data = kzalloc(sizeof(*data), GFP_KERNEL);
362 if (!data) {
363 sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
364 return -ENOMEM;
365 }
366
367 data->ir_dev = ir_dev;
368 data->enabled = 1;
369
370 spin_lock(&decoder_lock);
371 list_add_tail(&data->list, &decoder_list);
372 spin_unlock(&decoder_lock);
373
374 return 0;
375}
376
377static int ir_rc6_unregister(struct input_dev *input_dev)
378{
379 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
380 static struct decoder_data *data;
381
382 data = get_decoder_data(ir_dev);
383 if (!data)
384 return 0;
385
386 sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
387
388 spin_lock(&decoder_lock);
389 list_del(&data->list);
390 spin_unlock(&decoder_lock);
391
392 return 0;
393}
394
395static struct ir_raw_handler rc6_handler = { 257static struct ir_raw_handler rc6_handler = {
258 .protocols = IR_TYPE_RC6,
396 .decode = ir_rc6_decode, 259 .decode = ir_rc6_decode,
397 .raw_register = ir_rc6_register,
398 .raw_unregister = ir_rc6_unregister,
399}; 260};
400 261
401static int __init ir_rc6_decode_init(void) 262static int __init ir_rc6_decode_init(void)