aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/siano/smsir.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/siano/smsir.c')
-rw-r--r--drivers/media/dvb/siano/smsir.c254
1 files changed, 30 insertions, 224 deletions
diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c
index f8a4fd61e3d..d0e4639ee9d 100644
--- a/drivers/media/dvb/siano/smsir.c
+++ b/drivers/media/dvb/siano/smsir.c
@@ -4,6 +4,11 @@
4 MDTV receiver kernel modules. 4 MDTV receiver kernel modules.
5 Copyright (C) 2006-2009, Uri Shkolnik 5 Copyright (C) 2006-2009, Uri Shkolnik
6 6
7 Copyright (c) 2010 - Mauro Carvalho Chehab
8 - Ported the driver to use rc-core
9 - IR raw event decoding is now done at rc-core
10 - Code almost re-written
11
7 This program is free software: you can redistribute it and/or modify 12 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by 13 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or 14 the Free Software Foundation, either version 2 of the License, or
@@ -22,227 +27,27 @@
22 27
23#include <linux/types.h> 28#include <linux/types.h>
24#include <linux/input.h> 29#include <linux/input.h>
25#include <media/ir-core.h>
26 30
27#include "smscoreapi.h" 31#include "smscoreapi.h"
28#include "smsir.h" 32#include "smsir.h"
29#include "sms-cards.h" 33#include "sms-cards.h"
30 34
31/* In order to add new IR remote control - 35#define MODULE_NAME "smsmdtv"
32 * 1) Add it to the <enum ir_kb_type> @ smsir,h,
33 * 2) Add its map to keyboard_layout_maps below
34 * 3) Set your board (sms-cards sub-module) to use it
35 */
36
37static struct keyboard_layout_map_t keyboard_layout_maps[] = {
38 [SMS_IR_KB_DEFAULT_TV] = {
39 .ir_protocol = IR_RC5,
40 .rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
41 .keyboard_layout_map = {
42 KEY_0, KEY_1, KEY_2,
43 KEY_3, KEY_4, KEY_5,
44 KEY_6, KEY_7, KEY_8,
45 KEY_9, 0, 0, KEY_POWER,
46 KEY_MUTE, 0, 0,
47 KEY_VOLUMEUP, KEY_VOLUMEDOWN,
48 KEY_BRIGHTNESSUP,
49 KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
50 KEY_CHANNELDOWN,
51 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
56 }
57 },
58 [SMS_IR_KB_HCW_SILVER] = {
59 .ir_protocol = IR_RC5,
60 .rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
61 .keyboard_layout_map = {
62 KEY_0, KEY_1, KEY_2,
63 KEY_3, KEY_4, KEY_5,
64 KEY_6, KEY_7, KEY_8,
65 KEY_9, KEY_TEXT, KEY_RED,
66 KEY_RADIO, KEY_MENU,
67 KEY_SUBTITLE,
68 KEY_MUTE, KEY_VOLUMEUP,
69 KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
70 KEY_UP, KEY_DOWN, KEY_LEFT,
71 KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
72 KEY_MHP, KEY_EPG, KEY_TV,
73 0, KEY_NEXTSONG, KEY_EXIT,
74 KEY_CHANNELUP, KEY_CHANNELDOWN,
75 KEY_CHANNEL, 0,
76 KEY_PREVIOUSSONG, KEY_ENTER,
77 KEY_SLEEP, 0, 0, KEY_BLUE,
78 0, 0, 0, 0, KEY_GREEN, 0,
79 KEY_PAUSE, 0, KEY_REWIND,
80 0, KEY_FASTFORWARD, KEY_PLAY,
81 KEY_STOP, KEY_RECORD,
82 KEY_YELLOW, 0, 0, KEY_SELECT,
83 KEY_ZOOM, KEY_POWER, 0, 0
84 }
85 },
86 { } /* Terminating entry */
87};
88
89static u32 ir_pos;
90static u32 ir_word;
91static u32 ir_toggle;
92
93#define RC5_PUSH_BIT(dst, bit, pos) \
94 { dst <<= 1; dst |= bit; pos++; }
95
96
97static void sms_ir_rc5_event(struct smscore_device_t *coredev,
98 u32 toggle, u32 addr, u32 cmd)
99{
100 bool toggle_changed;
101 u16 keycode;
102
103 sms_log("IR RC5 word: address %d, command %d, toggle %d",
104 addr, cmd, toggle);
105
106 toggle_changed = ir_toggle != toggle;
107 /* keep toggle */
108 ir_toggle = toggle;
109
110 if (addr !=
111 keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
112 return; /* Check for valid address */
113 36
114 keycode = 37void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
115 keyboard_layout_maps
116 [coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
117
118 if (!toggle_changed &&
119 (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
120 return; /* accept only repeated volume, reject other keys */
121
122 sms_log("kernel input keycode (from ir) %d", keycode);
123 input_report_key(coredev->ir.input_dev, keycode, 1);
124 input_sync(coredev->ir.input_dev);
125
126}
127
128/* decode raw bit pattern to RC5 code */
129/* taken from ir-functions.c */
130static u32 ir_rc5_decode(unsigned int code)
131{ 38{
132/* unsigned int org_code = code;*/
133 unsigned int pair;
134 unsigned int rc5 = 0;
135 int i; 39 int i;
40 const s32 *samples = (const void *)buf;
136 41
137 for (i = 0; i < 14; ++i) { 42 for (i = 0; i < len >> 2; i++) {
138 pair = code & 0x3; 43 struct ir_raw_event ev;
139 code >>= 2;
140
141 rc5 <<= 1;
142 switch (pair) {
143 case 0:
144 case 2:
145 break;
146 case 1:
147 rc5 |= 1;
148 break;
149 case 3:
150/* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
151 sms_log("bad code");
152 return 0;
153 }
154 }
155/*
156 dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
157 toggle=%x, address=%x, "
158 "instr=%x\n", rc5, org_code, RC5_START(rc5),
159 RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
160*/
161 return rc5;
162}
163
164static void sms_rc5_parse_word(struct smscore_device_t *coredev)
165{
166 #define RC5_START(x) (((x)>>12)&3)
167 #define RC5_TOGGLE(x) (((x)>>11)&1)
168 #define RC5_ADDR(x) (((x)>>6)&0x1F)
169 #define RC5_INSTR(x) ((x)&0x3F)
170
171 int i, j;
172 u32 rc5_word = 0;
173
174 /* Reverse the IR word direction */
175 for (i = 0 ; i < 28 ; i++)
176 RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
177
178 rc5_word = ir_rc5_decode(rc5_word);
179 /* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
180
181 sms_ir_rc5_event(coredev,
182 RC5_TOGGLE(rc5_word),
183 RC5_ADDR(rc5_word),
184 RC5_INSTR(rc5_word));
185}
186
187
188static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
189 s32 ir_sample)
190{
191 #define RC5_TIME_GRANULARITY 200
192 #define RC5_DEF_BIT_TIME 889
193 #define RC5_MAX_SAME_BIT_CONT 4
194 #define RC5_WORD_LEN 27 /* 28 bit */
195
196 u32 i, j;
197 s32 delta_time;
198 u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
199 u32 level = (ir_sample < 0) ? 0 : 1;
200 44
201 for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) { 45 ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
202 delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY; 46 ev.pulse = (samples[i] > 0) ? false : true;
203 if (delta_time < 0)
204 continue; /* not so many consecutive bits */
205 if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
206 /* timeout */
207 if (ir_pos == (RC5_WORD_LEN-1))
208 /* complete last bit */
209 RC5_PUSH_BIT(ir_word, level, ir_pos)
210 47
211 if (ir_pos == RC5_WORD_LEN) 48 ir_raw_event_store(coredev->ir.input_dev, &ev);
212 sms_rc5_parse_word(coredev);
213 else if (ir_pos) /* timeout within a word */
214 sms_log("IR error parsing a word");
215
216 ir_pos = 0;
217 ir_word = 0;
218 /* sms_log("timeout %d", time); */
219 break;
220 }
221 /* The time is within the range of this number of bits */
222 for (j = 0 ; j < i ; j++)
223 RC5_PUSH_BIT(ir_word, level, ir_pos)
224
225 break;
226 } 49 }
227} 50 ir_raw_event_handle(coredev->ir.input_dev);
228
229void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
230{
231 #define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */
232 u32 i;
233 enum ir_protocol ir_protocol =
234 keyboard_layout_maps[coredev->ir.ir_kb_type]
235 .ir_protocol;
236 s32 *samples;
237 int count = len>>2;
238
239 samples = (s32 *)buf;
240/* sms_log("IR buffer received, length = %d", count);*/
241
242 for (i = 0; i < count; i++)
243 if (ir_protocol == IR_RC5)
244 sms_rc5_accumulate_bits(coredev, samples[i]);
245 /* IR_RCMM not implemented */
246} 51}
247 52
248int sms_ir_init(struct smscore_device_t *coredev) 53int sms_ir_init(struct smscore_device_t *coredev)
@@ -258,21 +63,14 @@ int sms_ir_init(struct smscore_device_t *coredev)
258 } 63 }
259 64
260 coredev->ir.input_dev = input_dev; 65 coredev->ir.input_dev = input_dev;
261 coredev->ir.ir_kb_type = sms_get_board(board_id)->ir_kb_type;
262 coredev->ir.keyboard_layout_map =
263 keyboard_layout_maps[coredev->ir.ir_kb_type].
264 keyboard_layout_map;
265 sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type);
266 66
267 coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ 67 coredev->ir.controller = 0; /* Todo: vega/nova SPI number */
268 coredev->ir.timeout = IR_DEFAULT_TIMEOUT; 68 coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
269 sms_log("IR port %d, timeout %d ms", 69 sms_log("IR port %d, timeout %d ms",
270 coredev->ir.controller, coredev->ir.timeout); 70 coredev->ir.controller, coredev->ir.timeout);
271 71
272 snprintf(coredev->ir.name, 72 snprintf(coredev->ir.name, sizeof(coredev->ir.name),
273 sizeof(coredev->ir.name), 73 "SMS IR (%s)", sms_get_board(board_id)->name);
274 "SMS IR (%s)",
275 sms_get_board(board_id)->name);
276 74
277 strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); 75 strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
278 strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys)); 76 strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
@@ -281,13 +79,22 @@ int sms_ir_init(struct smscore_device_t *coredev)
281 input_dev->phys = coredev->ir.phys; 79 input_dev->phys = coredev->ir.phys;
282 input_dev->dev.parent = coredev->device; 80 input_dev->dev.parent = coredev->device;
283 81
284 /* Key press events only */ 82#if 0
285 input_dev->evbit[0] = BIT_MASK(EV_KEY); 83 /* TODO: properly initialize the parameters bellow */
286 input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); 84 input_dev->id.bustype = BUS_USB;
85 input_dev->id.version = 1;
86 input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
87 input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
88#endif
89
90 coredev->ir.props.priv = coredev;
91 coredev->ir.props.driver_type = RC_DRIVER_IR_RAW;
92 coredev->ir.props.allowed_protos = IR_TYPE_ALL;
287 93
288 sms_log("Input device (IR) %s is set for key events", input_dev->name); 94 sms_log("Input device (IR) %s is set for key events", input_dev->name);
289 95
290 if (input_register_device(input_dev)) { 96 if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes,
97 &coredev->ir.props, MODULE_NAME)) {
291 sms_err("Failed to register device"); 98 sms_err("Failed to register device");
292 input_free_device(input_dev); 99 input_free_device(input_dev);
293 return -EACCES; 100 return -EACCES;
@@ -299,8 +106,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
299void sms_ir_exit(struct smscore_device_t *coredev) 106void sms_ir_exit(struct smscore_device_t *coredev)
300{ 107{
301 if (coredev->ir.input_dev) 108 if (coredev->ir.input_dev)
302 input_unregister_device(coredev->ir.input_dev); 109 ir_input_unregister(coredev->ir.input_dev);
303 110
304 sms_log(""); 111 sms_log("");
305} 112}
306