From patchwork Sat Apr 13 10:48:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Herrmann X-Patchwork-Id: 2440471 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 767E63FD1A for ; Sat, 13 Apr 2013 10:49:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754097Ab3DMKtE (ORCPT ); Sat, 13 Apr 2013 06:49:04 -0400 Received: from mail-ee0-f48.google.com ([74.125.83.48]:53110 "EHLO mail-ee0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754078Ab3DMKtD (ORCPT ); Sat, 13 Apr 2013 06:49:03 -0400 Received: by mail-ee0-f48.google.com with SMTP id b15so1624777eek.21 for ; Sat, 13 Apr 2013 03:49:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=sbDE5YoPQ5LDaUOzkbvNwsC/CmtXqXRZ1kdmWzjwKVc=; b=erV1K++En2RlUx233aleUxuq/AgBkDvuRS29PUpXpWcasBkclME91Z5HBS7WnVbpEX +9OQpvmeV/9yp9J8jz/b5VQc3OQldKIrAfhkSjwxT5ZoXD9GnVPV1nnVteN8Dh++UWwh zc/x6i18tdJSdL61mmoivfKjRUOFDm+Y4pRO4hKrkp1Y7agAvWKQUnt8zlNNhXxZIchp JElRz2UPW2Y6TafIVgJpyGWdeSXg7l/sqbQ8n2WcHHeB02C6E0amvHSQ1LN3zlFsP+2Q 3H189F2H6I6QGIrPkbtsCYjpyoqFjaW30ej4Qr6qpEKyl8bv+RHIGK6NQHmw0IziGlpk iFzQ== X-Received: by 10.15.102.3 with SMTP id bq3mr38198069eeb.42.1365850141941; Sat, 13 Apr 2013 03:49:01 -0700 (PDT) Received: from localhost.localdomain (stgt-5f71827d.pool.mediaWays.net. [95.113.130.125]) by mx.google.com with ESMTPS id t4sm15859796eel.0.2013.04.13.03.49.00 (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 13 Apr 2013 03:49:01 -0700 (PDT) From: David Herrmann To: linux-input@vger.kernel.org Cc: Jiri Kosina , David Herrmann Subject: [PATCH 20/21] HID: wiimote: add sysfs extension/device-type attrs Date: Sat, 13 Apr 2013 12:48:01 +0200 Message-Id: <1365850082-3585-21-git-send-email-dh.herrmann@gmail.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1365850082-3585-1-git-send-email-dh.herrmann@gmail.com> References: <1365850082-3585-1-git-send-email-dh.herrmann@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Two new attributes, "extension" and "device" 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. Signed-off-by: David Herrmann --- drivers/hid/hid-wiimote-core.c | 106 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 126c9d9..c5b5207 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1139,11 +1139,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) @@ -1562,6 +1569,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, "none\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(device, S_IRUGO, wiimote_dev_show, NULL); + static struct wiimote_data *wiimote_create(struct hid_device *hdev) { struct wiimote_data *wdata; @@ -1602,6 +1687,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_device); + device_remove_file(&wdata->hdev->dev, &dev_attr_extension); + wiimote_mp_unload(wdata); wiimote_ext_unload(wdata); wiimote_modules_unload(wdata); @@ -1644,6 +1732,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_device); + if (ret) { + hid_err(hdev, "cannot create sysfs attribute\n"); + goto err_ext; + } + ret = wiidebug_init(wdata); if (ret) goto err_free; @@ -1659,6 +1759,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: