*参照元 [#bde04a00] #backlinks *説明 [#a08d9573] -パス: [[linux-2.6.33/sound/core/pcm_lib.c]] -FIXME: これは何? --説明 **引数 [#y62f3299] -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]] **返り値 [#u18e23af] -snd_pcm_sframes_t -- --[[linux-2.6.33/snd_pcm_sframes_t]] **参考 [#cd0cf823] *実装 [#s8bfdbad] static snd_pcm_sframes_t snd_pcm_lib_write1(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: case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PAUSED: break; - --[[linux-2.6.33/SNDRV_PCM_STATE_PREPARED]] - --[[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_playback_avail(runtime); - --[[linux-2.6.33/snd_pcm_playback_avail()]] if (!avail) { if (nonblock) { err = -EAGAIN; goto _end_unlock; } err = wait_for_avail_min(substream, &avail); if (err < 0) goto _end_unlock; } - --[[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 型 --[[linux-2.6.33/snd_pcm_mmap_control]] - --[[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 型のメンバ --[[linux-2.6.33/snd_pcm_ops]] offset += frames; size -= frames; xfer += frames; if (runtime->status->state == SNDRV_PCM_STATE_PREPARED && snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { err = snd_pcm_start(substream); if (err < 0) goto _end_unlock; } - --[[linux-2.6.33/snd_pcm_start()]] } _end_unlock: snd_pcm_stream_unlock_irq(substream); _end: return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; } *コメント [#wada1da6]