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