Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
device.c
Go to the documentation of this file.
1 /*
2  * Device management routines
3  * Copyright (c) by Jaroslav Kysela <[email protected]>
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include <linux/slab.h>
23 #include <linux/time.h>
24 #include <linux/export.h>
25 #include <linux/errno.h>
26 #include <sound/core.h>
27 
45  void *device_data, struct snd_device_ops *ops)
46 {
47  struct snd_device *dev;
48 
49  if (snd_BUG_ON(!card || !device_data || !ops))
50  return -ENXIO;
51  dev = kzalloc(sizeof(*dev), GFP_KERNEL);
52  if (dev == NULL) {
53  snd_printk(KERN_ERR "Cannot allocate device\n");
54  return -ENOMEM;
55  }
56  dev->card = card;
57  dev->type = type;
58  dev->state = SNDRV_DEV_BUILD;
59  dev->device_data = device_data;
60  dev->ops = ops;
61  list_add(&dev->list, &card->devices); /* add to the head of list */
62  return 0;
63 }
64 
66 
80 {
81  struct snd_device *dev;
82 
83  if (snd_BUG_ON(!card || !device_data))
84  return -ENXIO;
85  list_for_each_entry(dev, &card->devices, list) {
86  if (dev->device_data != device_data)
87  continue;
88  /* unlink */
89  list_del(&dev->list);
90  if (dev->state == SNDRV_DEV_REGISTERED &&
91  dev->ops->dev_disconnect)
92  if (dev->ops->dev_disconnect(dev))
94  "device disconnect failure\n");
95  if (dev->ops->dev_free) {
96  if (dev->ops->dev_free(dev))
97  snd_printk(KERN_ERR "device free failure\n");
98  }
99  kfree(dev);
100  return 0;
101  }
102  snd_printd("device free %p (from %pF), not found\n", device_data,
103  __builtin_return_address(0));
104  return -ENXIO;
105 }
106 
108 
123 {
124  struct snd_device *dev;
125 
126  if (snd_BUG_ON(!card || !device_data))
127  return -ENXIO;
128  list_for_each_entry(dev, &card->devices, list) {
129  if (dev->device_data != device_data)
130  continue;
131  if (dev->state == SNDRV_DEV_REGISTERED &&
132  dev->ops->dev_disconnect) {
133  if (dev->ops->dev_disconnect(dev))
134  snd_printk(KERN_ERR "device disconnect failure\n");
136  }
137  return 0;
138  }
139  snd_printd("device disconnect %p (from %pF), not found\n", device_data,
140  __builtin_return_address(0));
141  return -ENXIO;
142 }
143 
158 {
159  struct snd_device *dev;
160  int err;
161 
162  if (snd_BUG_ON(!card || !device_data))
163  return -ENXIO;
164  list_for_each_entry(dev, &card->devices, list) {
165  if (dev->device_data != device_data)
166  continue;
167  if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
168  if ((err = dev->ops->dev_register(dev)) < 0)
169  return err;
171  return 0;
172  }
173  snd_printd("snd_device_register busy\n");
174  return -EBUSY;
175  }
176  snd_BUG();
177  return -ENXIO;
178 }
179 
181 
182 /*
183  * register all the devices on the card.
184  * called from init.c
185  */
187 {
188  struct snd_device *dev;
189  int err;
190 
191  if (snd_BUG_ON(!card))
192  return -ENXIO;
193  list_for_each_entry(dev, &card->devices, list) {
194  if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
195  if ((err = dev->ops->dev_register(dev)) < 0)
196  return err;
198  }
199  }
200  return 0;
201 }
202 
203 /*
204  * disconnect all the devices on the card.
205  * called from init.c
206  */
208 {
209  struct snd_device *dev;
210  int err = 0;
211 
212  if (snd_BUG_ON(!card))
213  return -ENXIO;
214  list_for_each_entry(dev, &card->devices, list) {
215  if (snd_device_disconnect(card, dev->device_data) < 0)
216  err = -ENXIO;
217  }
218  return err;
219 }
220 
221 /*
222  * release all the devices on the card.
223  * called from init.c
224  */
226 {
227  struct snd_device *dev;
228  int err;
229  unsigned int range_low, range_high, type;
230 
231  if (snd_BUG_ON(!card))
232  return -ENXIO;
233  range_low = (__force unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
234  range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
235  __again:
236  list_for_each_entry(dev, &card->devices, list) {
237  type = (__force unsigned int)dev->type;
238  if (type >= range_low && type <= range_high) {
239  if ((err = snd_device_free(card, dev->device_data)) < 0)
240  return err;
241  goto __again;
242  }
243  }
244  return 0;
245 }