From patchwork Thu Jul 28 16:08:31 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Herrmann X-Patchwork-Id: 1016862 X-Patchwork-Delegate: jikos@jikos.cz Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6SG9C9L028415 for ; Thu, 28 Jul 2011 16:09:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755002Ab1G1QJT (ORCPT ); Thu, 28 Jul 2011 12:09:19 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:53946 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755154Ab1G1QJS (ORCPT ); Thu, 28 Jul 2011 12:09:18 -0400 Received: by mail-fx0-f46.google.com with SMTP id 19so1400102fxh.19 for ; Thu, 28 Jul 2011 09:09:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=+yxIlEluAOOYKTylAKKhJ/d3SntOQv6eAaaOr0eJ6RM=; b=G5BsGur7fxu5FCbehiVD9IgxBxQXpe1OSo+HyQq6jkP8WZA7+1L1Ye9obd5xpeDd2B I+KrxDV/dTZ08Ng1TkepH0aARvRkrOo5F7akAVQh4i9dKmtCAZz6Tm8SYXBJ6IWOUsD3 +ExFjedkp9nHWWe/dJdQXYY9ogjgn19gPVQPc= Received: by 10.223.100.197 with SMTP id z5mr247851fan.46.1311869358250; Thu, 28 Jul 2011 09:09:18 -0700 (PDT) Received: from localhost.localdomain (stgt-5f739959.pool.mediaWays.net [95.115.153.89]) by mx.google.com with ESMTPS id a2sm240315fak.1.2011.07.28.09.09.16 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 28 Jul 2011 09:09:17 -0700 (PDT) From: David Herrmann To: linux-input@vger.kernel.org Cc: jkosina@suse.cz, padovan@profusion.mobi, dh.herrmann@googlemail.com Subject: [PATCH 11/16] HID: wiimote: Helper functions for synchronous requests Date: Thu, 28 Jul 2011 18:08:31 +0200 Message-Id: <1311869316-17128-12-git-send-email-dh.herrmann@googlemail.com> X-Mailer: git-send-email 1.7.6 In-Reply-To: <1311869316-17128-1-git-send-email-dh.herrmann@googlemail.com> References: <1311869316-17128-1-git-send-email-dh.herrmann@googlemail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 28 Jul 2011 16:09:23 +0000 (UTC) To initialize wiimote peripherals, the stream to the wiimote must be held exclusively by the initializer, otherwise the initialization will fail. Many initializations require multiple memory requests to be sent synchronously so we need a way to lock the stream and release it when we are done. This adds several helper functions which allow to lock the stream, then send requests, wait for the answers and release the stream again. When holding the lock, the function may sleep and interrupted by signals. Also it returns after a short timeout so userspace shouldn't notice long delays. Signed-off-by: David Herrmann --- drivers/hid/hid-wiimote.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 7b59822..0181971 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -11,10 +11,12 @@ */ #include +#include #include #include #include #include +#include #include #include "hid-ids.h" @@ -31,6 +33,12 @@ struct wiimote_state { spinlock_t lock; __u8 flags; __u8 accel_split[2]; + + /* synchronous cmd requests */ + struct mutex sync; + struct completion ready; + int cmd; + __u32 opt; }; struct wiimote_data { @@ -116,6 +124,52 @@ static __u16 wiiproto_keymap[] = { #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ dev)) +/* requires the state.lock spinlock to be held */ +static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, + __u32 opt) +{ + return wdata->state.cmd == cmd && wdata->state.opt == opt; +} + +/* requires the state.lock spinlock to be held */ +static inline void wiimote_cmd_complete(struct wiimote_data *wdata) +{ + wdata->state.cmd = WIIPROTO_REQ_NULL; + complete(&wdata->state.ready); +} + +static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) +{ + return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; +} + +/* requires the state.lock spinlock to be held */ +static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, + __u32 opt) +{ + INIT_COMPLETION(wdata->state.ready); + wdata->state.cmd = cmd; + wdata->state.opt = opt; +} + +static inline void wiimote_cmd_release(struct wiimote_data *wdata) +{ + mutex_unlock(&wdata->state.sync); +} + +static inline int wiimote_cmd_wait(struct wiimote_data *wdata) +{ + int ret; + + ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); + if (ret < 0) + return -ERESTARTSYS; + else if (ret == 0) + return -EIO; + else + return 0; +} + static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, size_t count) { @@ -823,6 +877,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) INIT_WORK(&wdata->worker, wiimote_worker); spin_lock_init(&wdata->state.lock); + init_completion(&wdata->state.ready); + mutex_init(&wdata->state.sync); return wdata; }