Skip to content

Commit

Permalink
ALSA: core - Refactor card id string creation code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
tiwai committed Mar 9, 2012
1 parent db05828 commit e7df2a3
Showing 1 changed file with 100 additions and 69 deletions.
169 changes: 100 additions & 69 deletions sound/core/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,74 +480,104 @@ int snd_card_free(struct snd_card *card)

EXPORT_SYMBOL(snd_card_free);

static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
/* retrieve the last word of shortname or longname */
static const char *retrieve_id_from_card_name(const char *name)
{
int i, len, idx_flag = 0, loops = SNDRV_CARDS;
const char *spos, *src;
char *id;

if (nid == NULL) {
id = card->shortname;
spos = src = id;
while (*id != '\0') {
if (*id == ' ')
spos = id + 1;
id++;
}
} else {
spos = src = nid;
const char *spos = name;

while (*name) {
if (isspace(*name) && isalnum(name[1]))
spos = name + 1;
name++;
}
id = card->id;
while (*spos != '\0' && !isalnum(*spos))
spos++;
if (isdigit(*spos))
*id++ = isalpha(src[0]) ? src[0] : 'D';
while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) {
if (isalnum(*spos))
*id++ = *spos;
spos++;
return spos;
}

/* return true if the given id string doesn't conflict any other card ids */
static bool card_id_ok(struct snd_card *card, const char *id)
{
int i;
if (!snd_info_check_reserved_words(id))
return false;
for (i = 0; i < snd_ecards_limit; i++) {
if (snd_cards[i] && snd_cards[i] != card &&
!strcmp(snd_cards[i]->id, id))
return false;
}
*id = '\0';
return true;
}

id = card->id;
/* copy to card->id only with valid letters from nid */
static void copy_valid_id_string(struct snd_card *card, const char *src,
const char *nid)
{
char *id = card->id;

while (*nid && !isalnum(*nid))
nid++;
if (isdigit(*nid))
*id++ = isalpha(*src) ? *src : 'D';
while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
if (isalnum(*nid))
*id++ = *nid;
nid++;
}
*id = 0;
}

/* Set card->id from the given string
* If the string conflicts with other ids, add a suffix to make it unique.
*/
static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
const char *nid)
{
int len, loops;
bool with_suffix;
bool is_default = false;
char *id;

if (*id == '\0')
copy_valid_id_string(card, src, nid);
id = card->id;

again:
/* use "Default" for obviously invalid strings
* ("card" conflicts with proc directories)
*/
if (!*id || !strncmp(id, "card", 4)) {
strcpy(id, "Default");
is_default = true;
}

while (1) {
if (loops-- == 0) {
snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
strcpy(card->id, card->proc_root->name);
return;
}
if (!snd_info_check_reserved_words(id))
goto __change;
for (i = 0; i < snd_ecards_limit; i++) {
if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
goto __change;
}
break;
with_suffix = false;
for (loops = 0; loops < SNDRV_CARDS; loops++) {
if (card_id_ok(card, id))
return; /* OK */

__change:
len = strlen(id);
if (idx_flag) {
if (id[len-1] != '9')
id[len-1]++;
else
id[len-1] = 'A';
} else if ((size_t)len <= sizeof(card->id) - 3) {
strcat(id, "_1");
idx_flag++;
if (!with_suffix) {
/* add the "_X" suffix */
char *spos = id + len;
if (len > sizeof(card->id) - 3)
spos = id + sizeof(card->id) - 3;
strcpy(spos, "_1");
with_suffix = true;
} else {
spos = id + len - 2;
if ((size_t)len <= sizeof(card->id) - 2)
spos++;
*(char *)spos++ = '_';
*(char *)spos++ = '1';
*(char *)spos++ = '\0';
idx_flag++;
/* modify the existing suffix */
if (id[len - 1] != '9')
id[len - 1]++;
else
id[len - 1] = 'A';
}
}
/* fallback to the default id */
if (!is_default) {
*id = 0;
goto again;
}
/* last resort... */
snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
if (card->proc_root->name)
strcpy(card->id, card->proc_root->name);
}

/**
Expand All @@ -564,7 +594,7 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
if (card->id[0] != '\0')
return;
mutex_lock(&snd_card_mutex);
snd_card_set_id_no_lock(card, nid);
snd_card_set_id_no_lock(card, nid, nid);
mutex_unlock(&snd_card_mutex);
}
EXPORT_SYMBOL(snd_card_set_id);
Expand Down Expand Up @@ -596,22 +626,12 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
memcpy(buf1, buf, copy);
buf1[copy] = '\0';
mutex_lock(&snd_card_mutex);
if (!snd_info_check_reserved_words(buf1)) {
__exist:
if (!card_id_ok(NULL, buf1)) {
mutex_unlock(&snd_card_mutex);
return -EEXIST;
}
for (idx = 0; idx < snd_ecards_limit; idx++) {
if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
if (card == snd_cards[idx])
goto __ok;
else
goto __exist;
}
}
strcpy(card->id, buf1);
snd_info_card_id_change(card);
__ok:
mutex_unlock(&snd_card_mutex);

return count;
Expand Down Expand Up @@ -665,7 +685,18 @@ int snd_card_register(struct snd_card *card)
mutex_unlock(&snd_card_mutex);
return 0;
}
snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id);
if (*card->id) {
/* make a unique id name from the given string */
char tmpid[sizeof(card->id)];
memcpy(tmpid, card->id, sizeof(card->id));
snd_card_set_id_no_lock(card, tmpid, tmpid);
} else {
/* create an id from either shortname or longname */
const char *src;
src = *card->shortname ? card->shortname : card->longname;
snd_card_set_id_no_lock(card, src,
retrieve_id_from_card_name(src));
}
snd_cards[card->number] = card;
mutex_unlock(&snd_card_mutex);
init_info_for_card(card);
Expand Down

0 comments on commit e7df2a3

Please sign in to comment.