diff options
author | Ville Syrjala <syrjala@sci.fi> | 2009-01-30 02:42:16 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-01-30 02:43:35 -0500 |
commit | d329e33c7c2bdcd955a00c84a9363cb309cad352 (patch) | |
tree | 0816ceb24200279445f71764464e2b18f4536e7e /drivers | |
parent | 169bc1efa84680d0a8c9567539f8577fd52e1a77 (diff) |
Input: ati_remote2 - add per device attrs
Add per device channel_mask and mode_mask attributes. They inherit
the values from the module parameters when the device is registered.
One additional benefit is that now runtime changes to channel_mask
can actually affect the hardware channel setup like they should.
Signed-off-by: Ville Syrjala <syrjala@sci.fi>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/misc/ati_remote2.c | 141 |
1 files changed, 126 insertions, 15 deletions
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 351eb9000def..0871d7b2df43 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -31,11 +31,16 @@ MODULE_LICENSE("GPL"); | |||
31 | * newly configured "channel". | 31 | * newly configured "channel". |
32 | */ | 32 | */ |
33 | 33 | ||
34 | static unsigned int channel_mask = 0xFFFF; | 34 | enum { |
35 | ATI_REMOTE2_MAX_CHANNEL_MASK = 0xFFFF, | ||
36 | ATI_REMOTE2_MAX_MODE_MASK = 0x1F, | ||
37 | }; | ||
38 | |||
39 | static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; | ||
35 | module_param(channel_mask, uint, 0644); | 40 | module_param(channel_mask, uint, 0644); |
36 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); | 41 | MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); |
37 | 42 | ||
38 | static unsigned int mode_mask = 0x1F; | 43 | static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; |
39 | module_param(mode_mask, uint, 0644); | 44 | module_param(mode_mask, uint, 0644); |
40 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); | 45 | MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); |
41 | 46 | ||
@@ -133,6 +138,9 @@ struct ati_remote2 { | |||
133 | u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; | 138 | u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; |
134 | 139 | ||
135 | unsigned int flags; | 140 | unsigned int flags; |
141 | |||
142 | unsigned int channel_mask; | ||
143 | unsigned int mode_mask; | ||
136 | }; | 144 | }; |
137 | 145 | ||
138 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); | 146 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); |
@@ -244,7 +252,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | |||
244 | 252 | ||
245 | channel = data[0] >> 4; | 253 | channel = data[0] >> 4; |
246 | 254 | ||
247 | if (!((1 << channel) & channel_mask)) | 255 | if (!((1 << channel) & ar2->channel_mask)) |
248 | return; | 256 | return; |
249 | 257 | ||
250 | mode = data[0] & 0x0F; | 258 | mode = data[0] & 0x0F; |
@@ -256,7 +264,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) | |||
256 | return; | 264 | return; |
257 | } | 265 | } |
258 | 266 | ||
259 | if (!((1 << mode) & mode_mask)) | 267 | if (!((1 << mode) & ar2->mode_mask)) |
260 | return; | 268 | return; |
261 | 269 | ||
262 | input_event(idev, EV_REL, REL_X, (s8) data[1]); | 270 | input_event(idev, EV_REL, REL_X, (s8) data[1]); |
@@ -283,7 +291,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
283 | 291 | ||
284 | channel = data[0] >> 4; | 292 | channel = data[0] >> 4; |
285 | 293 | ||
286 | if (!((1 << channel) & channel_mask)) | 294 | if (!((1 << channel) & ar2->channel_mask)) |
287 | return; | 295 | return; |
288 | 296 | ||
289 | mode = data[0] & 0x0F; | 297 | mode = data[0] & 0x0F; |
@@ -311,7 +319,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) | |||
311 | ar2->mode = mode; | 319 | ar2->mode = mode; |
312 | } | 320 | } |
313 | 321 | ||
314 | if (!((1 << mode) & mode_mask)) | 322 | if (!((1 << mode) & ar2->mode_mask)) |
315 | return; | 323 | return; |
316 | 324 | ||
317 | index = ati_remote2_lookup(hw_code); | 325 | index = ati_remote2_lookup(hw_code); |
@@ -416,7 +424,7 @@ static int ati_remote2_getkeycode(struct input_dev *idev, | |||
416 | int index, mode; | 424 | int index, mode; |
417 | 425 | ||
418 | mode = scancode >> 8; | 426 | mode = scancode >> 8; |
419 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | 427 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) |
420 | return -EINVAL; | 428 | return -EINVAL; |
421 | 429 | ||
422 | index = ati_remote2_lookup(scancode & 0xFF); | 430 | index = ati_remote2_lookup(scancode & 0xFF); |
@@ -433,7 +441,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc | |||
433 | int index, mode, old_keycode; | 441 | int index, mode, old_keycode; |
434 | 442 | ||
435 | mode = scancode >> 8; | 443 | mode = scancode >> 8; |
436 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) | 444 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) |
437 | return -EINVAL; | 445 | return -EINVAL; |
438 | 446 | ||
439 | index = ati_remote2_lookup(scancode & 0xFF); | 447 | index = ati_remote2_lookup(scancode & 0xFF); |
@@ -556,7 +564,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) | |||
556 | } | 564 | } |
557 | } | 565 | } |
558 | 566 | ||
559 | static int ati_remote2_setup(struct ati_remote2 *ar2) | 567 | static int ati_remote2_setup(struct ati_remote2 *ar2, unsigned int ch_mask) |
560 | { | 568 | { |
561 | int r, i, channel; | 569 | int r, i, channel; |
562 | 570 | ||
@@ -571,8 +579,8 @@ static int ati_remote2_setup(struct ati_remote2 *ar2) | |||
571 | 579 | ||
572 | channel = 0; | 580 | channel = 0; |
573 | for (i = 0; i < 16; i++) { | 581 | for (i = 0; i < 16; i++) { |
574 | if ((1 << i) & channel_mask) { | 582 | if ((1 << i) & ch_mask) { |
575 | if (!(~(1 << i) & 0xFFFF & channel_mask)) | 583 | if (!(~(1 << i) & ch_mask)) |
576 | channel = i + 1; | 584 | channel = i + 1; |
577 | break; | 585 | break; |
578 | } | 586 | } |
@@ -591,6 +599,99 @@ static int ati_remote2_setup(struct ati_remote2 *ar2) | |||
591 | return 0; | 599 | return 0; |
592 | } | 600 | } |
593 | 601 | ||
602 | static ssize_t ati_remote2_show_channel_mask(struct device *dev, | ||
603 | struct device_attribute *attr, | ||
604 | char *buf) | ||
605 | { | ||
606 | struct usb_device *udev = to_usb_device(dev); | ||
607 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
608 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
609 | |||
610 | return sprintf(buf, "0x%04x\n", ar2->channel_mask); | ||
611 | } | ||
612 | |||
613 | static ssize_t ati_remote2_store_channel_mask(struct device *dev, | ||
614 | struct device_attribute *attr, | ||
615 | const char *buf, size_t count) | ||
616 | { | ||
617 | struct usb_device *udev = to_usb_device(dev); | ||
618 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
619 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
620 | unsigned long mask; | ||
621 | int r; | ||
622 | |||
623 | if (strict_strtoul(buf, 0, &mask)) | ||
624 | return -EINVAL; | ||
625 | |||
626 | if (mask & ~ATI_REMOTE2_MAX_CHANNEL_MASK) | ||
627 | return -EINVAL; | ||
628 | |||
629 | r = usb_autopm_get_interface(ar2->intf[0]); | ||
630 | if (r) { | ||
631 | dev_err(&ar2->intf[0]->dev, | ||
632 | "%s(): usb_autopm_get_interface() = %d\n", __func__, r); | ||
633 | return r; | ||
634 | } | ||
635 | |||
636 | mutex_lock(&ati_remote2_mutex); | ||
637 | |||
638 | if (mask != ar2->channel_mask && !ati_remote2_setup(ar2, mask)) | ||
639 | ar2->channel_mask = mask; | ||
640 | |||
641 | mutex_unlock(&ati_remote2_mutex); | ||
642 | |||
643 | usb_autopm_put_interface(ar2->intf[0]); | ||
644 | |||
645 | return count; | ||
646 | } | ||
647 | |||
648 | static ssize_t ati_remote2_show_mode_mask(struct device *dev, | ||
649 | struct device_attribute *attr, | ||
650 | char *buf) | ||
651 | { | ||
652 | struct usb_device *udev = to_usb_device(dev); | ||
653 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
654 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
655 | |||
656 | return sprintf(buf, "0x%02x\n", ar2->mode_mask); | ||
657 | } | ||
658 | |||
659 | static ssize_t ati_remote2_store_mode_mask(struct device *dev, | ||
660 | struct device_attribute *attr, | ||
661 | const char *buf, size_t count) | ||
662 | { | ||
663 | struct usb_device *udev = to_usb_device(dev); | ||
664 | struct usb_interface *intf = usb_ifnum_to_if(udev, 0); | ||
665 | struct ati_remote2 *ar2 = usb_get_intfdata(intf); | ||
666 | unsigned long mask; | ||
667 | |||
668 | if (strict_strtoul(buf, 0, &mask)) | ||
669 | return -EINVAL; | ||
670 | |||
671 | if (mask & ~ATI_REMOTE2_MAX_MODE_MASK) | ||
672 | return -EINVAL; | ||
673 | |||
674 | ar2->mode_mask = mask; | ||
675 | |||
676 | return count; | ||
677 | } | ||
678 | |||
679 | static DEVICE_ATTR(channel_mask, 0644, ati_remote2_show_channel_mask, | ||
680 | ati_remote2_store_channel_mask); | ||
681 | |||
682 | static DEVICE_ATTR(mode_mask, 0644, ati_remote2_show_mode_mask, | ||
683 | ati_remote2_store_mode_mask); | ||
684 | |||
685 | static struct attribute *ati_remote2_attrs[] = { | ||
686 | &dev_attr_channel_mask.attr, | ||
687 | &dev_attr_mode_mask.attr, | ||
688 | NULL, | ||
689 | }; | ||
690 | |||
691 | static struct attribute_group ati_remote2_attr_group = { | ||
692 | .attrs = ati_remote2_attrs, | ||
693 | }; | ||
694 | |||
594 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) | 695 | static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) |
595 | { | 696 | { |
596 | struct usb_device *udev = interface_to_usbdev(interface); | 697 | struct usb_device *udev = interface_to_usbdev(interface); |
@@ -621,7 +722,10 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d | |||
621 | if (r) | 722 | if (r) |
622 | goto fail2; | 723 | goto fail2; |
623 | 724 | ||
624 | r = ati_remote2_setup(ar2); | 725 | ar2->channel_mask = channel_mask & ATI_REMOTE2_MAX_CHANNEL_MASK; |
726 | ar2->mode_mask = mode_mask & ATI_REMOTE2_MAX_MODE_MASK; | ||
727 | |||
728 | r = ati_remote2_setup(ar2, ar2->channel_mask); | ||
625 | if (r) | 729 | if (r) |
626 | goto fail2; | 730 | goto fail2; |
627 | 731 | ||
@@ -630,19 +734,24 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d | |||
630 | 734 | ||
631 | strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); | 735 | strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); |
632 | 736 | ||
633 | r = ati_remote2_input_init(ar2); | 737 | r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); |
634 | if (r) | 738 | if (r) |
635 | goto fail2; | 739 | goto fail2; |
636 | 740 | ||
741 | r = ati_remote2_input_init(ar2); | ||
742 | if (r) | ||
743 | goto fail3; | ||
744 | |||
637 | usb_set_intfdata(interface, ar2); | 745 | usb_set_intfdata(interface, ar2); |
638 | 746 | ||
639 | interface->needs_remote_wakeup = 1; | 747 | interface->needs_remote_wakeup = 1; |
640 | 748 | ||
641 | return 0; | 749 | return 0; |
642 | 750 | ||
751 | fail3: | ||
752 | sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); | ||
643 | fail2: | 753 | fail2: |
644 | ati_remote2_urb_cleanup(ar2); | 754 | ati_remote2_urb_cleanup(ar2); |
645 | |||
646 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | 755 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); |
647 | fail1: | 756 | fail1: |
648 | kfree(ar2); | 757 | kfree(ar2); |
@@ -663,6 +772,8 @@ static void ati_remote2_disconnect(struct usb_interface *interface) | |||
663 | 772 | ||
664 | input_unregister_device(ar2->idev); | 773 | input_unregister_device(ar2->idev); |
665 | 774 | ||
775 | sysfs_remove_group(&ar2->udev->dev.kobj, &ati_remote2_attr_group); | ||
776 | |||
666 | ati_remote2_urb_cleanup(ar2); | 777 | ati_remote2_urb_cleanup(ar2); |
667 | 778 | ||
668 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); | 779 | usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); |
@@ -736,7 +847,7 @@ static int ati_remote2_reset_resume(struct usb_interface *interface) | |||
736 | 847 | ||
737 | mutex_lock(&ati_remote2_mutex); | 848 | mutex_lock(&ati_remote2_mutex); |
738 | 849 | ||
739 | r = ati_remote2_setup(ar2); | 850 | r = ati_remote2_setup(ar2, ar2->channel_mask); |
740 | if (r) | 851 | if (r) |
741 | goto out; | 852 | goto out; |
742 | 853 | ||