*参照元 [#hf0c8264] #backlinks *説明 [#v168b9fc] -パス: [[linux-2.6.33/sound/core/pcm_lib.c]] -FIXME: これは何? --説明 **引数 [#y7fda71b] -struct snd_pcm_substream *substream -- --[[linux-2.6.33/snd_pcm_substream]] -unsigned long data -- -snd_pcm_uframes_t size -- --[[linux-2.6.33/snd_pcm_uframes_t]] -int nonblock -- -transfer_f transfer -- --[[linux-2.6.33/transfer_f]] **返り値 [#jbcb75e4] -snd_pcm_sframes_t -- --[[linux-2.6.33/snd_pcm_sframes_t]] **参考 [#j9421802] *実装 [#vd4afecb] static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, unsigned long data, snd_pcm_uframes_t size, int nonblock, transfer_f transfer) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t xfer = 0; snd_pcm_uframes_t offset = 0; int err = 0; - --[[linux-2.6.33/snd_pcm_runtime]] if (size == 0) return 0; snd_pcm_stream_lock_irq(substream); - --[[linux-2.6.33/snd_pcm_stream_lock_irq()]] switch (runtime->status->state) { case SNDRV_PCM_STATE_PREPARED: if (size >= runtime->start_threshold) { err = snd_pcm_start(substream); if (err < 0) goto _end_unlock; } - --[[linux-2.6.33/SNDRV_PCM_STATE_PREPARED]] - --[[linux-2.6.33/snd_pcm_start()]] break; case SNDRV_PCM_STATE_DRAINING: case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PAUSED: break; - --[[linux-2.6.33/SNDRV_PCM_STATE_DRAINING]] - --[[linux-2.6.33/SNDRV_PCM_STATE_RUNNING]] - --[[linux-2.6.33/SNDRV_PCM_STATE_PAUSED]] case SNDRV_PCM_STATE_XRUN: err = -EPIPE; goto _end_unlock; - --[[linux-2.6.33/SNDRV_PCM_STATE_XRUN]] case SNDRV_PCM_STATE_SUSPENDED: err = -ESTRPIPE; goto _end_unlock; - --[[linux-2.6.33/SNDRV_PCM_STATE_SUSPENDED]] default: err = -EBADFD; goto _end_unlock; } while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; snd_pcm_uframes_t avail; snd_pcm_uframes_t cont; if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) snd_pcm_update_hw_ptr(substream); - --[[linux-2.6.33/snd_pcm_update_hw_ptr()]] avail = snd_pcm_capture_avail(runtime); - --[[linux-2.6.33/snd_pcm_capture_avail()]] if (!avail) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); goto _end_unlock; } - --[[linux-2.6.33/snd_pcm_stop()]] - --[[linux-2.6.33/SNDRV_PCM_STATE_SETUP]] if (nonblock) { err = -EAGAIN; goto _end_unlock; } err = wait_for_avail_min(substream, &avail); if (err < 0) goto _end_unlock; if (!avail) continue; /* draining */ - --[[linux-2.6.33/wait_for_avail_min()]] } frames = size > avail ? avail : size; cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; if (frames > cont) frames = cont; if (snd_BUG_ON(!frames)) { snd_pcm_stream_unlock_irq(substream); return -EINVAL; } -runtime->control は snd_pcm_mmap_control 型 - --runtime->control は snd_pcm_mmap_control 型のメンバ --[[linux-2.6.33/snd_pcm_mmap_control]] - --[[linux-2.6.33/snd_BUG_ON()]] - --[[linux-2.6.33/snd_pcm_stream_unlock_irq()]] appl_ptr = runtime->control->appl_ptr; appl_ofs = appl_ptr % runtime->buffer_size; snd_pcm_stream_unlock_irq(substream); if ((err = transfer(substream, appl_ofs, data, offset, frames)) < 0) goto _end; snd_pcm_stream_lock_irq(substream); switch (runtime->status->state) { case SNDRV_PCM_STATE_XRUN: err = -EPIPE; goto _end_unlock; case SNDRV_PCM_STATE_SUSPENDED: err = -ESTRPIPE; goto _end_unlock; default: break; } appl_ptr += frames; if (appl_ptr >= runtime->boundary) appl_ptr -= runtime->boundary; runtime->control->appl_ptr = appl_ptr; if (substream->ops->ack) substream->ops->ack(substream); -substream->ops は snd_pcm_ops 型のメンバ - --substream->ops は snd_pcm_ops 型のメンバ --[[linux-2.6.33/snd_pcm_ops]] offset += frames; size -= frames; xfer += frames; } _end_unlock: snd_pcm_stream_unlock_irq(substream); _end: return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; } *コメント [#gf5a9c79]