diff options
author | Anssi Hannula <anssi.hannula@iki.fi> | 2011-08-06 17:18:08 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-09-22 09:51:31 -0400 |
commit | c34516e599d9c00388ab49e88f3e9e38f8fc5346 (patch) | |
tree | 6b00ab4f9bf8d58ff6f69d2f8f625b2ee772a14c /drivers/media/rc | |
parent | 9688efda3fb0abb487ae44ced1dd02d14a4312c4 (diff) |
[media] ati_remote: migrate to the rc subsystem
The keycode mangling algorithm is kept the same, so the new external
keymap has the same values as the old static table.
[mchehab@redhat.com: Fix some bad whitespacing]
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/rc')
-rw-r--r-- | drivers/media/rc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/rc/ati_remote.c | 262 | ||||
-rw-r--r-- | drivers/media/rc/keymaps/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/rc/keymaps/rc-ati-x10.c | 103 |
4 files changed, 268 insertions, 99 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 756884e007e6..ea45f35571a9 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
@@ -111,6 +111,7 @@ config IR_LIRC_CODEC | |||
111 | config RC_ATI_REMOTE | 111 | config RC_ATI_REMOTE |
112 | tristate "ATI / X10 USB RF remote control" | 112 | tristate "ATI / X10 USB RF remote control" |
113 | depends on USB_ARCH_HAS_HCD | 113 | depends on USB_ARCH_HAS_HCD |
114 | depends on RC_CORE | ||
114 | select USB | 115 | select USB |
115 | help | 116 | help |
116 | Say Y here if you want to use an ATI or X10 "Lola" USB remote control. | 117 | Say Y here if you want to use an ATI or X10 "Lola" USB remote control. |
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index 53388a558a57..4b4509a6d9d5 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * USB ATI Remote support | 2 | * USB ATI Remote support |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Anssi Hannula <anssi.hannula@iki.fi> | ||
4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> | 5 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> |
5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev | 6 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev |
6 | * | 7 | * |
@@ -90,9 +91,11 @@ | |||
90 | #include <linux/init.h> | 91 | #include <linux/init.h> |
91 | #include <linux/slab.h> | 92 | #include <linux/slab.h> |
92 | #include <linux/module.h> | 93 | #include <linux/module.h> |
94 | #include <linux/mutex.h> | ||
93 | #include <linux/usb/input.h> | 95 | #include <linux/usb/input.h> |
94 | #include <linux/wait.h> | 96 | #include <linux/wait.h> |
95 | #include <linux/jiffies.h> | 97 | #include <linux/jiffies.h> |
98 | #include <media/rc-core.h> | ||
96 | 99 | ||
97 | /* | 100 | /* |
98 | * Module and Version Information, Module Parameters | 101 | * Module and Version Information, Module Parameters |
@@ -139,6 +142,10 @@ static int repeat_delay = REPEAT_DELAY; | |||
139 | module_param(repeat_delay, int, 0644); | 142 | module_param(repeat_delay, int, 0644); |
140 | MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec"); | 143 | MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec"); |
141 | 144 | ||
145 | static bool mouse = true; | ||
146 | module_param(mouse, bool, 0444); | ||
147 | MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes"); | ||
148 | |||
142 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) | 149 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) |
143 | #undef err | 150 | #undef err |
144 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | 151 | #define err(format, arg...) printk(KERN_ERR format , ## arg) |
@@ -167,6 +174,7 @@ static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; | |||
167 | 174 | ||
168 | struct ati_remote { | 175 | struct ati_remote { |
169 | struct input_dev *idev; | 176 | struct input_dev *idev; |
177 | struct rc_dev *rdev; | ||
170 | struct usb_device *udev; | 178 | struct usb_device *udev; |
171 | struct usb_interface *interface; | 179 | struct usb_interface *interface; |
172 | 180 | ||
@@ -186,11 +194,16 @@ struct ati_remote { | |||
186 | 194 | ||
187 | unsigned int repeat_count; | 195 | unsigned int repeat_count; |
188 | 196 | ||
189 | char name[NAME_BUFSIZE]; | 197 | char rc_name[NAME_BUFSIZE]; |
190 | char phys[NAME_BUFSIZE]; | 198 | char rc_phys[NAME_BUFSIZE]; |
199 | char mouse_name[NAME_BUFSIZE]; | ||
200 | char mouse_phys[NAME_BUFSIZE]; | ||
191 | 201 | ||
192 | wait_queue_head_t wait; | 202 | wait_queue_head_t wait; |
193 | int send_flags; | 203 | int send_flags; |
204 | |||
205 | int users; /* 0-2, users are rc and input */ | ||
206 | struct mutex open_mutex; | ||
194 | }; | 207 | }; |
195 | 208 | ||
196 | /* "Kinds" of messages sent from the hardware to the driver. */ | 209 | /* "Kinds" of messages sent from the hardware to the driver. */ |
@@ -233,64 +246,11 @@ static const struct { | |||
233 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ | 246 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ |
234 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ | 247 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ |
235 | 248 | ||
236 | /* keyboard. */ | 249 | /* Non-mouse events are handled by rc-core */ |
237 | {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1}, | ||
238 | {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1}, | ||
239 | {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1}, | ||
240 | {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1}, | ||
241 | {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1}, | ||
242 | {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1}, | ||
243 | {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1}, | ||
244 | {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1}, | ||
245 | {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1}, | ||
246 | {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1}, | ||
247 | {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1}, | ||
248 | {KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1}, | ||
249 | {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1}, | ||
250 | {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1}, | ||
251 | {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1}, | ||
252 | {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1}, | ||
253 | |||
254 | /* "special" keys */ | ||
255 | {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */ | ||
256 | {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */ | ||
257 | {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */ | ||
258 | {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1}, /* TV */ | ||
259 | {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */ | ||
260 | {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */ | ||
261 | {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */ | ||
262 | {KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */ | ||
263 | {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1}, /* "timer" */ | ||
264 | {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1}, /* "max" */ | ||
265 | {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ | ||
266 | {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ | ||
267 | {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ | ||
268 | {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ | ||
269 | {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* "OK" */ | ||
270 | {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */ | ||
271 | {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */ | ||
272 | {KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */ | ||
273 | {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */ | ||
274 | {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */ | ||
275 | {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */ | ||
276 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ | ||
277 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ | ||
278 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ | ||
279 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ | ||
280 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ | ||
281 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ | ||
282 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ | ||
283 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ | ||
284 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ | ||
285 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ | ||
286 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ | ||
287 | |||
288 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} | 250 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} |
289 | }; | 251 | }; |
290 | 252 | ||
291 | /* Local function prototypes */ | 253 | /* Local function prototypes */ |
292 | static int ati_remote_open (struct input_dev *inputdev); | ||
293 | static void ati_remote_close (struct input_dev *inputdev); | ||
294 | static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); | 254 | static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); |
295 | static void ati_remote_irq_out (struct urb *urb); | 255 | static void ati_remote_irq_out (struct urb *urb); |
296 | static void ati_remote_irq_in (struct urb *urb); | 256 | static void ati_remote_irq_in (struct urb *urb); |
@@ -326,29 +286,60 @@ static void ati_remote_dump(struct device *dev, unsigned char *data, | |||
326 | /* | 286 | /* |
327 | * ati_remote_open | 287 | * ati_remote_open |
328 | */ | 288 | */ |
329 | static int ati_remote_open(struct input_dev *inputdev) | 289 | static int ati_remote_open(struct ati_remote *ati_remote) |
330 | { | 290 | { |
331 | struct ati_remote *ati_remote = input_get_drvdata(inputdev); | 291 | int err = 0; |
292 | |||
293 | mutex_lock(&ati_remote->open_mutex); | ||
294 | |||
295 | if (ati_remote->users++ != 0) | ||
296 | goto out; /* one was already active */ | ||
332 | 297 | ||
333 | /* On first open, submit the read urb which was set up previously. */ | 298 | /* On first open, submit the read urb which was set up previously. */ |
334 | ati_remote->irq_urb->dev = ati_remote->udev; | 299 | ati_remote->irq_urb->dev = ati_remote->udev; |
335 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { | 300 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { |
336 | dev_err(&ati_remote->interface->dev, | 301 | dev_err(&ati_remote->interface->dev, |
337 | "%s: usb_submit_urb failed!\n", __func__); | 302 | "%s: usb_submit_urb failed!\n", __func__); |
338 | return -EIO; | 303 | err = -EIO; |
339 | } | 304 | } |
340 | 305 | ||
341 | return 0; | 306 | out: mutex_unlock(&ati_remote->open_mutex); |
307 | return err; | ||
342 | } | 308 | } |
343 | 309 | ||
344 | /* | 310 | /* |
345 | * ati_remote_close | 311 | * ati_remote_close |
346 | */ | 312 | */ |
347 | static void ati_remote_close(struct input_dev *inputdev) | 313 | static void ati_remote_close(struct ati_remote *ati_remote) |
314 | { | ||
315 | mutex_lock(&ati_remote->open_mutex); | ||
316 | if (--ati_remote->users == 0) | ||
317 | usb_kill_urb(ati_remote->irq_urb); | ||
318 | mutex_unlock(&ati_remote->open_mutex); | ||
319 | } | ||
320 | |||
321 | static int ati_remote_input_open(struct input_dev *inputdev) | ||
348 | { | 322 | { |
349 | struct ati_remote *ati_remote = input_get_drvdata(inputdev); | 323 | struct ati_remote *ati_remote = input_get_drvdata(inputdev); |
324 | return ati_remote_open(ati_remote); | ||
325 | } | ||
350 | 326 | ||
351 | usb_kill_urb(ati_remote->irq_urb); | 327 | static void ati_remote_input_close(struct input_dev *inputdev) |
328 | { | ||
329 | struct ati_remote *ati_remote = input_get_drvdata(inputdev); | ||
330 | ati_remote_close(ati_remote); | ||
331 | } | ||
332 | |||
333 | static int ati_remote_rc_open(struct rc_dev *rdev) | ||
334 | { | ||
335 | struct ati_remote *ati_remote = rdev->priv; | ||
336 | return ati_remote_open(ati_remote); | ||
337 | } | ||
338 | |||
339 | static void ati_remote_rc_close(struct rc_dev *rdev) | ||
340 | { | ||
341 | struct ati_remote *ati_remote = rdev->priv; | ||
342 | ati_remote_close(ati_remote); | ||
352 | } | 343 | } |
353 | 344 | ||
354 | /* | 345 | /* |
@@ -413,10 +404,8 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
413 | /* | 404 | /* |
414 | * Decide if the table entry matches the remote input. | 405 | * Decide if the table entry matches the remote input. |
415 | */ | 406 | */ |
416 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && | 407 | if (ati_remote_tbl[i].data1 == d1 && |
417 | ((((ati_remote_tbl[i].data1 >> 4) - | 408 | ati_remote_tbl[i].data2 == d2) |
418 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && | ||
419 | (ati_remote_tbl[i].data2 == d2)) | ||
420 | return i; | 409 | return i; |
421 | 410 | ||
422 | } | 411 | } |
@@ -468,8 +457,10 @@ static void ati_remote_input_report(struct urb *urb) | |||
468 | struct ati_remote *ati_remote = urb->context; | 457 | struct ati_remote *ati_remote = urb->context; |
469 | unsigned char *data= ati_remote->inbuf; | 458 | unsigned char *data= ati_remote->inbuf; |
470 | struct input_dev *dev = ati_remote->idev; | 459 | struct input_dev *dev = ati_remote->idev; |
471 | int index, acc; | 460 | int index = -1; |
461 | int acc; | ||
472 | int remote_num; | 462 | int remote_num; |
463 | unsigned char scancode[2]; | ||
473 | 464 | ||
474 | /* Deal with strange looking inputs */ | 465 | /* Deal with strange looking inputs */ |
475 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || | 466 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || |
@@ -488,19 +479,26 @@ static void ati_remote_input_report(struct urb *urb) | |||
488 | return; | 479 | return; |
489 | } | 480 | } |
490 | 481 | ||
491 | /* Look up event code index in translation table */ | 482 | scancode[0] = (((data[1] - ((remote_num + 1) << 4)) & 0xf0) | (data[1] & 0x0f)); |
492 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); | 483 | |
493 | if (index < 0) { | 484 | scancode[1] = data[2]; |
494 | dev_warn(&ati_remote->interface->dev, | 485 | |
495 | "Unknown input from channel 0x%02x: data %02x,%02x\n", | 486 | /* Look up event code index in mouse translation table. */ |
496 | remote_num, data[1], data[2]); | 487 | index = ati_remote_event_lookup(remote_num, scancode[0], scancode[1]); |
497 | return; | 488 | |
498 | } | 489 | if (index >= 0) { |
499 | dbginfo(&ati_remote->interface->dev, | 490 | dbginfo(&ati_remote->interface->dev, |
500 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", | 491 | "channel 0x%02x; mouse data %02x,%02x; index %d; keycode %d\n", |
501 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); | 492 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); |
493 | if (!dev) | ||
494 | return; /* no mouse device */ | ||
495 | } else | ||
496 | dbginfo(&ati_remote->interface->dev, | ||
497 | "channel 0x%02x; key data %02x,%02x, scancode %02x,%02x\n", | ||
498 | remote_num, data[1], data[2], scancode[0], scancode[1]); | ||
502 | 499 | ||
503 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { | 500 | |
501 | if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) { | ||
504 | input_event(dev, ati_remote_tbl[index].type, | 502 | input_event(dev, ati_remote_tbl[index].type, |
505 | ati_remote_tbl[index].code, | 503 | ati_remote_tbl[index].code, |
506 | ati_remote_tbl[index].value); | 504 | ati_remote_tbl[index].value); |
@@ -510,7 +508,7 @@ static void ati_remote_input_report(struct urb *urb) | |||
510 | return; | 508 | return; |
511 | } | 509 | } |
512 | 510 | ||
513 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { | 511 | if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) { |
514 | unsigned long now = jiffies; | 512 | unsigned long now = jiffies; |
515 | 513 | ||
516 | /* Filter duplicate events which happen "too close" together. */ | 514 | /* Filter duplicate events which happen "too close" together. */ |
@@ -538,6 +536,19 @@ static void ati_remote_input_report(struct urb *urb) | |||
538 | msecs_to_jiffies(repeat_delay)))) | 536 | msecs_to_jiffies(repeat_delay)))) |
539 | return; | 537 | return; |
540 | 538 | ||
539 | if (index < 0) { | ||
540 | /* Not a mouse event, hand it to rc-core. */ | ||
541 | u32 rc_code = (scancode[0] << 8) | scancode[1]; | ||
542 | |||
543 | /* | ||
544 | * We don't use the rc-core repeat handling yet as | ||
545 | * it would cause ghost repeats which would be a | ||
546 | * regression for this driver. | ||
547 | */ | ||
548 | rc_keydown_notimeout(ati_remote->rdev, rc_code, 0); | ||
549 | rc_keyup(ati_remote->rdev); | ||
550 | return; | ||
551 | } | ||
541 | 552 | ||
542 | input_event(dev, ati_remote_tbl[index].type, | 553 | input_event(dev, ati_remote_tbl[index].type, |
543 | ati_remote_tbl[index].code, 1); | 554 | ati_remote_tbl[index].code, 1); |
@@ -675,16 +686,37 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) | |||
675 | 686 | ||
676 | input_set_drvdata(idev, ati_remote); | 687 | input_set_drvdata(idev, ati_remote); |
677 | 688 | ||
678 | idev->open = ati_remote_open; | 689 | idev->open = ati_remote_input_open; |
679 | idev->close = ati_remote_close; | 690 | idev->close = ati_remote_input_close; |
680 | 691 | ||
681 | idev->name = ati_remote->name; | 692 | idev->name = ati_remote->mouse_name; |
682 | idev->phys = ati_remote->phys; | 693 | idev->phys = ati_remote->mouse_phys; |
683 | 694 | ||
684 | usb_to_input_id(ati_remote->udev, &idev->id); | 695 | usb_to_input_id(ati_remote->udev, &idev->id); |
685 | idev->dev.parent = &ati_remote->udev->dev; | 696 | idev->dev.parent = &ati_remote->udev->dev; |
686 | } | 697 | } |
687 | 698 | ||
699 | static void ati_remote_rc_init(struct ati_remote *ati_remote) | ||
700 | { | ||
701 | struct rc_dev *rdev = ati_remote->rdev; | ||
702 | |||
703 | rdev->priv = ati_remote; | ||
704 | rdev->driver_type = RC_DRIVER_SCANCODE; | ||
705 | rdev->allowed_protos = RC_TYPE_OTHER; | ||
706 | rdev->driver_name = "ati_remote"; | ||
707 | |||
708 | rdev->open = ati_remote_rc_open; | ||
709 | rdev->close = ati_remote_rc_close; | ||
710 | |||
711 | rdev->input_name = ati_remote->rc_name; | ||
712 | rdev->input_phys = ati_remote->rc_phys; | ||
713 | |||
714 | usb_to_input_id(ati_remote->udev, &rdev->input_id); | ||
715 | rdev->dev.parent = &ati_remote->udev->dev; | ||
716 | |||
717 | rdev->map_name = RC_MAP_ATI_X10; | ||
718 | } | ||
719 | |||
688 | static int ati_remote_initialize(struct ati_remote *ati_remote) | 720 | static int ati_remote_initialize(struct ati_remote *ati_remote) |
689 | { | 721 | { |
690 | struct usb_device *udev = ati_remote->udev; | 722 | struct usb_device *udev = ati_remote->udev; |
@@ -735,6 +767,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
735 | struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; | 767 | struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; |
736 | struct ati_remote *ati_remote; | 768 | struct ati_remote *ati_remote; |
737 | struct input_dev *input_dev; | 769 | struct input_dev *input_dev; |
770 | struct rc_dev *rc_dev; | ||
738 | int err = -ENOMEM; | 771 | int err = -ENOMEM; |
739 | 772 | ||
740 | if (iface_host->desc.bNumEndpoints != 2) { | 773 | if (iface_host->desc.bNumEndpoints != 2) { |
@@ -755,8 +788,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
755 | } | 788 | } |
756 | 789 | ||
757 | ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); | 790 | ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); |
758 | input_dev = input_allocate_device(); | 791 | rc_dev = rc_allocate_device(); |
759 | if (!ati_remote || !input_dev) | 792 | if (!ati_remote || !rc_dev) |
760 | goto fail1; | 793 | goto fail1; |
761 | 794 | ||
762 | /* Allocate URB buffers, URBs */ | 795 | /* Allocate URB buffers, URBs */ |
@@ -766,44 +799,73 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
766 | ati_remote->endpoint_in = endpoint_in; | 799 | ati_remote->endpoint_in = endpoint_in; |
767 | ati_remote->endpoint_out = endpoint_out; | 800 | ati_remote->endpoint_out = endpoint_out; |
768 | ati_remote->udev = udev; | 801 | ati_remote->udev = udev; |
769 | ati_remote->idev = input_dev; | 802 | ati_remote->rdev = rc_dev; |
770 | ati_remote->interface = interface; | 803 | ati_remote->interface = interface; |
771 | 804 | ||
772 | usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); | 805 | usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys)); |
773 | strlcat(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); | 806 | strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys, |
807 | sizeof(ati_remote->mouse_phys)); | ||
808 | |||
809 | strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys)); | ||
810 | strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys)); | ||
774 | 811 | ||
775 | if (udev->manufacturer) | 812 | if (udev->manufacturer) |
776 | strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); | 813 | strlcpy(ati_remote->rc_name, udev->manufacturer, |
814 | sizeof(ati_remote->rc_name)); | ||
777 | 815 | ||
778 | if (udev->product) | 816 | if (udev->product) |
779 | snprintf(ati_remote->name, sizeof(ati_remote->name), | 817 | snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name), |
780 | "%s %s", ati_remote->name, udev->product); | 818 | "%s %s", ati_remote->rc_name, udev->product); |
781 | 819 | ||
782 | if (!strlen(ati_remote->name)) | 820 | if (!strlen(ati_remote->rc_name)) |
783 | snprintf(ati_remote->name, sizeof(ati_remote->name), | 821 | snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name), |
784 | DRIVER_DESC "(%04x,%04x)", | 822 | DRIVER_DESC "(%04x,%04x)", |
785 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), | 823 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), |
786 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); | 824 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); |
787 | 825 | ||
788 | ati_remote_input_init(ati_remote); | 826 | snprintf(ati_remote->mouse_name, sizeof(ati_remote->mouse_name), |
827 | "%s mouse", ati_remote->rc_name); | ||
828 | |||
829 | ati_remote_rc_init(ati_remote); | ||
830 | mutex_init(&ati_remote->open_mutex); | ||
789 | 831 | ||
790 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ | 832 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ |
791 | err = ati_remote_initialize(ati_remote); | 833 | err = ati_remote_initialize(ati_remote); |
792 | if (err) | 834 | if (err) |
793 | goto fail3; | 835 | goto fail3; |
794 | 836 | ||
795 | /* Set up and register input device */ | 837 | /* Set up and register rc device */ |
796 | err = input_register_device(ati_remote->idev); | 838 | err = rc_register_device(ati_remote->rdev); |
797 | if (err) | 839 | if (err) |
798 | goto fail3; | 840 | goto fail3; |
799 | 841 | ||
842 | /* use our delay for rc_dev */ | ||
843 | ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay; | ||
844 | |||
845 | /* Set up and register mouse input device */ | ||
846 | if (mouse) { | ||
847 | input_dev = input_allocate_device(); | ||
848 | if (!input_dev) | ||
849 | goto fail4; | ||
850 | |||
851 | ati_remote->idev = input_dev; | ||
852 | ati_remote_input_init(ati_remote); | ||
853 | err = input_register_device(input_dev); | ||
854 | |||
855 | if (err) | ||
856 | goto fail5; | ||
857 | } | ||
858 | |||
800 | usb_set_intfdata(interface, ati_remote); | 859 | usb_set_intfdata(interface, ati_remote); |
801 | return 0; | 860 | return 0; |
802 | 861 | ||
862 | fail5: input_free_device(input_dev); | ||
863 | fail4: rc_unregister_device(rc_dev); | ||
864 | rc_dev = NULL; | ||
803 | fail3: usb_kill_urb(ati_remote->irq_urb); | 865 | fail3: usb_kill_urb(ati_remote->irq_urb); |
804 | usb_kill_urb(ati_remote->out_urb); | 866 | usb_kill_urb(ati_remote->out_urb); |
805 | fail2: ati_remote_free_buffers(ati_remote); | 867 | fail2: ati_remote_free_buffers(ati_remote); |
806 | fail1: input_free_device(input_dev); | 868 | fail1: rc_free_device(rc_dev); |
807 | kfree(ati_remote); | 869 | kfree(ati_remote); |
808 | return err; | 870 | return err; |
809 | } | 871 | } |
@@ -824,7 +886,9 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
824 | 886 | ||
825 | usb_kill_urb(ati_remote->irq_urb); | 887 | usb_kill_urb(ati_remote->irq_urb); |
826 | usb_kill_urb(ati_remote->out_urb); | 888 | usb_kill_urb(ati_remote->out_urb); |
827 | input_unregister_device(ati_remote->idev); | 889 | if (ati_remote->idev) |
890 | input_unregister_device(ati_remote->idev); | ||
891 | rc_unregister_device(ati_remote->rdev); | ||
828 | ati_remote_free_buffers(ati_remote); | 892 | ati_remote_free_buffers(ati_remote); |
829 | kfree(ati_remote); | 893 | kfree(ati_remote); |
830 | } | 894 | } |
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index b57fc83fb4d2..8dd9fdf45c29 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile | |||
@@ -4,6 +4,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ | |||
4 | rc-apac-viewcomp.o \ | 4 | rc-apac-viewcomp.o \ |
5 | rc-asus-pc39.o \ | 5 | rc-asus-pc39.o \ |
6 | rc-ati-tv-wonder-hd-600.o \ | 6 | rc-ati-tv-wonder-hd-600.o \ |
7 | rc-ati-x10.o \ | ||
7 | rc-avermedia-a16d.o \ | 8 | rc-avermedia-a16d.o \ |
8 | rc-avermedia.o \ | 9 | rc-avermedia.o \ |
9 | rc-avermedia-cardbus.o \ | 10 | rc-avermedia-cardbus.o \ |
diff --git a/drivers/media/rc/keymaps/rc-ati-x10.c b/drivers/media/rc/keymaps/rc-ati-x10.c new file mode 100644 index 000000000000..f3397f8ab876 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-ati-x10.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * ATI X10 RF remote keytable | ||
3 | * | ||
4 | * Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi> | ||
5 | * | ||
6 | * This file is based on the static generic keytable previously found in | ||
7 | * ati_remote.c, which is | ||
8 | * Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> | ||
9 | * Copyright (c) 2002 Vladimir Dergachev | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License along | ||
22 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
24 | */ | ||
25 | |||
26 | #include <media/rc-map.h> | ||
27 | |||
28 | static struct rc_map_table ati_x10[] = { | ||
29 | { 0xd20d, KEY_1 }, | ||
30 | { 0xd30e, KEY_2 }, | ||
31 | { 0xd40f, KEY_3 }, | ||
32 | { 0xd510, KEY_4 }, | ||
33 | { 0xd611, KEY_5 }, | ||
34 | { 0xd712, KEY_6 }, | ||
35 | { 0xd813, KEY_7 }, | ||
36 | { 0xd914, KEY_8 }, | ||
37 | { 0xda15, KEY_9 }, | ||
38 | { 0xdc17, KEY_0 }, | ||
39 | { 0xc500, KEY_A }, | ||
40 | { 0xc601, KEY_B }, | ||
41 | { 0xde19, KEY_C }, | ||
42 | { 0xe01b, KEY_D }, | ||
43 | { 0xe621, KEY_E }, | ||
44 | { 0xe823, KEY_F }, | ||
45 | |||
46 | { 0xdd18, KEY_KPENTER }, /* "check" */ | ||
47 | { 0xdb16, KEY_MENU }, /* "menu" */ | ||
48 | { 0xc702, KEY_POWER }, /* Power */ | ||
49 | { 0xc803, KEY_TV }, /* TV */ | ||
50 | { 0xc904, KEY_DVD }, /* DVD */ | ||
51 | { 0xca05, KEY_WWW }, /* WEB */ | ||
52 | { 0xcb06, KEY_BOOKMARKS }, /* "book" */ | ||
53 | { 0xcc07, KEY_EDIT }, /* "hand" */ | ||
54 | { 0xe11c, KEY_COFFEE }, /* "timer" */ | ||
55 | { 0xe520, KEY_FRONT }, /* "max" */ | ||
56 | { 0xe21d, KEY_LEFT }, /* left */ | ||
57 | { 0xe41f, KEY_RIGHT }, /* right */ | ||
58 | { 0xe722, KEY_DOWN }, /* down */ | ||
59 | { 0xdf1a, KEY_UP }, /* up */ | ||
60 | { 0xe31e, KEY_OK }, /* "OK" */ | ||
61 | { 0xce09, KEY_VOLUMEDOWN }, /* VOL + */ | ||
62 | { 0xcd08, KEY_VOLUMEUP }, /* VOL - */ | ||
63 | { 0xcf0a, KEY_MUTE }, /* MUTE */ | ||
64 | { 0xd00b, KEY_CHANNELUP }, /* CH + */ | ||
65 | { 0xd10c, KEY_CHANNELDOWN },/* CH - */ | ||
66 | { 0xec27, KEY_RECORD }, /* ( o) red */ | ||
67 | { 0xea25, KEY_PLAY }, /* ( >) */ | ||
68 | { 0xe924, KEY_REWIND }, /* (<<) */ | ||
69 | { 0xeb26, KEY_FORWARD }, /* (>>) */ | ||
70 | { 0xed28, KEY_STOP }, /* ([]) */ | ||
71 | { 0xee29, KEY_PAUSE }, /* ('') */ | ||
72 | { 0xf02b, KEY_PREVIOUS }, /* (<-) */ | ||
73 | { 0xef2a, KEY_NEXT }, /* (>+) */ | ||
74 | { 0xf22d, KEY_INFO }, /* PLAYING */ | ||
75 | { 0xf32e, KEY_HOME }, /* TOP */ | ||
76 | { 0xf42f, KEY_END }, /* END */ | ||
77 | { 0xf530, KEY_SELECT }, /* SELECT */ | ||
78 | }; | ||
79 | |||
80 | static struct rc_map_list ati_x10_map = { | ||
81 | .map = { | ||
82 | .scan = ati_x10, | ||
83 | .size = ARRAY_SIZE(ati_x10), | ||
84 | .rc_type = RC_TYPE_OTHER, | ||
85 | .name = RC_MAP_ATI_X10, | ||
86 | } | ||
87 | }; | ||
88 | |||
89 | static int __init init_rc_map_ati_x10(void) | ||
90 | { | ||
91 | return rc_map_register(&ati_x10_map); | ||
92 | } | ||
93 | |||
94 | static void __exit exit_rc_map_ati_x10(void) | ||
95 | { | ||
96 | rc_map_unregister(&ati_x10_map); | ||
97 | } | ||
98 | |||
99 | module_init(init_rc_map_ati_x10) | ||
100 | module_exit(exit_rc_map_ati_x10) | ||
101 | |||
102 | MODULE_LICENSE("GPL"); | ||
103 | MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>"); | ||