HID: wiimote: add sysfs extension/device-type attrs

Two new attributes, "extension" and "devtype" now allow user-space to read
the extension type and device type. As device detection is asynchronous,
we send a CHANGED event after it is done. This also allows user-space to
wait for a device to settle before opening its input event devices.

The "extension" device is compatible with the old "extension" sysfs field
(which was registered by the static extension support code).

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
David Herrmann
2013-05-05 23:13:04 +02:00
committed by Jiri Kosina
parent d76f89e13a
commit c7da08677d
2 changed files with 128 additions and 2 deletions

View File

@@ -1166,11 +1166,18 @@ static void wiimote_init_worker(struct work_struct *work)
{
struct wiimote_data *wdata = container_of(work, struct wiimote_data,
init_worker);
bool changed = false;
if (wdata->state.devtype == WIIMOTE_DEV_PENDING)
if (wdata->state.devtype == WIIMOTE_DEV_PENDING) {
wiimote_init_detect(wdata);
changed = true;
}
if (!wiimote_init_check(wdata))
wiimote_init_hotplug(wdata);
if (changed)
kobject_uevent(&wdata->hdev->dev.kobj, KOBJ_CHANGE);
}
void __wiimote_schedule(struct wiimote_data *wdata)
@@ -1591,6 +1598,84 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
return 0;
}
static ssize_t wiimote_ext_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct wiimote_data *wdata = dev_to_wii(dev);
__u8 type;
unsigned long flags;
spin_lock_irqsave(&wdata->state.lock, flags);
type = wdata->state.exttype;
spin_unlock_irqrestore(&wdata->state.lock, flags);
switch (type) {
case WIIMOTE_EXT_NONE:
return sprintf(buf, "none\n");
case WIIMOTE_EXT_NUNCHUK:
return sprintf(buf, "nunchuk\n");
case WIIMOTE_EXT_CLASSIC_CONTROLLER:
return sprintf(buf, "classic\n");
case WIIMOTE_EXT_BALANCE_BOARD:
return sprintf(buf, "balanceboard\n");
case WIIMOTE_EXT_UNKNOWN:
/* fallthrough */
default:
return sprintf(buf, "unknown\n");
}
}
static ssize_t wiimote_ext_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct wiimote_data *wdata = dev_to_wii(dev);
if (!strcmp(buf, "scan")) {
wiimote_schedule(wdata);
} else {
return -EINVAL;
}
return strnlen(buf, PAGE_SIZE);
}
static DEVICE_ATTR(extension, S_IRUGO | S_IWUSR | S_IWGRP, wiimote_ext_show,
wiimote_ext_store);
static ssize_t wiimote_dev_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct wiimote_data *wdata = dev_to_wii(dev);
__u8 type;
unsigned long flags;
spin_lock_irqsave(&wdata->state.lock, flags);
type = wdata->state.devtype;
spin_unlock_irqrestore(&wdata->state.lock, flags);
switch (type) {
case WIIMOTE_DEV_GENERIC:
return sprintf(buf, "generic\n");
case WIIMOTE_DEV_GEN10:
return sprintf(buf, "gen10\n");
case WIIMOTE_DEV_GEN20:
return sprintf(buf, "gen20\n");
case WIIMOTE_DEV_BALANCE_BOARD:
return sprintf(buf, "balanceboard\n");
case WIIMOTE_DEV_PENDING:
return sprintf(buf, "pending\n");
case WIIMOTE_DEV_UNKNOWN:
/* fallthrough */
default:
return sprintf(buf, "unknown\n");
}
}
static DEVICE_ATTR(devtype, S_IRUGO, wiimote_dev_show, NULL);
static struct wiimote_data *wiimote_create(struct hid_device *hdev)
{
struct wiimote_data *wdata;
@@ -1631,6 +1716,9 @@ static void wiimote_destroy(struct wiimote_data *wdata)
cancel_work_sync(&wdata->init_worker);
del_timer_sync(&wdata->timer);
device_remove_file(&wdata->hdev->dev, &dev_attr_devtype);
device_remove_file(&wdata->hdev->dev, &dev_attr_extension);
wiimote_mp_unload(wdata);
wiimote_ext_unload(wdata);
wiimote_modules_unload(wdata);
@@ -1673,6 +1761,18 @@ static int wiimote_hid_probe(struct hid_device *hdev,
goto err_stop;
}
ret = device_create_file(&hdev->dev, &dev_attr_extension);
if (ret) {
hid_err(hdev, "cannot create sysfs attribute\n");
goto err_close;
}
ret = device_create_file(&hdev->dev, &dev_attr_devtype);
if (ret) {
hid_err(hdev, "cannot create sysfs attribute\n");
goto err_ext;
}
ret = wiidebug_init(wdata);
if (ret)
goto err_free;
@@ -1688,6 +1788,10 @@ err_free:
wiimote_destroy(wdata);
return ret;
err_ext:
device_remove_file(&wdata->hdev->dev, &dev_attr_extension);
err_close:
hid_hw_close(hdev);
err_stop:
hid_hw_stop(hdev);
err: