diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/input/ati_remote2.c | 89 |
1 files changed, 80 insertions, 9 deletions
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c index 83f1f79db7c7..6459be90599c 100644 --- a/drivers/usb/input/ati_remote2.c +++ b/drivers/usb/input/ati_remote2.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * ati_remote2 - ATI/Philips USB RF remote driver | 2 | * ati_remote2 - ATI/Philips USB RF remote driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> | 4 | * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi> |
5 | * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 | 8 | * it under the terms of the GNU General Public License version 2 |
@@ -11,13 +12,29 @@ | |||
11 | #include <linux/usb/input.h> | 12 | #include <linux/usb/input.h> |
12 | 13 | ||
13 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" | 14 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" |
14 | #define DRIVER_VERSION "0.1" | 15 | #define DRIVER_VERSION "0.2" |
15 | 16 | ||
16 | MODULE_DESCRIPTION(DRIVER_DESC); | 17 | MODULE_DESCRIPTION(DRIVER_DESC); |
17 | MODULE_VERSION(DRIVER_VERSION); | 18 | MODULE_VERSION(DRIVER_VERSION); |
18 | MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); | 19 | MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); |
19 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
20 | 21 | ||
22 | /* | ||
23 | * ATI Remote Wonder II Channel Configuration | ||
24 | * | ||
25 | * The remote control can by assigned one of sixteen "channels" in order to facilitate | ||
26 | * the use of multiple remote controls within range of each other. | ||
27 | * A remote's "channel" may be altered by pressing and holding the "PC" button for | ||
28 | * approximately 3 seconds, after which the button will slowly flash the count of the | ||
29 | * currently configured "channel", using the numeric keypad enter a number between 1 and | ||
30 | * 16 and then the "PC" button again, the button will slowly flash the count of the | ||
31 | * newly configured "channel". | ||
32 | */ | ||
33 | |||
34 | static unsigned int channel_mask = 0xFFFF; | ||
35 | module_param(channel_mask, uint, 0644); | ||
36 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | ||
37 | |||
21 | static unsigned int mode_mask = 0x1F; | 38 | static unsigned int mode_mask = 0x1F; |
22 | module_param(mode_mask, uint, 0644); | 39 | module_param(mode_mask, uint, 0644); |
23 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | 40 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); |
@@ -146,15 +163,23 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | |||
146 | { | 163 | { |
147 | struct input_dev *idev = ar2->idev; | 164 | struct input_dev *idev = ar2->idev; |
148 | u8 *data = ar2->buf[0]; | 165 | u8 *data = ar2->buf[0]; |
166 | int channel, mode; | ||
167 | |||
168 | channel = data[0] >> 4; | ||
169 | |||
170 | if (!((1 << channel) & channel_mask)) | ||
171 | return; | ||
149 | 172 | ||
150 | if (data[0] > 4) { | 173 | mode = data[0] & 0x0F; |
174 | |||
175 | if (mode > 4) { | ||
151 | dev_err(&ar2->intf[0]->dev, | 176 | dev_err(&ar2->intf[0]->dev, |
152 | "Unknown mode byte (%02x %02x %02x %02x)\n", | 177 | "Unknown mode byte (%02x %02x %02x %02x)\n", |
153 | data[3], data[2], data[1], data[0]); | 178 | data[3], data[2], data[1], data[0]); |
154 | return; | 179 | return; |
155 | } | 180 | } |
156 | 181 | ||
157 | if (!((1 << data[0]) & mode_mask)) | 182 | if (!((1 << mode) & mode_mask)) |
158 | return; | 183 | return; |
159 | 184 | ||
160 | input_event(idev, EV_REL, REL_X, (s8) data[1]); | 185 | input_event(idev, EV_REL, REL_X, (s8) data[1]); |
@@ -177,9 +202,16 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
177 | { | 202 | { |
178 | struct input_dev *idev = ar2->idev; | 203 | struct input_dev *idev = ar2->idev; |
179 | u8 *data = ar2->buf[1]; | 204 | u8 *data = ar2->buf[1]; |
180 | int hw_code, index; | 205 | int channel, mode, hw_code, index; |
206 | |||
207 | channel = data[0] >> 4; | ||
208 | |||
209 | if (!((1 << channel) & channel_mask)) | ||
210 | return; | ||
181 | 211 | ||
182 | if (data[0] > 4) { | 212 | mode = data[0] & 0x0F; |
213 | |||
214 | if (mode > 4) { | ||
183 | dev_err(&ar2->intf[1]->dev, | 215 | dev_err(&ar2->intf[1]->dev, |
184 | "Unknown mode byte (%02x %02x %02x %02x)\n", | 216 | "Unknown mode byte (%02x %02x %02x %02x)\n", |
185 | data[3], data[2], data[1], data[0]); | 217 | data[3], data[2], data[1], data[0]); |
@@ -199,16 +231,16 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
199 | * events for the mouse pad so we filter out any subsequent | 231 | * events for the mouse pad so we filter out any subsequent |
200 | * events from the same mode key. | 232 | * events from the same mode key. |
201 | */ | 233 | */ |
202 | if (ar2->mode == data[0]) | 234 | if (ar2->mode == mode) |
203 | return; | 235 | return; |
204 | 236 | ||
205 | if (data[1] == 0) | 237 | if (data[1] == 0) |
206 | ar2->mode = data[0]; | 238 | ar2->mode = mode; |
207 | 239 | ||
208 | hw_code |= data[0] << 8; | 240 | hw_code |= mode << 8; |
209 | } | 241 | } |
210 | 242 | ||
211 | if (!((1 << data[0]) & mode_mask)) | 243 | if (!((1 << mode) & mode_mask)) |
212 | return; | 244 | return; |
213 | 245 | ||
214 | index = ati_remote2_lookup(hw_code); | 246 | index = ati_remote2_lookup(hw_code); |
@@ -379,6 +411,41 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) | |||
379 | } | 411 | } |
380 | } | 412 | } |
381 | 413 | ||
414 | static int ati_remote2_setup(struct ati_remote2 *ar2) | ||
415 | { | ||
416 | int r, i, channel; | ||
417 | |||
418 | /* | ||
419 | * Configure receiver to only accept input from remote "channel" | ||
420 | * channel == 0 -> Accept input from any remote channel | ||
421 | * channel == 1 -> Only accept input from remote channel 1 | ||
422 | * channel == 2 -> Only accept input from remote channel 2 | ||
423 | * ... | ||
424 | * channel == 16 -> Only accept input from remote channel 16 | ||
425 | */ | ||
426 | |||
427 | channel = 0; | ||
428 | for (i = 0; i < 16; i++) { | ||
429 | if ((1 << i) & channel_mask) { | ||
430 | if (!(~(1 << i) & 0xFFFF & channel_mask)) | ||
431 | channel = i + 1; | ||
432 | break; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | r = usb_control_msg(ar2->udev, usb_sndctrlpipe(ar2->udev, 0), | ||
437 | 0x20, | ||
438 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
439 | channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
440 | if (r) { | ||
441 | dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n", | ||
442 | __FUNCTION__, r); | ||
443 | return r; | ||
444 | } | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
382 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) | 449 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) |
383 | { | 450 | { |
384 | struct usb_device *udev = interface_to_usbdev(interface); | 451 | struct usb_device *udev = interface_to_usbdev(interface); |
@@ -409,6 +476,10 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d | |||
409 | if (r) | 476 | if (r) |
410 | goto fail2; | 477 | goto fail2; |
411 | 478 | ||
479 | r = ati_remote2_setup(ar2); | ||
480 | if (r) | ||
481 | goto fail2; | ||
482 | |||
412 | usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); | 483 | usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); |
413 | strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); | 484 | strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); |
414 | 485 | ||