1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2786baecfSMauro Carvalho Chehab /* dvb-usb-remote.c is part of the DVB USB library.
3786baecfSMauro Carvalho Chehab *
499e44da7SPatrick Boettcher * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
5786baecfSMauro Carvalho Chehab * see dvb-usb-init.c for copyright information.
6786baecfSMauro Carvalho Chehab *
7786baecfSMauro Carvalho Chehab * This file contains functions for initializing the input-device and for handling remote-control-queries.
8786baecfSMauro Carvalho Chehab */
9786baecfSMauro Carvalho Chehab #include "dvb-usb-common.h"
10786baecfSMauro Carvalho Chehab #include <linux/usb/input.h>
11786baecfSMauro Carvalho Chehab
12786baecfSMauro Carvalho Chehab static unsigned int
legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry * ke,struct rc_map_table * keymap,unsigned int keymap_size)13786baecfSMauro Carvalho Chehab legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke,
14786baecfSMauro Carvalho Chehab struct rc_map_table *keymap,
15786baecfSMauro Carvalho Chehab unsigned int keymap_size)
16786baecfSMauro Carvalho Chehab {
17786baecfSMauro Carvalho Chehab unsigned int index;
18786baecfSMauro Carvalho Chehab unsigned int scancode;
19786baecfSMauro Carvalho Chehab
20786baecfSMauro Carvalho Chehab if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
21786baecfSMauro Carvalho Chehab index = ke->index;
22786baecfSMauro Carvalho Chehab } else {
23786baecfSMauro Carvalho Chehab if (input_scancode_to_scalar(ke, &scancode))
24786baecfSMauro Carvalho Chehab return keymap_size;
25786baecfSMauro Carvalho Chehab
26786baecfSMauro Carvalho Chehab /* See if we can match the raw key code. */
27786baecfSMauro Carvalho Chehab for (index = 0; index < keymap_size; index++)
28786baecfSMauro Carvalho Chehab if (keymap[index].scancode == scancode)
29786baecfSMauro Carvalho Chehab break;
30786baecfSMauro Carvalho Chehab
31786baecfSMauro Carvalho Chehab /* See if there is an unused hole in the map */
32786baecfSMauro Carvalho Chehab if (index >= keymap_size) {
33786baecfSMauro Carvalho Chehab for (index = 0; index < keymap_size; index++) {
34786baecfSMauro Carvalho Chehab if (keymap[index].keycode == KEY_RESERVED ||
35786baecfSMauro Carvalho Chehab keymap[index].keycode == KEY_UNKNOWN) {
36786baecfSMauro Carvalho Chehab break;
37786baecfSMauro Carvalho Chehab }
38786baecfSMauro Carvalho Chehab }
39786baecfSMauro Carvalho Chehab }
40786baecfSMauro Carvalho Chehab }
41786baecfSMauro Carvalho Chehab
42786baecfSMauro Carvalho Chehab return index;
43786baecfSMauro Carvalho Chehab }
44786baecfSMauro Carvalho Chehab
legacy_dvb_usb_getkeycode(struct input_dev * dev,struct input_keymap_entry * ke)45786baecfSMauro Carvalho Chehab static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
46786baecfSMauro Carvalho Chehab struct input_keymap_entry *ke)
47786baecfSMauro Carvalho Chehab {
48786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = input_get_drvdata(dev);
49786baecfSMauro Carvalho Chehab struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
50786baecfSMauro Carvalho Chehab unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
51786baecfSMauro Carvalho Chehab unsigned int index;
52786baecfSMauro Carvalho Chehab
53786baecfSMauro Carvalho Chehab index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
54786baecfSMauro Carvalho Chehab if (index >= keymap_size)
55786baecfSMauro Carvalho Chehab return -EINVAL;
56786baecfSMauro Carvalho Chehab
57786baecfSMauro Carvalho Chehab ke->keycode = keymap[index].keycode;
58786baecfSMauro Carvalho Chehab if (ke->keycode == KEY_UNKNOWN)
59786baecfSMauro Carvalho Chehab ke->keycode = KEY_RESERVED;
60786baecfSMauro Carvalho Chehab ke->len = sizeof(keymap[index].scancode);
61786baecfSMauro Carvalho Chehab memcpy(&ke->scancode, &keymap[index].scancode, ke->len);
62786baecfSMauro Carvalho Chehab ke->index = index;
63786baecfSMauro Carvalho Chehab
64786baecfSMauro Carvalho Chehab return 0;
65786baecfSMauro Carvalho Chehab }
66786baecfSMauro Carvalho Chehab
legacy_dvb_usb_setkeycode(struct input_dev * dev,const struct input_keymap_entry * ke,unsigned int * old_keycode)67786baecfSMauro Carvalho Chehab static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
68786baecfSMauro Carvalho Chehab const struct input_keymap_entry *ke,
69786baecfSMauro Carvalho Chehab unsigned int *old_keycode)
70786baecfSMauro Carvalho Chehab {
71786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = input_get_drvdata(dev);
72786baecfSMauro Carvalho Chehab struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
73786baecfSMauro Carvalho Chehab unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
74786baecfSMauro Carvalho Chehab unsigned int index;
75786baecfSMauro Carvalho Chehab
76786baecfSMauro Carvalho Chehab index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
77786baecfSMauro Carvalho Chehab /*
78786baecfSMauro Carvalho Chehab * FIXME: Currently, it is not possible to increase the size of
79786baecfSMauro Carvalho Chehab * scancode table. For it to happen, one possibility
80786baecfSMauro Carvalho Chehab * would be to allocate a table with key_map_size + 1,
81786baecfSMauro Carvalho Chehab * copying data, appending the new key on it, and freeing
82786baecfSMauro Carvalho Chehab * the old one - or maybe just allocating some spare space
83786baecfSMauro Carvalho Chehab */
84786baecfSMauro Carvalho Chehab if (index >= keymap_size)
85786baecfSMauro Carvalho Chehab return -EINVAL;
86786baecfSMauro Carvalho Chehab
87786baecfSMauro Carvalho Chehab *old_keycode = keymap[index].keycode;
88786baecfSMauro Carvalho Chehab keymap->keycode = ke->keycode;
89786baecfSMauro Carvalho Chehab __set_bit(ke->keycode, dev->keybit);
90786baecfSMauro Carvalho Chehab
91786baecfSMauro Carvalho Chehab if (*old_keycode != KEY_RESERVED) {
92786baecfSMauro Carvalho Chehab __clear_bit(*old_keycode, dev->keybit);
93786baecfSMauro Carvalho Chehab for (index = 0; index < keymap_size; index++) {
94786baecfSMauro Carvalho Chehab if (keymap[index].keycode == *old_keycode) {
95786baecfSMauro Carvalho Chehab __set_bit(*old_keycode, dev->keybit);
96786baecfSMauro Carvalho Chehab break;
97786baecfSMauro Carvalho Chehab }
98786baecfSMauro Carvalho Chehab }
99786baecfSMauro Carvalho Chehab }
100786baecfSMauro Carvalho Chehab
101786baecfSMauro Carvalho Chehab return 0;
102786baecfSMauro Carvalho Chehab }
103786baecfSMauro Carvalho Chehab
104786baecfSMauro Carvalho Chehab /* Remote-control poll function - called every dib->rc_query_interval ms to see
105786baecfSMauro Carvalho Chehab * whether the remote control has received anything.
106786baecfSMauro Carvalho Chehab *
107786baecfSMauro Carvalho Chehab * TODO: Fix the repeat rate of the input device.
108786baecfSMauro Carvalho Chehab */
legacy_dvb_usb_read_remote_control(struct work_struct * work)109786baecfSMauro Carvalho Chehab static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
110786baecfSMauro Carvalho Chehab {
111786baecfSMauro Carvalho Chehab struct dvb_usb_device *d =
112786baecfSMauro Carvalho Chehab container_of(work, struct dvb_usb_device, rc_query_work.work);
113786baecfSMauro Carvalho Chehab u32 event;
114786baecfSMauro Carvalho Chehab int state;
115786baecfSMauro Carvalho Chehab
116786baecfSMauro Carvalho Chehab /* TODO: need a lock here. We can simply skip checking for the remote control
117786baecfSMauro Carvalho Chehab if we're busy. */
118786baecfSMauro Carvalho Chehab
119786baecfSMauro Carvalho Chehab /* when the parameter has been set to 1 via sysfs while the driver was running */
120786baecfSMauro Carvalho Chehab if (dvb_usb_disable_rc_polling)
121786baecfSMauro Carvalho Chehab return;
122786baecfSMauro Carvalho Chehab
123786baecfSMauro Carvalho Chehab if (d->props.rc.legacy.rc_query(d,&event,&state)) {
124786baecfSMauro Carvalho Chehab err("error while querying for an remote control event.");
125786baecfSMauro Carvalho Chehab goto schedule;
126786baecfSMauro Carvalho Chehab }
127786baecfSMauro Carvalho Chehab
128786baecfSMauro Carvalho Chehab
129786baecfSMauro Carvalho Chehab switch (state) {
130786baecfSMauro Carvalho Chehab case REMOTE_NO_KEY_PRESSED:
131786baecfSMauro Carvalho Chehab break;
132786baecfSMauro Carvalho Chehab case REMOTE_KEY_PRESSED:
133786baecfSMauro Carvalho Chehab deb_rc("key pressed\n");
134786baecfSMauro Carvalho Chehab d->last_event = event;
13539c4806eSMauro Carvalho Chehab input_event(d->input_dev, EV_KEY, event, 1);
13639c4806eSMauro Carvalho Chehab input_sync(d->input_dev);
13739c4806eSMauro Carvalho Chehab input_event(d->input_dev, EV_KEY, d->last_event, 0);
13839c4806eSMauro Carvalho Chehab input_sync(d->input_dev);
13939c4806eSMauro Carvalho Chehab break;
140786baecfSMauro Carvalho Chehab case REMOTE_KEY_REPEAT:
141786baecfSMauro Carvalho Chehab deb_rc("key repeated\n");
142786baecfSMauro Carvalho Chehab input_event(d->input_dev, EV_KEY, event, 1);
143786baecfSMauro Carvalho Chehab input_sync(d->input_dev);
144786baecfSMauro Carvalho Chehab input_event(d->input_dev, EV_KEY, d->last_event, 0);
145786baecfSMauro Carvalho Chehab input_sync(d->input_dev);
146786baecfSMauro Carvalho Chehab break;
147786baecfSMauro Carvalho Chehab default:
148786baecfSMauro Carvalho Chehab break;
149786baecfSMauro Carvalho Chehab }
150786baecfSMauro Carvalho Chehab
151786baecfSMauro Carvalho Chehab /* improved repeat handling ???
152786baecfSMauro Carvalho Chehab switch (state) {
153786baecfSMauro Carvalho Chehab case REMOTE_NO_KEY_PRESSED:
154786baecfSMauro Carvalho Chehab deb_rc("NO KEY PRESSED\n");
155786baecfSMauro Carvalho Chehab if (d->last_state != REMOTE_NO_KEY_PRESSED) {
156786baecfSMauro Carvalho Chehab deb_rc("releasing event %d\n",d->last_event);
157786baecfSMauro Carvalho Chehab input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
158786baecfSMauro Carvalho Chehab input_sync(d->rc_input_dev);
159786baecfSMauro Carvalho Chehab }
160786baecfSMauro Carvalho Chehab d->last_state = REMOTE_NO_KEY_PRESSED;
161786baecfSMauro Carvalho Chehab d->last_event = 0;
162786baecfSMauro Carvalho Chehab break;
163786baecfSMauro Carvalho Chehab case REMOTE_KEY_PRESSED:
164786baecfSMauro Carvalho Chehab deb_rc("KEY PRESSED\n");
165786baecfSMauro Carvalho Chehab deb_rc("pressing event %d\n",event);
166786baecfSMauro Carvalho Chehab
167786baecfSMauro Carvalho Chehab input_event(d->rc_input_dev, EV_KEY, event, 1);
168786baecfSMauro Carvalho Chehab input_sync(d->rc_input_dev);
169786baecfSMauro Carvalho Chehab
170786baecfSMauro Carvalho Chehab d->last_event = event;
171786baecfSMauro Carvalho Chehab d->last_state = REMOTE_KEY_PRESSED;
172786baecfSMauro Carvalho Chehab break;
173786baecfSMauro Carvalho Chehab case REMOTE_KEY_REPEAT:
174786baecfSMauro Carvalho Chehab deb_rc("KEY_REPEAT\n");
175786baecfSMauro Carvalho Chehab if (d->last_state != REMOTE_NO_KEY_PRESSED) {
176786baecfSMauro Carvalho Chehab deb_rc("repeating event %d\n",d->last_event);
177786baecfSMauro Carvalho Chehab input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
178786baecfSMauro Carvalho Chehab input_sync(d->rc_input_dev);
179786baecfSMauro Carvalho Chehab d->last_state = REMOTE_KEY_REPEAT;
180786baecfSMauro Carvalho Chehab }
181786baecfSMauro Carvalho Chehab default:
182786baecfSMauro Carvalho Chehab break;
183786baecfSMauro Carvalho Chehab }
184786baecfSMauro Carvalho Chehab */
185786baecfSMauro Carvalho Chehab
186786baecfSMauro Carvalho Chehab schedule:
187786baecfSMauro Carvalho Chehab schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
188786baecfSMauro Carvalho Chehab }
189786baecfSMauro Carvalho Chehab
legacy_dvb_usb_remote_init(struct dvb_usb_device * d)190786baecfSMauro Carvalho Chehab static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d)
191786baecfSMauro Carvalho Chehab {
192786baecfSMauro Carvalho Chehab int i, err, rc_interval;
193786baecfSMauro Carvalho Chehab struct input_dev *input_dev;
194786baecfSMauro Carvalho Chehab
195786baecfSMauro Carvalho Chehab input_dev = input_allocate_device();
196786baecfSMauro Carvalho Chehab if (!input_dev)
197786baecfSMauro Carvalho Chehab return -ENOMEM;
198786baecfSMauro Carvalho Chehab
199786baecfSMauro Carvalho Chehab input_dev->evbit[0] = BIT_MASK(EV_KEY);
200786baecfSMauro Carvalho Chehab input_dev->name = "IR-receiver inside an USB DVB receiver";
201786baecfSMauro Carvalho Chehab input_dev->phys = d->rc_phys;
202786baecfSMauro Carvalho Chehab usb_to_input_id(d->udev, &input_dev->id);
203786baecfSMauro Carvalho Chehab input_dev->dev.parent = &d->udev->dev;
204786baecfSMauro Carvalho Chehab d->input_dev = input_dev;
205786baecfSMauro Carvalho Chehab d->rc_dev = NULL;
206786baecfSMauro Carvalho Chehab
207786baecfSMauro Carvalho Chehab input_dev->getkeycode = legacy_dvb_usb_getkeycode;
208786baecfSMauro Carvalho Chehab input_dev->setkeycode = legacy_dvb_usb_setkeycode;
209786baecfSMauro Carvalho Chehab
210786baecfSMauro Carvalho Chehab /* set the bits for the keys */
211786baecfSMauro Carvalho Chehab deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size);
212786baecfSMauro Carvalho Chehab for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
213786baecfSMauro Carvalho Chehab deb_rc("setting bit for event %d item %d\n",
214786baecfSMauro Carvalho Chehab d->props.rc.legacy.rc_map_table[i].keycode, i);
215786baecfSMauro Carvalho Chehab set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit);
216786baecfSMauro Carvalho Chehab }
217786baecfSMauro Carvalho Chehab
218786baecfSMauro Carvalho Chehab /* setting these two values to non-zero, we have to manage key repeats */
219786baecfSMauro Carvalho Chehab input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
220786baecfSMauro Carvalho Chehab input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150;
221786baecfSMauro Carvalho Chehab
222786baecfSMauro Carvalho Chehab input_set_drvdata(input_dev, d);
223786baecfSMauro Carvalho Chehab
224786baecfSMauro Carvalho Chehab err = input_register_device(input_dev);
225786baecfSMauro Carvalho Chehab if (err)
226786baecfSMauro Carvalho Chehab input_free_device(input_dev);
227786baecfSMauro Carvalho Chehab
228786baecfSMauro Carvalho Chehab rc_interval = d->props.rc.legacy.rc_interval;
229786baecfSMauro Carvalho Chehab
230786baecfSMauro Carvalho Chehab INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
231786baecfSMauro Carvalho Chehab
232786baecfSMauro Carvalho Chehab info("schedule remote query interval to %d msecs.", rc_interval);
233786baecfSMauro Carvalho Chehab schedule_delayed_work(&d->rc_query_work,
234786baecfSMauro Carvalho Chehab msecs_to_jiffies(rc_interval));
235786baecfSMauro Carvalho Chehab
236786baecfSMauro Carvalho Chehab d->state |= DVB_USB_STATE_REMOTE;
237786baecfSMauro Carvalho Chehab
238786baecfSMauro Carvalho Chehab return err;
239786baecfSMauro Carvalho Chehab }
240786baecfSMauro Carvalho Chehab
241786baecfSMauro Carvalho Chehab /* Remote-control poll function - called every dib->rc_query_interval ms to see
242786baecfSMauro Carvalho Chehab * whether the remote control has received anything.
243786baecfSMauro Carvalho Chehab *
244786baecfSMauro Carvalho Chehab * TODO: Fix the repeat rate of the input device.
245786baecfSMauro Carvalho Chehab */
dvb_usb_read_remote_control(struct work_struct * work)246786baecfSMauro Carvalho Chehab static void dvb_usb_read_remote_control(struct work_struct *work)
247786baecfSMauro Carvalho Chehab {
248786baecfSMauro Carvalho Chehab struct dvb_usb_device *d =
249786baecfSMauro Carvalho Chehab container_of(work, struct dvb_usb_device, rc_query_work.work);
250786baecfSMauro Carvalho Chehab int err;
251786baecfSMauro Carvalho Chehab
252786baecfSMauro Carvalho Chehab /* TODO: need a lock here. We can simply skip checking for the remote control
253786baecfSMauro Carvalho Chehab if we're busy. */
254786baecfSMauro Carvalho Chehab
255786baecfSMauro Carvalho Chehab /* when the parameter has been set to 1 via sysfs while the
256786baecfSMauro Carvalho Chehab * driver was running, or when bulk mode is enabled after IR init
257786baecfSMauro Carvalho Chehab */
258786baecfSMauro Carvalho Chehab if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
259786baecfSMauro Carvalho Chehab return;
260786baecfSMauro Carvalho Chehab
261786baecfSMauro Carvalho Chehab err = d->props.rc.core.rc_query(d);
262786baecfSMauro Carvalho Chehab if (err)
263786baecfSMauro Carvalho Chehab err("error %d while querying for an remote control event.", err);
264786baecfSMauro Carvalho Chehab
265786baecfSMauro Carvalho Chehab schedule_delayed_work(&d->rc_query_work,
266786baecfSMauro Carvalho Chehab msecs_to_jiffies(d->props.rc.core.rc_interval));
267786baecfSMauro Carvalho Chehab }
268786baecfSMauro Carvalho Chehab
rc_core_dvb_usb_remote_init(struct dvb_usb_device * d)269786baecfSMauro Carvalho Chehab static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
270786baecfSMauro Carvalho Chehab {
271786baecfSMauro Carvalho Chehab int err, rc_interval;
272786baecfSMauro Carvalho Chehab struct rc_dev *dev;
273786baecfSMauro Carvalho Chehab
2740f7499fdSAndi Shyti dev = rc_allocate_device(d->props.rc.core.driver_type);
275786baecfSMauro Carvalho Chehab if (!dev)
276786baecfSMauro Carvalho Chehab return -ENOMEM;
277786baecfSMauro Carvalho Chehab
278786baecfSMauro Carvalho Chehab dev->driver_name = d->props.rc.core.module_name;
279786baecfSMauro Carvalho Chehab dev->map_name = d->props.rc.core.rc_codes;
280786baecfSMauro Carvalho Chehab dev->change_protocol = d->props.rc.core.change_protocol;
281c5540fbbSDavid Härdeman dev->allowed_protocols = d->props.rc.core.allowed_protos;
282786baecfSMauro Carvalho Chehab usb_to_input_id(d->udev, &dev->input_id);
2833c03726aSSean Young dev->device_name = d->desc->name;
284786baecfSMauro Carvalho Chehab dev->input_phys = d->rc_phys;
285786baecfSMauro Carvalho Chehab dev->dev.parent = &d->udev->dev;
286786baecfSMauro Carvalho Chehab dev->priv = d;
287771f8726SSean Young dev->scancode_mask = d->props.rc.core.scancode_mask;
288786baecfSMauro Carvalho Chehab
289786baecfSMauro Carvalho Chehab err = rc_register_device(dev);
290786baecfSMauro Carvalho Chehab if (err < 0) {
291786baecfSMauro Carvalho Chehab rc_free_device(dev);
292786baecfSMauro Carvalho Chehab return err;
293786baecfSMauro Carvalho Chehab }
294786baecfSMauro Carvalho Chehab
295786baecfSMauro Carvalho Chehab d->input_dev = NULL;
296786baecfSMauro Carvalho Chehab d->rc_dev = dev;
297786baecfSMauro Carvalho Chehab
298786baecfSMauro Carvalho Chehab if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
299786baecfSMauro Carvalho Chehab return 0;
300786baecfSMauro Carvalho Chehab
301786baecfSMauro Carvalho Chehab /* Polling mode - initialize a work queue for handling it */
302786baecfSMauro Carvalho Chehab INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
303786baecfSMauro Carvalho Chehab
304786baecfSMauro Carvalho Chehab rc_interval = d->props.rc.core.rc_interval;
305786baecfSMauro Carvalho Chehab
306786baecfSMauro Carvalho Chehab info("schedule remote query interval to %d msecs.", rc_interval);
307786baecfSMauro Carvalho Chehab schedule_delayed_work(&d->rc_query_work,
308786baecfSMauro Carvalho Chehab msecs_to_jiffies(rc_interval));
309786baecfSMauro Carvalho Chehab
310786baecfSMauro Carvalho Chehab return 0;
311786baecfSMauro Carvalho Chehab }
312786baecfSMauro Carvalho Chehab
dvb_usb_remote_init(struct dvb_usb_device * d)313786baecfSMauro Carvalho Chehab int dvb_usb_remote_init(struct dvb_usb_device *d)
314786baecfSMauro Carvalho Chehab {
315786baecfSMauro Carvalho Chehab int err;
316786baecfSMauro Carvalho Chehab
317786baecfSMauro Carvalho Chehab if (dvb_usb_disable_rc_polling)
318786baecfSMauro Carvalho Chehab return 0;
319786baecfSMauro Carvalho Chehab
320786baecfSMauro Carvalho Chehab if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query)
321786baecfSMauro Carvalho Chehab d->props.rc.mode = DVB_RC_LEGACY;
322786baecfSMauro Carvalho Chehab else if (d->props.rc.core.rc_codes)
323786baecfSMauro Carvalho Chehab d->props.rc.mode = DVB_RC_CORE;
324786baecfSMauro Carvalho Chehab else
325786baecfSMauro Carvalho Chehab return 0;
326786baecfSMauro Carvalho Chehab
327786baecfSMauro Carvalho Chehab usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
328786baecfSMauro Carvalho Chehab strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
329786baecfSMauro Carvalho Chehab
330786baecfSMauro Carvalho Chehab /* Start the remote-control polling. */
331786baecfSMauro Carvalho Chehab if (d->props.rc.legacy.rc_interval < 40)
332786baecfSMauro Carvalho Chehab d->props.rc.legacy.rc_interval = 100; /* default */
333786baecfSMauro Carvalho Chehab
334786baecfSMauro Carvalho Chehab if (d->props.rc.mode == DVB_RC_LEGACY)
335786baecfSMauro Carvalho Chehab err = legacy_dvb_usb_remote_init(d);
336786baecfSMauro Carvalho Chehab else
337786baecfSMauro Carvalho Chehab err = rc_core_dvb_usb_remote_init(d);
338786baecfSMauro Carvalho Chehab if (err)
339786baecfSMauro Carvalho Chehab return err;
340786baecfSMauro Carvalho Chehab
341786baecfSMauro Carvalho Chehab d->state |= DVB_USB_STATE_REMOTE;
342786baecfSMauro Carvalho Chehab
343786baecfSMauro Carvalho Chehab return 0;
344786baecfSMauro Carvalho Chehab }
345786baecfSMauro Carvalho Chehab
dvb_usb_remote_exit(struct dvb_usb_device * d)346786baecfSMauro Carvalho Chehab int dvb_usb_remote_exit(struct dvb_usb_device *d)
347786baecfSMauro Carvalho Chehab {
348786baecfSMauro Carvalho Chehab if (d->state & DVB_USB_STATE_REMOTE) {
349786baecfSMauro Carvalho Chehab cancel_delayed_work_sync(&d->rc_query_work);
350786baecfSMauro Carvalho Chehab if (d->props.rc.mode == DVB_RC_LEGACY)
351786baecfSMauro Carvalho Chehab input_unregister_device(d->input_dev);
352786baecfSMauro Carvalho Chehab else
353786baecfSMauro Carvalho Chehab rc_unregister_device(d->rc_dev);
354786baecfSMauro Carvalho Chehab }
355786baecfSMauro Carvalho Chehab d->state &= ~DVB_USB_STATE_REMOTE;
356786baecfSMauro Carvalho Chehab return 0;
357786baecfSMauro Carvalho Chehab }
358786baecfSMauro Carvalho Chehab
359786baecfSMauro Carvalho Chehab #define DVB_USB_RC_NEC_EMPTY 0x00
360786baecfSMauro Carvalho Chehab #define DVB_USB_RC_NEC_KEY_PRESSED 0x01
361786baecfSMauro Carvalho Chehab #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)362786baecfSMauro Carvalho Chehab int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
363786baecfSMauro Carvalho Chehab u8 keybuf[5], u32 *event, int *state)
364786baecfSMauro Carvalho Chehab {
365786baecfSMauro Carvalho Chehab int i;
366786baecfSMauro Carvalho Chehab struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
367786baecfSMauro Carvalho Chehab *event = 0;
368786baecfSMauro Carvalho Chehab *state = REMOTE_NO_KEY_PRESSED;
369786baecfSMauro Carvalho Chehab switch (keybuf[0]) {
370786baecfSMauro Carvalho Chehab case DVB_USB_RC_NEC_EMPTY:
371786baecfSMauro Carvalho Chehab break;
372786baecfSMauro Carvalho Chehab case DVB_USB_RC_NEC_KEY_PRESSED:
373786baecfSMauro Carvalho Chehab if ((u8) ~keybuf[1] != keybuf[2] ||
374786baecfSMauro Carvalho Chehab (u8) ~keybuf[3] != keybuf[4]) {
375786baecfSMauro Carvalho Chehab deb_err("remote control checksum failed.\n");
376786baecfSMauro Carvalho Chehab break;
377786baecfSMauro Carvalho Chehab }
378786baecfSMauro Carvalho Chehab /* See if we can match the raw key code. */
379786baecfSMauro Carvalho Chehab for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
380786baecfSMauro Carvalho Chehab if (rc5_custom(&keymap[i]) == keybuf[1] &&
381786baecfSMauro Carvalho Chehab rc5_data(&keymap[i]) == keybuf[3]) {
382786baecfSMauro Carvalho Chehab *event = keymap[i].keycode;
383786baecfSMauro Carvalho Chehab *state = REMOTE_KEY_PRESSED;
384786baecfSMauro Carvalho Chehab return 0;
385786baecfSMauro Carvalho Chehab }
386786baecfSMauro Carvalho Chehab deb_err("key mapping failed - no appropriate key found in keymapping\n");
387786baecfSMauro Carvalho Chehab break;
388786baecfSMauro Carvalho Chehab case DVB_USB_RC_NEC_KEY_REPEATED:
389786baecfSMauro Carvalho Chehab *state = REMOTE_KEY_REPEAT;
390786baecfSMauro Carvalho Chehab break;
391786baecfSMauro Carvalho Chehab default:
392786baecfSMauro Carvalho Chehab deb_err("unknown type of remote status: %d\n",keybuf[0]);
393786baecfSMauro Carvalho Chehab break;
394786baecfSMauro Carvalho Chehab }
395786baecfSMauro Carvalho Chehab return 0;
396786baecfSMauro Carvalho Chehab }
397786baecfSMauro Carvalho Chehab EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
398