From patchwork Sun May 18 13:36:31 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 4197961 X-Patchwork-Delegate: tiwai@suse.de Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E6D51BEEAB for ; Sun, 18 May 2014 13:38:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BA66920274 for ; Sun, 18 May 2014 13:38:24 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 0A848201EC for ; Sun, 18 May 2014 13:38:23 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id DAE162651E6; Sun, 18 May 2014 15:38:21 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 6172B26500B; Sun, 18 May 2014 15:37:04 +0200 (CEST) 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 53EDA265004; Sun, 18 May 2014 15:37:01 +0200 (CEST) Received: from smtp302.phy.lolipop.jp (smtp302.phy.lolipop.jp [210.157.22.85]) by alsa0.perex.cz (Postfix) with ESMTP id 6B884264F34 for ; Sun, 18 May 2014 15:36:54 +0200 (CEST) Received: from smtp302.phy.lolipop.lan (HELO smtp302.phy.lolipop.jp) (172.17.1.85) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp302.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Sun, 18 May 2014 22:36:53 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp302.phy.lolipop.jp (LOLIPOP-Fsecure); Sun, 18 May 2014 22:36:39 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de Date: Sun, 18 May 2014 22:36:31 +0900 Message-Id: <1400420198-24312-7-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1400420198-24312-1-git-send-email-o-takashi@sakamocchi.jp> References: <1400420198-24312-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, ffado-devel@lists.sf.net Subject: [alsa-devel] [PATCH 06/13] dice: Split hwdep functionality into a file 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: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This commit adds a file and move some codes related to hwdep functionality. This interface is designed for mixer/control application. By using hwdep interface, the application can get information about firewire node, can lock/unlock kernel streaming and can get notification at starting/stopping kernel streaming. Additionally, this interface give a way to read Dice notification. Signed-off-by: Takashi Sakamoto --- sound/firewire/dice/Makefile | 3 +- sound/firewire/dice/dice.c | 182 +------------------------------------ sound/firewire/dice/dice.h | 2 + sound/firewire/dice/dice_hwdep.c | 190 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 182 deletions(-) create mode 100644 sound/firewire/dice/dice_hwdep.c diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile index c0e13aa..a11cc96 100644 --- a/sound/firewire/dice/Makefile +++ b/sound/firewire/dice/Makefile @@ -1,2 +1,3 @@ -snd-dice-objs := dice_transaction.o dice_stream.o dice_pcm.o dice.o +snd-dice-objs := dice_transaction.o dice_stream.o dice_pcm.o dice_hwdep.o \ + dice.o obj-m += snd-dice.o diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 74a3720..8a80a8f 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -11,186 +11,6 @@ MODULE_DESCRIPTION("DICE driver"); MODULE_AUTHOR("Clemens Ladisch "); MODULE_LICENSE("GPL v2"); -static long dice_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, - long count, loff_t *offset) -{ - struct snd_dice *dice = hwdep->private_data; - DEFINE_WAIT(wait); - union snd_firewire_event event; - - spin_lock_irq(&dice->lock); - - while (!dice->dev_lock_changed && dice->notification_bits == 0) { - prepare_to_wait(&dice->hwdep_wait, &wait, TASK_INTERRUPTIBLE); - spin_unlock_irq(&dice->lock); - schedule(); - finish_wait(&dice->hwdep_wait, &wait); - if (signal_pending(current)) - return -ERESTARTSYS; - spin_lock_irq(&dice->lock); - } - - memset(&event, 0, sizeof(event)); - if (dice->dev_lock_changed) { - event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; - event.lock_status.status = dice->dev_lock_count > 0; - dice->dev_lock_changed = false; - - count = min_t(long, count, sizeof(event.lock_status)); - } else { - event.dice_notification.type = - SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION; - event.dice_notification.notification = dice->notification_bits; - dice->notification_bits = 0; - - count = min_t(long, count, sizeof(event.dice_notification)); - } - - spin_unlock_irq(&dice->lock); - - if (copy_to_user(buf, &event, count)) - return -EFAULT; - - return count; -} - -static unsigned int dice_hwdep_poll(struct snd_hwdep *hwdep, struct file *file, - poll_table *wait) -{ - struct snd_dice *dice = hwdep->private_data; - unsigned int events; - - poll_wait(file, &dice->hwdep_wait, wait); - - spin_lock_irq(&dice->lock); - if (dice->dev_lock_changed || dice->notification_bits != 0) - events = POLLIN | POLLRDNORM; - else - events = 0; - spin_unlock_irq(&dice->lock); - - return events; -} - -static int dice_hwdep_get_info(struct snd_dice *dice, void __user *arg) -{ - struct fw_device *dev = fw_parent_device(dice->unit); - struct snd_firewire_get_info info; - - memset(&info, 0, sizeof(info)); - info.type = SNDRV_FIREWIRE_TYPE_DICE; - info.card = dev->card->index; - *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); - *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); - strlcpy(info.device_name, dev_name(&dev->device), - sizeof(info.device_name)); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - - return 0; -} - -static int dice_hwdep_lock(struct snd_dice *dice) -{ - int err; - - spin_lock_irq(&dice->lock); - - if (dice->dev_lock_count == 0) { - dice->dev_lock_count = -1; - err = 0; - } else { - err = -EBUSY; - } - - spin_unlock_irq(&dice->lock); - - return err; -} - -static int dice_hwdep_unlock(struct snd_dice *dice) -{ - int err; - - spin_lock_irq(&dice->lock); - - if (dice->dev_lock_count == -1) { - dice->dev_lock_count = 0; - err = 0; - } else { - err = -EBADFD; - } - - spin_unlock_irq(&dice->lock); - - return err; -} - -static int dice_hwdep_release(struct snd_hwdep *hwdep, struct file *file) -{ - struct snd_dice *dice = hwdep->private_data; - - spin_lock_irq(&dice->lock); - if (dice->dev_lock_count == -1) - dice->dev_lock_count = 0; - spin_unlock_irq(&dice->lock); - - return 0; -} - -static int dice_hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct snd_dice *dice = hwdep->private_data; - - switch (cmd) { - case SNDRV_FIREWIRE_IOCTL_GET_INFO: - return dice_hwdep_get_info(dice, (void __user *)arg); - case SNDRV_FIREWIRE_IOCTL_LOCK: - return dice_hwdep_lock(dice); - case SNDRV_FIREWIRE_IOCTL_UNLOCK: - return dice_hwdep_unlock(dice); - default: - return -ENOIOCTLCMD; - } -} - -#ifdef CONFIG_COMPAT -static int dice_hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return dice_hwdep_ioctl(hwdep, file, cmd, - (unsigned long)compat_ptr(arg)); -} -#else -#define dice_hwdep_compat_ioctl NULL -#endif - -static int dice_create_hwdep(struct snd_dice *dice) -{ - static const struct snd_hwdep_ops ops = { - .read = dice_hwdep_read, - .release = dice_hwdep_release, - .poll = dice_hwdep_poll, - .ioctl = dice_hwdep_ioctl, - .ioctl_compat = dice_hwdep_compat_ioctl, - }; - struct snd_hwdep *hwdep; - int err; - - err = snd_hwdep_new(dice->card, "DICE", 0, &hwdep); - if (err < 0) - return err; - strcpy(hwdep->name, "DICE"); - hwdep->iface = SNDRV_HWDEP_IFACE_FW_DICE; - hwdep->ops = ops; - hwdep->private_data = dice; - hwdep->exclusive = true; - - return 0; -} - static int dice_proc_read_mem(struct snd_dice *dice, void *buffer, unsigned int offset_q, unsigned int quadlets) { @@ -695,7 +515,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) if (err < 0) goto error; - err = dice_create_hwdep(dice); + err = snd_dice_create_hwdep(dice); if (err < 0) goto error; diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 4d9e55b..dcc8c78 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -173,4 +173,6 @@ void snd_dice_stream_lock_release(struct snd_dice *dice); int snd_dice_create_pcm(struct snd_dice *dice); +int snd_dice_create_hwdep(struct snd_dice *dice); + #endif diff --git a/sound/firewire/dice/dice_hwdep.c b/sound/firewire/dice/dice_hwdep.c new file mode 100644 index 0000000..8c1cf49 --- /dev/null +++ b/sound/firewire/dice/dice_hwdep.c @@ -0,0 +1,190 @@ +/* + * dice_hwdep.c - a part of driver for DICE based devices + * + * Copyright (c) Clemens Ladisch + * Copyright (c) 2014 Takashi Sakamoto + * + * Licensed under the terms of the GNU General Public License, version 2. + */ + +#include "dice.h" + +static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, + long count, loff_t *offset) +{ + struct snd_dice *dice = hwdep->private_data; + DEFINE_WAIT(wait); + union snd_firewire_event event; + + spin_lock_irq(&dice->lock); + + while (!dice->dev_lock_changed && dice->notification_bits == 0) { + prepare_to_wait(&dice->hwdep_wait, &wait, TASK_INTERRUPTIBLE); + spin_unlock_irq(&dice->lock); + schedule(); + finish_wait(&dice->hwdep_wait, &wait); + if (signal_pending(current)) + return -ERESTARTSYS; + spin_lock_irq(&dice->lock); + } + + memset(&event, 0, sizeof(event)); + if (dice->dev_lock_changed) { + event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS; + event.lock_status.status = dice->dev_lock_count > 0; + dice->dev_lock_changed = false; + + count = min_t(long, count, sizeof(event.lock_status)); + } else { + event.dice_notification.type = + SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION; + event.dice_notification.notification = dice->notification_bits; + dice->notification_bits = 0; + + count = min_t(long, count, sizeof(event.dice_notification)); + } + + spin_unlock_irq(&dice->lock); + + if (copy_to_user(buf, &event, count)) + return -EFAULT; + + return count; +} + +static unsigned int hwdep_poll(struct snd_hwdep *hwdep, struct file *file, + poll_table *wait) +{ + struct snd_dice *dice = hwdep->private_data; + unsigned int events; + + poll_wait(file, &dice->hwdep_wait, wait); + + spin_lock_irq(&dice->lock); + if (dice->dev_lock_changed || dice->notification_bits != 0) + events = POLLIN | POLLRDNORM; + else + events = 0; + spin_unlock_irq(&dice->lock); + + return events; +} + +static int hwdep_get_info(struct snd_dice *dice, void __user *arg) +{ + struct fw_device *dev = fw_parent_device(dice->unit); + struct snd_firewire_get_info info; + + memset(&info, 0, sizeof(info)); + info.type = SNDRV_FIREWIRE_TYPE_DICE; + info.card = dev->card->index; + *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]); + *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]); + strlcpy(info.device_name, dev_name(&dev->device), + sizeof(info.device_name)); + + if (copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; + + return 0; +} + +static int hwdep_lock(struct snd_dice *dice) +{ + int err; + + spin_lock_irq(&dice->lock); + + if (dice->dev_lock_count == 0) { + dice->dev_lock_count = -1; + err = 0; + } else { + err = -EBUSY; + } + + spin_unlock_irq(&dice->lock); + + return err; +} + +static int hwdep_unlock(struct snd_dice *dice) +{ + int err; + + spin_lock_irq(&dice->lock); + + if (dice->dev_lock_count == -1) { + dice->dev_lock_count = 0; + err = 0; + } else { + err = -EBADFD; + } + + spin_unlock_irq(&dice->lock); + + return err; +} + +static int hwdep_release(struct snd_hwdep *hwdep, struct file *file) +{ + struct snd_dice *dice = hwdep->private_data; + + spin_lock_irq(&dice->lock); + if (dice->dev_lock_count == -1) + dice->dev_lock_count = 0; + spin_unlock_irq(&dice->lock); + + return 0; +} + +static int hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct snd_dice *dice = hwdep->private_data; + + switch (cmd) { + case SNDRV_FIREWIRE_IOCTL_GET_INFO: + return hwdep_get_info(dice, (void __user *)arg); + case SNDRV_FIREWIRE_IOCTL_LOCK: + return hwdep_lock(dice); + case SNDRV_FIREWIRE_IOCTL_UNLOCK: + return hwdep_unlock(dice); + default: + return -ENOIOCTLCMD; + } +} + +#ifdef CONFIG_COMPAT +static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return hwdep_ioctl(hwdep, file, cmd, + (unsigned long)compat_ptr(arg)); +} +#else +#define dice_hwdep_compat_ioctl NULL +#endif + +int snd_dice_create_hwdep(struct snd_dice *dice) +{ + static const struct snd_hwdep_ops ops = { + .read = hwdep_read, + .release = hwdep_release, + .poll = hwdep_poll, + .ioctl = hwdep_ioctl, + .ioctl_compat = hwdep_compat_ioctl, + }; + struct snd_hwdep *hwdep; + int err; + + err = snd_hwdep_new(dice->card, "DICE", 0, &hwdep); + if (err < 0) + return err; + strcpy(hwdep->name, "DICE"); + hwdep->iface = SNDRV_HWDEP_IFACE_FW_DICE; + hwdep->ops = ops; + hwdep->private_data = dice; + hwdep->exclusive = true; + + return 0; +}