1c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/*
2c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      uvc_status.c  --  USB Video Class driver - Status endpoint
3c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
411fc5baf1dab2d30f03a391cabc5fd1808cfbe29Laurent Pinchart *      Copyright (C) 2005-2009
511fc5baf1dab2d30f03a391cabc5fd1808cfbe29Laurent Pinchart *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
6c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
7c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      This program is free software; you can redistribute it and/or modify
8c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      it under the terms of the GNU General Public License as published by
9c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      the Free Software Foundation; either version 2 of the License, or
10c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *      (at your option) any later version.
11c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart *
12c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
13c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
14c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/kernel.h>
15c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/input.h>
165a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
17c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/usb.h>
18c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include <linux/usb/input.h>
19c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
20c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart#include "uvcvideo.h"
21c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
22c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* --------------------------------------------------------------------------
23c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Input device
24c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
256833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart#ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
26c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic int uvc_input_init(struct uvc_device *dev)
27c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
28c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct input_dev *input;
29c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int ret;
30c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
31c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	input = input_allocate_device();
32c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (input == NULL)
33c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -ENOMEM;
34c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
35f180152376c984a6faa9decb8f2811c373da9141Laurent Pinchart	usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));
36f180152376c984a6faa9decb8f2811c373da9141Laurent Pinchart	strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
37c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
38c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	input->name = dev->name;
39f180152376c984a6faa9decb8f2811c373da9141Laurent Pinchart	input->phys = dev->input_phys;
40f180152376c984a6faa9decb8f2811c373da9141Laurent Pinchart	usb_to_input_id(dev->udev, &input->id);
41c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	input->dev.parent = &dev->intf->dev;
42c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
4374ca11c2056d01d9ebb3615cd781a148450c3c82Bastien Nocera	__set_bit(EV_KEY, input->evbit);
4474ca11c2056d01d9ebb3615cd781a148450c3c82Bastien Nocera	__set_bit(KEY_CAMERA, input->keybit);
45c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
46c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = input_register_device(input)) < 0)
47c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		goto error;
48c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
49c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->input = input;
50c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return 0;
51c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
52c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pincharterror:
53c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	input_free_device(input);
54c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	return ret;
55c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
56c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
57c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_input_cleanup(struct uvc_device *dev)
58c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
59c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (dev->input)
60c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		input_unregister_device(dev->input);
61c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
62c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
636833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchartstatic void uvc_input_report_key(struct uvc_device *dev, unsigned int code,
646833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart	int value)
656833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart{
6674ca11c2056d01d9ebb3615cd781a148450c3c82Bastien Nocera	if (dev->input) {
676833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart		input_report_key(dev->input, code, value);
6874ca11c2056d01d9ebb3615cd781a148450c3c82Bastien Nocera		input_sync(dev->input);
6974ca11c2056d01d9ebb3615cd781a148450c3c82Bastien Nocera	}
706833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart}
716833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart
726833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart#else
736833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart#define uvc_input_init(dev)
746833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart#define uvc_input_cleanup(dev)
756833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart#define uvc_input_report_key(dev, code, value)
766833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart#endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */
776833c917b4de1757febdbf946d709ece6dc7a86fLaurent Pinchart
78c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart/* --------------------------------------------------------------------------
79c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart * Status interrupt endpoint
80c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart */
81c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)
82c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
83c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (len < 3) {
84c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event "
85c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"received.\n");
86c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
87c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
88c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
89c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (data[2] == 0) {
90c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		if (len < 4)
91c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			return;
92c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
93c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			data[1], data[3] ? "pressed" : "released", len);
9474ca11c2056d01d9ebb3615cd781a148450c3c82Bastien Nocera		uvc_input_report_key(dev, KEY_CAMERA, data[3]);
95c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	} else {
96c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x "
97c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"len %d.\n", data[1], data[2], data[3], len);
98c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
99c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
100c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
101c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_event_control(struct uvc_device *dev, __u8 *data, int len)
102c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
103c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	char *attrs[3] = { "value", "info", "failure" };
104c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
105c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (len < 6 || data[2] != 0 || data[4] > 2) {
106c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_trace(UVC_TRACE_STATUS, "Invalid control status event "
107c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				"received.\n");
108c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
109c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
110c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
111c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n",
112c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		data[1], data[3], attrs[data[4]], len);
113c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
114c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
115c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartstatic void uvc_status_complete(struct urb *urb)
116c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
117c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct uvc_device *dev = urb->context;
118c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int len, ret;
119c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
120c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	switch (urb->status) {
121c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case 0:
122c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		break;
123c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
124c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case -ENOENT:		/* usb_kill_urb() called. */
125c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case -ECONNRESET:	/* usb_unlink_urb() called. */
126c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case -ESHUTDOWN:	/* The endpoint is being disabled. */
127c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	case -EPROTO:		/* Device is disconnected (reported by some
128c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart				 * host controller). */
129c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
130c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
131c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	default:
132c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_WARNING, "Non-zero status (%d) in status "
133c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			"completion handler.\n", urb->status);
134c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return;
135c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
136c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
137c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	len = urb->actual_length;
138c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (len > 0) {
139c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		switch (dev->status[0] & 0x0f) {
140c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case UVC_STATUS_TYPE_CONTROL:
141c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_event_control(dev, dev->status, len);
142c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
143c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
144c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		case UVC_STATUS_TYPE_STREAMING:
145c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			uvc_event_streaming(dev, dev->status, len);
146c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
147c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
148c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		default:
149bd0232c13419b7ce51e02942082ff6af231e0f84Laurent Pinchart			uvc_trace(UVC_TRACE_STATUS, "Unknown status event "
150bd0232c13419b7ce51e02942082ff6af231e0f84Laurent Pinchart				"type %u.\n", dev->status[0]);
151c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			break;
152c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		}
153c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
154c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
155c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* Resubmit the URB. */
156c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	urb->interval = dev->int_ep->desc.bInterval;
157c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
158c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",
159c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart			ret);
160c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	}
161c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
162c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
163c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartint uvc_status_init(struct uvc_device *dev)
164c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
165c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	struct usb_host_endpoint *ep = dev->int_ep;
166c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	unsigned int pipe;
167c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	int interval;
168c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
169c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (ep == NULL)
170c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return 0;
171c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
172c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_input_init(dev);
173c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
174a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei	dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);
175a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei	if (dev->status == NULL)
176a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei		return -ENOMEM;
177a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei
178c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
179a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei	if (dev->int_urb == NULL) {
180a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei		kfree(dev->status);
181c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		return -ENOMEM;
182a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei	}
183c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
184c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
185c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
186c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	/* For high-speed interrupt endpoints, the bInterval value is used as
187c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 * an exponent of two. Some developers forgot about it.
188c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	 */
189c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	interval = ep->desc.bInterval;
190c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&
191c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	    (dev->quirks & UVC_QUIRK_STATUS_INTERVAL))
192c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		interval = fls(interval) - 1;
193c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
194c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
195a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei		dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
196c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart		dev, interval);
197c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
19804a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart	return 0;
199c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
200c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
201c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchartvoid uvc_status_cleanup(struct uvc_device *dev)
202c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
203c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_kill_urb(dev->int_urb);
204c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_free_urb(dev->int_urb);
205a31a4055473bf0a7b2b06cb2262347200d0711e1Ming Lei	kfree(dev->status);
206c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	uvc_input_cleanup(dev);
207c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart}
208c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart
20917706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchartint uvc_status_start(struct uvc_device *dev, gfp_t flags)
21004a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart{
21104a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart	if (dev->int_urb == NULL)
21204a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart		return 0;
21304a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart
21417706f5653a90ff277b5b36c2eb60ff872df5e7aLaurent Pinchart	return usb_submit_urb(dev->int_urb, flags);
21504a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart}
21604a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart
21704a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchartvoid uvc_status_stop(struct uvc_device *dev)
218c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart{
219c0efd232929c2cd87238de2cccdaf4e845be5b0cLaurent Pinchart	usb_kill_urb(dev->int_urb);
22004a37e0f32f9882430bc1899899d2ed91b8aaf5bLaurent Pinchart}
221