📄 info.c
字号:
} return -ENXIO;}static const struct file_operations snd_info_entry_operations ={ .owner = THIS_MODULE, .llseek = snd_info_entry_llseek, .read = snd_info_entry_read, .write = snd_info_entry_write, .poll = snd_info_entry_poll, .unlocked_ioctl = snd_info_entry_ioctl, .mmap = snd_info_entry_mmap, .open = snd_info_entry_open, .release = snd_info_entry_release,};/** * snd_create_proc_entry - create a procfs entry * @name: the name of the proc file * @mode: the file permission bits, S_Ixxx * @parent: the parent proc-directory entry * * Creates a new proc file entry with the given name and permission * on the given directory. * * Returns the pointer of new instance or NULL on failure. */static struct proc_dir_entry *snd_create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent){ struct proc_dir_entry *p; p = create_proc_entry(name, mode, parent); if (p) snd_info_entry_prepare(p); return p;}int __init snd_info_init(void){ struct proc_dir_entry *p; p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, &proc_root); if (p == NULL) return -ENOMEM; snd_proc_root = p;#ifdef CONFIG_SND_OSSEMUL { struct snd_info_entry *entry; if ((entry = snd_info_create_module_entry(THIS_MODULE, "oss", NULL)) == NULL) return -ENOMEM; entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); return -ENOMEM; } snd_oss_root = entry; }#endif#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) { struct snd_info_entry *entry; if ((entry = snd_info_create_module_entry(THIS_MODULE, "seq", NULL)) == NULL) return -ENOMEM; entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); return -ENOMEM; } snd_seq_root = entry; }#endif snd_info_version_init(); snd_minor_info_init(); snd_minor_info_oss_init(); snd_card_info_init(); return 0;}int __exit snd_info_done(void){ snd_card_info_done(); snd_minor_info_oss_done(); snd_minor_info_done(); snd_info_version_done(); if (snd_proc_root) {#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) snd_info_free_entry(snd_seq_root);#endif#ifdef CONFIG_SND_OSSEMUL snd_info_free_entry(snd_oss_root);#endif snd_remove_proc_entry(&proc_root, snd_proc_root); } return 0;}/* *//* * create a card proc file * called from init.c */int snd_info_card_create(struct snd_card *card){ char str[8]; struct snd_info_entry *entry; snd_assert(card != NULL, return -ENXIO); sprintf(str, "card%i", card->number); if ((entry = snd_info_create_module_entry(card->module, str, NULL)) == NULL) return -ENOMEM; entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); return -ENOMEM; } card->proc_root = entry; return 0;}/* * register the card proc file * called from init.c */int snd_info_card_register(struct snd_card *card){ struct proc_dir_entry *p; snd_assert(card != NULL, return -ENXIO); if (!strcmp(card->id, card->proc_root->name)) return 0; p = proc_symlink(card->id, snd_proc_root, card->proc_root->name); if (p == NULL) return -ENOMEM; card->proc_root_link = p; return 0;}/* * de-register the card proc file * called from init.c */void snd_info_card_disconnect(struct snd_card *card){ snd_assert(card != NULL, return); mutex_lock(&info_mutex); if (card->proc_root_link) { snd_remove_proc_entry(snd_proc_root, card->proc_root_link); card->proc_root_link = NULL; } if (card->proc_root) snd_info_disconnect(card->proc_root); mutex_unlock(&info_mutex);}/* * release the card proc file resources * called from init.c */int snd_info_card_free(struct snd_card *card){ snd_assert(card != NULL, return -ENXIO); snd_info_free_entry(card->proc_root); card->proc_root = NULL; return 0;}/** * snd_info_get_line - read one line from the procfs buffer * @buffer: the procfs buffer * @line: the buffer to store * @len: the max. buffer size - 1 * * Reads one line from the buffer and stores the string. * * Returns zero if successful, or 1 if error or EOF. */int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len){ int c = -1; if (len <= 0 || buffer->stop || buffer->error) return 1; while (--len > 0) { c = buffer->buffer[buffer->curr++]; if (c == '\n') { if (buffer->curr >= buffer->size) buffer->stop = 1; break; } *line++ = c; if (buffer->curr >= buffer->size) { buffer->stop = 1; break; } } while (c != '\n' && !buffer->stop) { c = buffer->buffer[buffer->curr++]; if (buffer->curr >= buffer->size) buffer->stop = 1; } *line = '\0'; return 0;}EXPORT_SYMBOL(snd_info_get_line);/** * snd_info_get_str - parse a string token * @dest: the buffer to store the string token * @src: the original string * @len: the max. length of token - 1 * * Parses the original string and copy a token to the given * string buffer. * * Returns the updated pointer of the original string so that * it can be used for the next call. */char *snd_info_get_str(char *dest, char *src, int len){ int c; while (*src == ' ' || *src == '\t') src++; if (*src == '"' || *src == '\'') { c = *src++; while (--len > 0 && *src && *src != c) { *dest++ = *src++; } if (*src == c) src++; } else { while (--len > 0 && *src && *src != ' ' && *src != '\t') { *dest++ = *src++; } } *dest = 0; while (*src == ' ' || *src == '\t') src++; return src;}EXPORT_SYMBOL(snd_info_get_str);/** * snd_info_create_entry - create an info entry * @name: the proc file name * * Creates an info entry with the given file name and initializes as * the default state. * * Usually called from other functions such as * snd_info_create_card_entry(). * * Returns the pointer of the new instance, or NULL on failure. */static struct snd_info_entry *snd_info_create_entry(const char *name){ struct snd_info_entry *entry; entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (entry == NULL) return NULL; entry->name = kstrdup(name, GFP_KERNEL); if (entry->name == NULL) { kfree(entry); return NULL; } entry->mode = S_IFREG | S_IRUGO; entry->content = SNDRV_INFO_CONTENT_TEXT; mutex_init(&entry->access); INIT_LIST_HEAD(&entry->children); INIT_LIST_HEAD(&entry->list); return entry;}/** * snd_info_create_module_entry - create an info entry for the given module * @module: the module pointer * @name: the file name * @parent: the parent directory * * Creates a new info entry and assigns it to the given module. * * Returns the pointer of the new instance, or NULL on failure. */struct snd_info_entry *snd_info_create_module_entry(struct module * module, const char *name, struct snd_info_entry *parent){ struct snd_info_entry *entry = snd_info_create_entry(name); if (entry) { entry->module = module; entry->parent = parent; } return entry;}EXPORT_SYMBOL(snd_info_create_module_entry);/** * snd_info_create_card_entry - create an info entry for the given card * @card: the card instance * @name: the file name * @parent: the parent directory * * Creates a new info entry and assigns it to the given card. * * Returns the pointer of the new instance, or NULL on failure. */struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, const char *name, struct snd_info_entry * parent){ struct snd_info_entry *entry = snd_info_create_entry(name); if (entry) { entry->module = card->module; entry->card = card; entry->parent = parent; } return entry;}EXPORT_SYMBOL(snd_info_create_card_entry);static void snd_info_disconnect(struct snd_info_entry *entry){ struct list_head *p, *n; struct proc_dir_entry *root; list_for_each_safe(p, n, &entry->children) { snd_info_disconnect(list_entry(p, struct snd_info_entry, list)); } if (! entry->p) return; list_del_init(&entry->list); root = entry->parent == NULL ? snd_proc_root : entry->parent->p; snd_assert(root, return); snd_remove_proc_entry(root, entry->p); entry->p = NULL;}static int snd_info_dev_free_entry(struct snd_device *device){ struct snd_info_entry *entry = device->device_data; snd_info_free_entry(entry); return 0;}static int snd_info_dev_register_entry(struct snd_device *device){ struct snd_info_entry *entry = device->device_data; return snd_info_register(entry);}/** * snd_card_proc_new - create an info entry for the given card * @card: the card instance * @name: the file name * @entryp: the pointer to store the new info entry * * Creates a new info entry and assigns it to the given card. * Unlike snd_info_create_card_entry(), this function registers the * info entry as an ALSA device component, so that it can be * unregistered/released without explicit call. * Also, you don't have to register this entry via snd_info_register(), * since this will be registered by snd_card_register() automatically. * * The parent is assumed as card->proc_root. * * For releasing this entry, use snd_device_free() instead of * snd_info_free_entry(). * * Returns zero if successful, or a negative error code on failure. */int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp){ static struct snd_device_ops ops = { .dev_free = snd_info_dev_free_entry, .dev_register = snd_info_dev_register_entry, /* disconnect is done via snd_info_card_disconnect() */ }; struct snd_info_entry *entry; int err; entry = snd_info_create_card_entry(card, name, card->proc_root); if (! entry) return -ENOMEM; if ((err = snd_device_new(card, SNDRV_DEV_INFO, entry, &ops)) < 0) { snd_info_free_entry(entry); return err; } if (entryp) *entryp = entry; return 0;}EXPORT_SYMBOL(snd_card_proc_new);/** * snd_info_free_entry - release the info entry * @entry: the info entry * * Releases the info entry. Don't call this after registered. */void snd_info_free_entry(struct snd_info_entry * entry){ if (entry == NULL) return; if (entry->p) { mutex_lock(&info_mutex); snd_info_disconnect(entry); mutex_unlock(&info_mutex); } kfree(entry->name); if (entry->private_free) entry->private_free(entry); kfree(entry);}EXPORT_SYMBOL(snd_info_free_entry);/** * snd_info_register - register the info entry * @entry: the info entry * * Registers the proc info entry. * * Returns zero if successful, or a negative error code on failure. */int snd_info_register(struct snd_info_entry * entry){ struct proc_dir_entry *root, *p = NULL; snd_assert(entry != NULL, return -ENXIO); root = entry->parent == NULL ? snd_proc_root : entry->parent->p; mutex_lock(&info_mutex); p = snd_create_proc_entry(entry->name, entry->mode, root); if (!p) { mutex_unlock(&info_mutex); return -ENOMEM; } p->owner = entry->module; if (!S_ISDIR(entry->mode)) p->proc_fops = &snd_info_entry_operations; p->size = entry->size; p->data = entry; entry->p = p; if (entry->parent) list_add_tail(&entry->list, &entry->parent->children); mutex_unlock(&info_mutex); return 0;}EXPORT_SYMBOL(snd_info_register);/* */static struct snd_info_entry *snd_info_version_entry;static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer){ snd_iprintf(buffer, "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n" );}static int __init snd_info_version_init(void){ struct snd_info_entry *entry; entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); if (entry == NULL) return -ENOMEM; entry->c.text.read = snd_info_version_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); return -ENOMEM; } snd_info_version_entry = entry; return 0;}static int __exit snd_info_version_done(void){ snd_info_free_entry(snd_info_version_entry); return 0;}#endif /* CONFIG_PROC_FS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -