]> Git Repo - linux.git/blob - drivers/media/usb/uvc/uvc_status.c
KVM: x86: fix CPUID entries returned by KVM_GET_CPUID2 ioctl
[linux.git] / drivers / media / usb / uvc / uvc_status.c
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 ([email protected])
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/input.h>
11 #include <linux/slab.h>
12 #include <linux/usb.h>
13 #include <linux/usb/input.h>
14
15 #include "uvcvideo.h"
16
17 /* --------------------------------------------------------------------------
18  * Input device
19  */
20 #ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
21 static int uvc_input_init(struct uvc_device *dev)
22 {
23         struct input_dev *input;
24         int ret;
25
26         input = input_allocate_device();
27         if (input == NULL)
28                 return -ENOMEM;
29
30         usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));
31         strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
32
33         input->name = dev->name;
34         input->phys = dev->input_phys;
35         usb_to_input_id(dev->udev, &input->id);
36         input->dev.parent = &dev->intf->dev;
37
38         __set_bit(EV_KEY, input->evbit);
39         __set_bit(KEY_CAMERA, input->keybit);
40
41         if ((ret = input_register_device(input)) < 0)
42                 goto error;
43
44         dev->input = input;
45         return 0;
46
47 error:
48         input_free_device(input);
49         return ret;
50 }
51
52 static void uvc_input_unregister(struct uvc_device *dev)
53 {
54         if (dev->input)
55                 input_unregister_device(dev->input);
56 }
57
58 static void uvc_input_report_key(struct uvc_device *dev, unsigned int code,
59         int value)
60 {
61         if (dev->input) {
62                 input_report_key(dev->input, code, value);
63                 input_sync(dev->input);
64         }
65 }
66
67 #else
68 #define uvc_input_init(dev)
69 #define uvc_input_unregister(dev)
70 #define uvc_input_report_key(dev, code, value)
71 #endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */
72
73 /* --------------------------------------------------------------------------
74  * Status interrupt endpoint
75  */
76 struct uvc_streaming_status {
77         u8      bStatusType;
78         u8      bOriginator;
79         u8      bEvent;
80         u8      bValue[];
81 } __packed;
82
83 struct uvc_control_status {
84         u8      bStatusType;
85         u8      bOriginator;
86         u8      bEvent;
87         u8      bSelector;
88         u8      bAttribute;
89         u8      bValue[];
90 } __packed;
91
92 static void uvc_event_streaming(struct uvc_device *dev,
93                                 struct uvc_streaming_status *status, int len)
94 {
95         if (len < 3) {
96                 uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event "
97                                 "received.\n");
98                 return;
99         }
100
101         if (status->bEvent == 0) {
102                 if (len < 4)
103                         return;
104                 uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
105                           status->bOriginator,
106                           status->bValue[0] ? "pressed" : "released", len);
107                 uvc_input_report_key(dev, KEY_CAMERA, status->bValue[0]);
108         } else {
109                 uvc_trace(UVC_TRACE_STATUS,
110                           "Stream %u error event %02x len %d.\n",
111                           status->bOriginator, status->bEvent, len);
112         }
113 }
114
115 #define UVC_CTRL_VALUE_CHANGE   0
116 #define UVC_CTRL_INFO_CHANGE    1
117 #define UVC_CTRL_FAILURE_CHANGE 2
118 #define UVC_CTRL_MIN_CHANGE     3
119 #define UVC_CTRL_MAX_CHANGE     4
120
121 static struct uvc_control *uvc_event_entity_find_ctrl(struct uvc_entity *entity,
122                                                       u8 selector)
123 {
124         struct uvc_control *ctrl;
125         unsigned int i;
126
127         for (i = 0, ctrl = entity->controls; i < entity->ncontrols; i++, ctrl++)
128                 if (ctrl->info.selector == selector)
129                         return ctrl;
130
131         return NULL;
132 }
133
134 static struct uvc_control *uvc_event_find_ctrl(struct uvc_device *dev,
135                                         const struct uvc_control_status *status,
136                                         struct uvc_video_chain **chain)
137 {
138         list_for_each_entry((*chain), &dev->chains, list) {
139                 struct uvc_entity *entity;
140                 struct uvc_control *ctrl;
141
142                 list_for_each_entry(entity, &(*chain)->entities, chain) {
143                         if (entity->id != status->bOriginator)
144                                 continue;
145
146                         ctrl = uvc_event_entity_find_ctrl(entity,
147                                                           status->bSelector);
148                         if (ctrl)
149                                 return ctrl;
150                 }
151         }
152
153         return NULL;
154 }
155
156 static bool uvc_event_control(struct urb *urb,
157                               const struct uvc_control_status *status, int len)
158 {
159         static const char *attrs[] = { "value", "info", "failure", "min", "max" };
160         struct uvc_device *dev = urb->context;
161         struct uvc_video_chain *chain;
162         struct uvc_control *ctrl;
163
164         if (len < 6 || status->bEvent != 0 ||
165             status->bAttribute >= ARRAY_SIZE(attrs)) {
166                 uvc_trace(UVC_TRACE_STATUS, "Invalid control status event "
167                                 "received.\n");
168                 return false;
169         }
170
171         uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n",
172                   status->bOriginator, status->bSelector,
173                   attrs[status->bAttribute], len);
174
175         /* Find the control. */
176         ctrl = uvc_event_find_ctrl(dev, status, &chain);
177         if (!ctrl)
178                 return false;
179
180         switch (status->bAttribute) {
181         case UVC_CTRL_VALUE_CHANGE:
182                 return uvc_ctrl_status_event(urb, chain, ctrl, status->bValue);
183
184         case UVC_CTRL_INFO_CHANGE:
185         case UVC_CTRL_FAILURE_CHANGE:
186         case UVC_CTRL_MIN_CHANGE:
187         case UVC_CTRL_MAX_CHANGE:
188                 break;
189         }
190
191         return false;
192 }
193
194 static void uvc_status_complete(struct urb *urb)
195 {
196         struct uvc_device *dev = urb->context;
197         int len, ret;
198
199         switch (urb->status) {
200         case 0:
201                 break;
202
203         case -ENOENT:           /* usb_kill_urb() called. */
204         case -ECONNRESET:       /* usb_unlink_urb() called. */
205         case -ESHUTDOWN:        /* The endpoint is being disabled. */
206         case -EPROTO:           /* Device is disconnected (reported by some
207                                  * host controller). */
208                 return;
209
210         default:
211                 uvc_printk(KERN_WARNING, "Non-zero status (%d) in status "
212                         "completion handler.\n", urb->status);
213                 return;
214         }
215
216         len = urb->actual_length;
217         if (len > 0) {
218                 switch (dev->status[0] & 0x0f) {
219                 case UVC_STATUS_TYPE_CONTROL: {
220                         struct uvc_control_status *status =
221                                 (struct uvc_control_status *)dev->status;
222
223                         if (uvc_event_control(urb, status, len))
224                                 /* The URB will be resubmitted in work context. */
225                                 return;
226                         break;
227                 }
228
229                 case UVC_STATUS_TYPE_STREAMING: {
230                         struct uvc_streaming_status *status =
231                                 (struct uvc_streaming_status *)dev->status;
232
233                         uvc_event_streaming(dev, status, len);
234                         break;
235                 }
236
237                 default:
238                         uvc_trace(UVC_TRACE_STATUS, "Unknown status event "
239                                 "type %u.\n", dev->status[0]);
240                         break;
241                 }
242         }
243
244         /* Resubmit the URB. */
245         urb->interval = dev->int_ep->desc.bInterval;
246         if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
247                 uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",
248                         ret);
249         }
250 }
251
252 int uvc_status_init(struct uvc_device *dev)
253 {
254         struct usb_host_endpoint *ep = dev->int_ep;
255         unsigned int pipe;
256         int interval;
257
258         if (ep == NULL)
259                 return 0;
260
261         uvc_input_init(dev);
262
263         dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);
264         if (dev->status == NULL)
265                 return -ENOMEM;
266
267         dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
268         if (dev->int_urb == NULL) {
269                 kfree(dev->status);
270                 return -ENOMEM;
271         }
272
273         pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
274
275         /* For high-speed interrupt endpoints, the bInterval value is used as
276          * an exponent of two. Some developers forgot about it.
277          */
278         interval = ep->desc.bInterval;
279         if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&
280             (dev->quirks & UVC_QUIRK_STATUS_INTERVAL))
281                 interval = fls(interval) - 1;
282
283         usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
284                 dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
285                 dev, interval);
286
287         return 0;
288 }
289
290 void uvc_status_unregister(struct uvc_device *dev)
291 {
292         usb_kill_urb(dev->int_urb);
293         uvc_input_unregister(dev);
294 }
295
296 void uvc_status_cleanup(struct uvc_device *dev)
297 {
298         usb_free_urb(dev->int_urb);
299         kfree(dev->status);
300 }
301
302 int uvc_status_start(struct uvc_device *dev, gfp_t flags)
303 {
304         if (dev->int_urb == NULL)
305                 return 0;
306
307         return usb_submit_urb(dev->int_urb, flags);
308 }
309
310 void uvc_status_stop(struct uvc_device *dev)
311 {
312         usb_kill_urb(dev->int_urb);
313 }
This page took 0.049943 seconds and 4 git commands to generate.