/* call with stream_mutex locked */ staticvoid usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
{ int i; struct control_runtime *ctrl_rt = rt->chip->control;
if (rt->stream_state != STREAM_DISABLED) {
rt->stream_state = STREAM_STOPPING;
for (i = 0; i < PCM_N_URBS; i++) {
usb_kill_urb(&rt->in_urbs[i].instance);
usb_kill_urb(&rt->out_urbs[i].instance);
}
ctrl_rt->usb_streaming = false;
ctrl_rt->update_streaming(ctrl_rt);
rt->stream_state = STREAM_DISABLED;
}
}
/* call with stream_mutex locked */ staticint usb6fire_pcm_stream_start(struct pcm_runtime *rt)
{ int ret; int i; int k; struct usb_iso_packet_descriptor *packet;
if (rt->stream_state == STREAM_DISABLED) { /* submit our in urbs */
rt->stream_wait_cond = false;
rt->stream_state = STREAM_STARTING; for (i = 0; i < PCM_N_URBS; i++) { for (k = 0; k < PCM_N_PACKETS_PER_URB; k++) {
packet = &rt->in_urbs[i].packets[k];
packet->offset = k * rt->in_packet_size;
packet->length = rt->in_packet_size;
packet->actual_length = 0;
packet->status = 0;
}
ret = usb_submit_urb(&rt->in_urbs[i].instance,
GFP_ATOMIC); if (ret) {
usb6fire_pcm_stream_stop(rt); return ret;
}
}
/* wait for first out urb to return (sent in urb handler) */
wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond,
HZ); if (rt->stream_wait_cond)
rt->stream_state = STREAM_RUNNING; else {
usb6fire_pcm_stream_stop(rt); return -EIO;
}
} return 0;
}
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { /* at least 4 header bytes for valid packet.
* after that: 32 bits per sample for analog channels */ if (urb->packets[i].actual_length > 4)
frame_count = (urb->packets[i].actual_length - 4)
/ (rt->in_n_analog << 2); else
frame_count = 0;
if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
src = (u32 *) (urb->buffer + total_length); elseif (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
src = (u32 *) (urb->buffer - 1 + total_length); else return;
src++; /* skip leading 4 bytes of every packet */
total_length += urb->packets[i].length; for (frame = 0; frame < frame_count; frame++) {
memcpy(dest, src, bytes_per_frame);
dest += alsa_rt->channels;
src += rt->in_n_analog;
sub->dma_off++;
sub->period_off++; if (dest == dest_end) {
sub->dma_off = 0;
dest = (u32 *) alsa_rt->dma_area;
}
}
}
}
if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
dest = (u32 *) (urb->buffer - 1); elseif (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
dest = (u32 *) (urb->buffer); else {
dev_err(&rt->chip->dev->dev, "Unknown sample format."); return;
}
for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { /* at least 4 header bytes for valid packet.
* after that: 32 bits per sample for analog channels */ if (urb->packets[i].length > 4)
frame_count = (urb->packets[i].length - 4)
/ (rt->out_n_analog << 2); else
frame_count = 0;
dest++; /* skip leading 4 bytes of every frame */ for (frame = 0; frame < frame_count; frame++) {
memcpy(dest, src, bytes_per_frame);
src += alsa_rt->channels;
dest += rt->out_n_analog;
sub->dma_off++;
sub->period_off++; if (src == src_end) {
src = (u32 *) alsa_rt->dma_area;
sub->dma_off = 0;
}
}
}
}
staticvoid usb6fire_pcm_in_urb_handler(struct urb *usb_urb)
{ struct pcm_urb *in_urb = usb_urb->context; struct pcm_urb *out_urb = in_urb->peer; struct pcm_runtime *rt = in_urb->chip->pcm; struct pcm_substream *sub; unsignedlong flags; int total_length = 0; int frame_count; int frame; int channel; int i;
u8 *dest;
if (usb_urb->status || rt->panic || rt->stream_state == STREAM_STOPPING) return; for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) if (in_urb->packets[i].status) {
rt->panic = true; return;
}
if (rt->stream_state == STREAM_DISABLED) {
dev_err(&rt->chip->dev->dev, "internal error: stream disabled in in-urb handler.\n"); return;
}
/* receive our capture data */
sub = &rt->capture;
spin_lock_irqsave(&sub->lock, flags); if (sub->active) {
usb6fire_pcm_capture(sub, in_urb); if (sub->period_off >= sub->instance->runtime->period_size) {
sub->period_off %= sub->instance->runtime->period_size;
spin_unlock_irqrestore(&sub->lock, flags);
snd_pcm_period_elapsed(sub->instance);
} else
spin_unlock_irqrestore(&sub->lock, flags);
} else
spin_unlock_irqrestore(&sub->lock, flags);
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.