📄 pcm.c
字号:
{ struct snd_pcm_substream *substream = entry->private_data; struct snd_pcm_runtime *runtime = substream->runtime; if (!runtime) { snd_iprintf(buffer, "closed\n"); return; } if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); return; } snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); snd_iprintf(buffer, "period_step: %u\n", runtime->period_step); snd_iprintf(buffer, "sleep_min: %u\n", runtime->sleep_min); snd_iprintf(buffer, "avail_min: %lu\n", runtime->control->avail_min); snd_iprintf(buffer, "xfer_align: %lu\n", runtime->xfer_align); snd_iprintf(buffer, "start_threshold: %lu\n", runtime->start_threshold); snd_iprintf(buffer, "stop_threshold: %lu\n", runtime->stop_threshold); snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);}static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer){ struct snd_pcm_substream *substream = entry->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_status status; int err; if (!runtime) { snd_iprintf(buffer, "closed\n"); return; } memset(&status, 0, sizeof(status)); err = snd_pcm_status(substream, &status); if (err < 0) { snd_iprintf(buffer, "error %d\n", err); return; } snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state)); snd_iprintf(buffer, "trigger_time: %ld.%09ld\n", status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec); snd_iprintf(buffer, "tstamp : %ld.%09ld\n", status.tstamp.tv_sec, status.tstamp.tv_nsec); snd_iprintf(buffer, "delay : %ld\n", status.delay); snd_iprintf(buffer, "avail : %ld\n", status.avail); snd_iprintf(buffer, "avail_max : %ld\n", status.avail_max); snd_iprintf(buffer, "-----\n"); snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr); snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);}#ifdef CONFIG_SND_PCM_XRUN_DEBUGstatic void snd_pcm_xrun_debug_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer){ struct snd_pcm_str *pstr = entry->private_data; snd_iprintf(buffer, "%d\n", pstr->xrun_debug);}static void snd_pcm_xrun_debug_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer){ struct snd_pcm_str *pstr = entry->private_data; char line[64]; if (!snd_info_get_line(buffer, line, sizeof(line))) pstr->xrun_debug = simple_strtoul(line, NULL, 10);}#endifstatic int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr){ struct snd_pcm *pcm = pstr->pcm; struct snd_info_entry *entry; char name[16]; sprintf(name, "pcm%i%c", pcm->device, pstr->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c'); if ((entry = snd_info_create_card_entry(pcm->card, name, pcm->card->proc_root)) == NULL) return -ENOMEM; entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); return -ENOMEM; } pstr->proc_root = entry; if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) { snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } pstr->proc_info_entry = entry;#ifdef CONFIG_SND_PCM_XRUN_DEBUG if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", pstr->proc_root)) != NULL) { entry->c.text.read = snd_pcm_xrun_debug_read; entry->c.text.write = snd_pcm_xrun_debug_write; entry->mode |= S_IWUSR; entry->private_data = pstr; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } pstr->proc_xrun_debug_entry = entry;#endif return 0;}static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr){#ifdef CONFIG_SND_PCM_XRUN_DEBUG snd_info_free_entry(pstr->proc_xrun_debug_entry); pstr->proc_xrun_debug_entry = NULL;#endif snd_info_free_entry(pstr->proc_info_entry); pstr->proc_info_entry = NULL; snd_info_free_entry(pstr->proc_root); pstr->proc_root = NULL; return 0;}static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream){ struct snd_info_entry *entry; struct snd_card *card; char name[16]; card = substream->pcm->card; sprintf(name, "sub%i", substream->number); if ((entry = snd_info_create_card_entry(card, name, substream->pstr->proc_root)) == NULL) return -ENOMEM; entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); return -ENOMEM; } substream->proc_root = entry; if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) { snd_info_set_text_ops(entry, substream, snd_pcm_substream_proc_info_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } substream->proc_info_entry = entry; if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) { snd_info_set_text_ops(entry, substream, snd_pcm_substream_proc_hw_params_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } substream->proc_hw_params_entry = entry; if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) { snd_info_set_text_ops(entry, substream, snd_pcm_substream_proc_sw_params_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } substream->proc_sw_params_entry = entry; if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) { snd_info_set_text_ops(entry, substream, snd_pcm_substream_proc_status_read); if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } substream->proc_status_entry = entry; return 0;}static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream){ snd_info_free_entry(substream->proc_info_entry); substream->proc_info_entry = NULL; snd_info_free_entry(substream->proc_hw_params_entry); substream->proc_hw_params_entry = NULL; snd_info_free_entry(substream->proc_sw_params_entry); substream->proc_sw_params_entry = NULL; snd_info_free_entry(substream->proc_status_entry); substream->proc_status_entry = NULL; snd_info_free_entry(substream->proc_root); substream->proc_root = NULL; return 0;}#else /* !CONFIG_SND_VERBOSE_PROCFS */static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }#endif /* CONFIG_SND_VERBOSE_PROCFS *//** * snd_pcm_new_stream - create a new PCM stream * @pcm: the pcm instance * @stream: the stream direction, SNDRV_PCM_STREAM_XXX * @substream_count: the number of substreams * * Creates a new stream for the pcm. * The corresponding stream on the pcm must have been empty before * calling this, i.e. zero must be given to the argument of * snd_pcm_new(). * * Returns zero if successful, or a negative error code on failure. */int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count){ int idx, err; struct snd_pcm_str *pstr = &pcm->streams[stream]; struct snd_pcm_substream *substream, *prev;#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) mutex_init(&pstr->oss.setup_mutex);#endif pstr->stream = stream; pstr->pcm = pcm; pstr->substream_count = substream_count; if (substream_count > 0) { err = snd_pcm_stream_proc_init(pstr); if (err < 0) { snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); return err; } } prev = NULL; for (idx = 0, prev = NULL; idx < substream_count; idx++) { substream = kzalloc(sizeof(*substream), GFP_KERNEL); if (substream == NULL) { snd_printk(KERN_ERR "Cannot allocate PCM substream\n"); return -ENOMEM; } substream->pcm = pcm; substream->pstr = pstr; substream->number = idx; substream->stream = stream; sprintf(substream->name, "subdevice #%i", idx); snprintf(substream->latency_id, sizeof(substream->latency_id), "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device, (stream ? 'c' : 'p'), idx); substream->buffer_bytes_max = UINT_MAX; if (prev == NULL) pstr->substream = substream; else prev->next = substream; err = snd_pcm_substream_proc_init(substream); if (err < 0) { snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); if (prev == NULL) pstr->substream = NULL; else prev->next = NULL; kfree(substream); return err; } substream->group = &substream->self_group; spin_lock_init(&substream->self_group.lock); INIT_LIST_HEAD(&substream->self_group.substreams); list_add_tail(&substream->link_list, &substream->self_group.substreams); spin_lock_init(&substream->timer_lock); atomic_set(&substream->mmap_count, 0); prev = substream; } return 0;} EXPORT_SYMBOL(snd_pcm_new_stream);/** * snd_pcm_new - create a new PCM instance * @card: the card instance * @id: the id string * @device: the device index (zero based) * @playback_count: the number of substreams for playback * @capture_count: the number of substreams for capture * @rpcm: the pointer to store the new pcm instance * * Creates a new PCM instance. * * The pcm operators have to be set afterwards to the new instance * via snd_pcm_set_ops(). * * Returns zero if successful, or a negative error code on failure. */int snd_pcm_new(struct snd_card *card, char *id, int device, int playback_count, int capture_count, struct snd_pcm ** rpcm){ struct snd_pcm *pcm; int err; static struct snd_device_ops ops = { .dev_free = snd_pcm_dev_free, .dev_register = snd_pcm_dev_register, .dev_disconnect = snd_pcm_dev_disconnect, }; snd_assert(rpcm != NULL, return -EINVAL); *rpcm = NULL; snd_assert(card != NULL, return -ENXIO); pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (pcm == NULL) { snd_printk(KERN_ERR "Cannot allocate PCM\n"); return -ENOMEM; } pcm->card = card; pcm->device = device; if (id) strlcpy(pcm->id, id, sizeof(pcm->id)); if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { snd_pcm_free(pcm); return err; } if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)) < 0) { snd_pcm_free(pcm); return err; } mutex_init(&pcm->open_mutex); init_waitqueue_head(&pcm->open_wait); if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { snd_pcm_free(pcm); return err; } *rpcm = pcm; return 0;}EXPORT_SYMBOL(snd_pcm_new);static void snd_pcm_free_stream(struct snd_pcm_str * pstr){ struct snd_pcm_substream *substream, *substream_next;#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) struct snd_pcm_oss_setup *setup, *setupn;#endif substream = pstr->substream; while (substream) { substream_next = substream->next; snd_pcm_timer_done(substream); snd_pcm_substream_proc_done(substream); kfree(substream); substream = substream_next; } snd_pcm_stream_proc_done(pstr);#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) for (setup = pstr->oss.setup_list; setup; setup = setupn) { setupn = setup->next; kfree(setup->task_name); kfree(setup); }#endif}static int snd_pcm_free(struct snd_pcm *pcm){ struct snd_pcm_notify *notify; snd_assert(pcm != NULL, return -ENXIO); list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_unregister(pcm); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -