Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Herrmann and committed by
Jiri Kosina
c7da0867 d76f89e1

+128 -2
+23 -1
Documentation/ABI/testing/sysfs-driver-hid-wiimote
··· 12 12 What: /sys/bus/hid/drivers/wiimote/<dev>/extension 13 13 Date: August 2011 14 14 KernelVersion: 3.2 15 - Contact: David Herrmann <dh.herrmann@googlemail.com> 15 + Contact: David Herrmann <dh.herrmann@gmail.com> 16 16 Description: This file contains the currently connected and initialized 17 17 extensions. It can be one of: none, motionp, nunchuck, classic, 18 18 motionp+nunchuck, motionp+classic ··· 20 20 the official Nintendo Nunchuck extension and classic is the 21 21 Nintendo Classic Controller extension. The motionp extension can 22 22 be combined with the other two. 23 + Starting with kernel-version 3.11 Motion Plus hotplugging is 24 + supported and if detected, it's no longer reported as static 25 + extension. You will get uevent notifications for the motion-plus 26 + device then. 27 + 28 + What: /sys/bus/hid/drivers/wiimote/<dev>/devtype 29 + Date: May 2013 30 + KernelVersion: 3.11 31 + Contact: David Herrmann <dh.herrmann@gmail.com> 32 + Description: While a device is initialized by the wiimote driver, we perform 33 + a device detection and signal a "change" uevent after it is 34 + done. This file shows the detected device type. "pending" means 35 + that the detection is still ongoing, "unknown" means, that the 36 + device couldn't be detected or loaded. "generic" means, that the 37 + device couldn't be detected but supports basic Wii Remote 38 + features and can be used. 39 + Other strings for each device-type are available and may be 40 + added if new device-specific detections are added. 41 + Currently supported are: 42 + gen10: First Wii Remote generation 43 + gen20: Second Wii Remote Plus generation (builtin MP) 44 + balanceboard: Wii Balance Board
+105 -1
drivers/hid/hid-wiimote-core.c
··· 1166 1166 { 1167 1167 struct wiimote_data *wdata = container_of(work, struct wiimote_data, 1168 1168 init_worker); 1169 + bool changed = false; 1169 1170 1170 - if (wdata->state.devtype == WIIMOTE_DEV_PENDING) 1171 + if (wdata->state.devtype == WIIMOTE_DEV_PENDING) { 1171 1172 wiimote_init_detect(wdata); 1173 + changed = true; 1174 + } 1175 + 1172 1176 if (!wiimote_init_check(wdata)) 1173 1177 wiimote_init_hotplug(wdata); 1178 + 1179 + if (changed) 1180 + kobject_uevent(&wdata->hdev->dev.kobj, KOBJ_CHANGE); 1174 1181 } 1175 1182 1176 1183 void __wiimote_schedule(struct wiimote_data *wdata) ··· 1598 1591 return 0; 1599 1592 } 1600 1593 1594 + static ssize_t wiimote_ext_show(struct device *dev, 1595 + struct device_attribute *attr, 1596 + char *buf) 1597 + { 1598 + struct wiimote_data *wdata = dev_to_wii(dev); 1599 + __u8 type; 1600 + unsigned long flags; 1601 + 1602 + spin_lock_irqsave(&wdata->state.lock, flags); 1603 + type = wdata->state.exttype; 1604 + spin_unlock_irqrestore(&wdata->state.lock, flags); 1605 + 1606 + switch (type) { 1607 + case WIIMOTE_EXT_NONE: 1608 + return sprintf(buf, "none\n"); 1609 + case WIIMOTE_EXT_NUNCHUK: 1610 + return sprintf(buf, "nunchuk\n"); 1611 + case WIIMOTE_EXT_CLASSIC_CONTROLLER: 1612 + return sprintf(buf, "classic\n"); 1613 + case WIIMOTE_EXT_BALANCE_BOARD: 1614 + return sprintf(buf, "balanceboard\n"); 1615 + case WIIMOTE_EXT_UNKNOWN: 1616 + /* fallthrough */ 1617 + default: 1618 + return sprintf(buf, "unknown\n"); 1619 + } 1620 + } 1621 + 1622 + static ssize_t wiimote_ext_store(struct device *dev, 1623 + struct device_attribute *attr, 1624 + const char *buf, size_t count) 1625 + { 1626 + struct wiimote_data *wdata = dev_to_wii(dev); 1627 + 1628 + if (!strcmp(buf, "scan")) { 1629 + wiimote_schedule(wdata); 1630 + } else { 1631 + return -EINVAL; 1632 + } 1633 + 1634 + return strnlen(buf, PAGE_SIZE); 1635 + } 1636 + 1637 + static DEVICE_ATTR(extension, S_IRUGO | S_IWUSR | S_IWGRP, wiimote_ext_show, 1638 + wiimote_ext_store); 1639 + 1640 + static ssize_t wiimote_dev_show(struct device *dev, 1641 + struct device_attribute *attr, 1642 + char *buf) 1643 + { 1644 + struct wiimote_data *wdata = dev_to_wii(dev); 1645 + __u8 type; 1646 + unsigned long flags; 1647 + 1648 + spin_lock_irqsave(&wdata->state.lock, flags); 1649 + type = wdata->state.devtype; 1650 + spin_unlock_irqrestore(&wdata->state.lock, flags); 1651 + 1652 + switch (type) { 1653 + case WIIMOTE_DEV_GENERIC: 1654 + return sprintf(buf, "generic\n"); 1655 + case WIIMOTE_DEV_GEN10: 1656 + return sprintf(buf, "gen10\n"); 1657 + case WIIMOTE_DEV_GEN20: 1658 + return sprintf(buf, "gen20\n"); 1659 + case WIIMOTE_DEV_BALANCE_BOARD: 1660 + return sprintf(buf, "balanceboard\n"); 1661 + case WIIMOTE_DEV_PENDING: 1662 + return sprintf(buf, "pending\n"); 1663 + case WIIMOTE_DEV_UNKNOWN: 1664 + /* fallthrough */ 1665 + default: 1666 + return sprintf(buf, "unknown\n"); 1667 + } 1668 + } 1669 + 1670 + static DEVICE_ATTR(devtype, S_IRUGO, wiimote_dev_show, NULL); 1671 + 1601 1672 static struct wiimote_data *wiimote_create(struct hid_device *hdev) 1602 1673 { 1603 1674 struct wiimote_data *wdata; ··· 1715 1630 1716 1631 cancel_work_sync(&wdata->init_worker); 1717 1632 del_timer_sync(&wdata->timer); 1633 + 1634 + device_remove_file(&wdata->hdev->dev, &dev_attr_devtype); 1635 + device_remove_file(&wdata->hdev->dev, &dev_attr_extension); 1718 1636 1719 1637 wiimote_mp_unload(wdata); 1720 1638 wiimote_ext_unload(wdata); ··· 1761 1673 goto err_stop; 1762 1674 } 1763 1675 1676 + ret = device_create_file(&hdev->dev, &dev_attr_extension); 1677 + if (ret) { 1678 + hid_err(hdev, "cannot create sysfs attribute\n"); 1679 + goto err_close; 1680 + } 1681 + 1682 + ret = device_create_file(&hdev->dev, &dev_attr_devtype); 1683 + if (ret) { 1684 + hid_err(hdev, "cannot create sysfs attribute\n"); 1685 + goto err_ext; 1686 + } 1687 + 1764 1688 ret = wiidebug_init(wdata); 1765 1689 if (ret) 1766 1690 goto err_free; ··· 1788 1688 wiimote_destroy(wdata); 1789 1689 return ret; 1790 1690 1691 + err_ext: 1692 + device_remove_file(&wdata->hdev->dev, &dev_attr_extension); 1693 + err_close: 1694 + hid_hw_close(hdev); 1791 1695 err_stop: 1792 1696 hid_hw_stop(hdev); 1793 1697 err: