From patchwork Fri Nov 23 04:13:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 10695035 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E210C5A4 for ; Fri, 23 Nov 2018 04:14:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D048B2BD84 for ; Fri, 23 Nov 2018 04:14:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C49652BD93; Fri, 23 Nov 2018 04:14:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0EFD52BD84 for ; Fri, 23 Nov 2018 04:14:17 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id C5C82267A95; Fri, 23 Nov 2018 05:13:50 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id DCAA1267A8F; Fri, 23 Nov 2018 05:13:45 +0100 (CET) Received: from mail-pf1-f196.google.com (mail-pf1-f196.google.com [209.85.210.196]) by alsa0.perex.cz (Postfix) with ESMTP id 0C629267A8A for ; Fri, 23 Nov 2018 05:13:41 +0100 (CET) Received: by mail-pf1-f196.google.com with SMTP id c73so2736770pfe.13 for ; Thu, 22 Nov 2018 20:13:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vP5KBYlSudCszTSafJMmz+gl/HGZ3dN6Iqvw5KCLcB0=; b=pFDLgEW4rsE9OyqaMCCYOwoA4lrWXY3ORq+OQGXlO5hakpD2yX5hXos5bzHIGwIA/6 fwPwlJ7L0Qy0ReOG5qAzob27j7jvYTHqYBaeArNLgHYB+DbpqsFQArgXe3P7srIetnEw FmZdtg0C7qm35yS3CftbUNrsEUplBO7wxdeak7UG7TIRQ0W74FKnAQRqXHLHffqQVmBz Iqhiq48YskGULr5Ac2vbEwQd6RZvCycf5yIDAS2QKLD2idvtF7LWwUl9o3dzfkx/UEqv QowNM4sZ4Etv9G39+spR9LzzQBIAiBP850FocfWi1fhdSkykNPbzC1//rk7cUFOOJwZ4 XsqQ== X-Gm-Message-State: AA+aEWZxT2yeoi3c/rnDljizZUKr2cL6FsA9jKukyi3utXG7/FJ1A1eT OAe66Pz/gS17r3iAc4f+LL2Ofpdg X-Google-Smtp-Source: AFSGD/WS7dZlWtYdDGF9RxDsqzNS1Sy9gSIcp2FJKeHE4e9lstAinhTZEfEOR67TvKfYH5HJ7p7lgA== X-Received: by 2002:a63:fb46:: with SMTP id w6mr12673176pgj.321.1542946421021; Thu, 22 Nov 2018 20:13:41 -0800 (PST) Received: from localhost.localdomain ([2405:6580:9660:3200:4919:eeb8:ecba:c7a8]) by smtp.gmail.com with ESMTPSA id r83sm82199559pfc.115.2018.11.22.20.13.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Nov 2018 20:13:40 -0800 (PST) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de Date: Fri, 23 Nov 2018 13:13:07 +0900 Message-Id: <20181123041307.22980-6-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181123041307.22980-1-o-takashi@sakamocchi.jp> References: <20181123041307.22980-1-o-takashi@sakamocchi.jp> MIME-Version: 1.0 Cc: sbahling@suse.com, alsa-devel@alsa-project.org, ffado-devel@lists.sourceforge.net Subject: [alsa-devel] [PATCH 5/5] ALSA: firewire-tascam: notify events of change of state for userspace applications X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP In former commits, ALSA firewire-tascam driver queues events to notify change of state of control surface to userspace via ALSA hwdep interface. This commit implements actual notification of the events. The events are not governed by real time, thus no need to care underrun. Signed-off-by: Takashi Sakamoto --- include/uapi/sound/firewire.h | 7 +++ sound/firewire/tascam/amdtp-tascam.c | 2 + sound/firewire/tascam/tascam-hwdep.c | 65 +++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h index bb067efb09c6..ae12826ed641 100644 --- a/include/uapi/sound/firewire.h +++ b/include/uapi/sound/firewire.h @@ -12,6 +12,7 @@ #define SNDRV_FIREWIRE_EVENT_EFW_RESPONSE 0x4e617475 #define SNDRV_FIREWIRE_EVENT_DIGI00X_MESSAGE 0x746e736c #define SNDRV_FIREWIRE_EVENT_MOTU_NOTIFICATION 0x64776479 +#define SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL 0x7473636d struct snd_firewire_event_common { unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */ @@ -59,12 +60,18 @@ struct snd_firewire_tascam_change { __be32 after; }; +struct snd_firewire_event_tascam_control { + unsigned int type; + struct snd_firewire_tascam_change changes[0]; +}; + union snd_firewire_event { struct snd_firewire_event_common common; struct snd_firewire_event_lock_status lock_status; struct snd_firewire_event_dice_notification dice_notification; struct snd_firewire_event_efw_response efw_response; struct snd_firewire_event_digi00x_message digi00x_message; + struct snd_firewire_event_tascam_control tascam_control; struct snd_firewire_event_motu_notification motu_notification; }; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 0e8088c9ada9..a52d1f76c610 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -156,6 +156,8 @@ static void read_status_messages(struct amdtp_stream *s, if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT) tscm->push_pos = 0; spin_unlock_irq(&tscm->lock); + + wake_up(&tscm->hwdep_wait); } } diff --git a/sound/firewire/tascam/tascam-hwdep.c b/sound/firewire/tascam/tascam-hwdep.c index 8f34cede2e9f..0414abf5daa8 100644 --- a/sound/firewire/tascam/tascam-hwdep.c +++ b/sound/firewire/tascam/tascam-hwdep.c @@ -35,6 +35,65 @@ static long tscm_hwdep_read_locked(struct snd_tscm *tscm, char __user *buf, return count; } +static long tscm_hwdep_read_queue(struct snd_tscm *tscm, char __user *buf, + long remained, loff_t *offset) +{ + char __user *pos = buf; + unsigned int type = SNDRV_FIREWIRE_EVENT_TASCAM_CONTROL; + struct snd_firewire_tascam_change *entries = tscm->queue; + long count; + + // At least, one control event can be copied. + if (remained < sizeof(type) + sizeof(*entries)) { + spin_unlock_irq(&tscm->lock); + return -EINVAL; + } + + // Copy the type field later. + count = sizeof(type); + remained -= sizeof(type); + pos += sizeof(type); + + while (true) { + unsigned int head_pos; + unsigned int tail_pos; + unsigned int length; + + if (tscm->pull_pos == tscm->push_pos) + break; + else if (tscm->pull_pos < tscm->push_pos) + tail_pos = tscm->push_pos; + else + tail_pos = SND_TSCM_QUEUE_COUNT; + head_pos = tscm->pull_pos; + + length = (tail_pos - head_pos) * sizeof(*entries); + if (remained < length) + length = rounddown(remained, sizeof(*entries)); + if (length == 0) + break; + + spin_unlock_irq(&tscm->lock); + if (copy_to_user(pos, &entries[head_pos], length)) + return -EFAULT; + + spin_lock_irq(&tscm->lock); + + tscm->pull_pos = tail_pos % SND_TSCM_QUEUE_COUNT; + + count += length; + remained -= length; + pos += length; + } + + spin_unlock_irq(&tscm->lock); + + if (copy_to_user(buf, &type, sizeof(type))) + return -EFAULT; + + return count; +} + static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, loff_t *offset) { @@ -43,7 +102,7 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, spin_lock_irq(&tscm->lock); - while (!tscm->dev_lock_changed) { + while (!tscm->dev_lock_changed && tscm->push_pos == tscm->pull_pos) { prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE); spin_unlock_irq(&tscm->lock); schedule(); @@ -56,6 +115,8 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, // NOTE: The acquired lock should be released in callee side. if (tscm->dev_lock_changed) { count = tscm_hwdep_read_locked(tscm, buf, count, offset); + } else if (tscm->push_pos != tscm->pull_pos) { + count = tscm_hwdep_read_queue(tscm, buf, count, offset); } else { spin_unlock_irq(&tscm->lock); count = 0; @@ -73,7 +134,7 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_wait(file, &tscm->hwdep_wait, wait); spin_lock_irq(&tscm->lock); - if (tscm->dev_lock_changed) + if (tscm->dev_lock_changed || tscm->push_pos != tscm->pull_pos) events = EPOLLIN | EPOLLRDNORM; else events = 0;