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

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

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