Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/core/sound_oss.c
10814 views
1
/*
2
* Advanced Linux Sound Architecture
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
#ifdef CONFIG_SND_OSSEMUL
23
24
#if !defined(CONFIG_SOUND) && !(defined(MODULE) && defined(CONFIG_SOUND_MODULE))
25
#error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel."
26
#endif
27
28
#include <linux/init.h>
29
#include <linux/slab.h>
30
#include <linux/time.h>
31
#include <sound/core.h>
32
#include <sound/minors.h>
33
#include <sound/info.h>
34
#include <linux/sound.h>
35
#include <linux/mutex.h>
36
37
#define SNDRV_OSS_MINORS 128
38
39
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
40
static DEFINE_MUTEX(sound_oss_mutex);
41
42
void *snd_lookup_oss_minor_data(unsigned int minor, int type)
43
{
44
struct snd_minor *mreg;
45
void *private_data;
46
47
if (minor >= ARRAY_SIZE(snd_oss_minors))
48
return NULL;
49
mutex_lock(&sound_oss_mutex);
50
mreg = snd_oss_minors[minor];
51
if (mreg && mreg->type == type)
52
private_data = mreg->private_data;
53
else
54
private_data = NULL;
55
mutex_unlock(&sound_oss_mutex);
56
return private_data;
57
}
58
59
EXPORT_SYMBOL(snd_lookup_oss_minor_data);
60
61
static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
62
{
63
int minor;
64
65
switch (type) {
66
case SNDRV_OSS_DEVICE_TYPE_MIXER:
67
if (snd_BUG_ON(!card || dev < 0 || dev > 1))
68
return -EINVAL;
69
minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIXER1 : SNDRV_MINOR_OSS_MIXER));
70
break;
71
case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
72
minor = SNDRV_MINOR_OSS_SEQUENCER;
73
break;
74
case SNDRV_OSS_DEVICE_TYPE_MUSIC:
75
minor = SNDRV_MINOR_OSS_MUSIC;
76
break;
77
case SNDRV_OSS_DEVICE_TYPE_PCM:
78
if (snd_BUG_ON(!card || dev < 0 || dev > 1))
79
return -EINVAL;
80
minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_PCM1 : SNDRV_MINOR_OSS_PCM));
81
break;
82
case SNDRV_OSS_DEVICE_TYPE_MIDI:
83
if (snd_BUG_ON(!card || dev < 0 || dev > 1))
84
return -EINVAL;
85
minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIDI1 : SNDRV_MINOR_OSS_MIDI));
86
break;
87
case SNDRV_OSS_DEVICE_TYPE_DMFM:
88
minor = SNDRV_MINOR_OSS(card->number, SNDRV_MINOR_OSS_DMFM);
89
break;
90
case SNDRV_OSS_DEVICE_TYPE_SNDSTAT:
91
minor = SNDRV_MINOR_OSS_SNDSTAT;
92
break;
93
default:
94
return -EINVAL;
95
}
96
if (minor < 0 || minor >= SNDRV_OSS_MINORS)
97
return -EINVAL;
98
return minor;
99
}
100
101
int snd_register_oss_device(int type, struct snd_card *card, int dev,
102
const struct file_operations *f_ops, void *private_data,
103
const char *name)
104
{
105
int minor = snd_oss_kernel_minor(type, card, dev);
106
int minor_unit;
107
struct snd_minor *preg;
108
int cidx = SNDRV_MINOR_OSS_CARD(minor);
109
int track2 = -1;
110
int register1 = -1, register2 = -1;
111
struct device *carddev = snd_card_get_device_link(card);
112
113
if (card && card->number >= 8)
114
return 0; /* ignore silently */
115
if (minor < 0)
116
return minor;
117
preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL);
118
if (preg == NULL)
119
return -ENOMEM;
120
preg->type = type;
121
preg->card = card ? card->number : -1;
122
preg->device = dev;
123
preg->f_ops = f_ops;
124
preg->private_data = private_data;
125
mutex_lock(&sound_oss_mutex);
126
snd_oss_minors[minor] = preg;
127
minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
128
switch (minor_unit) {
129
case SNDRV_MINOR_OSS_PCM:
130
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO);
131
break;
132
case SNDRV_MINOR_OSS_MIDI:
133
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI);
134
break;
135
case SNDRV_MINOR_OSS_MIDI1:
136
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
137
break;
138
}
139
register1 = register_sound_special_device(f_ops, minor, carddev);
140
if (register1 != minor)
141
goto __end;
142
if (track2 >= 0) {
143
register2 = register_sound_special_device(f_ops, track2,
144
carddev);
145
if (register2 != track2)
146
goto __end;
147
snd_oss_minors[track2] = preg;
148
}
149
mutex_unlock(&sound_oss_mutex);
150
return 0;
151
152
__end:
153
if (register2 >= 0)
154
unregister_sound_special(register2);
155
if (register1 >= 0)
156
unregister_sound_special(register1);
157
snd_oss_minors[minor] = NULL;
158
mutex_unlock(&sound_oss_mutex);
159
kfree(preg);
160
return -EBUSY;
161
}
162
163
EXPORT_SYMBOL(snd_register_oss_device);
164
165
int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
166
{
167
int minor = snd_oss_kernel_minor(type, card, dev);
168
int cidx = SNDRV_MINOR_OSS_CARD(minor);
169
int track2 = -1;
170
struct snd_minor *mptr;
171
172
if (card && card->number >= 8)
173
return 0;
174
if (minor < 0)
175
return minor;
176
mutex_lock(&sound_oss_mutex);
177
mptr = snd_oss_minors[minor];
178
if (mptr == NULL) {
179
mutex_unlock(&sound_oss_mutex);
180
return -ENOENT;
181
}
182
unregister_sound_special(minor);
183
switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
184
case SNDRV_MINOR_OSS_PCM:
185
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO);
186
break;
187
case SNDRV_MINOR_OSS_MIDI:
188
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI);
189
break;
190
case SNDRV_MINOR_OSS_MIDI1:
191
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
192
break;
193
}
194
if (track2 >= 0) {
195
unregister_sound_special(track2);
196
snd_oss_minors[track2] = NULL;
197
}
198
snd_oss_minors[minor] = NULL;
199
mutex_unlock(&sound_oss_mutex);
200
kfree(mptr);
201
return 0;
202
}
203
204
EXPORT_SYMBOL(snd_unregister_oss_device);
205
206
/*
207
* INFO PART
208
*/
209
210
#ifdef CONFIG_PROC_FS
211
212
static struct snd_info_entry *snd_minor_info_oss_entry;
213
214
static const char *snd_oss_device_type_name(int type)
215
{
216
switch (type) {
217
case SNDRV_OSS_DEVICE_TYPE_MIXER:
218
return "mixer";
219
case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
220
case SNDRV_OSS_DEVICE_TYPE_MUSIC:
221
return "sequencer";
222
case SNDRV_OSS_DEVICE_TYPE_PCM:
223
return "digital audio";
224
case SNDRV_OSS_DEVICE_TYPE_MIDI:
225
return "raw midi";
226
case SNDRV_OSS_DEVICE_TYPE_DMFM:
227
return "hardware dependent";
228
default:
229
return "?";
230
}
231
}
232
233
static void snd_minor_info_oss_read(struct snd_info_entry *entry,
234
struct snd_info_buffer *buffer)
235
{
236
int minor;
237
struct snd_minor *mptr;
238
239
mutex_lock(&sound_oss_mutex);
240
for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
241
if (!(mptr = snd_oss_minors[minor]))
242
continue;
243
if (mptr->card >= 0)
244
snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor,
245
mptr->card, mptr->device,
246
snd_oss_device_type_name(mptr->type));
247
else
248
snd_iprintf(buffer, "%3i: : %s\n", minor,
249
snd_oss_device_type_name(mptr->type));
250
}
251
mutex_unlock(&sound_oss_mutex);
252
}
253
254
255
int __init snd_minor_info_oss_init(void)
256
{
257
struct snd_info_entry *entry;
258
259
entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
260
if (entry) {
261
entry->c.text.read = snd_minor_info_oss_read;
262
if (snd_info_register(entry) < 0) {
263
snd_info_free_entry(entry);
264
entry = NULL;
265
}
266
}
267
snd_minor_info_oss_entry = entry;
268
return 0;
269
}
270
271
int __exit snd_minor_info_oss_done(void)
272
{
273
snd_info_free_entry(snd_minor_info_oss_entry);
274
return 0;
275
}
276
#endif /* CONFIG_PROC_FS */
277
278
#endif /* CONFIG_SND_OSSEMUL */
279
280