V4L/DVB: ir-core: allow specifying multiple protocols at one open/write
[deliverable/linux.git] / drivers / media / IR / ir-sony-decoder.c
CommitLineData
3fe29c89
DH
1/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol
2 *
3 * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
4 *
5 * 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 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/bitrev.h>
16#include "ir-core-priv.h"
17
18#define SONY_UNIT 600000 /* ns */
19#define SONY_HEADER_PULSE (4 * SONY_UNIT)
20#define SONY_HEADER_SPACE (1 * SONY_UNIT)
21#define SONY_BIT_0_PULSE (1 * SONY_UNIT)
22#define SONY_BIT_1_PULSE (2 * SONY_UNIT)
23#define SONY_BIT_SPACE (1 * SONY_UNIT)
24#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */
25
26/* Used to register sony_decoder clients */
27static LIST_HEAD(decoder_list);
28static DEFINE_SPINLOCK(decoder_lock);
29
30enum sony_state {
31 STATE_INACTIVE,
32 STATE_HEADER_SPACE,
33 STATE_BIT_PULSE,
34 STATE_BIT_SPACE,
35 STATE_FINISHED,
36};
37
38struct decoder_data {
39 struct list_head list;
40 struct ir_input_dev *ir_dev;
3fe29c89
DH
41
42 /* State machine control */
43 enum sony_state state;
44 u32 sony_bits;
45 unsigned count;
46};
47
48
49/**
50 * get_decoder_data() - gets decoder data
51 * @input_dev: input device
52 *
53 * Returns the struct decoder_data that corresponds to a device
54 */
55static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
56{
57 struct decoder_data *data = NULL;
58
59 spin_lock(&decoder_lock);
60 list_for_each_entry(data, &decoder_list, list) {
61 if (data->ir_dev == ir_dev)
62 break;
63 }
64 spin_unlock(&decoder_lock);
65 return data;
66}
67
3fe29c89
DH
68/**
69 * ir_sony_decode() - Decode one Sony pulse or space
70 * @input_dev: the struct input_dev descriptor of the device
71 * @ev: the struct ir_raw_event descriptor of the pulse/space
72 *
73 * This function returns -EINVAL if the pulse violates the state machine
74 */
75static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
76{
77 struct decoder_data *data;
78 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
79 u32 scancode;
80 u8 device, subdevice, function;
81
82 data = get_decoder_data(ir_dev);
83 if (!data)
84 return -EINVAL;
85
667c9ebe 86 if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
3fe29c89
DH
87 return 0;
88
89 if (IS_RESET(ev)) {
90 data->state = STATE_INACTIVE;
91 return 0;
92 }
93
94 if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
95 goto out;
96
97 IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n",
98 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
99
100 switch (data->state) {
101
102 case STATE_INACTIVE:
103 if (!ev.pulse)
104 break;
105
106 if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
107 break;
108
109 data->count = 0;
110 data->state = STATE_HEADER_SPACE;
111 return 0;
112
113 case STATE_HEADER_SPACE:
114 if (ev.pulse)
115 break;
116
117 if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
118 break;
119
120 data->state = STATE_BIT_PULSE;
121 return 0;
122
123 case STATE_BIT_PULSE:
124 if (!ev.pulse)
125 break;
126
127 data->sony_bits <<= 1;
128 if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
129 data->sony_bits |= 1;
130 else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
131 break;
132
133 data->count++;
134 data->state = STATE_BIT_SPACE;
135 return 0;
136
137 case STATE_BIT_SPACE:
138 if (ev.pulse)
139 break;
140
141 if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
142 break;
143
144 decrease_duration(&ev, SONY_BIT_SPACE);
145
146 if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
147 data->state = STATE_BIT_PULSE;
148 return 0;
149 }
150
151 data->state = STATE_FINISHED;
152 /* Fall through */
153
154 case STATE_FINISHED:
155 if (ev.pulse)
156 break;
157
158 if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
159 break;
160
161 switch (data->count) {
162 case 12:
163 device = bitrev8((data->sony_bits << 3) & 0xF8);
164 subdevice = 0;
165 function = bitrev8((data->sony_bits >> 4) & 0xFE);
166 break;
167 case 15:
168 device = bitrev8((data->sony_bits >> 0) & 0xFF);
169 subdevice = 0;
170 function = bitrev8((data->sony_bits >> 7) & 0xFD);
171 break;
172 case 20:
173 device = bitrev8((data->sony_bits >> 5) & 0xF8);
174 subdevice = bitrev8((data->sony_bits >> 0) & 0xFF);
175 function = bitrev8((data->sony_bits >> 12) & 0xFE);
176 break;
177 default:
178 IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
179 goto out;
180 }
181
182 scancode = device << 16 | subdevice << 8 | function;
183 IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
184 ir_keydown(input_dev, scancode, 0);
185 data->state = STATE_INACTIVE;
186 return 0;
187 }
188
189out:
190 IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
191 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
192 data->state = STATE_INACTIVE;
193 return -EINVAL;
194}
195
196static int ir_sony_register(struct input_dev *input_dev)
197{
198 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
199 struct decoder_data *data;
3fe29c89
DH
200
201 data = kzalloc(sizeof(*data), GFP_KERNEL);
667c9ebe 202 if (!data)
3fe29c89 203 return -ENOMEM;
3fe29c89
DH
204
205 data->ir_dev = ir_dev;
3fe29c89
DH
206
207 spin_lock(&decoder_lock);
208 list_add_tail(&data->list, &decoder_list);
209 spin_unlock(&decoder_lock);
210
211 return 0;
212}
213
214static int ir_sony_unregister(struct input_dev *input_dev)
215{
216 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
217 static struct decoder_data *data;
218
219 data = get_decoder_data(ir_dev);
220 if (!data)
221 return 0;
222
3fe29c89
DH
223 spin_lock(&decoder_lock);
224 list_del(&data->list);
225 spin_unlock(&decoder_lock);
226
227 return 0;
228}
229
230static struct ir_raw_handler sony_handler = {
667c9ebe 231 .protocols = IR_TYPE_SONY,
3fe29c89
DH
232 .decode = ir_sony_decode,
233 .raw_register = ir_sony_register,
234 .raw_unregister = ir_sony_unregister,
235};
236
237static int __init ir_sony_decode_init(void)
238{
239 ir_raw_handler_register(&sony_handler);
240
241 printk(KERN_INFO "IR Sony protocol handler initialized\n");
242 return 0;
243}
244
245static void __exit ir_sony_decode_exit(void)
246{
247 ir_raw_handler_unregister(&sony_handler);
248}
249
250module_init(ir_sony_decode_init);
251module_exit(ir_sony_decode_exit);
252
253MODULE_LICENSE("GPL");
254MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
255MODULE_DESCRIPTION("Sony IR protocol decoder");
This page took 0.054423 seconds and 5 git commands to generate.