diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-03-09 11:41:53 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-03-09 11:41:53 -0500 |
commit | e7df2a3ae569ed6d178510f58b22308edac7a4c7 (patch) | |
tree | 3f306d31e7aecce8e45d4eefc2727da69c2998dc /sound/core/init.c | |
parent | db05828aadbcc71aeea1c0b33ffadc8655dec600 (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.c | 169 |
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 | ||
481 | EXPORT_SYMBOL(snd_card_free); | 481 | EXPORT_SYMBOL(snd_card_free); |
482 | 482 | ||
483 | static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid) | 483 | /* retrieve the last word of shortname or longname */ |
484 | static 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'; | 497 | static 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 */ |
511 | static 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 | */ | ||
531 | static 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 | } |
570 | EXPORT_SYMBOL(snd_card_set_id); | 600 | EXPORT_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); |