aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/init.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-09 11:41:53 -0500
committerTakashi Iwai <tiwai@suse.de>2012-03-09 11:41:53 -0500
commite7df2a3ae569ed6d178510f58b22308edac7a4c7 (patch)
tree3f306d31e7aecce8e45d4eefc2727da69c2998dc /sound/core/init.c
parentdb05828aadbcc71aeea1c0b33ffadc8655dec600 (diff)
ALSA: core - Refactor card id string creation code
The code to handle the card id string is fairly messy, so here is a tidy up. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/init.c')
-rw-r--r--sound/core/init.c169
1 files changed, 100 insertions, 69 deletions
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);