static void
uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req)
{
struct uvc_device *uvc = req->context;
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
if (uvc->event_setup_out) {
uvc->event_setup_out = 0;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DATA;
uvc_event->data.length = req->actual;
memcpy(&uvc_event->data.data, req->buf, req->actual);
v4l2_event_queue(&uvc->vdev, &v4l2_event);
}
}
/* Preallocate control endpoint request. */
uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
if (uvc->control_req == NULL || uvc->control_buf == NULL) {
ret = -ENOMEM;
goto error;
}
uvc->control_req->buf = uvc->control_buf;
uvc->control_req->complete = uvc_function_ep0_complete;
uvc->control_req->context = uvc;
/*
* s3c2410_udc_done
*/
static void s3c2410_udc_done(struct s3c2410_ep *ep,
struct s3c2410_request *req, int status)
{
unsigned halted = ep->halted;
list_del_init(&req->queue);
if (likely(req->req.status == -EINPROGRESS))
req->req.status = status;
else
status = req->req.status;
ep->halted = 1;
usb_gadget_giveback_request(&ep->ep, &req->req);
ep->halted = halted;
}
static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
struct s3c2410_ep *ep, int status)
{
/* Sanity check */
if (&ep->queue == NULL)
return;
while (!list_empty(&ep->queue)) {
struct s3c2410_request *req;
req = list_entry(ep->queue.next, struct s3c2410_request,
queue);
s3c2410_udc_done(ep, req, status);
}
}
/**
* usb_gadget_giveback_request - give the request back to the gadget layer
* Context: in_interrupt()
*
* This is called by device controller drivers in order to return the
* completed request back to the gadget layer.
*/
void usb_gadget_giveback_request(struct usb_ep *ep,
struct usb_request *req)
{
if (likely(req->status == 0))
usb_led_activity(USB_LED_EVENT_GADGET);
trace_usb_gadget_giveback_request(ep, req, 0);
req->complete(ep, req);
}
EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
/* Save index */
idx = udc_read(S3C2410_UDC_INDEX_REG);
/* Read status registers */
usb_status = udc_read(S3C2410_UDC_USB_INT_REG);
usbd_status = udc_read(S3C2410_UDC_EP_INT_REG);
pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
if (usbd_status & S3C2410_UDC_INT_EP0)
{
dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
/* Clear the interrupt bit by setting it to 1 */
udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
s3c2410_udc_handle_ep0(dev);
}
s3c2410_udc_irq
s3c2410_udc_handle_ep0
s3c2410_udc_handle_ep0_idle
s3c2410_udc_nuke(dev, ep, -EPROTO);
s3c2410_udc_done(ep, req, status);
usb_gadget_giveback_request(&ep->ep, &req->req);
req->complete(ep, req);
uvc_function_ep0_complete
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DATA;
uvc_event->data.length = req->actual;
memcpy(&uvc_event->data.data, req->buf, req->actual);
v4l2_event_queue(&uvc->vdev, &v4l2_event);
case UVC_EVENT_DATA:
ret = uvc_events_process_data(dev, &uvc_event->data);
if (ret < 0)
break;
return;
if (dev->control == UVC_VS_COMMIT_CONTROL)
{
if (uvc_video_get_uvc_process(dev->video_id))
return 0;
dev->fcc = format->fcc;
dev->width = frame->width;
dev->height = frame->height;
dev->fps = 10000000 / target->dwFrameInterval;
/*
* Try to set the default format at the V4L2 video capture
* device as requested by the user.
*/
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.field = V4L2_FIELD_ANY;
fmt.fmt.pix.width = frame->width;
fmt.fmt.pix.height = frame->height;
fmt.fmt.pix.pixelformat = format->fcc;
switch (format->fcc) {
case V4L2_PIX_FMT_YUYV:
fmt.fmt.pix.sizeimage = (fmt.fmt.pix.width * fmt.fmt.pix.height * 2);
break;
case V4L2_PIX_FMT_MJPEG:
case V4L2_PIX_FMT_H264:
fmt.fmt.pix.sizeimage = dev->imgsize;
break;
}
uvc_set_user_resolution(fmt.fmt.pix.width, fmt.fmt.pix.height, dev->video_id);
uvc_set_user_fcc(fmt.fmt.pix.pixelformat, dev->video_id);
if (uvc_buffer_init(dev->video_id))
goto err;
/*
* As per the new commit command received from the UVC host
* change the current format selection at both UVC and V4L2
* sides.
*/
ret = uvc_video_set_format(dev);
if (ret < 0)
goto err;
if (!dev->run_standalone) {
/* UVC - V4L2 integrated path. */
ret = v4l2_set_format(dev->vdev, &fmt);
if (ret < 0)
goto err;
}
if (dev->bulk) {
ret = uvc_handle_streamon_event(dev);
if (ret < 0)
goto err;
}
}
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved