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