1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 *      uvc_status.c  --  USB Video Class driver - Status endpoint
4 *
5 *      Copyright (C) 2005-2009
6 *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7 */
8
9#include <asm/barrier.h>
10#include <linux/kernel.h>
11#include <linux/input.h>
12#include <linux/slab.h>
13#include <linux/usb.h>
14#include <linux/usb/input.h>
15
16#include "uvcvideo.h"
17
18/* --------------------------------------------------------------------------
19 * Input device
20 */
21#ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
22static int uvc_input_init(struct uvc_device *dev)
23{
24	struct input_dev *input;
25	int ret;
26
27	input = input_allocate_device();
28	if (input == NULL)
29		return -ENOMEM;
30
31	usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));
32	strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
33
34	input->name = dev->name;
35	input->phys = dev->input_phys;
36	usb_to_input_id(dev->udev, &input->id);
37	input->dev.parent = &dev->intf->dev;
38
39	__set_bit(EV_KEY, input->evbit);
40	__set_bit(KEY_CAMERA, input->keybit);
41
42	if ((ret = input_register_device(input)) < 0)
43		goto error;
44
45	dev->input = input;
46	return 0;
47
48error:
49	input_free_device(input);
50	return ret;
51}
52
53static void uvc_input_unregister(struct uvc_device *dev)
54{
55	if (dev->input)
56		input_unregister_device(dev->input);
57}
58
59static void uvc_input_report_key(struct uvc_device *dev, unsigned int code,
60	int value)
61{
62	if (dev->input) {
63		input_report_key(dev->input, code, value);
64		input_sync(dev->input);
65	}
66}
67
68#else
69#define uvc_input_init(dev)
70#define uvc_input_unregister(dev)
71#define uvc_input_report_key(dev, code, value)
72#endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */
73
74/* --------------------------------------------------------------------------
75 * Status interrupt endpoint
76 */
77struct uvc_streaming_status {
78	u8	bStatusType;
79	u8	bOriginator;
80	u8	bEvent;
81	u8	bValue[];
82} __packed;
83
84struct uvc_control_status {
85	u8	bStatusType;
86	u8	bOriginator;
87	u8	bEvent;
88	u8	bSelector;
89	u8	bAttribute;
90	u8	bValue[];
91} __packed;
92
93static void uvc_event_streaming(struct uvc_device *dev,
94				struct uvc_streaming_status *status, int len)
95{
96	if (len < 3) {
97		uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event "
98				"received.\n");
99		return;
100	}
101
102	if (status->bEvent == 0) {
103		if (len < 4)
104			return;
105		uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
106			  status->bOriginator,
107			  status->bValue[0] ? "pressed" : "released", len);
108		uvc_input_report_key(dev, KEY_CAMERA, status->bValue[0]);
109	} else {
110		uvc_trace(UVC_TRACE_STATUS,
111			  "Stream %u error event %02x len %d.\n",
112			  status->bOriginator, status->bEvent, len);
113	}
114}
115
116#define UVC_CTRL_VALUE_CHANGE	0
117#define UVC_CTRL_INFO_CHANGE	1
118#define UVC_CTRL_FAILURE_CHANGE	2
119#define UVC_CTRL_MIN_CHANGE	3
120#define UVC_CTRL_MAX_CHANGE	4
121
122static struct uvc_control *uvc_event_entity_find_ctrl(struct uvc_entity *entity,
123						      u8 selector)
124{
125	struct uvc_control *ctrl;
126	unsigned int i;
127
128	for (i = 0, ctrl = entity->controls; i < entity->ncontrols; i++, ctrl++)
129		if (ctrl->info.selector == selector)
130			return ctrl;
131
132	return NULL;
133}
134
135static struct uvc_control *uvc_event_find_ctrl(struct uvc_device *dev,
136					const struct uvc_control_status *status,
137					struct uvc_video_chain **chain)
138{
139	list_for_each_entry((*chain), &dev->chains, list) {
140		struct uvc_entity *entity;
141		struct uvc_control *ctrl;
142
143		list_for_each_entry(entity, &(*chain)->entities, chain) {
144			if (entity->id != status->bOriginator)
145				continue;
146
147			ctrl = uvc_event_entity_find_ctrl(entity,
148							  status->bSelector);
149			if (ctrl)
150				return ctrl;
151		}
152	}
153
154	return NULL;
155}
156
157static bool uvc_event_control(struct urb *urb,
158			      const struct uvc_control_status *status, int len)
159{
160	static const char *attrs[] = { "value", "info", "failure", "min", "max" };
161	struct uvc_device *dev = urb->context;
162	struct uvc_video_chain *chain;
163	struct uvc_control *ctrl;
164
165	if (len < 6 || status->bEvent != 0 ||
166	    status->bAttribute >= ARRAY_SIZE(attrs)) {
167		uvc_trace(UVC_TRACE_STATUS, "Invalid control status event "
168				"received.\n");
169		return false;
170	}
171
172	uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n",
173		  status->bOriginator, status->bSelector,
174		  attrs[status->bAttribute], len);
175
176	/* Find the control. */
177	ctrl = uvc_event_find_ctrl(dev, status, &chain);
178	if (!ctrl)
179		return false;
180
181	switch (status->bAttribute) {
182	case UVC_CTRL_VALUE_CHANGE:
183		return uvc_ctrl_status_event_async(urb, chain, ctrl,
184						   status->bValue);
185
186	case UVC_CTRL_INFO_CHANGE:
187	case UVC_CTRL_FAILURE_CHANGE:
188	case UVC_CTRL_MIN_CHANGE:
189	case UVC_CTRL_MAX_CHANGE:
190		break;
191	}
192
193	return false;
194}
195
196static void uvc_status_complete(struct urb *urb)
197{
198	struct uvc_device *dev = urb->context;
199	int len, ret;
200
201	switch (urb->status) {
202	case 0:
203		break;
204
205	case -ENOENT:		/* usb_kill_urb() called. */
206	case -ECONNRESET:	/* usb_unlink_urb() called. */
207	case -ESHUTDOWN:	/* The endpoint is being disabled. */
208	case -EPROTO:		/* Device is disconnected (reported by some
209				 * host controller). */
210		return;
211
212	default:
213		uvc_printk(KERN_WARNING, "Non-zero status (%d) in status "
214			"completion handler.\n", urb->status);
215		return;
216	}
217
218	len = urb->actual_length;
219	if (len > 0) {
220		switch (dev->status[0] & 0x0f) {
221		case UVC_STATUS_TYPE_CONTROL: {
222			struct uvc_control_status *status =
223				(struct uvc_control_status *)dev->status;
224
225			if (uvc_event_control(urb, status, len))
226				/* The URB will be resubmitted in work context. */
227				return;
228			break;
229		}
230
231		case UVC_STATUS_TYPE_STREAMING: {
232			struct uvc_streaming_status *status =
233				(struct uvc_streaming_status *)dev->status;
234
235			uvc_event_streaming(dev, status, len);
236			break;
237		}
238
239		default:
240			uvc_trace(UVC_TRACE_STATUS, "Unknown status event "
241				"type %u.\n", dev->status[0]);
242			break;
243		}
244	}
245
246	/* Resubmit the URB. */
247	urb->interval = dev->int_ep->desc.bInterval;
248	if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
249		uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",
250			ret);
251	}
252}
253
254int uvc_status_init(struct uvc_device *dev)
255{
256	struct usb_host_endpoint *ep = dev->int_ep;
257	unsigned int pipe;
258	int interval;
259
260	if (ep == NULL)
261		return 0;
262
263	uvc_input_init(dev);
264
265	dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);
266	if (dev->status == NULL)
267		return -ENOMEM;
268
269	dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
270	if (dev->int_urb == NULL) {
271		kfree(dev->status);
272		return -ENOMEM;
273	}
274
275	pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
276
277	/* For high-speed interrupt endpoints, the bInterval value is used as
278	 * an exponent of two. Some developers forgot about it.
279	 */
280	interval = ep->desc.bInterval;
281	if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&
282	    (dev->quirks & UVC_QUIRK_STATUS_INTERVAL))
283		interval = fls(interval) - 1;
284
285	usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
286		dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
287		dev, interval);
288
289	return 0;
290}
291
292void uvc_status_unregister(struct uvc_device *dev)
293{
294	usb_kill_urb(dev->int_urb);
295	uvc_input_unregister(dev);
296}
297
298void uvc_status_cleanup(struct uvc_device *dev)
299{
300	usb_free_urb(dev->int_urb);
301	kfree(dev->status);
302}
303
304int uvc_status_start(struct uvc_device *dev, gfp_t flags)
305{
306	if (dev->int_urb == NULL)
307		return 0;
308
309	return usb_submit_urb(dev->int_urb, flags);
310}
311
312void uvc_status_stop(struct uvc_device *dev)
313{
314	struct uvc_ctrl_work *w = &dev->async_ctrl;
315
316	/*
317	 * Prevent the asynchronous control handler from requeing the URB. The
318	 * barrier is needed so the flush_status change is visible to other
319	 * CPUs running the asynchronous handler before usb_kill_urb() is
320	 * called below.
321	 */
322	smp_store_release(&dev->flush_status, true);
323
324	/*
325	 * Cancel any pending asynchronous work. If any status event was queued,
326	 * process it synchronously.
327	 */
328	if (cancel_work_sync(&w->work))
329		uvc_ctrl_status_event(w->chain, w->ctrl, w->data);
330
331	/* Kill the urb. */
332	usb_kill_urb(dev->int_urb);
333
334	/*
335	 * The URB completion handler may have queued asynchronous work. This
336	 * won't resubmit the URB as flush_status is set, but it needs to be
337	 * cancelled before returning or it could then race with a future
338	 * uvc_status_start() call.
339	 */
340	if (cancel_work_sync(&w->work))
341		uvc_ctrl_status_event(w->chain, w->ctrl, w->data);
342
343	/*
344	 * From this point, there are no events on the queue and the status URB
345	 * is dead. No events will be queued until uvc_status_start() is called.
346	 * The barrier is needed to make sure that flush_status is visible to
347	 * uvc_ctrl_status_event_work() when uvc_status_start() will be called
348	 * again.
349	 */
350	smp_store_release(&dev->flush_status, false);
351}
352