diff options
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 259 |
1 files changed, 238 insertions, 21 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index bd6214d4ab3b..222af479150b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) | 4 | * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) |
5 | * | 5 | * |
6 | * Camera button input handling by Márton Németh | ||
7 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> | ||
8 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
8 | * Free Software Foundation; either version 2 of the License, or (at your | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -37,6 +40,11 @@ | |||
37 | 40 | ||
38 | #include "gspca.h" | 41 | #include "gspca.h" |
39 | 42 | ||
43 | #ifdef CONFIG_INPUT | ||
44 | #include <linux/input.h> | ||
45 | #include <linux/usb/input.h> | ||
46 | #endif | ||
47 | |||
40 | /* global values */ | 48 | /* global values */ |
41 | #define DEF_NURBS 3 /* default number of URBs */ | 49 | #define DEF_NURBS 3 /* default number of URBs */ |
42 | #if DEF_NURBS > MAX_NURBS | 50 | #if DEF_NURBS > MAX_NURBS |
@@ -47,7 +55,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
47 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 55 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
48 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
49 | 57 | ||
50 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 8, 0) | 58 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 9, 0) |
51 | 59 | ||
52 | #ifdef GSPCA_DEBUG | 60 | #ifdef GSPCA_DEBUG |
53 | int gspca_debug = D_ERR | D_PROBE; | 61 | int gspca_debug = D_ERR | D_PROBE; |
@@ -104,15 +112,185 @@ static const struct vm_operations_struct gspca_vm_ops = { | |||
104 | .close = gspca_vm_close, | 112 | .close = gspca_vm_close, |
105 | }; | 113 | }; |
106 | 114 | ||
115 | /* | ||
116 | * Input and interrupt endpoint handling functions | ||
117 | */ | ||
118 | #ifdef CONFIG_INPUT | ||
119 | static void int_irq(struct urb *urb) | ||
120 | { | ||
121 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
122 | int ret; | ||
123 | |||
124 | ret = urb->status; | ||
125 | switch (ret) { | ||
126 | case 0: | ||
127 | if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev, | ||
128 | urb->transfer_buffer, urb->actual_length) < 0) { | ||
129 | PDEBUG(D_ERR, "Unknown packet received"); | ||
130 | } | ||
131 | break; | ||
132 | |||
133 | case -ENOENT: | ||
134 | case -ECONNRESET: | ||
135 | case -ENODEV: | ||
136 | case -ESHUTDOWN: | ||
137 | /* Stop is requested either by software or hardware is gone, | ||
138 | * keep the ret value non-zero and don't resubmit later. | ||
139 | */ | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status); | ||
144 | urb->status = 0; | ||
145 | ret = 0; | ||
146 | } | ||
147 | |||
148 | if (ret == 0) { | ||
149 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
150 | if (ret < 0) | ||
151 | PDEBUG(D_ERR, "Resubmit URB failed with error %i", ret); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static int gspca_input_connect(struct gspca_dev *dev) | ||
156 | { | ||
157 | struct input_dev *input_dev; | ||
158 | int err = 0; | ||
159 | |||
160 | dev->input_dev = NULL; | ||
161 | if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input) { | ||
162 | input_dev = input_allocate_device(); | ||
163 | if (!input_dev) | ||
164 | return -ENOMEM; | ||
165 | |||
166 | usb_make_path(dev->dev, dev->phys, sizeof(dev->phys)); | ||
167 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | ||
168 | |||
169 | input_dev->name = dev->sd_desc->name; | ||
170 | input_dev->phys = dev->phys; | ||
171 | |||
172 | usb_to_input_id(dev->dev, &input_dev->id); | ||
173 | |||
174 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
175 | input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); | ||
176 | input_dev->dev.parent = &dev->dev->dev; | ||
177 | |||
178 | err = input_register_device(input_dev); | ||
179 | if (err) { | ||
180 | PDEBUG(D_ERR, "Input device registration failed " | ||
181 | "with error %i", err); | ||
182 | input_dev->dev.parent = NULL; | ||
183 | input_free_device(input_dev); | ||
184 | } else { | ||
185 | dev->input_dev = input_dev; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | return err; | ||
190 | } | ||
191 | |||
192 | static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, | ||
193 | struct usb_endpoint_descriptor *ep) | ||
194 | { | ||
195 | unsigned int buffer_len; | ||
196 | int interval; | ||
197 | struct urb *urb; | ||
198 | struct usb_device *dev; | ||
199 | void *buffer = NULL; | ||
200 | int ret = -EINVAL; | ||
201 | |||
202 | buffer_len = ep->wMaxPacketSize; | ||
203 | interval = ep->bInterval; | ||
204 | PDEBUG(D_PROBE, "found int in endpoint: 0x%x, " | ||
205 | "buffer_len=%u, interval=%u", | ||
206 | ep->bEndpointAddress, buffer_len, interval); | ||
207 | |||
208 | dev = gspca_dev->dev; | ||
209 | |||
210 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
211 | if (!urb) { | ||
212 | ret = -ENOMEM; | ||
213 | goto error; | ||
214 | } | ||
215 | |||
216 | buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize, | ||
217 | GFP_KERNEL, &urb->transfer_dma); | ||
218 | if (!buffer) { | ||
219 | ret = -ENOMEM; | ||
220 | goto error_buffer; | ||
221 | } | ||
222 | usb_fill_int_urb(urb, dev, | ||
223 | usb_rcvintpipe(dev, ep->bEndpointAddress), | ||
224 | buffer, buffer_len, | ||
225 | int_irq, (void *)gspca_dev, interval); | ||
226 | gspca_dev->int_urb = urb; | ||
227 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
228 | if (ret < 0) { | ||
229 | PDEBUG(D_ERR, "submit URB failed with error %i", ret); | ||
230 | goto error_submit; | ||
231 | } | ||
232 | return ret; | ||
233 | |||
234 | error_submit: | ||
235 | usb_buffer_free(dev, | ||
236 | urb->transfer_buffer_length, | ||
237 | urb->transfer_buffer, | ||
238 | urb->transfer_dma); | ||
239 | error_buffer: | ||
240 | usb_free_urb(urb); | ||
241 | error: | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static void gspca_input_create_urb(struct gspca_dev *gspca_dev) | ||
246 | { | ||
247 | struct usb_interface *intf; | ||
248 | struct usb_host_interface *intf_desc; | ||
249 | struct usb_endpoint_descriptor *ep; | ||
250 | int i; | ||
251 | |||
252 | if (gspca_dev->sd_desc->int_pkt_scan) { | ||
253 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | ||
254 | intf_desc = intf->cur_altsetting; | ||
255 | for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { | ||
256 | ep = &intf_desc->endpoint[i].desc; | ||
257 | if (usb_endpoint_dir_in(ep) && | ||
258 | usb_endpoint_xfer_int(ep)) { | ||
259 | |||
260 | alloc_and_submit_int_urb(gspca_dev, ep); | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) | ||
268 | { | ||
269 | struct urb *urb; | ||
270 | |||
271 | urb = gspca_dev->int_urb; | ||
272 | if (urb) { | ||
273 | gspca_dev->int_urb = NULL; | ||
274 | usb_kill_urb(urb); | ||
275 | usb_buffer_free(gspca_dev->dev, | ||
276 | urb->transfer_buffer_length, | ||
277 | urb->transfer_buffer, | ||
278 | urb->transfer_dma); | ||
279 | usb_free_urb(urb); | ||
280 | } | ||
281 | } | ||
282 | #else | ||
283 | #define gspca_input_connect(gspca_dev) 0 | ||
284 | #define gspca_input_create_urb(gspca_dev) | ||
285 | #define gspca_input_destroy_urb(gspca_dev) | ||
286 | #endif | ||
287 | |||
107 | /* get the current input frame buffer */ | 288 | /* get the current input frame buffer */ |
108 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) | 289 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) |
109 | { | 290 | { |
110 | struct gspca_frame *frame; | 291 | struct gspca_frame *frame; |
111 | int i; | ||
112 | 292 | ||
113 | i = gspca_dev->fr_i; | 293 | frame = gspca_dev->cur_frame; |
114 | i = gspca_dev->fr_queue[i]; | ||
115 | frame = &gspca_dev->frame[i]; | ||
116 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | 294 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) |
117 | != V4L2_BUF_FLAG_QUEUED) | 295 | != V4L2_BUF_FLAG_QUEUED) |
118 | return NULL; | 296 | return NULL; |
@@ -486,11 +664,13 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) | |||
486 | i, ep->desc.bEndpointAddress); | 664 | i, ep->desc.bEndpointAddress); |
487 | gspca_dev->alt = i; /* memorize the current alt setting */ | 665 | gspca_dev->alt = i; /* memorize the current alt setting */ |
488 | if (gspca_dev->nbalt > 1) { | 666 | if (gspca_dev->nbalt > 1) { |
667 | gspca_input_destroy_urb(gspca_dev); | ||
489 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); | 668 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); |
490 | if (ret < 0) { | 669 | if (ret < 0) { |
491 | err("set alt %d err %d", i, ret); | 670 | err("set alt %d err %d", i, ret); |
492 | return NULL; | 671 | ep = NULL; |
493 | } | 672 | } |
673 | gspca_input_create_urb(gspca_dev); | ||
494 | } | 674 | } |
495 | return ep; | 675 | return ep; |
496 | } | 676 | } |
@@ -534,26 +714,22 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
534 | nurbs = 1; | 714 | nurbs = 1; |
535 | } | 715 | } |
536 | 716 | ||
537 | gspca_dev->nurbs = nurbs; | ||
538 | for (n = 0; n < nurbs; n++) { | 717 | for (n = 0; n < nurbs; n++) { |
539 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 718 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
540 | if (!urb) { | 719 | if (!urb) { |
541 | err("usb_alloc_urb failed"); | 720 | err("usb_alloc_urb failed"); |
542 | destroy_urbs(gspca_dev); | ||
543 | return -ENOMEM; | 721 | return -ENOMEM; |
544 | } | 722 | } |
723 | gspca_dev->urb[n] = urb; | ||
545 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, | 724 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, |
546 | bsize, | 725 | bsize, |
547 | GFP_KERNEL, | 726 | GFP_KERNEL, |
548 | &urb->transfer_dma); | 727 | &urb->transfer_dma); |
549 | 728 | ||
550 | if (urb->transfer_buffer == NULL) { | 729 | if (urb->transfer_buffer == NULL) { |
551 | usb_free_urb(urb); | 730 | err("usb_buffer_alloc failed"); |
552 | err("usb_buffer_urb failed"); | ||
553 | destroy_urbs(gspca_dev); | ||
554 | return -ENOMEM; | 731 | return -ENOMEM; |
555 | } | 732 | } |
556 | gspca_dev->urb[n] = urb; | ||
557 | urb->dev = gspca_dev->dev; | 733 | urb->dev = gspca_dev->dev; |
558 | urb->context = gspca_dev; | 734 | urb->context = gspca_dev; |
559 | urb->transfer_buffer_length = bsize; | 735 | urb->transfer_buffer_length = bsize; |
@@ -585,6 +761,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
585 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) | 761 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) |
586 | { | 762 | { |
587 | struct usb_host_endpoint *ep; | 763 | struct usb_host_endpoint *ep; |
764 | struct urb *urb; | ||
588 | int n, ret; | 765 | int n, ret; |
589 | 766 | ||
590 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 767 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
@@ -595,6 +772,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
595 | goto out; | 772 | goto out; |
596 | } | 773 | } |
597 | 774 | ||
775 | gspca_dev->usb_err = 0; | ||
776 | |||
598 | /* set the higher alternate setting and | 777 | /* set the higher alternate setting and |
599 | * loop until urb submit succeeds */ | 778 | * loop until urb submit succeeds */ |
600 | if (gspca_dev->cam.reverse_alts) | 779 | if (gspca_dev->cam.reverse_alts) |
@@ -613,10 +792,15 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
613 | goto out; | 792 | goto out; |
614 | } | 793 | } |
615 | for (;;) { | 794 | for (;;) { |
616 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); | 795 | if (!gspca_dev->cam.no_urb_create) { |
617 | ret = create_urbs(gspca_dev, ep); | 796 | PDEBUG(D_STREAM, "init transfer alt %d", |
618 | if (ret < 0) | 797 | gspca_dev->alt); |
619 | goto out; | 798 | ret = create_urbs(gspca_dev, ep); |
799 | if (ret < 0) { | ||
800 | destroy_urbs(gspca_dev); | ||
801 | goto out; | ||
802 | } | ||
803 | } | ||
620 | 804 | ||
621 | /* clear the bulk endpoint */ | 805 | /* clear the bulk endpoint */ |
622 | if (gspca_dev->cam.bulk) | 806 | if (gspca_dev->cam.bulk) |
@@ -636,8 +820,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
636 | break; | 820 | break; |
637 | 821 | ||
638 | /* submit the URBs */ | 822 | /* submit the URBs */ |
639 | for (n = 0; n < gspca_dev->nurbs; n++) { | 823 | for (n = 0; n < MAX_NURBS; n++) { |
640 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 824 | urb = gspca_dev->urb[n]; |
825 | if (urb == NULL) | ||
826 | break; | ||
827 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
641 | if (ret < 0) | 828 | if (ret < 0) |
642 | break; | 829 | break; |
643 | } | 830 | } |
@@ -694,7 +881,9 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) | |||
694 | if (gspca_dev->sd_desc->stopN) | 881 | if (gspca_dev->sd_desc->stopN) |
695 | gspca_dev->sd_desc->stopN(gspca_dev); | 882 | gspca_dev->sd_desc->stopN(gspca_dev); |
696 | destroy_urbs(gspca_dev); | 883 | destroy_urbs(gspca_dev); |
884 | gspca_input_destroy_urb(gspca_dev); | ||
697 | gspca_set_alt0(gspca_dev); | 885 | gspca_set_alt0(gspca_dev); |
886 | gspca_input_create_urb(gspca_dev); | ||
698 | } | 887 | } |
699 | 888 | ||
700 | /* always call stop0 to free the subdriver's resources */ | 889 | /* always call stop0 to free the subdriver's resources */ |
@@ -2060,11 +2249,12 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2060 | PDEBUG(D_ERR, "Too many config"); | 2249 | PDEBUG(D_ERR, "Too many config"); |
2061 | return -ENODEV; | 2250 | return -ENODEV; |
2062 | } | 2251 | } |
2252 | |||
2253 | /* the USB video interface must be the first one */ | ||
2063 | interface = &intf->cur_altsetting->desc; | 2254 | interface = &intf->cur_altsetting->desc; |
2064 | if (interface->bInterfaceNumber > 0) { | 2255 | if (dev->config->desc.bNumInterfaces != 1 && |
2065 | PDEBUG(D_ERR, "intf != 0"); | 2256 | interface->bInterfaceNumber != 0) |
2066 | return -ENODEV; | 2257 | return -ENODEV; |
2067 | } | ||
2068 | 2258 | ||
2069 | /* create the device */ | 2259 | /* create the device */ |
2070 | if (dev_size < sizeof *gspca_dev) | 2260 | if (dev_size < sizeof *gspca_dev) |
@@ -2096,6 +2286,10 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2096 | goto out; | 2286 | goto out; |
2097 | gspca_set_default_mode(gspca_dev); | 2287 | gspca_set_default_mode(gspca_dev); |
2098 | 2288 | ||
2289 | ret = gspca_input_connect(gspca_dev); | ||
2290 | if (ret) | ||
2291 | goto out; | ||
2292 | |||
2099 | mutex_init(&gspca_dev->usb_lock); | 2293 | mutex_init(&gspca_dev->usb_lock); |
2100 | mutex_init(&gspca_dev->read_lock); | 2294 | mutex_init(&gspca_dev->read_lock); |
2101 | mutex_init(&gspca_dev->queue_lock); | 2295 | mutex_init(&gspca_dev->queue_lock); |
@@ -2116,8 +2310,15 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2116 | 2310 | ||
2117 | usb_set_intfdata(intf, gspca_dev); | 2311 | usb_set_intfdata(intf, gspca_dev); |
2118 | PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); | 2312 | PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); |
2313 | |||
2314 | gspca_input_create_urb(gspca_dev); | ||
2315 | |||
2119 | return 0; | 2316 | return 0; |
2120 | out: | 2317 | out: |
2318 | #ifdef CONFIG_INPUT | ||
2319 | if (gspca_dev->input_dev) | ||
2320 | input_unregister_device(gspca_dev->input_dev); | ||
2321 | #endif | ||
2121 | kfree(gspca_dev->usb_buf); | 2322 | kfree(gspca_dev->usb_buf); |
2122 | kfree(gspca_dev); | 2323 | kfree(gspca_dev); |
2123 | return ret; | 2324 | return ret; |
@@ -2133,6 +2334,9 @@ EXPORT_SYMBOL(gspca_dev_probe); | |||
2133 | void gspca_disconnect(struct usb_interface *intf) | 2334 | void gspca_disconnect(struct usb_interface *intf) |
2134 | { | 2335 | { |
2135 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 2336 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
2337 | #ifdef CONFIG_INPUT | ||
2338 | struct input_dev *input_dev; | ||
2339 | #endif | ||
2136 | 2340 | ||
2137 | PDEBUG(D_PROBE, "%s disconnect", | 2341 | PDEBUG(D_PROBE, "%s disconnect", |
2138 | video_device_node_name(&gspca_dev->vdev)); | 2342 | video_device_node_name(&gspca_dev->vdev)); |
@@ -2144,6 +2348,15 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2144 | wake_up_interruptible(&gspca_dev->wq); | 2348 | wake_up_interruptible(&gspca_dev->wq); |
2145 | } | 2349 | } |
2146 | 2350 | ||
2351 | #ifdef CONFIG_INPUT | ||
2352 | gspca_input_destroy_urb(gspca_dev); | ||
2353 | input_dev = gspca_dev->input_dev; | ||
2354 | if (input_dev) { | ||
2355 | gspca_dev->input_dev = NULL; | ||
2356 | input_unregister_device(input_dev); | ||
2357 | } | ||
2358 | #endif | ||
2359 | |||
2147 | /* the device is freed at exit of this function */ | 2360 | /* the device is freed at exit of this function */ |
2148 | gspca_dev->dev = NULL; | 2361 | gspca_dev->dev = NULL; |
2149 | mutex_unlock(&gspca_dev->usb_lock); | 2362 | mutex_unlock(&gspca_dev->usb_lock); |
@@ -2169,6 +2382,7 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message) | |||
2169 | if (gspca_dev->sd_desc->stopN) | 2382 | if (gspca_dev->sd_desc->stopN) |
2170 | gspca_dev->sd_desc->stopN(gspca_dev); | 2383 | gspca_dev->sd_desc->stopN(gspca_dev); |
2171 | destroy_urbs(gspca_dev); | 2384 | destroy_urbs(gspca_dev); |
2385 | gspca_input_destroy_urb(gspca_dev); | ||
2172 | gspca_set_alt0(gspca_dev); | 2386 | gspca_set_alt0(gspca_dev); |
2173 | if (gspca_dev->sd_desc->stop0) | 2387 | if (gspca_dev->sd_desc->stop0) |
2174 | gspca_dev->sd_desc->stop0(gspca_dev); | 2388 | gspca_dev->sd_desc->stop0(gspca_dev); |
@@ -2182,6 +2396,7 @@ int gspca_resume(struct usb_interface *intf) | |||
2182 | 2396 | ||
2183 | gspca_dev->frozen = 0; | 2397 | gspca_dev->frozen = 0; |
2184 | gspca_dev->sd_desc->init(gspca_dev); | 2398 | gspca_dev->sd_desc->init(gspca_dev); |
2399 | gspca_input_create_urb(gspca_dev); | ||
2185 | if (gspca_dev->streaming) | 2400 | if (gspca_dev->streaming) |
2186 | return gspca_init_transfer(gspca_dev); | 2401 | return gspca_init_transfer(gspca_dev); |
2187 | return 0; | 2402 | return 0; |
@@ -2205,6 +2420,8 @@ int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum, | |||
2205 | int retval = 0; | 2420 | int retval = 0; |
2206 | 2421 | ||
2207 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { | 2422 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { |
2423 | if (gspca_dev->ctrl_dis & (1 << i)) | ||
2424 | continue; | ||
2208 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) | 2425 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) |
2209 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; | 2426 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; |
2210 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) | 2427 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) |