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