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

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

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php