1/* dvb-usb-remote.c is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * This file contains functions for initializing the input-device and for handling remote-control-queries.
7 */
8#include "dvb-usb-common.h"
9#include <linux/usb/input.h>
10
11static unsigned int
12legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke,
13				struct rc_map_table *keymap,
14				unsigned int keymap_size)
15{
16	unsigned int index;
17	unsigned int scancode;
18
19	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
20		index = ke->index;
21	} else {
22		if (input_scancode_to_scalar(ke, &scancode))
23			return keymap_size;
24
25		/* See if we can match the raw key code. */
26		for (index = 0; index < keymap_size; index++)
27			if (keymap[index].scancode == scancode)
28				break;
29
30		/* See if there is an unused hole in the map */
31		if (index >= keymap_size) {
32			for (index = 0; index < keymap_size; index++) {
33				if (keymap[index].keycode == KEY_RESERVED ||
34				    keymap[index].keycode == KEY_UNKNOWN) {
35					break;
36				}
37			}
38		}
39	}
40
41	return index;
42}
43
44static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
45				     struct input_keymap_entry *ke)
46{
47	struct dvb_usb_device *d = input_get_drvdata(dev);
48	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
49	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
50	unsigned int index;
51
52	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
53	if (index >= keymap_size)
54		return -EINVAL;
55
56	ke->keycode = keymap[index].keycode;
57	if (ke->keycode == KEY_UNKNOWN)
58		ke->keycode = KEY_RESERVED;
59	ke->len = sizeof(keymap[index].scancode);
60	memcpy(&ke->scancode, &keymap[index].scancode, ke->len);
61	ke->index = index;
62
63	return 0;
64}
65
66static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
67				     const struct input_keymap_entry *ke,
68				     unsigned int *old_keycode)
69{
70	struct dvb_usb_device *d = input_get_drvdata(dev);
71	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
72	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
73	unsigned int index;
74
75	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
76	/*
77	 * FIXME: Currently, it is not possible to increase the size of
78	 * scancode table. For it to happen, one possibility
79	 * would be to allocate a table with key_map_size + 1,
80	 * copying data, appending the new key on it, and freeing
81	 * the old one - or maybe just allocating some spare space
82	 */
83	if (index >= keymap_size)
84		return -EINVAL;
85
86	*old_keycode = keymap[index].keycode;
87	keymap->keycode = ke->keycode;
88	__set_bit(ke->keycode, dev->keybit);
89
90	if (*old_keycode != KEY_RESERVED) {
91		__clear_bit(*old_keycode, dev->keybit);
92		for (index = 0; index < keymap_size; index++) {
93			if (keymap[index].keycode == *old_keycode) {
94				__set_bit(*old_keycode, dev->keybit);
95				break;
96			}
97		}
98	}
99
100	return 0;
101}
102
103/* Remote-control poll function - called every dib->rc_query_interval ms to see
104 * whether the remote control has received anything.
105 *
106 * TODO: Fix the repeat rate of the input device.
107 */
108static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
109{
110	struct dvb_usb_device *d =
111		container_of(work, struct dvb_usb_device, rc_query_work.work);
112	u32 event;
113	int state;
114
115	/* TODO: need a lock here.  We can simply skip checking for the remote control
116	   if we're busy. */
117
118	/* when the parameter has been set to 1 via sysfs while the driver was running */
119	if (dvb_usb_disable_rc_polling)
120		return;
121
122	if (d->props.rc.legacy.rc_query(d,&event,&state)) {
123		err("error while querying for an remote control event.");
124		goto schedule;
125	}
126
127
128	switch (state) {
129		case REMOTE_NO_KEY_PRESSED:
130			break;
131		case REMOTE_KEY_PRESSED:
132			deb_rc("key pressed\n");
133			d->last_event = event;
134		case REMOTE_KEY_REPEAT:
135			deb_rc("key repeated\n");
136			input_event(d->input_dev, EV_KEY, event, 1);
137			input_sync(d->input_dev);
138			input_event(d->input_dev, EV_KEY, d->last_event, 0);
139			input_sync(d->input_dev);
140			break;
141		default:
142			break;
143	}
144
145/* improved repeat handling ???
146	switch (state) {
147		case REMOTE_NO_KEY_PRESSED:
148			deb_rc("NO KEY PRESSED\n");
149			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
150				deb_rc("releasing event %d\n",d->last_event);
151				input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
152				input_sync(d->rc_input_dev);
153			}
154			d->last_state = REMOTE_NO_KEY_PRESSED;
155			d->last_event = 0;
156			break;
157		case REMOTE_KEY_PRESSED:
158			deb_rc("KEY PRESSED\n");
159			deb_rc("pressing event %d\n",event);
160
161			input_event(d->rc_input_dev, EV_KEY, event, 1);
162			input_sync(d->rc_input_dev);
163
164			d->last_event = event;
165			d->last_state = REMOTE_KEY_PRESSED;
166			break;
167		case REMOTE_KEY_REPEAT:
168			deb_rc("KEY_REPEAT\n");
169			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
170				deb_rc("repeating event %d\n",d->last_event);
171				input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
172				input_sync(d->rc_input_dev);
173				d->last_state = REMOTE_KEY_REPEAT;
174			}
175		default:
176			break;
177	}
178*/
179
180schedule:
181	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
182}
183
184static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d)
185{
186	int i, err, rc_interval;
187	struct input_dev *input_dev;
188
189	input_dev = input_allocate_device();
190	if (!input_dev)
191		return -ENOMEM;
192
193	input_dev->evbit[0] = BIT_MASK(EV_KEY);
194	input_dev->name = "IR-receiver inside an USB DVB receiver";
195	input_dev->phys = d->rc_phys;
196	usb_to_input_id(d->udev, &input_dev->id);
197	input_dev->dev.parent = &d->udev->dev;
198	d->input_dev = input_dev;
199	d->rc_dev = NULL;
200
201	input_dev->getkeycode = legacy_dvb_usb_getkeycode;
202	input_dev->setkeycode = legacy_dvb_usb_setkeycode;
203
204	/* set the bits for the keys */
205	deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size);
206	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
207		deb_rc("setting bit for event %d item %d\n",
208			d->props.rc.legacy.rc_map_table[i].keycode, i);
209		set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit);
210	}
211
212	/* setting these two values to non-zero, we have to manage key repeats */
213	input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
214	input_dev->rep[REP_DELAY]  = d->props.rc.legacy.rc_interval + 150;
215
216	input_set_drvdata(input_dev, d);
217
218	err = input_register_device(input_dev);
219	if (err)
220		input_free_device(input_dev);
221
222	rc_interval = d->props.rc.legacy.rc_interval;
223
224	INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
225
226	info("schedule remote query interval to %d msecs.", rc_interval);
227	schedule_delayed_work(&d->rc_query_work,
228			      msecs_to_jiffies(rc_interval));
229
230	d->state |= DVB_USB_STATE_REMOTE;
231
232	return err;
233}
234
235/* Remote-control poll function - called every dib->rc_query_interval ms to see
236 * whether the remote control has received anything.
237 *
238 * TODO: Fix the repeat rate of the input device.
239 */
240static void dvb_usb_read_remote_control(struct work_struct *work)
241{
242	struct dvb_usb_device *d =
243		container_of(work, struct dvb_usb_device, rc_query_work.work);
244	int err;
245
246	/* TODO: need a lock here.  We can simply skip checking for the remote control
247	   if we're busy. */
248
249	/* when the parameter has been set to 1 via sysfs while the
250	 * driver was running, or when bulk mode is enabled after IR init
251	 */
252	if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
253		return;
254
255	err = d->props.rc.core.rc_query(d);
256	if (err)
257		err("error %d while querying for an remote control event.", err);
258
259	schedule_delayed_work(&d->rc_query_work,
260			      msecs_to_jiffies(d->props.rc.core.rc_interval));
261}
262
263static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
264{
265	int err, rc_interval;
266	struct rc_dev *dev;
267
268	dev = rc_allocate_device();
269	if (!dev)
270		return -ENOMEM;
271
272	dev->driver_name = d->props.rc.core.module_name;
273	dev->map_name = d->props.rc.core.rc_codes;
274	dev->change_protocol = d->props.rc.core.change_protocol;
275	dev->allowed_protocols = d->props.rc.core.allowed_protos;
276	dev->driver_type = d->props.rc.core.driver_type;
277	usb_to_input_id(d->udev, &dev->input_id);
278	dev->input_name = "IR-receiver inside an USB DVB receiver";
279	dev->input_phys = d->rc_phys;
280	dev->dev.parent = &d->udev->dev;
281	dev->priv = d;
282
283	err = rc_register_device(dev);
284	if (err < 0) {
285		rc_free_device(dev);
286		return err;
287	}
288
289	d->input_dev = NULL;
290	d->rc_dev = dev;
291
292	if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
293		return 0;
294
295	/* Polling mode - initialize a work queue for handling it */
296	INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
297
298	rc_interval = d->props.rc.core.rc_interval;
299
300	info("schedule remote query interval to %d msecs.", rc_interval);
301	schedule_delayed_work(&d->rc_query_work,
302			      msecs_to_jiffies(rc_interval));
303
304	return 0;
305}
306
307int dvb_usb_remote_init(struct dvb_usb_device *d)
308{
309	int err;
310
311	if (dvb_usb_disable_rc_polling)
312		return 0;
313
314	if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query)
315		d->props.rc.mode = DVB_RC_LEGACY;
316	else if (d->props.rc.core.rc_codes)
317		d->props.rc.mode = DVB_RC_CORE;
318	else
319		return 0;
320
321	usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
322	strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
323
324	/* Start the remote-control polling. */
325	if (d->props.rc.legacy.rc_interval < 40)
326		d->props.rc.legacy.rc_interval = 100; /* default */
327
328	if (d->props.rc.mode == DVB_RC_LEGACY)
329		err = legacy_dvb_usb_remote_init(d);
330	else
331		err = rc_core_dvb_usb_remote_init(d);
332	if (err)
333		return err;
334
335	d->state |= DVB_USB_STATE_REMOTE;
336
337	return 0;
338}
339
340int dvb_usb_remote_exit(struct dvb_usb_device *d)
341{
342	if (d->state & DVB_USB_STATE_REMOTE) {
343		cancel_delayed_work_sync(&d->rc_query_work);
344		if (d->props.rc.mode == DVB_RC_LEGACY)
345			input_unregister_device(d->input_dev);
346		else
347			rc_unregister_device(d->rc_dev);
348	}
349	d->state &= ~DVB_USB_STATE_REMOTE;
350	return 0;
351}
352
353#define DVB_USB_RC_NEC_EMPTY           0x00
354#define DVB_USB_RC_NEC_KEY_PRESSED     0x01
355#define DVB_USB_RC_NEC_KEY_REPEATED    0x02
356int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
357		u8 keybuf[5], u32 *event, int *state)
358{
359	int i;
360	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
361	*event = 0;
362	*state = REMOTE_NO_KEY_PRESSED;
363	switch (keybuf[0]) {
364		case DVB_USB_RC_NEC_EMPTY:
365			break;
366		case DVB_USB_RC_NEC_KEY_PRESSED:
367			if ((u8) ~keybuf[1] != keybuf[2] ||
368				(u8) ~keybuf[3] != keybuf[4]) {
369				deb_err("remote control checksum failed.\n");
370				break;
371			}
372			/* See if we can match the raw key code. */
373			for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
374				if (rc5_custom(&keymap[i]) == keybuf[1] &&
375					rc5_data(&keymap[i]) == keybuf[3]) {
376					*event = keymap[i].keycode;
377					*state = REMOTE_KEY_PRESSED;
378					return 0;
379				}
380			deb_err("key mapping failed - no appropriate key found in keymapping\n");
381			break;
382		case DVB_USB_RC_NEC_KEY_REPEATED:
383			*state = REMOTE_KEY_REPEAT;
384			break;
385		default:
386			deb_err("unknown type of remote status: %d\n",keybuf[0]);
387			break;
388	}
389	return 0;
390}
391EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
392