~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/firewire/tascam/tascam-hwdep.c

Version: ~ [ linux-5.16-rc1 ] ~ [ linux-5.15.2 ] ~ [ linux-5.14.18 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.79 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.159 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.217 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.255 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.290 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.292 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * tascam-hwdep.c - a part of driver for TASCAM FireWire series
  3  *
  4  * Copyright (c) 2015 Takashi Sakamoto
  5  *
  6  * Licensed under the terms of the GNU General Public License, version 2.
  7  */
  8 
  9 /*
 10  * This codes give three functionality.
 11  *
 12  * 1.get firewire node information
 13  * 2.get notification about starting/stopping stream
 14  * 3.lock/unlock stream
 15  */
 16 
 17 #include "tascam.h"
 18 
 19 static long hwdep_read_locked(struct snd_tscm *tscm, char __user *buf,
 20                               long count)
 21 {
 22         union snd_firewire_event event;
 23 
 24         memset(&event, 0, sizeof(event));
 25 
 26         event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
 27         event.lock_status.status = (tscm->dev_lock_count > 0);
 28         tscm->dev_lock_changed = false;
 29 
 30         count = min_t(long, count, sizeof(event.lock_status));
 31 
 32         if (copy_to_user(buf, &event, count))
 33                 return -EFAULT;
 34 
 35         return count;
 36 }
 37 
 38 static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
 39                        loff_t *offset)
 40 {
 41         struct snd_tscm *tscm = hwdep->private_data;
 42         DEFINE_WAIT(wait);
 43         union snd_firewire_event event;
 44 
 45         spin_lock_irq(&tscm->lock);
 46 
 47         while (!tscm->dev_lock_changed) {
 48                 prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
 49                 spin_unlock_irq(&tscm->lock);
 50                 schedule();
 51                 finish_wait(&tscm->hwdep_wait, &wait);
 52                 if (signal_pending(current))
 53                         return -ERESTARTSYS;
 54                 spin_lock_irq(&tscm->lock);
 55         }
 56 
 57         memset(&event, 0, sizeof(event));
 58         count = hwdep_read_locked(tscm, buf, count);
 59         spin_unlock_irq(&tscm->lock);
 60 
 61         return count;
 62 }
 63 
 64 static unsigned int hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
 65                                poll_table *wait)
 66 {
 67         struct snd_tscm *tscm = hwdep->private_data;
 68         unsigned int events;
 69 
 70         poll_wait(file, &tscm->hwdep_wait, wait);
 71 
 72         spin_lock_irq(&tscm->lock);
 73         if (tscm->dev_lock_changed)
 74                 events = POLLIN | POLLRDNORM;
 75         else
 76                 events = 0;
 77         spin_unlock_irq(&tscm->lock);
 78 
 79         return events;
 80 }
 81 
 82 static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg)
 83 {
 84         struct fw_device *dev = fw_parent_device(tscm->unit);
 85         struct snd_firewire_get_info info;
 86 
 87         memset(&info, 0, sizeof(info));
 88         info.type = SNDRV_FIREWIRE_TYPE_TASCAM;
 89         info.card = dev->card->index;
 90         *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
 91         *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
 92         strlcpy(info.device_name, dev_name(&dev->device),
 93                 sizeof(info.device_name));
 94 
 95         if (copy_to_user(arg, &info, sizeof(info)))
 96                 return -EFAULT;
 97 
 98         return 0;
 99 }
100 
101 static int hwdep_lock(struct snd_tscm *tscm)
102 {
103         int err;
104 
105         spin_lock_irq(&tscm->lock);
106 
107         if (tscm->dev_lock_count == 0) {
108                 tscm->dev_lock_count = -1;
109                 err = 0;
110         } else {
111                 err = -EBUSY;
112         }
113 
114         spin_unlock_irq(&tscm->lock);
115 
116         return err;
117 }
118 
119 static int hwdep_unlock(struct snd_tscm *tscm)
120 {
121         int err;
122 
123         spin_lock_irq(&tscm->lock);
124 
125         if (tscm->dev_lock_count == -1) {
126                 tscm->dev_lock_count = 0;
127                 err = 0;
128         } else {
129                 err = -EBADFD;
130         }
131 
132         spin_unlock_irq(&tscm->lock);
133 
134         return err;
135 }
136 
137 static int hwdep_release(struct snd_hwdep *hwdep, struct file *file)
138 {
139         struct snd_tscm *tscm = hwdep->private_data;
140 
141         spin_lock_irq(&tscm->lock);
142         if (tscm->dev_lock_count == -1)
143                 tscm->dev_lock_count = 0;
144         spin_unlock_irq(&tscm->lock);
145 
146         return 0;
147 }
148 
149 static int hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file,
150             unsigned int cmd, unsigned long arg)
151 {
152         struct snd_tscm *tscm = hwdep->private_data;
153 
154         switch (cmd) {
155         case SNDRV_FIREWIRE_IOCTL_GET_INFO:
156                 return hwdep_get_info(tscm, (void __user *)arg);
157         case SNDRV_FIREWIRE_IOCTL_LOCK:
158                 return hwdep_lock(tscm);
159         case SNDRV_FIREWIRE_IOCTL_UNLOCK:
160                 return hwdep_unlock(tscm);
161         default:
162                 return -ENOIOCTLCMD;
163         }
164 }
165 
166 #ifdef CONFIG_COMPAT
167 static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
168                               unsigned int cmd, unsigned long arg)
169 {
170         return hwdep_ioctl(hwdep, file, cmd,
171                            (unsigned long)compat_ptr(arg));
172 }
173 #else
174 #define hwdep_compat_ioctl NULL
175 #endif
176 
177 static const struct snd_hwdep_ops hwdep_ops = {
178         .read           = hwdep_read,
179         .release        = hwdep_release,
180         .poll           = hwdep_poll,
181         .ioctl          = hwdep_ioctl,
182         .ioctl_compat   = hwdep_compat_ioctl,
183 };
184 
185 int snd_tscm_create_hwdep_device(struct snd_tscm *tscm)
186 {
187         struct snd_hwdep *hwdep;
188         int err;
189 
190         err = snd_hwdep_new(tscm->card, "Tascam", 0, &hwdep);
191         if (err < 0)
192                 return err;
193 
194         strcpy(hwdep->name, "Tascam");
195         hwdep->iface = SNDRV_HWDEP_IFACE_FW_TASCAM;
196         hwdep->ops = hwdep_ops;
197         hwdep->private_data = tscm;
198         hwdep->exclusive = true;
199 
200         return err;
201 }
202 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp