brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 6f93316 Raw
195 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * bebob_hwdep.c - a part of driver for BeBoB based devices4 *5 * Copyright (c) 2013-2014 Takashi Sakamoto6 */7 8/*9 * This codes give three functionality.10 *11 * 1.get firewire node infomation12 * 2.get notification about starting/stopping stream13 * 3.lock/unlock stream14 */15 16#include "bebob.h"17 18static long19hwdep_read(struct snd_hwdep *hwdep, char __user *buf,  long count,20	   loff_t *offset)21{22	struct snd_bebob *bebob = hwdep->private_data;23	DEFINE_WAIT(wait);24	union snd_firewire_event event;25 26	spin_lock_irq(&bebob->lock);27 28	while (!bebob->dev_lock_changed) {29		prepare_to_wait(&bebob->hwdep_wait, &wait, TASK_INTERRUPTIBLE);30		spin_unlock_irq(&bebob->lock);31		schedule();32		finish_wait(&bebob->hwdep_wait, &wait);33		if (signal_pending(current))34			return -ERESTARTSYS;35		spin_lock_irq(&bebob->lock);36	}37 38	memset(&event, 0, sizeof(event));39	count = min_t(long, count, sizeof(event.lock_status));40	event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;41	event.lock_status.status = (bebob->dev_lock_count > 0);42	bebob->dev_lock_changed = false;43 44	spin_unlock_irq(&bebob->lock);45 46	if (copy_to_user(buf, &event, count))47		return -EFAULT;48 49	return count;50}51 52static __poll_t53hwdep_poll(struct snd_hwdep *hwdep, struct file *file, poll_table *wait)54{55	struct snd_bebob *bebob = hwdep->private_data;56	__poll_t events;57 58	poll_wait(file, &bebob->hwdep_wait, wait);59 60	spin_lock_irq(&bebob->lock);61	if (bebob->dev_lock_changed)62		events = EPOLLIN | EPOLLRDNORM;63	else64		events = 0;65	spin_unlock_irq(&bebob->lock);66 67	return events;68}69 70static int71hwdep_get_info(struct snd_bebob *bebob, void __user *arg)72{73	struct fw_device *dev = fw_parent_device(bebob->unit);74	struct snd_firewire_get_info info;75 76	memset(&info, 0, sizeof(info));77	info.type = SNDRV_FIREWIRE_TYPE_BEBOB;78	info.card = dev->card->index;79	*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);80	*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);81	strscpy(info.device_name, dev_name(&dev->device),82		sizeof(info.device_name));83 84	if (copy_to_user(arg, &info, sizeof(info)))85		return -EFAULT;86 87	return 0;88}89 90static int91hwdep_lock(struct snd_bebob *bebob)92{93	int err;94 95	spin_lock_irq(&bebob->lock);96 97	if (bebob->dev_lock_count == 0) {98		bebob->dev_lock_count = -1;99		err = 0;100	} else {101		err = -EBUSY;102	}103 104	spin_unlock_irq(&bebob->lock);105 106	return err;107}108 109static int110hwdep_unlock(struct snd_bebob *bebob)111{112	int err;113 114	spin_lock_irq(&bebob->lock);115 116	if (bebob->dev_lock_count == -1) {117		bebob->dev_lock_count = 0;118		err = 0;119	} else {120		err = -EBADFD;121	}122 123	spin_unlock_irq(&bebob->lock);124 125	return err;126}127 128static int129hwdep_release(struct snd_hwdep *hwdep, struct file *file)130{131	struct snd_bebob *bebob = hwdep->private_data;132 133	spin_lock_irq(&bebob->lock);134	if (bebob->dev_lock_count == -1)135		bebob->dev_lock_count = 0;136	spin_unlock_irq(&bebob->lock);137 138	return 0;139}140 141static int142hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file,143	    unsigned int cmd, unsigned long arg)144{145	struct snd_bebob *bebob = hwdep->private_data;146 147	switch (cmd) {148	case SNDRV_FIREWIRE_IOCTL_GET_INFO:149		return hwdep_get_info(bebob, (void __user *)arg);150	case SNDRV_FIREWIRE_IOCTL_LOCK:151		return hwdep_lock(bebob);152	case SNDRV_FIREWIRE_IOCTL_UNLOCK:153		return hwdep_unlock(bebob);154	default:155		return -ENOIOCTLCMD;156	}157}158 159#ifdef CONFIG_COMPAT160static int161hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,162		   unsigned int cmd, unsigned long arg)163{164	return hwdep_ioctl(hwdep, file, cmd,165			   (unsigned long)compat_ptr(arg));166}167#else168#define hwdep_compat_ioctl NULL169#endif170 171int snd_bebob_create_hwdep_device(struct snd_bebob *bebob)172{173	static const struct snd_hwdep_ops ops = {174		.read		= hwdep_read,175		.release	= hwdep_release,176		.poll		= hwdep_poll,177		.ioctl		= hwdep_ioctl,178		.ioctl_compat	= hwdep_compat_ioctl,179	};180	struct snd_hwdep *hwdep;181	int err;182 183	err = snd_hwdep_new(bebob->card, "BeBoB", 0, &hwdep);184	if (err < 0)185		goto end;186	strcpy(hwdep->name, "BeBoB");187	hwdep->iface = SNDRV_HWDEP_IFACE_FW_BEBOB;188	hwdep->ops = ops;189	hwdep->private_data = bebob;190	hwdep->exclusive = true;191end:192	return err;193}194 195