]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/media/dvb/dvb-usb/dvb-usb-remote.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6.git] / drivers / media / dvb / dvb-usb / dvb-usb-remote.c
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
11 static int dvb_usb_getkeycode(struct input_dev *dev,
12                                 unsigned int scancode, unsigned int *keycode)
13 {
14         struct dvb_usb_device *d = input_get_drvdata(dev);
15
16         struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
17         int i;
18
19         /* See if we can match the raw key code. */
20         for (i = 0; i < d->props.rc_key_map_size; i++)
21                 if (keymap[i].scan == scancode) {
22                         *keycode = keymap[i].event;
23                         return 0;
24                 }
25
26         /*
27          * If is there extra space, returns KEY_RESERVED,
28          * otherwise, input core won't let dvb_usb_setkeycode
29          * to work
30          */
31         for (i = 0; i < d->props.rc_key_map_size; i++)
32                 if (keymap[i].event == KEY_RESERVED ||
33                     keymap[i].event == KEY_UNKNOWN) {
34                         *keycode = KEY_RESERVED;
35                         return 0;
36                 }
37
38         return -EINVAL;
39 }
40
41 static int dvb_usb_setkeycode(struct input_dev *dev,
42                                 unsigned int scancode, unsigned int keycode)
43 {
44         struct dvb_usb_device *d = input_get_drvdata(dev);
45
46         struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
47         int i;
48
49         /* Search if it is replacing an existing keycode */
50         for (i = 0; i < d->props.rc_key_map_size; i++)
51                 if (keymap[i].scan == scancode) {
52                         keymap[i].event = keycode;
53                         return 0;
54                 }
55
56         /* Search if is there a clean entry. If so, use it */
57         for (i = 0; i < d->props.rc_key_map_size; i++)
58                 if (keymap[i].event == KEY_RESERVED ||
59                     keymap[i].event == KEY_UNKNOWN) {
60                         keymap[i].scan = scancode;
61                         keymap[i].event = keycode;
62                         return 0;
63                 }
64
65         /*
66          * FIXME: Currently, it is not possible to increase the size of
67          * scancode table. For it to happen, one possibility
68          * would be to allocate a table with key_map_size + 1,
69          * copying data, appending the new key on it, and freeing
70          * the old one - or maybe just allocating some spare space
71          */
72
73         return -EINVAL;
74 }
75
76 /* Remote-control poll function - called every dib->rc_query_interval ms to see
77  * whether the remote control has received anything.
78  *
79  * TODO: Fix the repeat rate of the input device.
80  */
81 static void dvb_usb_read_remote_control(struct work_struct *work)
82 {
83         struct dvb_usb_device *d =
84                 container_of(work, struct dvb_usb_device, rc_query_work.work);
85         u32 event;
86         int state;
87
88         /* TODO: need a lock here.  We can simply skip checking for the remote control
89            if we're busy. */
90
91         /* when the parameter has been set to 1 via sysfs while the driver was running */
92         if (dvb_usb_disable_rc_polling)
93                 return;
94
95         if (d->props.rc_query(d,&event,&state)) {
96                 err("error while querying for an remote control event.");
97                 goto schedule;
98         }
99
100
101         switch (state) {
102                 case REMOTE_NO_KEY_PRESSED:
103                         break;
104                 case REMOTE_KEY_PRESSED:
105                         deb_rc("key pressed\n");
106                         d->last_event = event;
107                 case REMOTE_KEY_REPEAT:
108                         deb_rc("key repeated\n");
109                         input_event(d->rc_input_dev, EV_KEY, event, 1);
110                         input_sync(d->rc_input_dev);
111                         input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
112                         input_sync(d->rc_input_dev);
113                         break;
114                 default:
115                         break;
116         }
117
118 /* improved repeat handling ???
119         switch (state) {
120                 case REMOTE_NO_KEY_PRESSED:
121                         deb_rc("NO KEY PRESSED\n");
122                         if (d->last_state != REMOTE_NO_KEY_PRESSED) {
123                                 deb_rc("releasing event %d\n",d->last_event);
124                                 input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
125                                 input_sync(d->rc_input_dev);
126                         }
127                         d->last_state = REMOTE_NO_KEY_PRESSED;
128                         d->last_event = 0;
129                         break;
130                 case REMOTE_KEY_PRESSED:
131                         deb_rc("KEY PRESSED\n");
132                         deb_rc("pressing event %d\n",event);
133
134                         input_event(d->rc_input_dev, EV_KEY, event, 1);
135                         input_sync(d->rc_input_dev);
136
137                         d->last_event = event;
138                         d->last_state = REMOTE_KEY_PRESSED;
139                         break;
140                 case REMOTE_KEY_REPEAT:
141                         deb_rc("KEY_REPEAT\n");
142                         if (d->last_state != REMOTE_NO_KEY_PRESSED) {
143                                 deb_rc("repeating event %d\n",d->last_event);
144                                 input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
145                                 input_sync(d->rc_input_dev);
146                                 d->last_state = REMOTE_KEY_REPEAT;
147                         }
148                 default:
149                         break;
150         }
151 */
152
153 schedule:
154         schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
155 }
156
157 int dvb_usb_remote_init(struct dvb_usb_device *d)
158 {
159         struct input_dev *input_dev;
160         int i;
161         int err;
162
163         if (d->props.rc_key_map == NULL ||
164                 d->props.rc_query == NULL ||
165                 dvb_usb_disable_rc_polling)
166                 return 0;
167
168         usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
169         strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
170
171         input_dev = input_allocate_device();
172         if (!input_dev)
173                 return -ENOMEM;
174
175         input_dev->evbit[0] = BIT_MASK(EV_KEY);
176         input_dev->name = "IR-receiver inside an USB DVB receiver";
177         input_dev->phys = d->rc_phys;
178         usb_to_input_id(d->udev, &input_dev->id);
179         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
191         /* Start the remote-control polling. */
192         if (d->props.rc_interval < 40)
193                 d->props.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
207         d->rc_input_dev = input_dev;
208
209         INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
210
211         info("schedule remote query interval to %d msecs.", d->props.rc_interval);
212         schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
213
214         d->state |= DVB_USB_STATE_REMOTE;
215
216         return 0;
217 }
218
219 int dvb_usb_remote_exit(struct dvb_usb_device *d)
220 {
221         if (d->state & DVB_USB_STATE_REMOTE) {
222                 cancel_rearming_delayed_work(&d->rc_query_work);
223                 flush_scheduled_work();
224                 input_unregister_device(d->rc_input_dev);
225         }
226         d->state &= ~DVB_USB_STATE_REMOTE;
227         return 0;
228 }
229
230 #define DVB_USB_RC_NEC_EMPTY           0x00
231 #define DVB_USB_RC_NEC_KEY_PRESSED     0x01
232 #define DVB_USB_RC_NEC_KEY_REPEATED    0x02
233 int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
234                 u8 keybuf[5], u32 *event, int *state)
235 {
236         int i;
237         struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
238         *event = 0;
239         *state = REMOTE_NO_KEY_PRESSED;
240         switch (keybuf[0]) {
241                 case DVB_USB_RC_NEC_EMPTY:
242                         break;
243                 case DVB_USB_RC_NEC_KEY_PRESSED:
244                         if ((u8) ~keybuf[1] != keybuf[2] ||
245                                 (u8) ~keybuf[3] != keybuf[4]) {
246                                 deb_err("remote control checksum failed.\n");
247                                 break;
248                         }
249                         /* See if we can match the raw key code. */
250                         for (i = 0; i < d->props.rc_key_map_size; i++)
251                                 if (rc5_custom(&keymap[i]) == keybuf[1] &&
252                                         rc5_data(&keymap[i]) == keybuf[3]) {
253                                         *event = keymap[i].event;
254                                         *state = REMOTE_KEY_PRESSED;
255                                         return 0;
256                                 }
257                         deb_err("key mapping failed - no appropriate key found in keymapping\n");
258                         break;
259                 case DVB_USB_RC_NEC_KEY_REPEATED:
260                         *state = REMOTE_KEY_REPEAT;
261                         break;
262                 default:
263                         deb_err("unknown type of remote status: %d\n",keybuf[0]);
264                         break;
265         }
266         return 0;
267 }
268 EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);