diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb/dvb-usb-remote.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 198 |
1 files changed, 140 insertions, 58 deletions
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 852fe89539cf..b579fed3ab3f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
@@ -8,29 +8,29 @@ | |||
8 | #include "dvb-usb-common.h" | 8 | #include "dvb-usb-common.h" |
9 | #include <linux/usb/input.h> | 9 | #include <linux/usb/input.h> |
10 | 10 | ||
11 | static int dvb_usb_getkeycode(struct input_dev *dev, | 11 | static int legacy_dvb_usb_getkeycode(struct input_dev *dev, |
12 | unsigned int scancode, unsigned int *keycode) | 12 | unsigned int scancode, unsigned int *keycode) |
13 | { | 13 | { |
14 | struct dvb_usb_device *d = input_get_drvdata(dev); | 14 | struct dvb_usb_device *d = input_get_drvdata(dev); |
15 | 15 | ||
16 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 16 | struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; |
17 | int i; | 17 | int i; |
18 | 18 | ||
19 | /* See if we can match the raw key code. */ | 19 | /* See if we can match the raw key code. */ |
20 | for (i = 0; i < d->props.rc_key_map_size; i++) | 20 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) |
21 | if (keymap[i].scan == scancode) { | 21 | if (keymap[i].scancode == scancode) { |
22 | *keycode = keymap[i].event; | 22 | *keycode = keymap[i].keycode; |
23 | return 0; | 23 | return 0; |
24 | } | 24 | } |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * If is there extra space, returns KEY_RESERVED, | 27 | * If is there extra space, returns KEY_RESERVED, |
28 | * otherwise, input core won't let dvb_usb_setkeycode | 28 | * otherwise, input core won't let legacy_dvb_usb_setkeycode |
29 | * to work | 29 | * to work |
30 | */ | 30 | */ |
31 | for (i = 0; i < d->props.rc_key_map_size; i++) | 31 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) |
32 | if (keymap[i].event == KEY_RESERVED || | 32 | if (keymap[i].keycode == KEY_RESERVED || |
33 | keymap[i].event == KEY_UNKNOWN) { | 33 | keymap[i].keycode == KEY_UNKNOWN) { |
34 | *keycode = KEY_RESERVED; | 34 | *keycode = KEY_RESERVED; |
35 | return 0; | 35 | return 0; |
36 | } | 36 | } |
@@ -38,27 +38,27 @@ static int dvb_usb_getkeycode(struct input_dev *dev, | |||
38 | return -EINVAL; | 38 | return -EINVAL; |
39 | } | 39 | } |
40 | 40 | ||
41 | static int dvb_usb_setkeycode(struct input_dev *dev, | 41 | static int legacy_dvb_usb_setkeycode(struct input_dev *dev, |
42 | unsigned int scancode, unsigned int keycode) | 42 | unsigned int scancode, unsigned int keycode) |
43 | { | 43 | { |
44 | struct dvb_usb_device *d = input_get_drvdata(dev); | 44 | struct dvb_usb_device *d = input_get_drvdata(dev); |
45 | 45 | ||
46 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 46 | struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; |
47 | int i; | 47 | int i; |
48 | 48 | ||
49 | /* Search if it is replacing an existing keycode */ | 49 | /* Search if it is replacing an existing keycode */ |
50 | for (i = 0; i < d->props.rc_key_map_size; i++) | 50 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) |
51 | if (keymap[i].scan == scancode) { | 51 | if (keymap[i].scancode == scancode) { |
52 | keymap[i].event = keycode; | 52 | keymap[i].keycode = keycode; |
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | /* Search if is there a clean entry. If so, use it */ | 56 | /* Search if is there a clean entry. If so, use it */ |
57 | for (i = 0; i < d->props.rc_key_map_size; i++) | 57 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) |
58 | if (keymap[i].event == KEY_RESERVED || | 58 | if (keymap[i].keycode == KEY_RESERVED || |
59 | keymap[i].event == KEY_UNKNOWN) { | 59 | keymap[i].keycode == KEY_UNKNOWN) { |
60 | keymap[i].scan = scancode; | 60 | keymap[i].scancode = scancode; |
61 | keymap[i].event = keycode; | 61 | keymap[i].keycode = keycode; |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
@@ -78,7 +78,7 @@ static int dvb_usb_setkeycode(struct input_dev *dev, | |||
78 | * | 78 | * |
79 | * TODO: Fix the repeat rate of the input device. | 79 | * TODO: Fix the repeat rate of the input device. |
80 | */ | 80 | */ |
81 | static void dvb_usb_read_remote_control(struct work_struct *work) | 81 | static void legacy_dvb_usb_read_remote_control(struct work_struct *work) |
82 | { | 82 | { |
83 | struct dvb_usb_device *d = | 83 | struct dvb_usb_device *d = |
84 | container_of(work, struct dvb_usb_device, rc_query_work.work); | 84 | container_of(work, struct dvb_usb_device, rc_query_work.work); |
@@ -92,7 +92,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work) | |||
92 | if (dvb_usb_disable_rc_polling) | 92 | if (dvb_usb_disable_rc_polling) |
93 | return; | 93 | return; |
94 | 94 | ||
95 | if (d->props.rc_query(d,&event,&state)) { | 95 | if (d->props.rc.legacy.rc_query(d,&event,&state)) { |
96 | err("error while querying for an remote control event."); | 96 | err("error while querying for an remote control event."); |
97 | goto schedule; | 97 | goto schedule; |
98 | } | 98 | } |
@@ -151,18 +151,117 @@ static void dvb_usb_read_remote_control(struct work_struct *work) | |||
151 | */ | 151 | */ |
152 | 152 | ||
153 | schedule: | 153 | schedule: |
154 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); | 154 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval)); |
155 | } | ||
156 | |||
157 | static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d, | ||
158 | struct input_dev *input_dev) | ||
159 | { | ||
160 | int i, err, rc_interval; | ||
161 | |||
162 | input_dev->getkeycode = legacy_dvb_usb_getkeycode; | ||
163 | input_dev->setkeycode = legacy_dvb_usb_setkeycode; | ||
164 | |||
165 | /* set the bits for the keys */ | ||
166 | deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size); | ||
167 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) { | ||
168 | deb_rc("setting bit for event %d item %d\n", | ||
169 | d->props.rc.legacy.rc_key_map[i].keycode, i); | ||
170 | set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit); | ||
171 | } | ||
172 | |||
173 | /* setting these two values to non-zero, we have to manage key repeats */ | ||
174 | input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval; | ||
175 | input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150; | ||
176 | |||
177 | input_set_drvdata(input_dev, d); | ||
178 | |||
179 | err = input_register_device(input_dev); | ||
180 | if (err) | ||
181 | input_free_device(input_dev); | ||
182 | |||
183 | rc_interval = d->props.rc.legacy.rc_interval; | ||
184 | |||
185 | INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control); | ||
186 | |||
187 | info("schedule remote query interval to %d msecs.", rc_interval); | ||
188 | schedule_delayed_work(&d->rc_query_work, | ||
189 | msecs_to_jiffies(rc_interval)); | ||
190 | |||
191 | d->state |= DVB_USB_STATE_REMOTE; | ||
192 | |||
193 | return err; | ||
194 | } | ||
195 | |||
196 | /* Remote-control poll function - called every dib->rc_query_interval ms to see | ||
197 | * whether the remote control has received anything. | ||
198 | * | ||
199 | * TODO: Fix the repeat rate of the input device. | ||
200 | */ | ||
201 | static void dvb_usb_read_remote_control(struct work_struct *work) | ||
202 | { | ||
203 | struct dvb_usb_device *d = | ||
204 | container_of(work, struct dvb_usb_device, rc_query_work.work); | ||
205 | int err; | ||
206 | |||
207 | /* TODO: need a lock here. We can simply skip checking for the remote control | ||
208 | if we're busy. */ | ||
209 | |||
210 | /* when the parameter has been set to 1 via sysfs while the | ||
211 | * driver was running, or when bulk mode is enabled after IR init | ||
212 | */ | ||
213 | if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode) | ||
214 | return; | ||
215 | |||
216 | err = d->props.rc.core.rc_query(d); | ||
217 | if (err) | ||
218 | err("error %d while querying for an remote control event.", err); | ||
219 | |||
220 | schedule_delayed_work(&d->rc_query_work, | ||
221 | msecs_to_jiffies(d->props.rc.core.rc_interval)); | ||
222 | } | ||
223 | |||
224 | static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d, | ||
225 | struct input_dev *input_dev) | ||
226 | { | ||
227 | int err, rc_interval; | ||
228 | |||
229 | d->props.rc.core.rc_props.priv = d; | ||
230 | err = ir_input_register(input_dev, | ||
231 | d->props.rc.core.rc_codes, | ||
232 | &d->props.rc.core.rc_props, | ||
233 | d->props.rc.core.module_name); | ||
234 | if (err < 0) | ||
235 | return err; | ||
236 | |||
237 | if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode) | ||
238 | return 0; | ||
239 | |||
240 | /* Polling mode - initialize a work queue for handling it */ | ||
241 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); | ||
242 | |||
243 | rc_interval = d->props.rc.core.rc_interval; | ||
244 | |||
245 | info("schedule remote query interval to %d msecs.", rc_interval); | ||
246 | schedule_delayed_work(&d->rc_query_work, | ||
247 | msecs_to_jiffies(rc_interval)); | ||
248 | |||
249 | return 0; | ||
155 | } | 250 | } |
156 | 251 | ||
157 | int dvb_usb_remote_init(struct dvb_usb_device *d) | 252 | int dvb_usb_remote_init(struct dvb_usb_device *d) |
158 | { | 253 | { |
159 | struct input_dev *input_dev; | 254 | struct input_dev *input_dev; |
160 | int i; | ||
161 | int err; | 255 | int err; |
162 | 256 | ||
163 | if (d->props.rc_key_map == NULL || | 257 | if (dvb_usb_disable_rc_polling) |
164 | d->props.rc_query == NULL || | 258 | return 0; |
165 | dvb_usb_disable_rc_polling) | 259 | |
260 | if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query) | ||
261 | d->props.rc.mode = DVB_RC_LEGACY; | ||
262 | else if (d->props.rc.core.rc_codes) | ||
263 | d->props.rc.mode = DVB_RC_CORE; | ||
264 | else | ||
166 | return 0; | 265 | return 0; |
167 | 266 | ||
168 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); | 267 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); |
@@ -177,39 +276,19 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) | |||
177 | input_dev->phys = d->rc_phys; | 276 | input_dev->phys = d->rc_phys; |
178 | usb_to_input_id(d->udev, &input_dev->id); | 277 | usb_to_input_id(d->udev, &input_dev->id); |
179 | input_dev->dev.parent = &d->udev->dev; | 278 | input_dev->dev.parent = &d->udev->dev; |
180 | input_dev->getkeycode = dvb_usb_getkeycode; | ||
181 | input_dev->setkeycode = dvb_usb_setkeycode; | ||
182 | |||
183 | /* set the bits for the keys */ | ||
184 | deb_rc("key map size: %d\n", d->props.rc_key_map_size); | ||
185 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
186 | deb_rc("setting bit for event %d item %d\n", | ||
187 | d->props.rc_key_map[i].event, i); | ||
188 | set_bit(d->props.rc_key_map[i].event, input_dev->keybit); | ||
189 | } | ||
190 | 279 | ||
191 | /* Start the remote-control polling. */ | 280 | /* Start the remote-control polling. */ |
192 | if (d->props.rc_interval < 40) | 281 | if (d->props.rc.legacy.rc_interval < 40) |
193 | d->props.rc_interval = 100; /* default */ | 282 | d->props.rc.legacy.rc_interval = 100; /* default */ |
194 | |||
195 | /* setting these two values to non-zero, we have to manage key repeats */ | ||
196 | input_dev->rep[REP_PERIOD] = d->props.rc_interval; | ||
197 | input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; | ||
198 | |||
199 | input_set_drvdata(input_dev, d); | ||
200 | |||
201 | err = input_register_device(input_dev); | ||
202 | if (err) { | ||
203 | input_free_device(input_dev); | ||
204 | return err; | ||
205 | } | ||
206 | 283 | ||
207 | d->rc_input_dev = input_dev; | 284 | d->rc_input_dev = input_dev; |
208 | 285 | ||
209 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); | 286 | if (d->props.rc.mode == DVB_RC_LEGACY) |
210 | 287 | err = legacy_dvb_usb_remote_init(d, input_dev); | |
211 | info("schedule remote query interval to %d msecs.", d->props.rc_interval); | 288 | else |
212 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); | 289 | err = rc_core_dvb_usb_remote_init(d, input_dev); |
290 | if (err) | ||
291 | return err; | ||
213 | 292 | ||
214 | d->state |= DVB_USB_STATE_REMOTE; | 293 | d->state |= DVB_USB_STATE_REMOTE; |
215 | 294 | ||
@@ -221,7 +300,10 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d) | |||
221 | if (d->state & DVB_USB_STATE_REMOTE) { | 300 | if (d->state & DVB_USB_STATE_REMOTE) { |
222 | cancel_rearming_delayed_work(&d->rc_query_work); | 301 | cancel_rearming_delayed_work(&d->rc_query_work); |
223 | flush_scheduled_work(); | 302 | flush_scheduled_work(); |
224 | input_unregister_device(d->rc_input_dev); | 303 | if (d->props.rc.mode == DVB_RC_LEGACY) |
304 | input_unregister_device(d->rc_input_dev); | ||
305 | else | ||
306 | ir_input_unregister(d->rc_input_dev); | ||
225 | } | 307 | } |
226 | d->state &= ~DVB_USB_STATE_REMOTE; | 308 | d->state &= ~DVB_USB_STATE_REMOTE; |
227 | return 0; | 309 | return 0; |
@@ -234,7 +316,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, | |||
234 | u8 keybuf[5], u32 *event, int *state) | 316 | u8 keybuf[5], u32 *event, int *state) |
235 | { | 317 | { |
236 | int i; | 318 | int i; |
237 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 319 | struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map; |
238 | *event = 0; | 320 | *event = 0; |
239 | *state = REMOTE_NO_KEY_PRESSED; | 321 | *state = REMOTE_NO_KEY_PRESSED; |
240 | switch (keybuf[0]) { | 322 | switch (keybuf[0]) { |
@@ -247,10 +329,10 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, | |||
247 | break; | 329 | break; |
248 | } | 330 | } |
249 | /* See if we can match the raw key code. */ | 331 | /* See if we can match the raw key code. */ |
250 | for (i = 0; i < d->props.rc_key_map_size; i++) | 332 | for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) |
251 | if (rc5_custom(&keymap[i]) == keybuf[1] && | 333 | if (rc5_custom(&keymap[i]) == keybuf[1] && |
252 | rc5_data(&keymap[i]) == keybuf[3]) { | 334 | rc5_data(&keymap[i]) == keybuf[3]) { |
253 | *event = keymap[i].event; | 335 | *event = keymap[i].keycode; |
254 | *state = REMOTE_KEY_PRESSED; | 336 | *state = REMOTE_KEY_PRESSED; |
255 | return 0; | 337 | return 0; |
256 | } | 338 | } |