root/sound/firewire/bebob/bebob_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_bebob_create_hwdep_device

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

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