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

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

Version: ~ [ linux-5.16-rc3 ] ~ [ linux-5.15.5 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.82 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.162 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.218 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.256 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.291 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.293 ] ~ [ 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(struct snd_hwdep *hwdep, char __user *buf, long count,
 20                        loff_t *offset)
 21 {
 22         struct snd_tscm *tscm = hwdep->private_data;
 23         DEFINE_WAIT(wait);
 24         union snd_firewire_event event = {
 25                 .lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS,
 26         };
 27 
 28         spin_lock_irq(&tscm->lock);
 29 
 30         while (!tscm->dev_lock_changed) {
 31                 prepare_to_wait(&tscm->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
 32                 spin_unlock_irq(&tscm->lock);
 33                 schedule();
 34                 finish_wait(&tscm->hwdep_wait, &wait);
 35                 if (signal_pending(current))
 36                         return -ERESTARTSYS;
 37                 spin_lock_irq(&tscm->lock);
 38         }
 39 
 40         event.lock_status.status = (tscm->dev_lock_count > 0);
 41         tscm->dev_lock_changed = false;
 42 
 43         spin_unlock_irq(&tscm->lock);
 44 
 45         count = min_t(long, count, sizeof(event.lock_status));
 46 
 47         if (copy_to_user(buf, &event, count))
 48                 return -EFAULT;
 49 
 50         return count;
 51 }
 52 
 53 static unsigned int hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
 54                                poll_table *wait)
 55 {
 56         struct snd_tscm *tscm = hwdep->private_data;
 57         unsigned int events;
 58 
 59         poll_wait(file, &tscm->hwdep_wait, wait);
 60 
 61         spin_lock_irq(&tscm->lock);
 62         if (tscm->dev_lock_changed)
 63                 events = POLLIN | POLLRDNORM;
 64         else
 65                 events = 0;
 66         spin_unlock_irq(&tscm->lock);
 67 
 68         return events;
 69 }
 70 
 71 static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg)
 72 {
 73         struct fw_device *dev = fw_parent_device(tscm->unit);
 74         struct snd_firewire_get_info info;
 75 
 76         memset(&info, 0, sizeof(info));
 77         info.type = SNDRV_FIREWIRE_TYPE_TASCAM;
 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         strlcpy(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 
 90 static int hwdep_lock(struct snd_tscm *tscm)
 91 {
 92         int err;
 93 
 94         spin_lock_irq(&tscm->lock);
 95 
 96         if (tscm->dev_lock_count == 0) {
 97                 tscm->dev_lock_count = -1;
 98                 err = 0;
 99         } else {
100                 err = -EBUSY;
101         }
102 
103         spin_unlock_irq(&tscm->lock);
104 
105         return err;
106 }
107 
108 static int hwdep_unlock(struct snd_tscm *tscm)
109 {
110         int err;
111 
112         spin_lock_irq(&tscm->lock);
113 
114         if (tscm->dev_lock_count == -1) {
115                 tscm->dev_lock_count = 0;
116                 err = 0;
117         } else {
118                 err = -EBADFD;
119         }
120 
121         spin_unlock_irq(&tscm->lock);
122 
123         return err;
124 }
125 
126 static int hwdep_release(struct snd_hwdep *hwdep, struct file *file)
127 {
128         struct snd_tscm *tscm = hwdep->private_data;
129 
130         spin_lock_irq(&tscm->lock);
131         if (tscm->dev_lock_count == -1)
132                 tscm->dev_lock_count = 0;
133         spin_unlock_irq(&tscm->lock);
134 
135         return 0;
136 }
137 
138 static int hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file,
139             unsigned int cmd, unsigned long arg)
140 {
141         struct snd_tscm *tscm = hwdep->private_data;
142 
143         switch (cmd) {
144         case SNDRV_FIREWIRE_IOCTL_GET_INFO:
145                 return hwdep_get_info(tscm, (void __user *)arg);
146         case SNDRV_FIREWIRE_IOCTL_LOCK:
147                 return hwdep_lock(tscm);
148         case SNDRV_FIREWIRE_IOCTL_UNLOCK:
149                 return hwdep_unlock(tscm);
150         default:
151                 return -ENOIOCTLCMD;
152         }
153 }
154 
155 #ifdef CONFIG_COMPAT
156 static int hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
157                               unsigned int cmd, unsigned long arg)
158 {
159         return hwdep_ioctl(hwdep, file, cmd,
160                            (unsigned long)compat_ptr(arg));
161 }
162 #else
163 #define hwdep_compat_ioctl NULL
164 #endif
165 
166 static const struct snd_hwdep_ops hwdep_ops = {
167         .read           = hwdep_read,
168         .release        = hwdep_release,
169         .poll           = hwdep_poll,
170         .ioctl          = hwdep_ioctl,
171         .ioctl_compat   = hwdep_compat_ioctl,
172 };
173 
174 int snd_tscm_create_hwdep_device(struct snd_tscm *tscm)
175 {
176         struct snd_hwdep *hwdep;
177         int err;
178 
179         err = snd_hwdep_new(tscm->card, "Tascam", 0, &hwdep);
180         if (err < 0)
181                 return err;
182 
183         strcpy(hwdep->name, "Tascam");
184         hwdep->iface = SNDRV_HWDEP_IFACE_FW_TASCAM;
185         hwdep->ops = hwdep_ops;
186         hwdep->private_data = tscm;
187         hwdep->exclusive = true;
188 
189         return err;
190 }
191 

~ [ 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