aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-18 13:22:33 -0400
committerTakashi Iwai <tiwai@suse.de>2012-03-18 13:22:33 -0400
commit44c76a960a62fcc46cbcaa0a22a34e666a729329 (patch)
treed3887c858f6adffb6714da3cdc0059f93588344c /sound/core
parentdbf117cbb9c89991727d42e3161e68b868a1b6ae (diff)
parentc6b76d1f02e2ab1109d8549877a3a24c6a2b4587 (diff)
Merge branch 'topic/misc' into for-linus
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/control.c2
-rw-r--r--sound/core/init.c169
-rw-r--r--sound/core/misc.c2
-rw-r--r--sound/core/pcm_lib.c3
-rw-r--r--sound/core/pcm_native.c15
5 files changed, 114 insertions, 77 deletions
diff --git a/sound/core/control.c b/sound/core/control.c
index 819a5c579a39..2487a6bb1c54 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1313,7 +1313,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
1313 err = -EPERM; 1313 err = -EPERM;
1314 goto __kctl_end; 1314 goto __kctl_end;
1315 } 1315 }
1316 err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv); 1316 err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
1317 if (err > 0) { 1317 if (err > 0) {
1318 up_read(&card->controls_rwsem); 1318 up_read(&card->controls_rwsem);
1319 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id); 1319 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
diff --git a/sound/core/init.c b/sound/core/init.c
index 3ac49b1b7cb8..068cf08d3ffb 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -480,74 +480,104 @@ int snd_card_free(struct snd_card *card)
480 480
481EXPORT_SYMBOL(snd_card_free); 481EXPORT_SYMBOL(snd_card_free);
482 482
483static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid) 483/* retrieve the last word of shortname or longname */
484static const char *retrieve_id_from_card_name(const char *name)
484{ 485{
485 int i, len, idx_flag = 0, loops = SNDRV_CARDS; 486 const char *spos = name;
486 const char *spos, *src; 487
487 char *id; 488 while (*name) {
488 489 if (isspace(*name) && isalnum(name[1]))
489 if (nid == NULL) { 490 spos = name + 1;
490 id = card->shortname; 491 name++;
491 spos = src = id;
492 while (*id != '\0') {
493 if (*id == ' ')
494 spos = id + 1;
495 id++;
496 }
497 } else {
498 spos = src = nid;
499 } 492 }
500 id = card->id; 493 return spos;
501 while (*spos != '\0' && !isalnum(*spos)) 494}
502 spos++; 495
503 if (isdigit(*spos)) 496/* return true if the given id string doesn't conflict any other card ids */
504 *id++ = isalpha(src[0]) ? src[0] : 'D'; 497static bool card_id_ok(struct snd_card *card, const char *id)
505 while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) { 498{
506 if (isalnum(*spos)) 499 int i;
507 *id++ = *spos; 500 if (!snd_info_check_reserved_words(id))
508 spos++; 501 return false;
502 for (i = 0; i < snd_ecards_limit; i++) {
503 if (snd_cards[i] && snd_cards[i] != card &&
504 !strcmp(snd_cards[i]->id, id))
505 return false;
509 } 506 }
510 *id = '\0'; 507 return true;
508}
511 509
512 id = card->id; 510/* copy to card->id only with valid letters from nid */
511static void copy_valid_id_string(struct snd_card *card, const char *src,
512 const char *nid)
513{
514 char *id = card->id;
515
516 while (*nid && !isalnum(*nid))
517 nid++;
518 if (isdigit(*nid))
519 *id++ = isalpha(*src) ? *src : 'D';
520 while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
521 if (isalnum(*nid))
522 *id++ = *nid;
523 nid++;
524 }
525 *id = 0;
526}
527
528/* Set card->id from the given string
529 * If the string conflicts with other ids, add a suffix to make it unique.
530 */
531static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
532 const char *nid)
533{
534 int len, loops;
535 bool with_suffix;
536 bool is_default = false;
537 char *id;
513 538
514 if (*id == '\0') 539 copy_valid_id_string(card, src, nid);
540 id = card->id;
541
542 again:
543 /* use "Default" for obviously invalid strings
544 * ("card" conflicts with proc directories)
545 */
546 if (!*id || !strncmp(id, "card", 4)) {
515 strcpy(id, "Default"); 547 strcpy(id, "Default");
548 is_default = true;
549 }
516 550
517 while (1) { 551 with_suffix = false;
518 if (loops-- == 0) { 552 for (loops = 0; loops < SNDRV_CARDS; loops++) {
519 snd_printk(KERN_ERR "unable to set card id (%s)\n", id); 553 if (card_id_ok(card, id))
520 strcpy(card->id, card->proc_root->name); 554 return; /* OK */
521 return;
522 }
523 if (!snd_info_check_reserved_words(id))
524 goto __change;
525 for (i = 0; i < snd_ecards_limit; i++) {
526 if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
527 goto __change;
528 }
529 break;
530 555
531 __change:
532 len = strlen(id); 556 len = strlen(id);
533 if (idx_flag) { 557 if (!with_suffix) {
534 if (id[len-1] != '9') 558 /* add the "_X" suffix */
535 id[len-1]++; 559 char *spos = id + len;
536 else 560 if (len > sizeof(card->id) - 3)
537 id[len-1] = 'A'; 561 spos = id + sizeof(card->id) - 3;
538 } else if ((size_t)len <= sizeof(card->id) - 3) { 562 strcpy(spos, "_1");
539 strcat(id, "_1"); 563 with_suffix = true;
540 idx_flag++;
541 } else { 564 } else {
542 spos = id + len - 2; 565 /* modify the existing suffix */
543 if ((size_t)len <= sizeof(card->id) - 2) 566 if (id[len - 1] != '9')
544 spos++; 567 id[len - 1]++;
545 *(char *)spos++ = '_'; 568 else
546 *(char *)spos++ = '1'; 569 id[len - 1] = 'A';
547 *(char *)spos++ = '\0';
548 idx_flag++;
549 } 570 }
550 } 571 }
572 /* fallback to the default id */
573 if (!is_default) {
574 *id = 0;
575 goto again;
576 }
577 /* last resort... */
578 snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
579 if (card->proc_root->name)
580 strcpy(card->id, card->proc_root->name);
551} 581}
552 582
553/** 583/**
@@ -564,7 +594,7 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
564 if (card->id[0] != '\0') 594 if (card->id[0] != '\0')
565 return; 595 return;
566 mutex_lock(&snd_card_mutex); 596 mutex_lock(&snd_card_mutex);
567 snd_card_set_id_no_lock(card, nid); 597 snd_card_set_id_no_lock(card, nid, nid);
568 mutex_unlock(&snd_card_mutex); 598 mutex_unlock(&snd_card_mutex);
569} 599}
570EXPORT_SYMBOL(snd_card_set_id); 600EXPORT_SYMBOL(snd_card_set_id);
@@ -596,22 +626,12 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
596 memcpy(buf1, buf, copy); 626 memcpy(buf1, buf, copy);
597 buf1[copy] = '\0'; 627 buf1[copy] = '\0';
598 mutex_lock(&snd_card_mutex); 628 mutex_lock(&snd_card_mutex);
599 if (!snd_info_check_reserved_words(buf1)) { 629 if (!card_id_ok(NULL, buf1)) {
600 __exist:
601 mutex_unlock(&snd_card_mutex); 630 mutex_unlock(&snd_card_mutex);
602 return -EEXIST; 631 return -EEXIST;
603 } 632 }
604 for (idx = 0; idx < snd_ecards_limit; idx++) {
605 if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
606 if (card == snd_cards[idx])
607 goto __ok;
608 else
609 goto __exist;
610 }
611 }
612 strcpy(card->id, buf1); 633 strcpy(card->id, buf1);
613 snd_info_card_id_change(card); 634 snd_info_card_id_change(card);
614__ok:
615 mutex_unlock(&snd_card_mutex); 635 mutex_unlock(&snd_card_mutex);
616 636
617 return count; 637 return count;
@@ -665,7 +685,18 @@ int snd_card_register(struct snd_card *card)
665 mutex_unlock(&snd_card_mutex); 685 mutex_unlock(&snd_card_mutex);
666 return 0; 686 return 0;
667 } 687 }
668 snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id); 688 if (*card->id) {
689 /* make a unique id name from the given string */
690 char tmpid[sizeof(card->id)];
691 memcpy(tmpid, card->id, sizeof(card->id));
692 snd_card_set_id_no_lock(card, tmpid, tmpid);
693 } else {
694 /* create an id from either shortname or longname */
695 const char *src;
696 src = *card->shortname ? card->shortname : card->longname;
697 snd_card_set_id_no_lock(card, src,
698 retrieve_id_from_card_name(src));
699 }
669 snd_cards[card->number] = card; 700 snd_cards[card->number] = card;
670 mutex_unlock(&snd_card_mutex); 701 mutex_unlock(&snd_card_mutex);
671 init_info_for_card(card); 702 init_info_for_card(card);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 465f0ce772cb..768167925409 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -72,7 +72,7 @@ void __snd_printk(unsigned int level, const char *path, int line,
72 char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; 72 char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV";
73#endif 73#endif
74 74
75#ifdef CONFIG_SND_DEBUG 75#ifdef CONFIG_SND_DEBUG
76 if (debug < level) 76 if (debug < level)
77 return; 77 return;
78#endif 78#endif
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 3420bd3da5d7..4d18941178e6 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1029,7 +1029,8 @@ static int snd_interval_ratden(struct snd_interval *i,
1029 * 1029 *
1030 * Returns non-zero if the value is changed, zero if not changed. 1030 * Returns non-zero if the value is changed, zero if not changed.
1031 */ 1031 */
1032int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask) 1032int snd_interval_list(struct snd_interval *i, unsigned int count,
1033 const unsigned int *list, unsigned int mask)
1033{ 1034{
1034 unsigned int k; 1035 unsigned int k;
1035 struct snd_interval list_range; 1036 struct snd_interval list_range;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 25ed9fe41b89..3fe99e644eb8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1586,12 +1586,18 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
1586 struct file *file; 1586 struct file *file;
1587 struct snd_pcm_file *pcm_file; 1587 struct snd_pcm_file *pcm_file;
1588 struct snd_pcm_substream *substream1; 1588 struct snd_pcm_substream *substream1;
1589 struct snd_pcm_group *group;
1589 1590
1590 file = snd_pcm_file_fd(fd); 1591 file = snd_pcm_file_fd(fd);
1591 if (!file) 1592 if (!file)
1592 return -EBADFD; 1593 return -EBADFD;
1593 pcm_file = file->private_data; 1594 pcm_file = file->private_data;
1594 substream1 = pcm_file->substream; 1595 substream1 = pcm_file->substream;
1596 group = kmalloc(sizeof(*group), GFP_KERNEL);
1597 if (!group) {
1598 res = -ENOMEM;
1599 goto _nolock;
1600 }
1595 down_write(&snd_pcm_link_rwsem); 1601 down_write(&snd_pcm_link_rwsem);
1596 write_lock_irq(&snd_pcm_link_rwlock); 1602 write_lock_irq(&snd_pcm_link_rwlock);
1597 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || 1603 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
@@ -1604,11 +1610,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
1604 goto _end; 1610 goto _end;
1605 } 1611 }
1606 if (!snd_pcm_stream_linked(substream)) { 1612 if (!snd_pcm_stream_linked(substream)) {
1607 substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC); 1613 substream->group = group;
1608 if (substream->group == NULL) {
1609 res = -ENOMEM;
1610 goto _end;
1611 }
1612 spin_lock_init(&substream->group->lock); 1614 spin_lock_init(&substream->group->lock);
1613 INIT_LIST_HEAD(&substream->group->substreams); 1615 INIT_LIST_HEAD(&substream->group->substreams);
1614 list_add_tail(&substream->link_list, &substream->group->substreams); 1616 list_add_tail(&substream->link_list, &substream->group->substreams);
@@ -1620,7 +1622,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
1620 _end: 1622 _end:
1621 write_unlock_irq(&snd_pcm_link_rwlock); 1623 write_unlock_irq(&snd_pcm_link_rwlock);
1622 up_write(&snd_pcm_link_rwsem); 1624 up_write(&snd_pcm_link_rwsem);
1625 _nolock:
1623 fput(file); 1626 fput(file);
1627 if (res < 0)
1628 kfree(group);
1624 return res; 1629 return res;
1625} 1630}
1626 1631