root/sound/firewire/dice/dice-hwdep.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hwdep_read
  2. hwdep_poll
  3. hwdep_get_info
  4. hwdep_lock
  5. hwdep_unlock
  6. hwdep_release
  7. hwdep_ioctl
  8. hwdep_compat_ioctl
  9. snd_dice_create_hwdep

   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         strlcpy(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 }

/* [<][>][^][v][top][bottom][index][help] */