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>
This commit is contained in:
parent
169bc1efa8
commit
d329e33c7c
|
@ -31,11 +31,16 @@ MODULE_LICENSE("GPL");
|
||||||
* newly configured "channel".
|
* newly configured "channel".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static unsigned int channel_mask = 0xFFFF;
|
enum {
|
||||||
|
ATI_REMOTE2_MAX_CHANNEL_MASK = 0xFFFF,
|
||||||
|
ATI_REMOTE2_MAX_MODE_MASK = 0x1F,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK;
|
||||||
module_param(channel_mask, uint, 0644);
|
module_param(channel_mask, uint, 0644);
|
||||||
MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>");
|
MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>");
|
||||||
|
|
||||||
static unsigned int mode_mask = 0x1F;
|
static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK;
|
||||||
module_param(mode_mask, uint, 0644);
|
module_param(mode_mask, uint, 0644);
|
||||||
MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
|
MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
|
||||||
|
|
||||||
|
@ -133,6 +138,9 @@ struct ati_remote2 {
|
||||||
u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)];
|
u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)];
|
||||||
|
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
|
unsigned int channel_mask;
|
||||||
|
unsigned int mode_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id);
|
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)
|
||||||
|
|
||||||
channel = data[0] >> 4;
|
channel = data[0] >> 4;
|
||||||
|
|
||||||
if (!((1 << channel) & channel_mask))
|
if (!((1 << channel) & ar2->channel_mask))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mode = data[0] & 0x0F;
|
mode = data[0] & 0x0F;
|
||||||
|
@ -256,7 +264,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((1 << mode) & mode_mask))
|
if (!((1 << mode) & ar2->mode_mask))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
input_event(idev, EV_REL, REL_X, (s8) data[1]);
|
input_event(idev, EV_REL, REL_X, (s8) data[1]);
|
||||||
|
@ -283,7 +291,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
|
||||||
|
|
||||||
channel = data[0] >> 4;
|
channel = data[0] >> 4;
|
||||||
|
|
||||||
if (!((1 << channel) & channel_mask))
|
if (!((1 << channel) & ar2->channel_mask))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mode = data[0] & 0x0F;
|
mode = data[0] & 0x0F;
|
||||||
|
@ -311,7 +319,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
|
||||||
ar2->mode = mode;
|
ar2->mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((1 << mode) & mode_mask))
|
if (!((1 << mode) & ar2->mode_mask))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
index = ati_remote2_lookup(hw_code);
|
index = ati_remote2_lookup(hw_code);
|
||||||
|
@ -416,7 +424,7 @@ static int ati_remote2_getkeycode(struct input_dev *idev,
|
||||||
int index, mode;
|
int index, mode;
|
||||||
|
|
||||||
mode = scancode >> 8;
|
mode = scancode >> 8;
|
||||||
if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask))
|
if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
index = ati_remote2_lookup(scancode & 0xFF);
|
index = ati_remote2_lookup(scancode & 0xFF);
|
||||||
|
@ -433,7 +441,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc
|
||||||
int index, mode, old_keycode;
|
int index, mode, old_keycode;
|
||||||
|
|
||||||
mode = scancode >> 8;
|
mode = scancode >> 8;
|
||||||
if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask))
|
if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
index = ati_remote2_lookup(scancode & 0xFF);
|
index = ati_remote2_lookup(scancode & 0xFF);
|
||||||
|
@ -556,7 +564,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ati_remote2_setup(struct ati_remote2 *ar2)
|
static int ati_remote2_setup(struct ati_remote2 *ar2, unsigned int ch_mask)
|
||||||
{
|
{
|
||||||
int r, i, channel;
|
int r, i, channel;
|
||||||
|
|
||||||
|
@ -571,8 +579,8 @@ static int ati_remote2_setup(struct ati_remote2 *ar2)
|
||||||
|
|
||||||
channel = 0;
|
channel = 0;
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
if ((1 << i) & channel_mask) {
|
if ((1 << i) & ch_mask) {
|
||||||
if (!(~(1 << i) & 0xFFFF & channel_mask))
|
if (!(~(1 << i) & ch_mask))
|
||||||
channel = i + 1;
|
channel = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -591,6 +599,99 @@ static int ati_remote2_setup(struct ati_remote2 *ar2)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t ati_remote2_show_channel_mask(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct usb_device *udev = to_usb_device(dev);
|
||||||
|
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
|
||||||
|
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
|
||||||
|
|
||||||
|
return sprintf(buf, "0x%04x\n", ar2->channel_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ati_remote2_store_channel_mask(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct usb_device *udev = to_usb_device(dev);
|
||||||
|
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
|
||||||
|
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
|
||||||
|
unsigned long mask;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (strict_strtoul(buf, 0, &mask))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (mask & ~ATI_REMOTE2_MAX_CHANNEL_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
r = usb_autopm_get_interface(ar2->intf[0]);
|
||||||
|
if (r) {
|
||||||
|
dev_err(&ar2->intf[0]->dev,
|
||||||
|
"%s(): usb_autopm_get_interface() = %d\n", __func__, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ati_remote2_mutex);
|
||||||
|
|
||||||
|
if (mask != ar2->channel_mask && !ati_remote2_setup(ar2, mask))
|
||||||
|
ar2->channel_mask = mask;
|
||||||
|
|
||||||
|
mutex_unlock(&ati_remote2_mutex);
|
||||||
|
|
||||||
|
usb_autopm_put_interface(ar2->intf[0]);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ati_remote2_show_mode_mask(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct usb_device *udev = to_usb_device(dev);
|
||||||
|
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
|
||||||
|
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
|
||||||
|
|
||||||
|
return sprintf(buf, "0x%02x\n", ar2->mode_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ati_remote2_store_mode_mask(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct usb_device *udev = to_usb_device(dev);
|
||||||
|
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
|
||||||
|
struct ati_remote2 *ar2 = usb_get_intfdata(intf);
|
||||||
|
unsigned long mask;
|
||||||
|
|
||||||
|
if (strict_strtoul(buf, 0, &mask))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (mask & ~ATI_REMOTE2_MAX_MODE_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ar2->mode_mask = mask;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(channel_mask, 0644, ati_remote2_show_channel_mask,
|
||||||
|
ati_remote2_store_channel_mask);
|
||||||
|
|
||||||
|
static DEVICE_ATTR(mode_mask, 0644, ati_remote2_show_mode_mask,
|
||||||
|
ati_remote2_store_mode_mask);
|
||||||
|
|
||||||
|
static struct attribute *ati_remote2_attrs[] = {
|
||||||
|
&dev_attr_channel_mask.attr,
|
||||||
|
&dev_attr_mode_mask.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group ati_remote2_attr_group = {
|
||||||
|
.attrs = ati_remote2_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id)
|
static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
struct usb_device *udev = interface_to_usbdev(interface);
|
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
|
||||||
if (r)
|
if (r)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
r = ati_remote2_setup(ar2);
|
ar2->channel_mask = channel_mask & ATI_REMOTE2_MAX_CHANNEL_MASK;
|
||||||
|
ar2->mode_mask = mode_mask & ATI_REMOTE2_MAX_MODE_MASK;
|
||||||
|
|
||||||
|
r = ati_remote2_setup(ar2, ar2->channel_mask);
|
||||||
if (r)
|
if (r)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
|
@ -630,19 +734,24 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
|
||||||
|
|
||||||
strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name));
|
strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name));
|
||||||
|
|
||||||
r = ati_remote2_input_init(ar2);
|
r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group);
|
||||||
if (r)
|
if (r)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
|
r = ati_remote2_input_init(ar2);
|
||||||
|
if (r)
|
||||||
|
goto fail3;
|
||||||
|
|
||||||
usb_set_intfdata(interface, ar2);
|
usb_set_intfdata(interface, ar2);
|
||||||
|
|
||||||
interface->needs_remote_wakeup = 1;
|
interface->needs_remote_wakeup = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail3:
|
||||||
|
sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group);
|
||||||
fail2:
|
fail2:
|
||||||
ati_remote2_urb_cleanup(ar2);
|
ati_remote2_urb_cleanup(ar2);
|
||||||
|
|
||||||
usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
|
usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
|
||||||
fail1:
|
fail1:
|
||||||
kfree(ar2);
|
kfree(ar2);
|
||||||
|
@ -663,6 +772,8 @@ static void ati_remote2_disconnect(struct usb_interface *interface)
|
||||||
|
|
||||||
input_unregister_device(ar2->idev);
|
input_unregister_device(ar2->idev);
|
||||||
|
|
||||||
|
sysfs_remove_group(&ar2->udev->dev.kobj, &ati_remote2_attr_group);
|
||||||
|
|
||||||
ati_remote2_urb_cleanup(ar2);
|
ati_remote2_urb_cleanup(ar2);
|
||||||
|
|
||||||
usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
|
usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
|
||||||
|
@ -736,7 +847,7 @@ static int ati_remote2_reset_resume(struct usb_interface *interface)
|
||||||
|
|
||||||
mutex_lock(&ati_remote2_mutex);
|
mutex_lock(&ati_remote2_mutex);
|
||||||
|
|
||||||
r = ati_remote2_setup(ar2);
|
r = ati_remote2_setup(ar2, ar2->channel_mask);
|
||||||
if (r)
|
if (r)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue