aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/hwdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/hwdep.c')
-rw-r--r--sound/core/hwdep.c91
1 files changed, 42 insertions, 49 deletions
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 27d5bf7266f0..b8c0c8c4d126 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -35,8 +35,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
35MODULE_DESCRIPTION("Hardware dependent layer"); 35MODULE_DESCRIPTION("Hardware dependent layer");
36MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
37 37
38static struct snd_hwdep *snd_hwdep_devices[SNDRV_CARDS * SNDRV_MINOR_HWDEPS]; 38static LIST_HEAD(snd_hwdep_devices);
39
40static DECLARE_MUTEX(register_mutex); 39static DECLARE_MUTEX(register_mutex);
41 40
42static int snd_hwdep_free(struct snd_hwdep *hwdep); 41static int snd_hwdep_free(struct snd_hwdep *hwdep);
@@ -44,9 +43,19 @@ static int snd_hwdep_dev_free(struct snd_device *device);
44static int snd_hwdep_dev_register(struct snd_device *device); 43static int snd_hwdep_dev_register(struct snd_device *device);
45static int snd_hwdep_dev_unregister(struct snd_device *device); 44static int snd_hwdep_dev_unregister(struct snd_device *device);
46 45
47/*
48 46
49 */ 47static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
48{
49 struct list_head *p;
50 struct snd_hwdep *hwdep;
51
52 list_for_each(p, &snd_hwdep_devices) {
53 hwdep = list_entry(p, struct snd_hwdep, list);
54 if (hwdep->card == card && hwdep->device == device)
55 return hwdep;
56 }
57 return NULL;
58}
50 59
51static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig) 60static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
52{ 61{
@@ -77,34 +86,25 @@ static ssize_t snd_hwdep_write(struct file * file, const char __user *buf,
77static int snd_hwdep_open(struct inode *inode, struct file * file) 86static int snd_hwdep_open(struct inode *inode, struct file * file)
78{ 87{
79 int major = imajor(inode); 88 int major = imajor(inode);
80 int cardnum;
81 int device;
82 struct snd_hwdep *hw; 89 struct snd_hwdep *hw;
83 int err; 90 int err;
84 wait_queue_t wait; 91 wait_queue_t wait;
85 92
86 if (major == snd_major) { 93 if (major == snd_major) {
87 cardnum = SNDRV_MINOR_CARD(iminor(inode)); 94 hw = snd_lookup_minor_data(iminor(inode),
88 device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP; 95 SNDRV_DEVICE_TYPE_HWDEP);
89#ifdef CONFIG_SND_OSSEMUL 96#ifdef CONFIG_SND_OSSEMUL
90 } else if (major == SOUND_MAJOR) { 97 } else if (major == SOUND_MAJOR) {
91 cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); 98 hw = snd_lookup_oss_minor_data(iminor(inode),
92 device = 0; 99 SNDRV_OSS_DEVICE_TYPE_DMFM);
93#endif 100#endif
94 } else 101 } else
95 return -ENXIO; 102 return -ENXIO;
96 cardnum %= SNDRV_CARDS;
97 device %= SNDRV_MINOR_HWDEPS;
98 hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device];
99 if (hw == NULL) 103 if (hw == NULL)
100 return -ENODEV; 104 return -ENODEV;
101 105
102 if (!hw->ops.open) 106 if (!hw->ops.open)
103 return -ENXIO; 107 return -ENXIO;
104#ifdef CONFIG_SND_OSSEMUL
105 if (major == SOUND_MAJOR && hw->oss_type < 0)
106 return -ENXIO;
107#endif
108 108
109 if (!try_module_get(hw->card->module)) 109 if (!try_module_get(hw->card->module))
110 return -EFAULT; 110 return -EFAULT;
@@ -265,9 +265,6 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
265 struct snd_ctl_file * control, 265 struct snd_ctl_file * control,
266 unsigned int cmd, unsigned long arg) 266 unsigned int cmd, unsigned long arg)
267{ 267{
268 unsigned int tmp;
269
270 tmp = card->number * SNDRV_MINOR_HWDEPS;
271 switch (cmd) { 268 switch (cmd) {
272 case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE: 269 case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
273 { 270 {
@@ -275,14 +272,16 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
275 272
276 if (get_user(device, (int __user *)arg)) 273 if (get_user(device, (int __user *)arg))
277 return -EFAULT; 274 return -EFAULT;
275 down(&register_mutex);
278 device = device < 0 ? 0 : device + 1; 276 device = device < 0 ? 0 : device + 1;
279 while (device < SNDRV_MINOR_HWDEPS) { 277 while (device < SNDRV_MINOR_HWDEPS) {
280 if (snd_hwdep_devices[tmp + device]) 278 if (snd_hwdep_search(card, device))
281 break; 279 break;
282 device++; 280 device++;
283 } 281 }
284 if (device >= SNDRV_MINOR_HWDEPS) 282 if (device >= SNDRV_MINOR_HWDEPS)
285 device = -1; 283 device = -1;
284 up(&register_mutex);
286 if (put_user(device, (int __user *)arg)) 285 if (put_user(device, (int __user *)arg))
287 return -EFAULT; 286 return -EFAULT;
288 return 0; 287 return 0;
@@ -290,17 +289,19 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
290 case SNDRV_CTL_IOCTL_HWDEP_INFO: 289 case SNDRV_CTL_IOCTL_HWDEP_INFO:
291 { 290 {
292 struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg; 291 struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg;
293 int device; 292 int device, err;
294 struct snd_hwdep *hwdep; 293 struct snd_hwdep *hwdep;
295 294
296 if (get_user(device, &info->device)) 295 if (get_user(device, &info->device))
297 return -EFAULT; 296 return -EFAULT;
298 if (device < 0 || device >= SNDRV_MINOR_HWDEPS) 297 down(&register_mutex);
299 return -ENXIO; 298 hwdep = snd_hwdep_search(card, device);
300 hwdep = snd_hwdep_devices[tmp + device]; 299 if (hwdep)
301 if (hwdep == NULL) 300 err = snd_hwdep_info(hwdep, info);
302 return -ENXIO; 301 else
303 return snd_hwdep_info(hwdep, info); 302 err = -ENXIO;
303 up(&register_mutex);
304 return err;
304 } 305 }
305 } 306 }
306 return -ENOIOCTLCMD; 307 return -ENOIOCTLCMD;
@@ -397,23 +398,22 @@ static int snd_hwdep_dev_free(struct snd_device *device)
397static int snd_hwdep_dev_register(struct snd_device *device) 398static int snd_hwdep_dev_register(struct snd_device *device)
398{ 399{
399 struct snd_hwdep *hwdep = device->device_data; 400 struct snd_hwdep *hwdep = device->device_data;
400 int idx, err; 401 int err;
401 char name[32]; 402 char name[32];
402 403
403 down(&register_mutex); 404 down(&register_mutex);
404 idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; 405 if (snd_hwdep_search(hwdep->card, hwdep->device)) {
405 if (snd_hwdep_devices[idx]) {
406 up(&register_mutex); 406 up(&register_mutex);
407 return -EBUSY; 407 return -EBUSY;
408 } 408 }
409 snd_hwdep_devices[idx] = hwdep; 409 list_add_tail(&hwdep->list, &snd_hwdep_devices);
410 sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); 410 sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device);
411 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, 411 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
412 hwdep->card, hwdep->device, 412 hwdep->card, hwdep->device,
413 &snd_hwdep_f_ops, name)) < 0) { 413 &snd_hwdep_f_ops, hwdep, name)) < 0) {
414 snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", 414 snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
415 hwdep->card->number, hwdep->device); 415 hwdep->card->number, hwdep->device);
416 snd_hwdep_devices[idx] = NULL; 416 list_del(&hwdep->list);
417 up(&register_mutex); 417 up(&register_mutex);
418 return err; 418 return err;
419 } 419 }
@@ -425,7 +425,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
425 } else { 425 } else {
426 if (snd_register_oss_device(hwdep->oss_type, 426 if (snd_register_oss_device(hwdep->oss_type,
427 hwdep->card, hwdep->device, 427 hwdep->card, hwdep->device,
428 &snd_hwdep_f_ops, 428 &snd_hwdep_f_ops, hwdep,
429 hwdep->oss_dev) < 0) { 429 hwdep->oss_dev) < 0) {
430 snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n", 430 snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
431 hwdep->card->number, hwdep->device); 431 hwdep->card->number, hwdep->device);
@@ -441,12 +441,10 @@ static int snd_hwdep_dev_register(struct snd_device *device)
441static int snd_hwdep_dev_unregister(struct snd_device *device) 441static int snd_hwdep_dev_unregister(struct snd_device *device)
442{ 442{
443 struct snd_hwdep *hwdep = device->device_data; 443 struct snd_hwdep *hwdep = device->device_data;
444 int idx;
445 444
446 snd_assert(hwdep != NULL, return -ENXIO); 445 snd_assert(hwdep != NULL, return -ENXIO);
447 down(&register_mutex); 446 down(&register_mutex);
448 idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; 447 if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
449 if (snd_hwdep_devices[idx] != hwdep) {
450 up(&register_mutex); 448 up(&register_mutex);
451 return -EINVAL; 449 return -EINVAL;
452 } 450 }
@@ -455,7 +453,7 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
455 snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); 453 snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
456#endif 454#endif
457 snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); 455 snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
458 snd_hwdep_devices[idx] = NULL; 456 list_del(&hwdep->list);
459 up(&register_mutex); 457 up(&register_mutex);
460 return snd_hwdep_free(hwdep); 458 return snd_hwdep_free(hwdep);
461} 459}
@@ -467,18 +465,14 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
467static void snd_hwdep_proc_read(struct snd_info_entry *entry, 465static void snd_hwdep_proc_read(struct snd_info_entry *entry,
468 struct snd_info_buffer *buffer) 466 struct snd_info_buffer *buffer)
469{ 467{
470 int idx; 468 struct list_head *p;
471 struct snd_hwdep *hwdep; 469 struct snd_hwdep *hwdep;
472 470
473 down(&register_mutex); 471 down(&register_mutex);
474 for (idx = 0; idx < SNDRV_CARDS * SNDRV_MINOR_HWDEPS; idx++) { 472 list_for_each(p, &snd_hwdep_devices) {
475 hwdep = snd_hwdep_devices[idx]; 473 hwdep = list_entry(p, struct snd_hwdep, list);
476 if (hwdep == NULL)
477 continue;
478 snd_iprintf(buffer, "%02i-%02i: %s\n", 474 snd_iprintf(buffer, "%02i-%02i: %s\n",
479 idx / SNDRV_MINOR_HWDEPS, 475 hwdep->card->number, hwdep->device, hwdep->name);
480 idx % SNDRV_MINOR_HWDEPS,
481 hwdep->name);
482 } 476 }
483 up(&register_mutex); 477 up(&register_mutex);
484} 478}
@@ -493,9 +487,8 @@ static int __init alsa_hwdep_init(void)
493{ 487{
494 struct snd_info_entry *entry; 488 struct snd_info_entry *entry;
495 489
496 memset(snd_hwdep_devices, 0, sizeof(snd_hwdep_devices));
497 if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { 490 if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
498 entry->c.text.read_size = 512; 491 entry->c.text.read_size = PAGE_SIZE;
499 entry->c.text.read = snd_hwdep_proc_read; 492 entry->c.text.read = snd_hwdep_proc_read;
500 if (snd_info_register(entry) < 0) { 493 if (snd_info_register(entry) < 0) {
501 snd_info_free_entry(entry); 494 snd_info_free_entry(entry);