static void uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf) { void *mem = req->buf; int len = video->req_size; int ret; /* Add the header. */ ret = uvc_video_encode_header(video, buf, mem, len); mem += ret; len -= ret; /* Process video data. */ ret = uvc_video_encode_data(video, buf, mem, len); len -= ret; req->length = video->req_size - len; if (buf->buf.bytesused == video->queue.buf_used) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; uvc_queue_next_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; } }
void uvc_video_decode_isight (struct urb *urb, struct uvc_video_device *video, struct uvc_buffer *buf) { int ret, i; for (i = 0; i < urb->number_of_packets; ++i) { if (urb->iso_frame_desc[i].status < 0) { uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " "lost (%d).\n", urb->iso_frame_desc[i].status); } /* Decode the payload packet. * uvc_video_decode is entered twice when a frame transition * has been detected because the end of frame can only be * reliably detected when the first packet of the new frame * is processed. The first pass detects the transition and * closes the previous frame's buffer, the second pass * processes the data of the first payload of the new frame. */ do { ret = isight_decode(&video->queue, buf, urb->transfer_buffer + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); if (buf == NULL) break; if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) buf = uvc_queue_next_buffer(&video->queue, buf); } while (ret == -EAGAIN); } }
/* * Completion handler for video URBs. */ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf) { u8 *mem; int ret, i; for (i = 0; i < urb->number_of_packets; ++i) { if (urb->iso_frame_desc[i].status < 0) { uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " "lost (%d).\n", urb->iso_frame_desc[i].status); /* Mark the buffer as faulty. */ if (buf != NULL) buf->error = 1; continue; } /* Decode the payload header. */ mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; do { ret = uvc_video_decode_start(stream, buf, mem, urb->iso_frame_desc[i].actual_length); if (ret == -EAGAIN) { uvc_video_validate_buffer(stream, buf); buf = uvc_queue_next_buffer(&stream->queue, buf); } } while (ret == -EAGAIN); if (ret < 0) continue; /* Decode the payload data. */ uvc_video_decode_data(stream, buf, mem + ret, urb->iso_frame_desc[i].actual_length - ret); /* Process the header again. */ uvc_video_decode_end(stream, buf, mem, urb->iso_frame_desc[i].actual_length); if (buf->state == UVC_BUF_STATE_READY) { uvc_video_validate_buffer(stream, buf); buf = uvc_queue_next_buffer(&stream->queue, buf); } } }
static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf) { u8 *mem = urb->transfer_buffer; int len = stream->urb_size, ret; if (buf == NULL) { urb->transfer_buffer_length = 0; return; } /* If the URB is the first of its payload, add the header. */ if (stream->bulk.header_size == 0) { ret = uvc_video_encode_header(stream, buf, mem, len); stream->bulk.header_size = ret; stream->bulk.payload_size += ret; mem += ret; len -= ret; } /* Process video data. */ ret = uvc_video_encode_data(stream, buf, mem, len); stream->bulk.payload_size += ret; len -= ret; if (buf->bytesused == stream->queue.buf_used || stream->bulk.payload_size == stream->bulk.max_payload_size) { if (buf->bytesused == stream->queue.buf_used) { stream->queue.buf_used = 0; buf->state = UVC_BUF_STATE_READY; buf->buf.v4l2_buf.sequence = ++stream->sequence; uvc_queue_next_buffer(&stream->queue, buf); stream->last_fid ^= UVC_STREAM_FID; } stream->bulk.header_size = 0; stream->bulk.payload_size = 0; } urb->transfer_buffer_length = stream->urb_size - len; }
static void uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf) { void *mem = req->buf; int len = video->req_size; int ret; /* */ if (video->payload_size == 0) { ret = uvc_video_encode_header(video, buf, mem, len); video->payload_size += ret; mem += ret; len -= ret; } /* */ len = min((int)(video->max_payload_size - video->payload_size), len); ret = uvc_video_encode_data(video, buf, mem, len); video->payload_size += ret; len -= ret; req->length = video->req_size - len; req->zero = video->payload_size == video->max_payload_size; if (buf->buf.bytesused == video->queue.buf_used) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; uvc_queue_next_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; video->payload_size = 0; } if (video->payload_size == video->max_payload_size || buf->buf.bytesused == video->queue.buf_used) video->payload_size = 0; }
void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf) { int ret, i; for (i = 0; i < urb->number_of_packets; ++i) { if (urb->iso_frame_desc[i].status < 0) { uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " "lost (%d).\n", urb->iso_frame_desc[i].status); } /* */ do { ret = isight_decode(&stream->queue, buf, urb->transfer_buffer + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); if (buf == NULL) break; if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) buf = uvc_queue_next_buffer(&stream->queue, buf); } while (ret == -EAGAIN); } }
static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf) { u8 *mem; int len, ret; /* * Ignore ZLPs if they're not part of a frame, otherwise process them * to trigger the end of payload detection. */ if (urb->actual_length == 0 && stream->bulk.header_size == 0) return; mem = urb->transfer_buffer; len = urb->actual_length; stream->bulk.payload_size += len; /* If the URB is the first of its payload, decode and save the * header. */ if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) { do { ret = uvc_video_decode_start(stream, buf, mem, len); if (ret == -EAGAIN) buf = uvc_queue_next_buffer(&stream->queue, buf); } while (ret == -EAGAIN); /* If an error occurred skip the rest of the payload. */ if (ret < 0 || buf == NULL) { stream->bulk.skip_payload = 1; } else { memcpy(stream->bulk.header, mem, ret); stream->bulk.header_size = ret; mem += ret; len -= ret; } } /* The buffer queue might have been cancelled while a bulk transfer * was in progress, so we can reach here with buf equal to NULL. Make * sure buf is never dereferenced if NULL. */ /* Process video data. */ if (!stream->bulk.skip_payload && buf != NULL) uvc_video_decode_data(stream, buf, mem, len); /* Detect the payload end by a URB smaller than the maximum size (or * a payload size equal to the maximum) and process the header again. */ if (urb->actual_length < urb->transfer_buffer_length || stream->bulk.payload_size >= stream->bulk.max_payload_size) { if (!stream->bulk.skip_payload && buf != NULL) { uvc_video_decode_end(stream, buf, stream->bulk.header, stream->bulk.payload_size); if (buf->state == UVC_BUF_STATE_READY) buf = uvc_queue_next_buffer(&stream->queue, buf); } stream->bulk.header_size = 0; stream->bulk.skip_payload = 0; stream->bulk.payload_size = 0; } }