staticchar *slots[SNDRV_CARDS];
module_param_array(slots, charp, NULL, 0444);
MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
/* return non-zero if the given index is reserved for the given *moduleviaslotsoption
*/ staticint module_slot_match(struct module *module, int idx)
{ int match = 1; #ifdef CONFIG_MODULES constchar *s1, *s2;
if (!module || !*module->name || !slots[idx]) return0;
s1 = module->name;
s2 = slots[idx]; if (*s2 == '!') {
match = 0; /* negative match */
s2++;
} /* compare module name strings *hyphensarehandledasequivalentwithunderscore
*/ for (;;) { char c1 = *s1++; char c2 = *s2++; if (c1 == '-')
c1 = '_'; if (c2 == '-')
c2 = '_'; if (c1 != c2) return !match; if (!c1) break;
} #endif/* CONFIG_MODULES */ return match;
}
#if IS_ENABLED(CONFIG_SND_MIXER_OSS) int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
EXPORT_SYMBOL(snd_mixer_oss_notify_callback); #endif
/* return an empty slot number (>= 0) found in the given bitmask @mask. *@mask==-1==0xffffffffmeans:takeanyfreeslotupto32 *whennoslotisavailable,returntheoriginal@maskasis.
*/ staticint get_slot_from_bitmask(int mask, int (*check)(struct module *, int), struct module *module)
{ int slot;
for (slot = 0; slot < SNDRV_CARDS; slot++) { if (slot < 32 && !(mask & (1U << slot))) continue; if (!test_bit(slot, snd_cards_lock)) { if (check(module, slot)) return slot; /* found */
}
} return mask; /* unchanged */
}
/* the default release callback set in snd_device_alloc() */ staticvoid default_release_alloc(struct device *dev)
{
kfree(dev);
}
/* the control interface cannot be accessed from the user space until */ /* snd_cards_bitmask and snd_cards are set with snd_card_register */
err = snd_ctl_create(card); if (err < 0) {
dev_err(parent, "unable to register control minors\n"); goto __error;
}
err = snd_info_card_create(card); if (err < 0) {
dev_err(parent, "unable to create card info\n"); goto __error_ctl;
}
/* return non-zero if a card is already locked */ int snd_card_locked(int card)
{
guard(mutex)(&snd_card_mutex); return test_bit(card, snd_cards_lock);
}
scoped_guard(spinlock, &card->files_lock) { if (card->shutdown) return;
card->shutdown = 1;
/* replace file->f_op with special dummy operations */
list_for_each_entry(mfile, &card->files_list, list) { /* it's critical part, use endless loop */ /* we have no room to fail */
mfile->disconnected_f_op = mfile->file->f_op;
#ifdef CONFIG_PM /* wake up sleepers here before other callbacks for avoiding potential *deadlockswithotherlocks(e.g.inkctls); *thenthisnotifiestheshutdownandsleeperswouldabortimmediately
*/
wake_up_all(&card->power_sleep); #endif
/* notify all connected devices about disconnection */ /* at this point, they cannot respond to any calls except release() */
#if IS_ENABLED(CONFIG_SND_MIXER_OSS) if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT); #endif
/* notify all devices that we are disconnected */
snd_device_disconnect_all(card);
if (card->sync_irq > 0)
synchronize_irq(card->sync_irq);
/* The call of snd_card_free() is allowed from various code paths; *amanualcallfromthedriverandthecallviadevres_free,and *weneedtoavoiddouble-free.Moreover,thereleaseviadevres *maycallsnd_card_free()twiceduetoitsnature,weneedtohave *thecheckhereatthebeginning.
*/ if (card->releasing) return;
/* wait, until all devices are ready for the free operation */
wait_for_completion(&released);
}
EXPORT_SYMBOL(snd_card_free);
/* check, if the character is in the valid ASCII range */ staticinlinebool safe_ascii_char(char c)
{ return isascii(c) && isalnum(c);
}
/* retrieve the last word of shortname or longname */ staticconstchar *retrieve_id_from_card_name(constchar *name)
{ constchar *spos = name;
while (*name) { if (isspace(*name) && safe_ascii_char(name[1]))
spos = name + 1;
name++;
} return spos;
}
/* return true if the given id string doesn't conflict any other card ids */ staticbool card_id_ok(struct snd_card *card, constchar *id)
{ int i; if (!snd_info_check_reserved_words(id)) returnfalse; for (i = 0; i < snd_ecards_limit; i++) { if (snd_cards[i] && snd_cards[i] != card &&
!strcmp(snd_cards[i]->id, id)) returnfalse;
} returntrue;
}
/* copy to card->id only with valid letters from nid */ staticvoid copy_valid_id_string(struct snd_card *card, constchar *src, constchar *nid)
{ char *id = card->id;
while (*nid && !safe_ascii_char(*nid))
nid++; if (isdigit(*nid))
*id++ = isalpha(*src) ? *src : 'D'; while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) { if (safe_ascii_char(*nid))
*id++ = *nid;
nid++;
}
*id = 0;
}
/* Set card->id from the given string *Ifthestringconflictswithotherids,addasuffixtomakeitunique.
*/ staticvoid snd_card_set_id_no_lock(struct snd_card *card, constchar *src, constchar *nid)
{ int len, loops; bool is_default = false; char *id;
copy_valid_id_string(card, src, nid);
id = card->id;
again: /* use "Default" for obviously invalid strings *("card"conflictswithprocdirectories)
*/ if (!*id || !strncmp(id, "card", 4)) {
strscpy(card->id, "Default");
is_default = true;
}
len = strlen(id); for (loops = 0; loops < SNDRV_CARDS; loops++) { char sfxstr[5]; /* "_012" */ int sfxlen, slen;
if (card_id_ok(card, id)) return; /* OK */
/* Add _XYZ suffix */
sfxlen = scnprintf(sfxstr, sizeof(sfxstr), "_%X", loops + 1); if (len + sfxlen >= sizeof(card->id))
slen = sizeof(card->id) - sfxlen - 1; else
slen = len;
strscpy(id + slen, sfxstr, sizeof(card->id) - slen);
} /* fallback to the default id */ if (!is_default) {
*id = 0; goto again;
} /* last resort... */
dev_err(card->dev, "unable to set card id (%s)\n", id); if (card->proc_root->name)
strscpy(card->id, card->proc_root->name, sizeof(card->id));
}
/** *snd_card_set_id-setcardidentificationname *@card:soundcardstructure *@nid:newidentificationstring * *Thisfunctionsetsthecardidentificationandchecksforname *collisions.
*/ void snd_card_set_id(struct snd_card *card, constchar *nid)
{ /* check if user specified own card->id */ if (card->id[0] != '\0') return;
guard(mutex)(&snd_card_mutex);
snd_card_set_id_no_lock(card, nid, nid);
}
EXPORT_SYMBOL(snd_card_set_id);
/** *snd_card_add_dev_attr-Appendanewsysfsattributegrouptocard *@card:cardinstance *@group:attributegrouptoappend * *Return:zeroifsuccessful,oranegativeerrorcode
*/ int snd_card_add_dev_attr(struct snd_card *card, conststruct attribute_group *group)
{ int i;
/* loop for (arraysize-1) here to keep NULL at the last entry */ for (i = 0; i < ARRAY_SIZE(card->dev_groups) - 1; i++) { if (!card->dev_groups[i]) {
card->dev_groups[i] = group; return0;
}
}
dev_err(card->dev, "Too many groups assigned\n"); return -ENOSPC;
}
EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
/** *snd_card_register-registerthesoundcard *@card:soundcardstructure * *Thisfunctionregistersallthedevicesassignedtothesoundcard. *Untilcallingthis,theALSAcontrolinterfaceisblockedfromthe *externalaccesses.Thus,youshouldcallthisfunctionattheend *oftheinitializationofthecard. * *Return:Zerootherwiseanegativeerrorcodeiftheregistrationfailed.
*/ int snd_card_register(struct snd_card *card)
{ int err;
if (snd_BUG_ON(!card)) return -EINVAL;
if (!card->registered) {
err = device_add(&card->card_dev); if (err < 0) return err;
card->registered = true;
} else { if (card->managed)
devm_remove_action(card->dev, trigger_card_free, card);
}
if (card->managed) {
err = devm_add_action(card->dev, trigger_card_free, card); if (err < 0) return err;
}
err = snd_device_register_all(card); if (err < 0) return err;
scoped_guard(mutex, &snd_card_mutex) { if (snd_cards[card->number]) { /* already registered */ return snd_info_card_register(card); /* register pending info */
} 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 */ constchar *src;
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.36Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.