Root/
1 | /* |
2 | * Device management routines |
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
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/errno.h> |
25 | #include <sound/core.h> |
26 | |
27 | /** |
28 | * snd_device_new - create an ALSA device component |
29 | * @card: the card instance |
30 | * @type: the device type, SNDRV_DEV_XXX |
31 | * @device_data: the data pointer of this device |
32 | * @ops: the operator table |
33 | * |
34 | * Creates a new device component for the given data pointer. |
35 | * The device will be assigned to the card and managed together |
36 | * by the card. |
37 | * |
38 | * The data pointer plays a role as the identifier, too, so the |
39 | * pointer address must be unique and unchanged. |
40 | * |
41 | * Returns zero if successful, or a negative error code on failure. |
42 | */ |
43 | int snd_device_new(struct snd_card *card, snd_device_type_t type, |
44 | void *device_data, struct snd_device_ops *ops) |
45 | { |
46 | struct snd_device *dev; |
47 | |
48 | if (snd_BUG_ON(!card || !device_data || !ops)) |
49 | return -ENXIO; |
50 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
51 | if (dev == NULL) { |
52 | snd_printk(KERN_ERR "Cannot allocate device\n"); |
53 | return -ENOMEM; |
54 | } |
55 | dev->card = card; |
56 | dev->type = type; |
57 | dev->state = SNDRV_DEV_BUILD; |
58 | dev->device_data = device_data; |
59 | dev->ops = ops; |
60 | list_add(&dev->list, &card->devices); /* add to the head of list */ |
61 | return 0; |
62 | } |
63 | |
64 | EXPORT_SYMBOL(snd_device_new); |
65 | |
66 | /** |
67 | * snd_device_free - release the device from the card |
68 | * @card: the card instance |
69 | * @device_data: the data pointer to release |
70 | * |
71 | * Removes the device from the list on the card and invokes the |
72 | * callbacks, dev_disconnect and dev_free, corresponding to the state. |
73 | * Then release the device. |
74 | * |
75 | * Returns zero if successful, or a negative error code on failure or if the |
76 | * device not found. |
77 | */ |
78 | int snd_device_free(struct snd_card *card, void *device_data) |
79 | { |
80 | struct snd_device *dev; |
81 | |
82 | if (snd_BUG_ON(!card || !device_data)) |
83 | return -ENXIO; |
84 | list_for_each_entry(dev, &card->devices, list) { |
85 | if (dev->device_data != device_data) |
86 | continue; |
87 | /* unlink */ |
88 | list_del(&dev->list); |
89 | if (dev->state == SNDRV_DEV_REGISTERED && |
90 | dev->ops->dev_disconnect) |
91 | if (dev->ops->dev_disconnect(dev)) |
92 | snd_printk(KERN_ERR |
93 | "device disconnect failure\n"); |
94 | if (dev->ops->dev_free) { |
95 | if (dev->ops->dev_free(dev)) |
96 | snd_printk(KERN_ERR "device free failure\n"); |
97 | } |
98 | kfree(dev); |
99 | return 0; |
100 | } |
101 | snd_printd("device free %p (from %pF), not found\n", device_data, |
102 | __builtin_return_address(0)); |
103 | return -ENXIO; |
104 | } |
105 | |
106 | EXPORT_SYMBOL(snd_device_free); |
107 | |
108 | /** |
109 | * snd_device_disconnect - disconnect the device |
110 | * @card: the card instance |
111 | * @device_data: the data pointer to disconnect |
112 | * |
113 | * Turns the device into the disconnection state, invoking |
114 | * dev_disconnect callback, if the device was already registered. |
115 | * |
116 | * Usually called from snd_card_disconnect(). |
117 | * |
118 | * Returns zero if successful, or a negative error code on failure or if the |
119 | * device not found. |
120 | */ |
121 | int snd_device_disconnect(struct snd_card *card, void *device_data) |
122 | { |
123 | struct snd_device *dev; |
124 | |
125 | if (snd_BUG_ON(!card || !device_data)) |
126 | return -ENXIO; |
127 | list_for_each_entry(dev, &card->devices, list) { |
128 | if (dev->device_data != device_data) |
129 | continue; |
130 | if (dev->state == SNDRV_DEV_REGISTERED && |
131 | dev->ops->dev_disconnect) { |
132 | if (dev->ops->dev_disconnect(dev)) |
133 | snd_printk(KERN_ERR "device disconnect failure\n"); |
134 | dev->state = SNDRV_DEV_DISCONNECTED; |
135 | } |
136 | return 0; |
137 | } |
138 | snd_printd("device disconnect %p (from %pF), not found\n", device_data, |
139 | __builtin_return_address(0)); |
140 | return -ENXIO; |
141 | } |
142 | |
143 | /** |
144 | * snd_device_register - register the device |
145 | * @card: the card instance |
146 | * @device_data: the data pointer to register |
147 | * |
148 | * Registers the device which was already created via |
149 | * snd_device_new(). Usually this is called from snd_card_register(), |
150 | * but it can be called later if any new devices are created after |
151 | * invocation of snd_card_register(). |
152 | * |
153 | * Returns zero if successful, or a negative error code on failure or if the |
154 | * device not found. |
155 | */ |
156 | int snd_device_register(struct snd_card *card, void *device_data) |
157 | { |
158 | struct snd_device *dev; |
159 | int err; |
160 | |
161 | if (snd_BUG_ON(!card || !device_data)) |
162 | return -ENXIO; |
163 | list_for_each_entry(dev, &card->devices, list) { |
164 | if (dev->device_data != device_data) |
165 | continue; |
166 | if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { |
167 | if ((err = dev->ops->dev_register(dev)) < 0) |
168 | return err; |
169 | dev->state = SNDRV_DEV_REGISTERED; |
170 | return 0; |
171 | } |
172 | snd_printd("snd_device_register busy\n"); |
173 | return -EBUSY; |
174 | } |
175 | snd_BUG(); |
176 | return -ENXIO; |
177 | } |
178 | |
179 | EXPORT_SYMBOL(snd_device_register); |
180 | |
181 | /* |
182 | * register all the devices on the card. |
183 | * called from init.c |
184 | */ |
185 | int snd_device_register_all(struct snd_card *card) |
186 | { |
187 | struct snd_device *dev; |
188 | int err; |
189 | |
190 | if (snd_BUG_ON(!card)) |
191 | return -ENXIO; |
192 | list_for_each_entry(dev, &card->devices, list) { |
193 | if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { |
194 | if ((err = dev->ops->dev_register(dev)) < 0) |
195 | return err; |
196 | dev->state = SNDRV_DEV_REGISTERED; |
197 | } |
198 | } |
199 | return 0; |
200 | } |
201 | |
202 | /* |
203 | * disconnect all the devices on the card. |
204 | * called from init.c |
205 | */ |
206 | int snd_device_disconnect_all(struct snd_card *card) |
207 | { |
208 | struct snd_device *dev; |
209 | int err = 0; |
210 | |
211 | if (snd_BUG_ON(!card)) |
212 | return -ENXIO; |
213 | list_for_each_entry(dev, &card->devices, list) { |
214 | if (snd_device_disconnect(card, dev->device_data) < 0) |
215 | err = -ENXIO; |
216 | } |
217 | return err; |
218 | } |
219 | |
220 | /* |
221 | * release all the devices on the card. |
222 | * called from init.c |
223 | */ |
224 | int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd) |
225 | { |
226 | struct snd_device *dev; |
227 | int err; |
228 | unsigned int range_low, range_high; |
229 | |
230 | if (snd_BUG_ON(!card)) |
231 | return -ENXIO; |
232 | range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE; |
233 | range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1; |
234 | __again: |
235 | list_for_each_entry(dev, &card->devices, list) { |
236 | if (dev->type >= range_low && dev->type <= range_high) { |
237 | if ((err = snd_device_free(card, dev->device_data)) < 0) |
238 | return err; |
239 | goto __again; |
240 | } |
241 | } |
242 | return 0; |
243 | } |
244 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9