diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-06-12 09:58:58 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:14:45 -0400 |
commit | d43fa32fec442571f10f5d0c3b553413288728de (patch) | |
tree | 6bbf2a57d5b9a94bca4246518094f32758eecb1e /drivers/media/video/gspca/gspca.c | |
parent | 4aa0d037a6c8e6b37ecfd986a444f83190c32a21 (diff) |
V4L/DVB (8156): Many bug fixes, zc3xx added.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 991 |
1 files changed, 768 insertions, 223 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 04dbaba4b78f..423ebbdc4b4f 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -35,12 +35,18 @@ | |||
35 | 35 | ||
36 | #include "gspca.h" | 36 | #include "gspca.h" |
37 | 37 | ||
38 | /* option */ | ||
39 | #define GSPCA_HLP 0 | ||
40 | |||
41 | /* global values */ | ||
42 | #define DEF_NURBS 2 /* default number of URBs (mmap) */ | ||
43 | |||
38 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 44 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); |
39 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 45 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
40 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
41 | 47 | ||
42 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 1) | 48 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 15) |
43 | static const char version[] = "0.1.1"; | 49 | static const char version[] = "0.2.15"; |
44 | 50 | ||
45 | static int video_nr = -1; | 51 | static int video_nr = -1; |
46 | 52 | ||
@@ -71,6 +77,229 @@ static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h) | |||
71 | #define PDEBUG_MODE(txt, pixfmt, w, h) | 77 | #define PDEBUG_MODE(txt, pixfmt, w, h) |
72 | #endif | 78 | #endif |
73 | 79 | ||
80 | /* specific memory types - !! should different from V4L2_MEMORY_xxx */ | ||
81 | #define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */ | ||
82 | #define GSPCA_MEMORY_READ 7 | ||
83 | |||
84 | #ifndef GSPCA_HLP | ||
85 | #define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE) | ||
86 | #else | ||
87 | #define GSPCA_BUF_FLAG_DECODE 0x1000 /* internal buffer flag */ | ||
88 | #define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE \ | ||
89 | | GSPCA_BUF_FLAG_DECODE) | ||
90 | |||
91 | static int autostart = 4; | ||
92 | module_param(autostart, int, 0644); | ||
93 | MODULE_PARM_DESC(autostart, | ||
94 | "Automatically start the helper process"); | ||
95 | |||
96 | /* try to start the helper process */ | ||
97 | static void start_hlp(void) | ||
98 | { | ||
99 | int ret; | ||
100 | static char *argv[] = {"gspca_hlp", NULL}; | ||
101 | static char *env[] = {NULL}; | ||
102 | |||
103 | if (autostart <= 0) { | ||
104 | if (autostart < 0) | ||
105 | PDEBUG(D_ERR|D_PROBE, "Too many helper restart"); | ||
106 | return; | ||
107 | } | ||
108 | autostart--; | ||
109 | if (autostart == 0) | ||
110 | autostart = -1; | ||
111 | ret = call_usermodehelper("/sbin/gspca_hlp", argv, env, | ||
112 | UMH_WAIT_EXEC); | ||
113 | if (ret != 0) | ||
114 | PDEBUG(D_ERR|D_PROBE, | ||
115 | "/sbin/gspca_hlp start failed %d", ret); | ||
116 | } | ||
117 | |||
118 | /* /dev/gspca_hlp stuff */ | ||
119 | #include <linux/miscdevice.h> | ||
120 | #include "gspca_hlp.h" | ||
121 | |||
122 | /* !! possible decodings defined in decoder.c */ | ||
123 | static __u32 bayer_to_tb[] = { | ||
124 | V4L2_PIX_FMT_SBGGR8, | ||
125 | V4L2_PIX_FMT_YUYV, | ||
126 | V4L2_PIX_FMT_YUV420, | ||
127 | V4L2_PIX_FMT_RGB24, | ||
128 | V4L2_PIX_FMT_BGR24, | ||
129 | V4L2_PIX_FMT_RGB565, | ||
130 | }; | ||
131 | static __u32 jpeg_to_tb[] = { | ||
132 | V4L2_PIX_FMT_JPEG, | ||
133 | V4L2_PIX_FMT_YUYV, | ||
134 | V4L2_PIX_FMT_YUV420, | ||
135 | V4L2_PIX_FMT_RGB24, | ||
136 | V4L2_PIX_FMT_BGR24, | ||
137 | V4L2_PIX_FMT_RGB565, | ||
138 | }; | ||
139 | |||
140 | /* /dev/gspca_hlp device */ | ||
141 | struct hlp_dev { | ||
142 | struct gspca_dev *gspca_dev; /* associated device */ | ||
143 | struct gspca_frame *frame; /* frame being decoded */ | ||
144 | __u32 pixfmt; /* webcam pixel format */ | ||
145 | atomic_t nevent; /* nb of frames ready to decode */ | ||
146 | wait_queue_head_t wq; /* wait queue */ | ||
147 | char fr_d; /* next frame to decode */ | ||
148 | } *hlp; | ||
149 | |||
150 | static int hlp_open(struct inode *inode, struct file *file) | ||
151 | { | ||
152 | struct hlp_dev *hlp_dev; | ||
153 | |||
154 | PDEBUG(D_CONF, "hlp open"); | ||
155 | if (hlp != 0) | ||
156 | return -EBUSY; | ||
157 | hlp_dev = kzalloc(sizeof *hlp_dev, GFP_KERNEL); | ||
158 | if (hlp_dev == NULL) { | ||
159 | err("couldn't kzalloc hlp struct"); | ||
160 | return -EIO; | ||
161 | } | ||
162 | init_waitqueue_head(&hlp_dev->wq); | ||
163 | file->private_data = hlp_dev; | ||
164 | hlp = hlp_dev; | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int hlp_close(struct inode *inode, struct file *file) | ||
169 | { | ||
170 | struct gspca_dev *gspca_dev; | ||
171 | int mode; | ||
172 | |||
173 | PDEBUG(D_CONF, "hlp close"); | ||
174 | file->private_data = NULL; | ||
175 | |||
176 | /* stop decoding */ | ||
177 | gspca_dev = hlp->gspca_dev; | ||
178 | if (gspca_dev != 0) { | ||
179 | mode = gspca_dev->curr_mode; | ||
180 | gspca_dev->pixfmt = gspca_dev->cam.cam_mode[mode].pixfmt; | ||
181 | } | ||
182 | |||
183 | /* destroy the helper structure */ | ||
184 | kfree(hlp); | ||
185 | hlp = 0; | ||
186 | |||
187 | /* try to restart the helper process */ | ||
188 | start_hlp(); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static ssize_t hlp_read(struct file *file, char __user *buf, | ||
193 | size_t cnt, loff_t *ppos) | ||
194 | { | ||
195 | struct hlp_dev *hlp_dev = file->private_data; | ||
196 | struct gspca_dev *gspca_dev; | ||
197 | struct gspca_frame *frame; | ||
198 | struct gspca_hlp_read_hd head; | ||
199 | int i, j, len, ret; | ||
200 | |||
201 | PDEBUG(D_FRAM, "hlp read (%d)", cnt); | ||
202 | |||
203 | /* check / wait till a frame is ready */ | ||
204 | for (;;) { | ||
205 | gspca_dev = hlp_dev->gspca_dev; | ||
206 | if (gspca_dev != 0 && gspca_dev->streaming) { | ||
207 | i = hlp_dev->fr_d; /* frame to decode */ | ||
208 | j = gspca_dev->fr_queue[i]; | ||
209 | frame = &gspca_dev->frame[j]; | ||
210 | if (frame->v4l2_buf.flags & GSPCA_BUF_FLAG_DECODE) | ||
211 | break; | ||
212 | } | ||
213 | ret = wait_event_interruptible(hlp_dev->wq, | ||
214 | atomic_read(&hlp_dev->nevent) > 0); | ||
215 | if (ret < 0) { /* helper process is killed */ | ||
216 | autostart = 0; /* don't restart it */ | ||
217 | return ret; | ||
218 | } | ||
219 | } | ||
220 | atomic_dec(&hlp_dev->nevent); | ||
221 | hlp_dev->fr_d = (i + 1) % gspca_dev->nframes; | ||
222 | PDEBUG(D_FRAM, "hlp read q:%d i:%d d:%d o:%d", | ||
223 | gspca_dev->fr_q, | ||
224 | gspca_dev->fr_i, | ||
225 | hlp_dev->fr_d, | ||
226 | gspca_dev->fr_o); | ||
227 | |||
228 | hlp_dev->frame = frame; /* memorize the current frame */ | ||
229 | len = frame->v4l2_buf.bytesused; | ||
230 | if (cnt < sizeof head - sizeof head.data + len) | ||
231 | /*fixme: special errno?*/ | ||
232 | return -EINVAL; | ||
233 | head.pixfmt_out = gspca_dev->pixfmt; | ||
234 | head.pixfmt_in = hlp_dev->pixfmt; | ||
235 | head.width = gspca_dev->width; | ||
236 | head.height = gspca_dev->height; | ||
237 | copy_to_user(buf, &head, sizeof head); | ||
238 | copy_to_user(buf + sizeof head - sizeof head.data, | ||
239 | frame->data, len); | ||
240 | return sizeof head - sizeof head.data + len; | ||
241 | } | ||
242 | |||
243 | static ssize_t hlp_write(struct file *file, | ||
244 | const char __user *buf, | ||
245 | size_t cnt, loff_t *ppos) | ||
246 | { | ||
247 | struct hlp_dev *hlp_dev = file->private_data; | ||
248 | struct gspca_dev *gspca_dev; | ||
249 | struct gspca_frame *frame; | ||
250 | |||
251 | PDEBUG(D_FRAM, "hlp write (%d)", cnt); | ||
252 | gspca_dev = hlp_dev->gspca_dev; | ||
253 | if (gspca_dev == 0) | ||
254 | return cnt; | ||
255 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | ||
256 | return -ERESTARTSYS; | ||
257 | if (!gspca_dev->streaming) | ||
258 | goto out; | ||
259 | frame = hlp_dev->frame; | ||
260 | hlp_dev->frame = 0; | ||
261 | if (frame == 0) | ||
262 | goto out; | ||
263 | if (cnt > frame->v4l2_buf.length) { | ||
264 | PDEBUG(D_ERR|D_FRAM, "bad frame size %d - %d", | ||
265 | cnt, frame->v4l2_buf.length); | ||
266 | cnt = -EINVAL; | ||
267 | goto out; | ||
268 | } | ||
269 | copy_from_user(frame->data, buf, cnt); | ||
270 | frame->v4l2_buf.bytesused = cnt; | ||
271 | frame->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_QUEUED | ||
272 | | GSPCA_BUF_FLAG_DECODE); | ||
273 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; | ||
274 | mutex_unlock(&gspca_dev->queue_lock); | ||
275 | atomic_inc(&gspca_dev->nevent); | ||
276 | wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ | ||
277 | PDEBUG(D_FRAM, "hlp write q:%d i:%d d:%d o:%d", | ||
278 | gspca_dev->fr_q, | ||
279 | gspca_dev->fr_i, | ||
280 | hlp_dev->fr_d, | ||
281 | gspca_dev->fr_o); | ||
282 | return cnt; | ||
283 | out: | ||
284 | mutex_unlock(&gspca_dev->queue_lock); | ||
285 | return cnt; | ||
286 | } | ||
287 | |||
288 | static struct file_operations hlp_fops = { | ||
289 | .owner = THIS_MODULE, | ||
290 | .open = hlp_open, | ||
291 | .release = hlp_close, | ||
292 | .read = hlp_read, | ||
293 | .write = hlp_write, | ||
294 | .llseek = no_llseek | ||
295 | }; | ||
296 | static struct miscdevice hlp_device = { | ||
297 | .minor = MISC_DYNAMIC_MINOR, | ||
298 | .name = "gspca_hlp", | ||
299 | .fops = &hlp_fops, | ||
300 | }; | ||
301 | #endif | ||
302 | |||
74 | /* | 303 | /* |
75 | * VMA operations. | 304 | * VMA operations. |
76 | */ | 305 | */ |
@@ -96,22 +325,16 @@ static struct vm_operations_struct gspca_vm_ops = { | |||
96 | }; | 325 | }; |
97 | 326 | ||
98 | /* | 327 | /* |
99 | * ISOC message interrupt from the USB device | 328 | * fill a video frame from an URB and resubmit |
100 | * | ||
101 | * Analyse each packet and call the subdriver for doing the copy | ||
102 | * to the frame buffer. | ||
103 | */ | 329 | */ |
104 | static void isoc_irq(struct urb *urb) | 330 | static void fill_frame(struct gspca_dev *gspca_dev, |
331 | struct urb *urb) | ||
105 | { | 332 | { |
106 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
107 | struct gspca_frame *frame; | 333 | struct gspca_frame *frame; |
108 | unsigned char *data; /* address of data in the iso message */ | 334 | unsigned char *data; /* address of data in the iso message */ |
109 | int i, j, len, st; | 335 | int i, j, len, st; |
110 | cam_pkt_op pkt_scan; | 336 | cam_pkt_op pkt_scan; |
111 | 337 | ||
112 | PDEBUG(D_PACK, "isoc irq"); | ||
113 | if (!gspca_dev->streaming) | ||
114 | return; | ||
115 | pkt_scan = gspca_dev->sd_desc->pkt_scan; | 338 | pkt_scan = gspca_dev->sd_desc->pkt_scan; |
116 | for (i = 0; i < urb->number_of_packets; i++) { | 339 | for (i = 0; i < urb->number_of_packets; i++) { |
117 | 340 | ||
@@ -119,8 +342,7 @@ static void isoc_irq(struct urb *urb) | |||
119 | j = gspca_dev->fr_i; | 342 | j = gspca_dev->fr_i; |
120 | j = gspca_dev->fr_queue[j]; | 343 | j = gspca_dev->fr_queue[j]; |
121 | frame = &gspca_dev->frame[j]; | 344 | frame = &gspca_dev->frame[j]; |
122 | if ((frame->v4l2_buf.flags | 345 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) |
123 | & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) | ||
124 | != V4L2_BUF_FLAG_QUEUED) { | 346 | != V4L2_BUF_FLAG_QUEUED) { |
125 | gspca_dev->last_packet_type = DISCARD_PACKET; | 347 | gspca_dev->last_packet_type = DISCARD_PACKET; |
126 | break; | 348 | break; |
@@ -147,6 +369,7 @@ static void isoc_irq(struct urb *urb) | |||
147 | } | 369 | } |
148 | 370 | ||
149 | /* resubmit the URB */ | 371 | /* resubmit the URB */ |
372 | /*fixme: don't do that when userptr and too many URBs sent*/ | ||
150 | urb->status = 0; | 373 | urb->status = 0; |
151 | st = usb_submit_urb(urb, GFP_ATOMIC); | 374 | st = usb_submit_urb(urb, GFP_ATOMIC); |
152 | if (st < 0) | 375 | if (st < 0) |
@@ -154,9 +377,78 @@ static void isoc_irq(struct urb *urb) | |||
154 | } | 377 | } |
155 | 378 | ||
156 | /* | 379 | /* |
380 | * ISOC message interrupt from the USB device | ||
381 | * | ||
382 | * Analyse each packet and call the subdriver for copy | ||
383 | * to the frame buffer. | ||
384 | * | ||
385 | * There are 2 functions: | ||
386 | * - the first one (isoc_irq_mmap) is used when the application | ||
387 | * buffers are mapped. The frame detection and copy is done | ||
388 | * at interrupt level. | ||
389 | * - the second one (isoc_irq_user) is used when the application | ||
390 | * buffers are in user space (userptr). The frame detection | ||
391 | * and copy is done by the application. | ||
392 | */ | ||
393 | static void isoc_irq_mmap(struct urb *urb) | ||
394 | { | ||
395 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
396 | |||
397 | PDEBUG(D_PACK, "isoc irq mmap"); | ||
398 | if (!gspca_dev->streaming) | ||
399 | return; | ||
400 | fill_frame(gspca_dev, urb); | ||
401 | } | ||
402 | |||
403 | static void isoc_irq_user(struct urb *urb) | ||
404 | { | ||
405 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
406 | int i; | ||
407 | |||
408 | PDEBUG(D_PACK, "isoc irq user"); | ||
409 | if (!gspca_dev->streaming) | ||
410 | return; | ||
411 | |||
412 | i = gspca_dev->urb_in % gspca_dev->nurbs; | ||
413 | if (urb != gspca_dev->urb[i]) { | ||
414 | PDEBUG(D_ERR|D_PACK, "urb out of sequence"); | ||
415 | return; /* should never occur */ | ||
416 | } | ||
417 | |||
418 | gspca_dev->urb_in++; | ||
419 | atomic_inc(&gspca_dev->nevent); /* new event */ | ||
420 | wake_up_interruptible(&gspca_dev->wq); | ||
421 | /*fixme: submit a new URBs until urb_in == urb_out (% nurbs)*/ | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * treat the isoc messages | ||
426 | * | ||
427 | * This routine is called by the application (case userptr). | ||
428 | */ | ||
429 | static void isoc_transfer(struct gspca_dev *gspca_dev) | ||
430 | { | ||
431 | struct urb *urb; | ||
432 | int i; | ||
433 | |||
434 | for (;;) { | ||
435 | i = gspca_dev->urb_out; | ||
436 | PDEBUG(D_PACK, "isoc transf i:%d o:%d", gspca_dev->urb_in, i); | ||
437 | if (i == gspca_dev->urb_in) /* isoc message to read */ | ||
438 | break; /* no (more) message */ | ||
439 | atomic_dec(&gspca_dev->nevent); | ||
440 | /*PDEBUG(D_PACK, "isoc_trf nevent: %d", atomic_read(&gspca_dev->nevent));*/ | ||
441 | gspca_dev->urb_out = i + 1; /* message treated */ | ||
442 | urb = gspca_dev->urb[i % gspca_dev->nurbs]; | ||
443 | fill_frame(gspca_dev, urb); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /* | ||
157 | * add data to the current frame | 448 | * add data to the current frame |
158 | * | 449 | * |
159 | * This function is called by the subdrivers at interrupt level. | 450 | * This function is called by the subdrivers at interrupt level |
451 | * or user level. | ||
160 | * To build a frame, these ones must add | 452 | * To build a frame, these ones must add |
161 | * - one FIRST_PACKET | 453 | * - one FIRST_PACKET |
162 | * - 0 or many INTER_PACKETs | 454 | * - 0 or many INTER_PACKETs |
@@ -177,9 +469,8 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
177 | /* when start of a new frame, if the current frame buffer | 469 | /* when start of a new frame, if the current frame buffer |
178 | * is not queued, discard the whole frame */ | 470 | * is not queued, discard the whole frame */ |
179 | if (packet_type == FIRST_PACKET) { | 471 | if (packet_type == FIRST_PACKET) { |
180 | if ((frame->v4l2_buf.flags | 472 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) |
181 | & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) | 473 | != V4L2_BUF_FLAG_QUEUED) { |
182 | != V4L2_BUF_FLAG_QUEUED) { | ||
183 | gspca_dev->last_packet_type = DISCARD_PACKET; | 474 | gspca_dev->last_packet_type = DISCARD_PACKET; |
184 | return frame; | 475 | return frame; |
185 | } | 476 | } |
@@ -187,10 +478,11 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
187 | jiffies_to_timeval(get_jiffies_64(), | 478 | jiffies_to_timeval(get_jiffies_64(), |
188 | &frame->v4l2_buf.timestamp); | 479 | &frame->v4l2_buf.timestamp); |
189 | frame->v4l2_buf.sequence = ++gspca_dev->sequence; | 480 | frame->v4l2_buf.sequence = ++gspca_dev->sequence; |
190 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) | 481 | } else if (gspca_dev->last_packet_type == DISCARD_PACKET) { |
191 | return frame; | 482 | return frame; |
483 | } | ||
192 | 484 | ||
193 | /* append the packet in the frame buffer */ | 485 | /* append the packet to the frame buffer */ |
194 | if (len > 0) { | 486 | if (len > 0) { |
195 | if (frame->data_end - frame->data + len | 487 | if (frame->data_end - frame->data + len |
196 | > frame->v4l2_buf.length) { | 488 | > frame->v4l2_buf.length) { |
@@ -211,12 +503,25 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
211 | /* if last packet, wake the application and advance in the queue */ | 503 | /* if last packet, wake the application and advance in the queue */ |
212 | if (packet_type == LAST_PACKET) { | 504 | if (packet_type == LAST_PACKET) { |
213 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; | 505 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; |
506 | #ifndef GSPCA_HLP | ||
214 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | 507 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; |
215 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; | 508 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; |
216 | atomic_inc(&gspca_dev->nevent); | 509 | atomic_inc(&gspca_dev->nevent); |
217 | wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ | 510 | wake_up_interruptible(&gspca_dev->wq); /* event = new frame */ |
218 | i = gspca_dev->fr_i; | 511 | #else /*GSPCA_HLP*/ |
219 | i = (i + 1) % gspca_dev->nframes; | 512 | if (hlp != 0 && hlp->gspca_dev == gspca_dev) { |
513 | frame->v4l2_buf.flags |= GSPCA_BUF_FLAG_DECODE; | ||
514 | atomic_inc(&hlp->nevent); | ||
515 | wake_up_interruptible(&hlp->wq); | ||
516 | } else { | ||
517 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
518 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; | ||
519 | atomic_inc(&gspca_dev->nevent); | ||
520 | wake_up_interruptible(&gspca_dev->wq); /* new frame */ | ||
521 | } | ||
522 | #endif /*GSPCA_HLP*/ | ||
523 | i = (gspca_dev->fr_i + 1) % gspca_dev->nframes; | ||
524 | gspca_dev->fr_i = i; | ||
220 | PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d", | 525 | PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d", |
221 | frame->v4l2_buf.bytesused, | 526 | frame->v4l2_buf.bytesused, |
222 | gspca_dev->fr_q, | 527 | gspca_dev->fr_q, |
@@ -224,7 +529,6 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
224 | gspca_dev->fr_o); | 529 | gspca_dev->fr_o); |
225 | j = gspca_dev->fr_queue[i]; | 530 | j = gspca_dev->fr_queue[i]; |
226 | frame = &gspca_dev->frame[j]; | 531 | frame = &gspca_dev->frame[j]; |
227 | gspca_dev->fr_i = i; | ||
228 | } | 532 | } |
229 | return frame; | 533 | return frame; |
230 | } | 534 | } |
@@ -245,7 +549,7 @@ static void *rvmalloc(unsigned long size) | |||
245 | void *mem; | 549 | void *mem; |
246 | unsigned long adr; | 550 | unsigned long adr; |
247 | 551 | ||
248 | size = PAGE_ALIGN(size); | 552 | /* size = PAGE_ALIGN(size); (already done) */ |
249 | mem = vmalloc_32(size); | 553 | mem = vmalloc_32(size); |
250 | if (mem != 0) { | 554 | if (mem != 0) { |
251 | memset(mem, 0, size); | 555 | memset(mem, 0, size); |
@@ -274,27 +578,65 @@ static void rvfree(void *mem, unsigned long size) | |||
274 | vfree(mem); | 578 | vfree(mem); |
275 | } | 579 | } |
276 | 580 | ||
581 | static __u32 get_v4l2_depth(__u32 pixfmt) | ||
582 | { | ||
583 | switch (pixfmt) { | ||
584 | case V4L2_PIX_FMT_BGR32: | ||
585 | case V4L2_PIX_FMT_RGB32: | ||
586 | return 32; | ||
587 | case V4L2_PIX_FMT_RGB24: /* 'RGB3' */ | ||
588 | case V4L2_PIX_FMT_BGR24: | ||
589 | return 24; | ||
590 | case V4L2_PIX_FMT_RGB565: /* 'RGBP' */ | ||
591 | case V4L2_PIX_FMT_YUYV: /* 'YUYV' packed 4.2.2 */ | ||
592 | case V4L2_PIX_FMT_YYUV: /* 'YYUV' */ | ||
593 | return 16; | ||
594 | case V4L2_PIX_FMT_YUV420: /* 'YU12' planar 4.2.0 */ | ||
595 | return 12; | ||
596 | case V4L2_PIX_FMT_MJPEG: | ||
597 | case V4L2_PIX_FMT_JPEG: | ||
598 | case V4L2_PIX_FMT_SBGGR8: /* 'BA81' Bayer */ | ||
599 | return 8; | ||
600 | } | ||
601 | PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c", | ||
602 | pixfmt & 0xff, | ||
603 | (pixfmt >> 8) & 0xff, | ||
604 | (pixfmt >> 16) & 0xff, | ||
605 | pixfmt >> 24); | ||
606 | return -EINVAL; | ||
607 | } | ||
608 | |||
609 | static int gspca_get_buff_size(struct gspca_dev *gspca_dev) | ||
610 | { | ||
611 | unsigned int size; | ||
612 | |||
613 | size = gspca_dev->width * gspca_dev->height | ||
614 | * get_v4l2_depth(gspca_dev->pixfmt) / 8; | ||
615 | if (!size) | ||
616 | return -ENOMEM; | ||
617 | return size; | ||
618 | } | ||
619 | |||
277 | static int frame_alloc(struct gspca_dev *gspca_dev, | 620 | static int frame_alloc(struct gspca_dev *gspca_dev, |
278 | unsigned int count, | 621 | unsigned int count) |
279 | unsigned int frsz, | ||
280 | enum v4l2_memory memory) | ||
281 | { | 622 | { |
282 | int i, ret = 0; | 623 | struct gspca_frame *frame; |
624 | unsigned int frsz; | ||
625 | int i; | ||
283 | 626 | ||
627 | frsz = gspca_get_buff_size(gspca_dev); | ||
628 | if (frsz < 0) | ||
629 | return frsz; | ||
284 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); | 630 | PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); |
285 | if (gspca_dev->nframes != 0) { | ||
286 | PDEBUG(D_ERR|D_STREAM, "alloc frame already done"); | ||
287 | return -EBUSY; | ||
288 | } | ||
289 | if (count > GSPCA_MAX_FRAMES) | 631 | if (count > GSPCA_MAX_FRAMES) |
290 | count = GSPCA_MAX_FRAMES; | 632 | count = GSPCA_MAX_FRAMES; |
291 | /* if compressed, reduce the buffer size */ | 633 | /* if compressed (JPEG), reduce the buffer size */ |
292 | if (gspca_is_compressed(gspca_dev->pixfmt)) | 634 | if (gspca_is_compressed(gspca_dev->pixfmt)) |
293 | frsz = (frsz * comp_fac) / 100; | 635 | frsz = (frsz * comp_fac) / 100 + 600; /* plus JPEG header */ |
294 | frsz = PAGE_ALIGN(frsz); | 636 | frsz = PAGE_ALIGN(frsz); |
295 | PDEBUG(D_STREAM, "new fr_sz: %d", frsz); | 637 | PDEBUG(D_STREAM, "new fr_sz: %d", frsz); |
296 | gspca_dev->frsz = frsz; | 638 | gspca_dev->frsz = frsz; |
297 | if (memory == V4L2_MEMORY_MMAP) { | 639 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) { |
298 | gspca_dev->frbuf = rvmalloc(frsz * count); | 640 | gspca_dev->frbuf = rvmalloc(frsz * count); |
299 | if (!gspca_dev->frbuf) { | 641 | if (!gspca_dev->frbuf) { |
300 | err("frame alloc failed"); | 642 | err("frame alloc failed"); |
@@ -303,25 +645,36 @@ static int frame_alloc(struct gspca_dev *gspca_dev, | |||
303 | } | 645 | } |
304 | gspca_dev->nframes = count; | 646 | gspca_dev->nframes = count; |
305 | for (i = 0; i < count; i++) { | 647 | for (i = 0; i < count; i++) { |
306 | gspca_dev->frame[i].v4l2_buf.index = i; | 648 | frame = &gspca_dev->frame[i]; |
307 | gspca_dev->frame[i].v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 649 | frame->v4l2_buf.index = i; |
308 | gspca_dev->frame[i].v4l2_buf.flags = 0; | 650 | frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
309 | gspca_dev->frame[i].v4l2_buf.field = V4L2_FIELD_NONE; | 651 | frame->v4l2_buf.flags = 0; |
310 | gspca_dev->frame[i].v4l2_buf.length = frsz; | 652 | frame->v4l2_buf.field = V4L2_FIELD_NONE; |
311 | gspca_dev->frame[i].v4l2_buf.memory = memory; | 653 | frame->v4l2_buf.length = frsz; |
312 | if (memory == V4L2_MEMORY_MMAP) { | 654 | frame->v4l2_buf.memory = gspca_dev->memory; |
313 | gspca_dev->frame[i].data | 655 | frame->v4l2_buf.sequence = 0; |
314 | = gspca_dev->frame[i].data_end | 656 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) { |
315 | = gspca_dev->frbuf + i * frsz; | 657 | frame->data = frame->data_end = |
316 | gspca_dev->frame[i].v4l2_buf.m.offset = i * frsz; | 658 | gspca_dev->frbuf + i * frsz; |
659 | frame->v4l2_buf.m.offset = i * frsz; | ||
317 | } | 660 | } |
318 | gspca_dev->frame[i].v4l2_buf.flags = 0; /* buf in app space */ | ||
319 | } | 661 | } |
320 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; | 662 | gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0; |
663 | #ifdef GSPCA_HLP | ||
664 | { | ||
665 | struct hlp_dev *hlp_dev; | ||
666 | |||
667 | hlp_dev = hlp; | ||
668 | if (hlp != 0 && hlp_dev->gspca_dev == gspca_dev) { | ||
669 | hlp_dev->fr_d = 0; | ||
670 | atomic_set(&hlp_dev->nevent, 0); | ||
671 | } | ||
672 | } | ||
673 | #endif /*GSPCA_HLP*/ | ||
321 | gspca_dev->last_packet_type = DISCARD_PACKET; | 674 | gspca_dev->last_packet_type = DISCARD_PACKET; |
322 | gspca_dev->sequence = 0; | 675 | gspca_dev->sequence = 0; |
323 | atomic_set(&gspca_dev->nevent, 0); | 676 | atomic_set(&gspca_dev->nevent, 0); |
324 | return ret; | 677 | return 0; |
325 | } | 678 | } |
326 | 679 | ||
327 | static void frame_free(struct gspca_dev *gspca_dev) | 680 | static void frame_free(struct gspca_dev *gspca_dev) |
@@ -339,16 +692,16 @@ static void frame_free(struct gspca_dev *gspca_dev) | |||
339 | gspca_dev->nframes = 0; | 692 | gspca_dev->nframes = 0; |
340 | } | 693 | } |
341 | 694 | ||
342 | static int gspca_kill_transfer(struct gspca_dev *gspca_dev) | 695 | static void destroy_urbs(struct gspca_dev *gspca_dev) |
343 | { | 696 | { |
344 | struct urb *urb; | 697 | struct urb *urb; |
345 | unsigned int i; | 698 | unsigned int i; |
346 | 699 | ||
347 | PDEBUG(D_STREAM, "kill transfer"); | 700 | PDEBUG(D_STREAM, "kill transfer"); |
348 | for (i = 0; i < NURBS; ++i) { | 701 | for (i = 0; i < MAX_NURBS; ++i) { |
349 | urb = gspca_dev->urb[i]; | 702 | urb = gspca_dev->urb[i]; |
350 | if (urb == NULL) | 703 | if (urb == NULL) |
351 | continue; | 704 | break; |
352 | 705 | ||
353 | gspca_dev->urb[i] = NULL; | 706 | gspca_dev->urb[i] = NULL; |
354 | usb_kill_urb(urb); | 707 | usb_kill_urb(urb); |
@@ -359,7 +712,6 @@ static int gspca_kill_transfer(struct gspca_dev *gspca_dev) | |||
359 | urb->transfer_dma); | 712 | urb->transfer_dma); |
360 | usb_free_urb(urb); | 713 | usb_free_urb(urb); |
361 | } | 714 | } |
362 | return 0; | ||
363 | } | 715 | } |
364 | 716 | ||
365 | /* | 717 | /* |
@@ -417,7 +769,7 @@ struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) | |||
417 | err("set interface err %d", ret); | 769 | err("set interface err %d", ret); |
418 | return NULL; | 770 | return NULL; |
419 | } | 771 | } |
420 | gspca_dev->alt = i; | 772 | gspca_dev->alt = i; /* memorize the current alt setting */ |
421 | return ep; | 773 | return ep; |
422 | } | 774 | } |
423 | 775 | ||
@@ -428,28 +780,28 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
428 | struct usb_host_endpoint *ep) | 780 | struct usb_host_endpoint *ep) |
429 | { | 781 | { |
430 | struct urb *urb; | 782 | struct urb *urb; |
431 | int n, i, psize, npkt, bsize; | 783 | int n, nurbs, i, psize, npkt, bsize; |
784 | usb_complete_t usb_complete; | ||
432 | 785 | ||
433 | /* calculate the packet size and the number of packets */ | 786 | /* calculate the packet size and the number of packets */ |
434 | /* the URB buffer size must be a power of 2 */ | ||
435 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 787 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
788 | |||
436 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ | 789 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ |
437 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | 790 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); |
438 | npkt = ISO_MAX_SIZE / psize; | 791 | npkt = ISO_MAX_SIZE / psize; |
439 | if (npkt > ISO_MAX_PKT) | 792 | if (npkt > ISO_MAX_PKT) |
440 | npkt = ISO_MAX_PKT; | 793 | npkt = ISO_MAX_PKT; |
441 | bsize = psize * npkt; | 794 | bsize = psize * npkt; |
442 | for (n = ISO_MAX_SIZE; n > 0; n >>= 1) { | ||
443 | if (n & bsize) /* !! assume ISO_MAX_SIZE is a power of 2 */ | ||
444 | break; | ||
445 | } | ||
446 | if (n != 0) { | ||
447 | npkt = n / psize; | ||
448 | bsize = psize * npkt; | ||
449 | } | ||
450 | PDEBUG(D_STREAM, | 795 | PDEBUG(D_STREAM, |
451 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); | 796 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); |
452 | for (n = 0; n < NURBS; n++) { | 797 | /*fixme:change for userptr*/ |
798 | /*fixme:don't submit all URBs when userptr*/ | ||
799 | gspca_dev->nurbs = nurbs = DEF_NURBS; | ||
800 | if (gspca_dev->memory == V4L2_MEMORY_MMAP) | ||
801 | usb_complete = isoc_irq_mmap; | ||
802 | else | ||
803 | usb_complete = isoc_irq_user; | ||
804 | for (n = 0; n < nurbs; n++) { | ||
453 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 805 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
454 | if (!urb) { | 806 | if (!urb) { |
455 | err("usb_alloc_urb failed"); | 807 | err("usb_alloc_urb failed"); |
@@ -462,7 +814,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
462 | 814 | ||
463 | if (urb->transfer_buffer == NULL) { | 815 | if (urb->transfer_buffer == NULL) { |
464 | usb_free_urb(urb); | 816 | usb_free_urb(urb); |
465 | gspca_kill_transfer(gspca_dev); | 817 | destroy_urbs(gspca_dev); |
466 | err("usb_buffer_urb failed"); | 818 | err("usb_buffer_urb failed"); |
467 | return -ENOMEM; | 819 | return -ENOMEM; |
468 | } | 820 | } |
@@ -474,7 +826,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
474 | urb->transfer_flags = URB_ISO_ASAP | 826 | urb->transfer_flags = URB_ISO_ASAP |
475 | | URB_NO_TRANSFER_DMA_MAP; | 827 | | URB_NO_TRANSFER_DMA_MAP; |
476 | urb->interval = ep->desc.bInterval; | 828 | urb->interval = ep->desc.bInterval; |
477 | urb->complete = isoc_irq; | 829 | urb->complete = usb_complete; |
478 | urb->number_of_packets = npkt; | 830 | urb->number_of_packets = npkt; |
479 | urb->transfer_buffer_length = bsize; | 831 | urb->transfer_buffer_length = bsize; |
480 | for (i = 0; i < npkt; i++) { | 832 | for (i = 0; i < npkt; i++) { |
@@ -482,6 +834,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
482 | urb->iso_frame_desc[i].offset = psize * i; | 834 | urb->iso_frame_desc[i].offset = psize * i; |
483 | } | 835 | } |
484 | } | 836 | } |
837 | gspca_dev->urb_in = gspca_dev->urb_out = 0; | ||
485 | return 0; | 838 | return 0; |
486 | } | 839 | } |
487 | 840 | ||
@@ -490,18 +843,17 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
490 | */ | 843 | */ |
491 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) | 844 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) |
492 | { | 845 | { |
493 | struct usb_interface *intf; | ||
494 | struct usb_host_endpoint *ep; | 846 | struct usb_host_endpoint *ep; |
495 | int n, ret; | 847 | int n, ret; |
496 | 848 | ||
497 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 849 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
498 | return -ERESTARTSYS; | 850 | return -ERESTARTSYS; |
499 | 851 | ||
500 | /* set the max alternate setting and loop until urb submit succeeds */ | 852 | /* set the higher alternate setting and |
501 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | 853 | * loop until urb submit succeeds */ |
502 | gspca_dev->alt = intf->num_altsetting; | 854 | gspca_dev->alt = gspca_dev->nbalt; |
503 | for (;;) { | 855 | for (;;) { |
504 | PDEBUG(D_STREAM, "init transfer nbalt %d", gspca_dev->alt); | 856 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); |
505 | ep = get_isoc_ep(gspca_dev); | 857 | ep = get_isoc_ep(gspca_dev); |
506 | if (ep == NULL) { | 858 | if (ep == NULL) { |
507 | ret = -EIO; | 859 | ret = -EIO; |
@@ -517,13 +869,13 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
517 | atomic_set(&gspca_dev->nevent, 0); | 869 | atomic_set(&gspca_dev->nevent, 0); |
518 | 870 | ||
519 | /* submit the URBs */ | 871 | /* submit the URBs */ |
520 | for (n = 0; n < NURBS; n++) { | 872 | for (n = 0; n < gspca_dev->nurbs; n++) { |
521 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 873 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); |
522 | if (ret < 0) { | 874 | if (ret < 0) { |
523 | PDEBUG(D_ERR|D_STREAM, | 875 | PDEBUG(D_ERR|D_STREAM, |
524 | "usb_submit_urb [%d] err %d", n, ret); | 876 | "usb_submit_urb [%d] err %d", n, ret); |
525 | gspca_dev->streaming = 0; | 877 | gspca_dev->streaming = 0; |
526 | gspca_kill_transfer(gspca_dev); | 878 | destroy_urbs(gspca_dev); |
527 | if (ret == -ENOSPC) | 879 | if (ret == -ENOSPC) |
528 | break; /* try the previous alt */ | 880 | break; /* try the previous alt */ |
529 | goto out; | 881 | goto out; |
@@ -551,21 +903,32 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) | |||
551 | static void gspca_stream_off(struct gspca_dev *gspca_dev) | 903 | static void gspca_stream_off(struct gspca_dev *gspca_dev) |
552 | { | 904 | { |
553 | gspca_dev->streaming = 0; | 905 | gspca_dev->streaming = 0; |
906 | atomic_set(&gspca_dev->nevent, 0); | ||
907 | #ifdef GSPCA_HLP | ||
908 | { | ||
909 | struct hlp_dev *hlp_dev; | ||
910 | |||
911 | hlp_dev = hlp; | ||
912 | if (hlp_dev != 0 | ||
913 | && hlp_dev->gspca_dev == gspca_dev) | ||
914 | atomic_set(&hlp_dev->nevent, 0); | ||
915 | } | ||
916 | #endif | ||
554 | if (gspca_dev->present) { | 917 | if (gspca_dev->present) { |
555 | gspca_dev->sd_desc->stopN(gspca_dev); | 918 | gspca_dev->sd_desc->stopN(gspca_dev); |
556 | gspca_kill_transfer(gspca_dev); | 919 | destroy_urbs(gspca_dev); |
557 | gspca_set_alt0(gspca_dev); | 920 | gspca_set_alt0(gspca_dev); |
558 | gspca_dev->sd_desc->stop0(gspca_dev); | 921 | gspca_dev->sd_desc->stop0(gspca_dev); |
559 | PDEBUG(D_STREAM, "stream off OK"); | 922 | PDEBUG(D_STREAM, "stream off OK"); |
560 | } else { | 923 | } else { |
561 | gspca_kill_transfer(gspca_dev); | 924 | destroy_urbs(gspca_dev); |
562 | atomic_inc(&gspca_dev->nevent); | 925 | atomic_inc(&gspca_dev->nevent); |
563 | wake_up_interruptible(&gspca_dev->wq); | 926 | wake_up_interruptible(&gspca_dev->wq); |
564 | PDEBUG(D_ERR|D_STREAM, "stream off no device ??"); | 927 | PDEBUG(D_ERR|D_STREAM, "stream off no device ??"); |
565 | } | 928 | } |
566 | } | 929 | } |
567 | 930 | ||
568 | static int gspca_set_default_mode(struct gspca_dev *gspca_dev) | 931 | static void gspca_set_default_mode(struct gspca_dev *gspca_dev) |
569 | { | 932 | { |
570 | int i; | 933 | int i; |
571 | 934 | ||
@@ -574,7 +937,6 @@ static int gspca_set_default_mode(struct gspca_dev *gspca_dev) | |||
574 | gspca_dev->width = gspca_dev->cam.cam_mode[i].width; | 937 | gspca_dev->width = gspca_dev->cam.cam_mode[i].width; |
575 | gspca_dev->height = gspca_dev->cam.cam_mode[i].height; | 938 | gspca_dev->height = gspca_dev->cam.cam_mode[i].height; |
576 | gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt; | 939 | gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt; |
577 | return 0; | ||
578 | } | 940 | } |
579 | 941 | ||
580 | static int wxh_to_mode(struct gspca_dev *gspca_dev, | 942 | static int wxh_to_mode(struct gspca_dev *gspca_dev, |
@@ -582,46 +944,14 @@ static int wxh_to_mode(struct gspca_dev *gspca_dev, | |||
582 | { | 944 | { |
583 | int i; | 945 | int i; |
584 | 946 | ||
585 | for (i = gspca_dev->cam.nmodes - 1; --i >= 0; ) { | 947 | for (i = gspca_dev->cam.nmodes; --i > 0; ) { |
586 | if (width > gspca_dev->cam.cam_mode[i].width) | 948 | if (width >= gspca_dev->cam.cam_mode[i].width |
949 | && height >= gspca_dev->cam.cam_mode[i].height) | ||
587 | break; | 950 | break; |
588 | } | 951 | } |
589 | i++; | ||
590 | while (i < gspca_dev->cam.nmodes - 1 | ||
591 | && width == gspca_dev->cam.cam_mode[i + 1].width | ||
592 | && height < gspca_dev->cam.cam_mode[i + 1].height) | ||
593 | i++; | ||
594 | return i; | 952 | return i; |
595 | } | 953 | } |
596 | 954 | ||
597 | static __u32 get_v4l2_depth(__u32 pixfmt) | ||
598 | { | ||
599 | switch (pixfmt) { | ||
600 | case V4L2_PIX_FMT_BGR32: | ||
601 | case V4L2_PIX_FMT_RGB32: | ||
602 | return 32; | ||
603 | case V4L2_PIX_FMT_RGB24: | ||
604 | case V4L2_PIX_FMT_BGR24: | ||
605 | return 24; | ||
606 | case V4L2_PIX_FMT_RGB565: | ||
607 | case V4L2_PIX_FMT_YUYV: /* packed 4.2.2 */ | ||
608 | case V4L2_PIX_FMT_YYUV: | ||
609 | return 16; | ||
610 | case V4L2_PIX_FMT_YUV420: /* planar 4.2.0 */ | ||
611 | return 12; | ||
612 | case V4L2_PIX_FMT_MJPEG: | ||
613 | case V4L2_PIX_FMT_JPEG: | ||
614 | case V4L2_PIX_FMT_SBGGR8: /* Bayer */ | ||
615 | return 8; | ||
616 | } | ||
617 | PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c", | ||
618 | pixfmt & 0xff, | ||
619 | (pixfmt >> 8) & 0xff, | ||
620 | (pixfmt >> 16) & 0xff, | ||
621 | pixfmt >> 24); | ||
622 | return -EINVAL; | ||
623 | } | ||
624 | |||
625 | /* | 955 | /* |
626 | * search a mode with the right pixel format | 956 | * search a mode with the right pixel format |
627 | */ | 957 | */ |
@@ -649,11 +979,15 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv, | |||
649 | struct v4l2_fmtdesc *fmtdesc) | 979 | struct v4l2_fmtdesc *fmtdesc) |
650 | { | 980 | { |
651 | struct gspca_dev *gspca_dev = priv; | 981 | struct gspca_dev *gspca_dev = priv; |
652 | int i, j, index; | 982 | int i; |
983 | #ifndef GSPCA_HLP | ||
984 | int j, index; | ||
653 | __u32 fmt_tb[8]; | 985 | __u32 fmt_tb[8]; |
986 | #endif | ||
654 | 987 | ||
655 | PDEBUG(D_CONF, "enum fmt cap"); | 988 | PDEBUG(D_CONF, "enum fmt cap"); |
656 | 989 | ||
990 | #ifndef GSPCA_HLP | ||
657 | /* give an index to each format */ | 991 | /* give an index to each format */ |
658 | index = 0; | 992 | index = 0; |
659 | j = 0; | 993 | j = 0; |
@@ -676,10 +1010,40 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv, | |||
676 | if (i < 0) | 1010 | if (i < 0) |
677 | return -EINVAL; /* no more format */ | 1011 | return -EINVAL; /* no more format */ |
678 | 1012 | ||
679 | fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
680 | fmtdesc->pixelformat = fmt_tb[index]; | 1013 | fmtdesc->pixelformat = fmt_tb[index]; |
681 | if (gspca_is_compressed(fmt_tb[index])) | 1014 | if (gspca_is_compressed(fmt_tb[index])) |
682 | fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; | 1015 | fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; |
1016 | #else /*GSPCA_HLP*/ | ||
1017 | /* !! code tied to the decoding functions in decoder.c */ | ||
1018 | i = gspca_dev->cam.nmodes - 1; | ||
1019 | if (fmtdesc->index == 0) { /* (assume one format per subdriver) */ | ||
1020 | fmtdesc->pixelformat = gspca_dev->cam.cam_mode[i].pixfmt; | ||
1021 | if (gspca_is_compressed(fmtdesc->pixelformat)) | ||
1022 | fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED; | ||
1023 | } else { | ||
1024 | if (hlp == 0 | ||
1025 | || (hlp->gspca_dev != 0 | ||
1026 | && hlp->gspca_dev != gspca_dev)) | ||
1027 | return -EINVAL; | ||
1028 | switch (gspca_dev->cam.cam_mode[i].pixfmt) { | ||
1029 | case V4L2_PIX_FMT_JPEG: | ||
1030 | if (fmtdesc->index >= sizeof jpeg_to_tb | ||
1031 | / sizeof jpeg_to_tb[0]) | ||
1032 | return -EINVAL; | ||
1033 | fmtdesc->pixelformat = jpeg_to_tb[fmtdesc->index]; | ||
1034 | break; | ||
1035 | case V4L2_PIX_FMT_SBGGR8: | ||
1036 | if (fmtdesc->index >= sizeof bayer_to_tb | ||
1037 | / sizeof bayer_to_tb[0]) | ||
1038 | return -EINVAL; | ||
1039 | fmtdesc->pixelformat = bayer_to_tb[fmtdesc->index]; | ||
1040 | break; | ||
1041 | default: | ||
1042 | return -EINVAL; | ||
1043 | } | ||
1044 | } | ||
1045 | #endif /*GSPCA_HLP*/ | ||
1046 | fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
683 | fmtdesc->description[0] = fmtdesc->pixelformat & 0xff; | 1047 | fmtdesc->description[0] = fmtdesc->pixelformat & 0xff; |
684 | fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff; | 1048 | fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff; |
685 | fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff; | 1049 | fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff; |
@@ -688,22 +1052,26 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv, | |||
688 | return 0; | 1052 | return 0; |
689 | } | 1053 | } |
690 | 1054 | ||
691 | static int gspca_get_buff_size(struct gspca_dev *gspca_dev) | ||
692 | { | ||
693 | unsigned int size; | ||
694 | |||
695 | size = gspca_dev->width * gspca_dev->height | ||
696 | * get_v4l2_depth(gspca_dev->pixfmt) / 8; | ||
697 | if (!size) | ||
698 | return -ENOMEM; | ||
699 | return size; | ||
700 | } | ||
701 | |||
702 | static int vidioc_g_fmt_cap(struct file *file, void *priv, | 1055 | static int vidioc_g_fmt_cap(struct file *file, void *priv, |
703 | struct v4l2_format *fmt) | 1056 | struct v4l2_format *fmt) |
704 | { | 1057 | { |
705 | struct gspca_dev *gspca_dev = priv; | 1058 | struct gspca_dev *gspca_dev = priv; |
706 | 1059 | ||
1060 | #ifdef GSPCA_HLP | ||
1061 | int i; | ||
1062 | |||
1063 | /* if the pixel format is not the one of the device and | ||
1064 | * if the helper is inactive or busy, restore */ | ||
1065 | i = gspca_dev->curr_mode; | ||
1066 | if (gspca_dev->pixfmt != gspca_dev->cam.cam_mode[i].pixfmt) { | ||
1067 | struct hlp_dev *hlp_dev; | ||
1068 | |||
1069 | hlp_dev = hlp; | ||
1070 | if (hlp_dev == 0 || hlp_dev->gspca_dev != gspca_dev) | ||
1071 | gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt; | ||
1072 | } | ||
1073 | #endif /*GSPCA_HLP*/ | ||
1074 | |||
707 | fmt->fmt.pix.width = gspca_dev->width; | 1075 | fmt->fmt.pix.width = gspca_dev->width; |
708 | fmt->fmt.pix.height = gspca_dev->height; | 1076 | fmt->fmt.pix.height = gspca_dev->height; |
709 | fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; | 1077 | fmt->fmt.pix.pixelformat = gspca_dev->pixfmt; |
@@ -733,6 +1101,10 @@ static int try_fmt_cap(struct gspca_dev *gspca_dev, | |||
733 | 1101 | ||
734 | w = fmt->fmt.pix.width; | 1102 | w = fmt->fmt.pix.width; |
735 | h = fmt->fmt.pix.height; | 1103 | h = fmt->fmt.pix.height; |
1104 | |||
1105 | /* (luvcview problem) */ | ||
1106 | if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) | ||
1107 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; | ||
736 | #ifdef GSPCA_DEBUG | 1108 | #ifdef GSPCA_DEBUG |
737 | if (gspca_debug & D_CONF) | 1109 | if (gspca_debug & D_CONF) |
738 | PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); | 1110 | PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h); |
@@ -746,13 +1118,46 @@ static int try_fmt_cap(struct gspca_dev *gspca_dev, | |||
746 | /* else, search the closest mode with the same pixel format */ | 1118 | /* else, search the closest mode with the same pixel format */ |
747 | mode2 = gspca_get_mode(gspca_dev, mode, | 1119 | mode2 = gspca_get_mode(gspca_dev, mode, |
748 | fmt->fmt.pix.pixelformat); | 1120 | fmt->fmt.pix.pixelformat); |
749 | if (mode2 >= 0) | 1121 | if (mode2 >= 0) { |
750 | mode = mode2; | 1122 | mode = mode2; |
751 | else { | 1123 | } else { |
1124 | __u32 pixfmt; | ||
1125 | |||
1126 | pixfmt = gspca_dev->cam.cam_mode[mode].pixfmt; | ||
1127 | #ifndef GSPCA_HLP | ||
752 | 1128 | ||
753 | /* no chance, return this mode */ | 1129 | /* no chance, return this mode */ |
754 | fmt->fmt.pix.pixelformat | 1130 | fmt->fmt.pix.pixelformat = pixfmt; |
755 | = gspca_dev->cam.cam_mode[mode].pixfmt; | 1131 | #else /*GSPCA_HLP*/ |
1132 | if (hlp != 0 | ||
1133 | && (hlp->gspca_dev == 0 | ||
1134 | || hlp->gspca_dev == gspca_dev) | ||
1135 | /* decoding works for JPEG and Bayer only */ | ||
1136 | && (pixfmt == V4L2_PIX_FMT_JPEG | ||
1137 | || pixfmt == V4L2_PIX_FMT_SBGGR8)) { | ||
1138 | switch (fmt->fmt.pix.pixelformat) { | ||
1139 | case V4L2_PIX_FMT_YUYV: /* 'YUYV' */ | ||
1140 | case V4L2_PIX_FMT_BGR24: /* 'BGR3' */ | ||
1141 | case V4L2_PIX_FMT_RGB24: /* 'RGB3' */ | ||
1142 | case V4L2_PIX_FMT_YUV420: /* 'YU12' */ | ||
1143 | case V4L2_PIX_FMT_RGB565: /* 'RGBP' */ | ||
1144 | break; | ||
1145 | default: { | ||
1146 | /* return any of the supported fmt's */ | ||
1147 | __u8 u; | ||
1148 | |||
1149 | u = get_jiffies_64(); | ||
1150 | u %= sizeof bayer_to_tb | ||
1151 | / sizeof bayer_to_tb[0] - 1; | ||
1152 | fmt->fmt.pix.pixelformat = | ||
1153 | bayer_to_tb[u + 1]; | ||
1154 | break; | ||
1155 | } | ||
1156 | } | ||
1157 | } else { | ||
1158 | fmt->fmt.pix.pixelformat = pixfmt; | ||
1159 | } | ||
1160 | #endif /*GSPCA_HLP*/ | ||
756 | #ifdef GSPCA_DEBUG | 1161 | #ifdef GSPCA_DEBUG |
757 | if (gspca_debug & D_CONF) { | 1162 | if (gspca_debug & D_CONF) { |
758 | PDEBUG_MODE("new format", | 1163 | PDEBUG_MODE("new format", |
@@ -791,7 +1196,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, | |||
791 | struct v4l2_format *fmt) | 1196 | struct v4l2_format *fmt) |
792 | { | 1197 | { |
793 | struct gspca_dev *gspca_dev = priv; | 1198 | struct gspca_dev *gspca_dev = priv; |
794 | int ret, was_streaming; | 1199 | int ret; |
795 | 1200 | ||
796 | #ifdef GSPCA_DEBUG | 1201 | #ifdef GSPCA_DEBUG |
797 | if (gspca_debug & D_CONF) { | 1202 | if (gspca_debug & D_CONF) { |
@@ -802,32 +1207,56 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, | |||
802 | #endif | 1207 | #endif |
803 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1208 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
804 | return -ERESTARTSYS; | 1209 | return -ERESTARTSYS; |
1210 | |||
805 | ret = try_fmt_cap(gspca_dev, fmt); | 1211 | ret = try_fmt_cap(gspca_dev, fmt); |
806 | if (ret < 0) | 1212 | if (ret < 0) |
807 | goto out; | 1213 | goto out; |
808 | 1214 | ||
1215 | if (gspca_dev->nframes != 0 | ||
1216 | && fmt->fmt.pix.sizeimage > gspca_dev->frsz) { | ||
1217 | ret = -EINVAL; | ||
1218 | goto out; | ||
1219 | } | ||
1220 | |||
1221 | #ifndef GSPCA_HLP | ||
809 | if (ret == gspca_dev->curr_mode) | 1222 | if (ret == gspca_dev->curr_mode) |
810 | goto out; /* same mode */ | 1223 | goto out; /* same mode */ |
811 | was_streaming = gspca_dev->streaming; | 1224 | #else /*GSPCA_HLP*/ |
812 | if (was_streaming) { | 1225 | if (ret == gspca_dev->curr_mode |
813 | if (gspca_dev->capt_file != 0 | 1226 | && gspca_dev->pixfmt == fmt->fmt.pix.pixelformat) |
814 | && gspca_dev->capt_file != file) { | 1227 | goto out; /* same mode */ |
815 | ret = -EBUSY; | 1228 | #endif /*GSPCA_HLP*/ |
816 | goto out; | 1229 | |
817 | } | 1230 | if (gspca_dev->streaming) { |
818 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { | 1231 | ret = -EBUSY; |
819 | ret = -ERESTARTSYS; | 1232 | goto out; |
820 | goto out; | ||
821 | } | ||
822 | gspca_stream_off(gspca_dev); | ||
823 | mutex_unlock(&gspca_dev->usb_lock); | ||
824 | } | 1233 | } |
825 | gspca_dev->width = fmt->fmt.pix.width; | 1234 | gspca_dev->width = fmt->fmt.pix.width; |
826 | gspca_dev->height = fmt->fmt.pix.height; | 1235 | gspca_dev->height = fmt->fmt.pix.height; |
827 | gspca_dev->pixfmt = fmt->fmt.pix.pixelformat; | 1236 | gspca_dev->pixfmt = fmt->fmt.pix.pixelformat; |
828 | gspca_dev->curr_mode = ret; | 1237 | gspca_dev->curr_mode = ret; |
829 | if (was_streaming) | 1238 | |
830 | ret = gspca_init_transfer(gspca_dev); | 1239 | #ifdef GSPCA_HLP |
1240 | /* if frame decoding is required */ | ||
1241 | if (gspca_dev->pixfmt != gspca_dev->cam.cam_mode[ret].pixfmt) { | ||
1242 | struct hlp_dev *hlp_dev; | ||
1243 | |||
1244 | hlp_dev = hlp; | ||
1245 | if (hlp_dev == 0 | ||
1246 | || (hlp_dev->gspca_dev != 0 | ||
1247 | && hlp_dev->gspca_dev != gspca_dev)) { /* helper busy */ | ||
1248 | fmt->fmt.pix.pixelformat = | ||
1249 | gspca_dev->pixfmt = | ||
1250 | gspca_dev->cam.cam_mode[ret].pixfmt; | ||
1251 | } else { /* helper active */ | ||
1252 | hlp_dev->gspca_dev = gspca_dev; | ||
1253 | hlp_dev->pixfmt = gspca_dev->cam.cam_mode[ret].pixfmt; | ||
1254 | hlp_dev->fr_d = gspca_dev->fr_i; | ||
1255 | } | ||
1256 | } else if (hlp != 0 && hlp->gspca_dev == gspca_dev) | ||
1257 | hlp->gspca_dev = 0; | ||
1258 | #endif /*GSPCA_HLP*/ | ||
1259 | ret = 0; | ||
831 | out: | 1260 | out: |
832 | mutex_unlock(&gspca_dev->queue_lock); | 1261 | mutex_unlock(&gspca_dev->queue_lock); |
833 | return ret; | 1262 | return ret; |
@@ -838,7 +1267,7 @@ static int dev_open(struct inode *inode, struct file *file) | |||
838 | struct gspca_dev *gspca_dev; | 1267 | struct gspca_dev *gspca_dev; |
839 | int ret; | 1268 | int ret; |
840 | 1269 | ||
841 | PDEBUG(D_STREAM, "opening"); | 1270 | PDEBUG(D_STREAM, "%s open", current->comm); |
842 | gspca_dev = (struct gspca_dev *) video_devdata(file); | 1271 | gspca_dev = (struct gspca_dev *) video_devdata(file); |
843 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1272 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
844 | return -ERESTARTSYS; | 1273 | return -ERESTARTSYS; |
@@ -867,7 +1296,7 @@ static int dev_open(struct inode *inode, struct file *file) | |||
867 | file->private_data = gspca_dev; | 1296 | file->private_data = gspca_dev; |
868 | #ifdef GSPCA_DEBUG | 1297 | #ifdef GSPCA_DEBUG |
869 | /* activate the v4l2 debug */ | 1298 | /* activate the v4l2 debug */ |
870 | if (gspca_debug & D_CONF) | 1299 | if (gspca_debug & D_V4L2) |
871 | gspca_dev->vdev.debug |= 3; | 1300 | gspca_dev->vdev.debug |= 3; |
872 | else | 1301 | else |
873 | gspca_dev->vdev.debug &= ~3; | 1302 | gspca_dev->vdev.debug &= ~3; |
@@ -877,7 +1306,7 @@ out: | |||
877 | if (ret != 0) | 1306 | if (ret != 0) |
878 | PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret); | 1307 | PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret); |
879 | else | 1308 | else |
880 | PDEBUG(D_STREAM, "open OK"); | 1309 | PDEBUG(D_STREAM, "open done"); |
881 | return ret; | 1310 | return ret; |
882 | } | 1311 | } |
883 | 1312 | ||
@@ -885,7 +1314,7 @@ static int dev_close(struct inode *inode, struct file *file) | |||
885 | { | 1314 | { |
886 | struct gspca_dev *gspca_dev = file->private_data; | 1315 | struct gspca_dev *gspca_dev = file->private_data; |
887 | 1316 | ||
888 | PDEBUG(D_STREAM, "closing"); | 1317 | PDEBUG(D_STREAM, "%s close", current->comm); |
889 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1318 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
890 | return -ERESTARTSYS; | 1319 | return -ERESTARTSYS; |
891 | gspca_dev->users--; | 1320 | gspca_dev->users--; |
@@ -898,11 +1327,28 @@ static int dev_close(struct inode *inode, struct file *file) | |||
898 | gspca_dev->sd_desc->close(gspca_dev); | 1327 | gspca_dev->sd_desc->close(gspca_dev); |
899 | mutex_unlock(&gspca_dev->usb_lock); | 1328 | mutex_unlock(&gspca_dev->usb_lock); |
900 | frame_free(gspca_dev); | 1329 | frame_free(gspca_dev); |
901 | file->private_data = NULL; | ||
902 | gspca_dev->capt_file = 0; | 1330 | gspca_dev->capt_file = 0; |
1331 | gspca_dev->memory = GSPCA_MEMORY_NO; | ||
1332 | #ifdef GSPCA_HLP | ||
1333 | { | ||
1334 | struct hlp_dev *hlp_dev; | ||
1335 | int mode; | ||
1336 | |||
1337 | hlp_dev = hlp; | ||
1338 | if (hlp_dev != 0 | ||
1339 | && hlp_dev->gspca_dev == gspca_dev) { | ||
1340 | hlp_dev->gspca_dev = 0; | ||
1341 | hlp_dev->frame = 0; | ||
1342 | mode = gspca_dev->curr_mode; | ||
1343 | gspca_dev->pixfmt = | ||
1344 | gspca_dev->cam.cam_mode[mode].pixfmt; | ||
1345 | } | ||
1346 | } | ||
1347 | #endif /*GSPCA_HLP*/ | ||
903 | } | 1348 | } |
1349 | file->private_data = NULL; | ||
904 | mutex_unlock(&gspca_dev->queue_lock); | 1350 | mutex_unlock(&gspca_dev->queue_lock); |
905 | PDEBUG(D_STREAM, "closed"); | 1351 | PDEBUG(D_STREAM, "close done"); |
906 | return 0; | 1352 | return 0; |
907 | } | 1353 | } |
908 | 1354 | ||
@@ -1036,32 +1482,50 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1036 | struct v4l2_requestbuffers *rb) | 1482 | struct v4l2_requestbuffers *rb) |
1037 | { | 1483 | { |
1038 | struct gspca_dev *gspca_dev = priv; | 1484 | struct gspca_dev *gspca_dev = priv; |
1039 | int frsz, ret; | 1485 | int i, ret = 0; |
1040 | 1486 | ||
1041 | PDEBUG(D_STREAM, "reqbufs %d", rb->count); | 1487 | PDEBUG(D_STREAM, "reqbufs %d", rb->count); |
1042 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1488 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1043 | return -EINVAL; | 1489 | return -EINVAL; |
1044 | if (rb->memory != V4L2_MEMORY_MMAP | 1490 | switch (rb->memory) { |
1045 | && rb->memory != V4L2_MEMORY_USERPTR) | 1491 | case V4L2_MEMORY_MMAP: |
1492 | break; | ||
1493 | case V4L2_MEMORY_USERPTR: | ||
1494 | #ifdef GSPCA_HLP | ||
1495 | if (hlp == 0 || hlp->gspca_dev != gspca_dev) | ||
1496 | break; | ||
1497 | #endif | ||
1046 | return -EINVAL; | 1498 | return -EINVAL; |
1047 | if (rb->count == 0) | 1499 | default: |
1048 | return -EINVAL; | 1500 | return -EINVAL; |
1049 | frsz = gspca_get_buff_size(gspca_dev); | 1501 | } |
1050 | if (frsz < 0) | ||
1051 | return frsz; | ||
1052 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1502 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1053 | return -ERESTARTSYS; | 1503 | return -ERESTARTSYS; |
1054 | if (gspca_dev->capt_file != 0) { /* only one file may do capture */ | 1504 | |
1505 | for (i = 0; i < gspca_dev->nframes; i++) { | ||
1506 | if (gspca_dev->frame[i].vma_use_count) { | ||
1507 | ret = -EBUSY; | ||
1508 | goto out; | ||
1509 | } | ||
1510 | } | ||
1511 | |||
1512 | /* only one file may do capture */ | ||
1513 | if ((gspca_dev->capt_file != 0 && gspca_dev->capt_file != file) | ||
1514 | || gspca_dev->streaming) { | ||
1055 | ret = -EBUSY; | 1515 | ret = -EBUSY; |
1056 | goto out; | 1516 | goto out; |
1057 | } | 1517 | } |
1058 | ret = frame_alloc(gspca_dev, | 1518 | |
1059 | rb->count, | 1519 | if (rb->count == 0) { /* unrequest? */ |
1060 | (unsigned int) frsz, | 1520 | frame_free(gspca_dev); |
1061 | rb->memory); | 1521 | gspca_dev->capt_file = 0; |
1062 | if (ret == 0) { | 1522 | } else { |
1063 | rb->count = gspca_dev->nframes; | 1523 | gspca_dev->memory = rb->memory; |
1064 | gspca_dev->capt_file = file; | 1524 | ret = frame_alloc(gspca_dev, rb->count); |
1525 | if (ret == 0) { | ||
1526 | rb->count = gspca_dev->nframes; | ||
1527 | gspca_dev->capt_file = file; | ||
1528 | } | ||
1065 | } | 1529 | } |
1066 | out: | 1530 | out: |
1067 | mutex_unlock(&gspca_dev->queue_lock); | 1531 | mutex_unlock(&gspca_dev->queue_lock); |
@@ -1224,12 +1688,25 @@ static int vidiocgmbuf(struct file *file, void *priv, | |||
1224 | if (gspca_dev->nframes == 0) { | 1688 | if (gspca_dev->nframes == 0) { |
1225 | struct v4l2_requestbuffers rb; | 1689 | struct v4l2_requestbuffers rb; |
1226 | int ret; | 1690 | int ret; |
1227 | 1691 | __u32 pixfmt; | |
1692 | short width, height; | ||
1693 | |||
1694 | /* as the final format is not yet defined, allocate | ||
1695 | buffers with the max size */ | ||
1696 | pixfmt = gspca_dev->pixfmt; | ||
1697 | width = gspca_dev->width; | ||
1698 | height = gspca_dev->height; | ||
1699 | gspca_dev->pixfmt = V4L2_PIX_FMT_BGR32; | ||
1700 | gspca_dev->width = 640; | ||
1701 | gspca_dev->height = 480; | ||
1228 | memset(&rb, 0, sizeof rb); | 1702 | memset(&rb, 0, sizeof rb); |
1229 | rb.count = 4; | 1703 | rb.count = 4; |
1230 | rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1704 | rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1231 | rb.memory = V4L2_MEMORY_MMAP; | 1705 | rb.memory = V4L2_MEMORY_MMAP; |
1232 | ret = vidioc_reqbufs(file, priv, &rb); | 1706 | ret = vidioc_reqbufs(file, priv, &rb); |
1707 | gspca_dev->pixfmt = pixfmt; | ||
1708 | gspca_dev->width = width; | ||
1709 | gspca_dev->height = height; | ||
1233 | if (ret != 0) | 1710 | if (ret != 0) |
1234 | return ret; | 1711 | return ret; |
1235 | } | 1712 | } |
@@ -1328,43 +1805,22 @@ out: | |||
1328 | return ret; | 1805 | return ret; |
1329 | } | 1806 | } |
1330 | 1807 | ||
1331 | static unsigned int dev_poll(struct file *file, poll_table * wait) | ||
1332 | { | ||
1333 | struct gspca_dev *gspca_dev = file->private_data; | ||
1334 | int i, ret; | ||
1335 | |||
1336 | PDEBUG(D_FRAM, "poll"); | ||
1337 | |||
1338 | poll_wait(file, &gspca_dev->wq, wait); | ||
1339 | |||
1340 | if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) | ||
1341 | return POLLERR; | ||
1342 | if (gspca_dev->dev == 0 | ||
1343 | || !gspca_dev->streaming) /* if not streaming */ | ||
1344 | ret = POLLERR; | ||
1345 | else { | ||
1346 | i = gspca_dev->fr_o; | ||
1347 | i = gspca_dev->fr_queue[i]; | ||
1348 | if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE) | ||
1349 | ret = POLLIN | POLLRDNORM; /* something to read */ | ||
1350 | else | ||
1351 | ret = 0; | ||
1352 | } | ||
1353 | mutex_unlock(&gspca_dev->queue_lock); | ||
1354 | return ret; | ||
1355 | } | ||
1356 | |||
1357 | /* | 1808 | /* |
1358 | * wait for a video frame | 1809 | * wait for a video frame |
1359 | * | 1810 | * |
1360 | * If a frame is ready, its index is returned. | 1811 | * If a frame is ready, its index is returned. |
1361 | */ | 1812 | */ |
1362 | static int gspca_frame_wait(struct gspca_dev *gspca_dev, | 1813 | static int frame_wait(struct gspca_dev *gspca_dev, |
1363 | int nonblock_ing) | 1814 | int nonblock_ing) |
1364 | { | 1815 | { |
1365 | struct gspca_frame *frame; | 1816 | struct gspca_frame *frame; |
1366 | int i, j, ret; | 1817 | int i, j, ret; |
1367 | 1818 | ||
1819 | /* if userptr, treat the awaiting URBs */ | ||
1820 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR) | ||
1821 | isoc_transfer(gspca_dev); | ||
1822 | |||
1823 | /* check if a frame is ready */ | ||
1368 | i = gspca_dev->fr_o; | 1824 | i = gspca_dev->fr_o; |
1369 | j = gspca_dev->fr_queue[i]; | 1825 | j = gspca_dev->fr_queue[i]; |
1370 | frame = &gspca_dev->frame[j]; | 1826 | frame = &gspca_dev->frame[j]; |
@@ -1385,13 +1841,14 @@ static int gspca_frame_wait(struct gspca_dev *gspca_dev, | |||
1385 | } | 1841 | } |
1386 | if (!gspca_dev->streaming || !gspca_dev->present) | 1842 | if (!gspca_dev->streaming || !gspca_dev->present) |
1387 | return -EIO; | 1843 | return -EIO; |
1844 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR) | ||
1845 | isoc_transfer(gspca_dev); | ||
1388 | i = gspca_dev->fr_o; | 1846 | i = gspca_dev->fr_o; |
1389 | j = gspca_dev->fr_queue[i]; | 1847 | j = gspca_dev->fr_queue[i]; |
1390 | frame = &gspca_dev->frame[j]; | 1848 | frame = &gspca_dev->frame[j]; |
1391 | if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) | 1849 | if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) |
1392 | break; | 1850 | break; |
1393 | } | 1851 | } |
1394 | |||
1395 | ok: | 1852 | ok: |
1396 | atomic_dec(&gspca_dev->nevent); | 1853 | atomic_dec(&gspca_dev->nevent); |
1397 | gspca_dev->fr_o = (i + 1) % gspca_dev->nframes; | 1854 | gspca_dev->fr_o = (i + 1) % gspca_dev->nframes; |
@@ -1434,7 +1891,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, | |||
1434 | if (mutex_lock_interruptible(&gspca_dev->read_lock)) | 1891 | if (mutex_lock_interruptible(&gspca_dev->read_lock)) |
1435 | return -ERESTARTSYS; | 1892 | return -ERESTARTSYS; |
1436 | 1893 | ||
1437 | ret = gspca_frame_wait(gspca_dev, file->f_flags & O_NONBLOCK); | 1894 | ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK); |
1438 | if (ret < 0) | 1895 | if (ret < 0) |
1439 | goto out; | 1896 | goto out; |
1440 | i = ret; /* frame index */ | 1897 | i = ret; /* frame index */ |
@@ -1467,14 +1924,14 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
1467 | 1924 | ||
1468 | index = v4l2_buf->index; | 1925 | index = v4l2_buf->index; |
1469 | if ((unsigned) index >= gspca_dev->nframes) { | 1926 | if ((unsigned) index >= gspca_dev->nframes) { |
1470 | PDEBUG(D_STREAM, | 1927 | PDEBUG(D_FRAM, |
1471 | "qbuf idx %d >= %d", index, gspca_dev->nframes); | 1928 | "qbuf idx %d >= %d", index, gspca_dev->nframes); |
1472 | return -EINVAL; | 1929 | return -EINVAL; |
1473 | } | 1930 | } |
1474 | frame = &gspca_dev->frame[index]; | 1931 | frame = &gspca_dev->frame[index]; |
1475 | 1932 | ||
1476 | if (v4l2_buf->memory != frame->v4l2_buf.memory) { | 1933 | if (v4l2_buf->memory != frame->v4l2_buf.memory) { |
1477 | PDEBUG(D_STREAM, "qbuf bad memory type"); | 1934 | PDEBUG(D_FRAM, "qbuf bad memory type"); |
1478 | return -EINVAL; | 1935 | return -EINVAL; |
1479 | } | 1936 | } |
1480 | if (gspca_dev->capt_file != file) | 1937 | if (gspca_dev->capt_file != file) |
@@ -1483,17 +1940,16 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
1483 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 1940 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
1484 | return -ERESTARTSYS; | 1941 | return -ERESTARTSYS; |
1485 | 1942 | ||
1486 | if (frame->v4l2_buf.flags | 1943 | if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) { |
1487 | & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) { | 1944 | PDEBUG(D_FRAM, "qbuf bad state"); |
1488 | PDEBUG(D_STREAM, "qbuf bad state"); | ||
1489 | ret = -EINVAL; | 1945 | ret = -EINVAL; |
1490 | goto out; | 1946 | goto out; |
1491 | } | 1947 | } |
1492 | 1948 | ||
1493 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; | 1949 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; |
1494 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; | 1950 | /* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */ |
1495 | 1951 | ||
1496 | if (v4l2_buf->memory == V4L2_MEMORY_USERPTR) { | 1952 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { |
1497 | frame->data = frame->data_end = | 1953 | frame->data = frame->data_end = |
1498 | (unsigned char *) v4l2_buf->m.userptr; | 1954 | (unsigned char *) v4l2_buf->m.userptr; |
1499 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; | 1955 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; |
@@ -1517,16 +1973,16 @@ out: | |||
1517 | return ret; | 1973 | return ret; |
1518 | } | 1974 | } |
1519 | 1975 | ||
1520 | static ssize_t dev_read(struct file *file, char __user *data, | 1976 | /* |
1521 | size_t count, loff_t *ppos) | 1977 | * allocate the resources for read() |
1978 | */ | ||
1979 | static int read_alloc(struct gspca_dev *gspca_dev, | ||
1980 | struct file *file) | ||
1522 | { | 1981 | { |
1523 | struct gspca_dev *gspca_dev = file->private_data; | ||
1524 | struct gspca_frame *frame; | ||
1525 | struct v4l2_buffer v4l2_buf; | 1982 | struct v4l2_buffer v4l2_buf; |
1526 | struct timeval timestamp; | 1983 | int i, ret; |
1527 | int i, ret, ret2; | ||
1528 | 1984 | ||
1529 | PDEBUG(D_FRAM, "read (%p, %d)", data, count); | 1985 | PDEBUG(D_STREAM, "read alloc"); |
1530 | if (gspca_dev->nframes == 0) { | 1986 | if (gspca_dev->nframes == 0) { |
1531 | struct v4l2_requestbuffers rb; | 1987 | struct v4l2_requestbuffers rb; |
1532 | 1988 | ||
@@ -1536,7 +1992,7 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1536 | rb.memory = V4L2_MEMORY_MMAP; | 1992 | rb.memory = V4L2_MEMORY_MMAP; |
1537 | ret = vidioc_reqbufs(file, gspca_dev, &rb); | 1993 | ret = vidioc_reqbufs(file, gspca_dev, &rb); |
1538 | if (ret != 0) { | 1994 | if (ret != 0) { |
1539 | PDEBUG(D_STREAM, "read reqbuf err: %d", ret); | 1995 | PDEBUG(D_STREAM, "read reqbuf err %d", ret); |
1540 | return ret; | 1996 | return ret; |
1541 | } | 1997 | } |
1542 | memset(&v4l2_buf, 0, sizeof v4l2_buf); | 1998 | memset(&v4l2_buf, 0, sizeof v4l2_buf); |
@@ -1553,18 +2009,89 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
1553 | return ret; | 2009 | return ret; |
1554 | } | 2010 | } |
1555 | } | 2011 | } |
1556 | } else if (gspca_dev->capt_file != file) | 2012 | gspca_dev->memory = GSPCA_MEMORY_READ; |
1557 | return -EINVAL; | 2013 | } |
1558 | 2014 | ||
2015 | /* start streaming */ | ||
2016 | ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
2017 | if (ret != 0) | ||
2018 | PDEBUG(D_STREAM, "read streamon err %d", ret); | ||
2019 | return ret; | ||
2020 | } | ||
2021 | |||
2022 | static unsigned int dev_poll(struct file *file, poll_table *wait) | ||
2023 | { | ||
2024 | struct gspca_dev *gspca_dev = file->private_data; | ||
2025 | int i, ret; | ||
2026 | |||
2027 | PDEBUG(D_FRAM, "poll"); | ||
2028 | |||
2029 | poll_wait(file, &gspca_dev->wq, wait); | ||
2030 | if (!gspca_dev->present) | ||
2031 | return POLLERR; | ||
2032 | |||
2033 | /* if not streaming, the user would use read() */ | ||
1559 | if (!gspca_dev->streaming) { | 2034 | if (!gspca_dev->streaming) { |
1560 | ret = vidioc_streamon(file, gspca_dev, | 2035 | if (gspca_dev->memory != GSPCA_MEMORY_NO) { |
1561 | V4L2_BUF_TYPE_VIDEO_CAPTURE); | 2036 | ret = POLLERR; /* not the 1st time */ |
2037 | goto out; | ||
2038 | } | ||
2039 | ret = read_alloc(gspca_dev, file); | ||
1562 | if (ret != 0) { | 2040 | if (ret != 0) { |
1563 | PDEBUG(D_STREAM, "read streamon err %d", ret); | 2041 | ret = POLLERR; |
1564 | return ret; | 2042 | goto out; |
1565 | } | 2043 | } |
1566 | } | 2044 | } |
1567 | 2045 | ||
2046 | if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) | ||
2047 | return POLLERR; | ||
2048 | if (!gspca_dev->present) { | ||
2049 | ret = POLLERR; | ||
2050 | goto out; | ||
2051 | } | ||
2052 | |||
2053 | /* if not mmap, treat the awaiting URBs */ | ||
2054 | if (gspca_dev->memory == V4L2_MEMORY_USERPTR | ||
2055 | && gspca_dev->capt_file == file) | ||
2056 | isoc_transfer(gspca_dev); | ||
2057 | |||
2058 | i = gspca_dev->fr_o; | ||
2059 | i = gspca_dev->fr_queue[i]; | ||
2060 | if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE) | ||
2061 | ret = POLLIN | POLLRDNORM; /* something to read */ | ||
2062 | else | ||
2063 | ret = 0; | ||
2064 | out: | ||
2065 | mutex_unlock(&gspca_dev->queue_lock); | ||
2066 | return ret; | ||
2067 | } | ||
2068 | |||
2069 | static ssize_t dev_read(struct file *file, char __user *data, | ||
2070 | size_t count, loff_t *ppos) | ||
2071 | { | ||
2072 | struct gspca_dev *gspca_dev = file->private_data; | ||
2073 | struct gspca_frame *frame; | ||
2074 | struct v4l2_buffer v4l2_buf; | ||
2075 | struct timeval timestamp; | ||
2076 | int i, ret, ret2; | ||
2077 | |||
2078 | PDEBUG(D_FRAM, "read (%d)", count); | ||
2079 | if (!gspca_dev->present) | ||
2080 | return -ENODEV; | ||
2081 | switch (gspca_dev->memory) { | ||
2082 | case GSPCA_MEMORY_NO: /* first time */ | ||
2083 | ret = read_alloc(gspca_dev, file); | ||
2084 | if (ret != 0) | ||
2085 | return ret; | ||
2086 | break; | ||
2087 | case GSPCA_MEMORY_READ: | ||
2088 | if (gspca_dev->capt_file != file) | ||
2089 | return -EINVAL; | ||
2090 | break; | ||
2091 | default: | ||
2092 | return -EINVAL; | ||
2093 | } | ||
2094 | |||
1568 | /* get a frame */ | 2095 | /* get a frame */ |
1569 | jiffies_to_timeval(get_jiffies_64(), ×tamp); | 2096 | jiffies_to_timeval(get_jiffies_64(), ×tamp); |
1570 | timestamp.tv_sec--; | 2097 | timestamp.tv_sec--; |
@@ -1615,7 +2142,7 @@ out: | |||
1615 | return ret; | 2142 | return ret; |
1616 | } | 2143 | } |
1617 | 2144 | ||
1618 | static void gspca_dev_release(struct video_device *vfd) | 2145 | static void dev_release(struct video_device *vfd) |
1619 | { | 2146 | { |
1620 | /* nothing */ | 2147 | /* nothing */ |
1621 | } | 2148 | } |
@@ -1635,7 +2162,7 @@ static struct video_device gspca_template = { | |||
1635 | .name = "gspca main driver", | 2162 | .name = "gspca main driver", |
1636 | .type = VID_TYPE_CAPTURE, | 2163 | .type = VID_TYPE_CAPTURE, |
1637 | .fops = &dev_fops, | 2164 | .fops = &dev_fops, |
1638 | .release = gspca_dev_release, /* mandatory */ | 2165 | .release = dev_release, /* mandatory */ |
1639 | .minor = -1, | 2166 | .minor = -1, |
1640 | .vidioc_querycap = vidioc_querycap, | 2167 | .vidioc_querycap = vidioc_querycap, |
1641 | .vidioc_dqbuf = vidioc_dqbuf, | 2168 | .vidioc_dqbuf = vidioc_dqbuf, |
@@ -1673,7 +2200,8 @@ static struct video_device gspca_template = { | |||
1673 | int gspca_dev_probe(struct usb_interface *intf, | 2200 | int gspca_dev_probe(struct usb_interface *intf, |
1674 | const struct usb_device_id *id, | 2201 | const struct usb_device_id *id, |
1675 | const struct sd_desc *sd_desc, | 2202 | const struct sd_desc *sd_desc, |
1676 | int dev_size) | 2203 | int dev_size, |
2204 | struct module *module) | ||
1677 | { | 2205 | { |
1678 | struct usb_interface_descriptor *interface; | 2206 | struct usb_interface_descriptor *interface; |
1679 | struct gspca_dev *gspca_dev; | 2207 | struct gspca_dev *gspca_dev; |
@@ -1682,8 +2210,8 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1682 | __u16 vendor; | 2210 | __u16 vendor; |
1683 | __u16 product; | 2211 | __u16 product; |
1684 | 2212 | ||
1685 | vendor = le16_to_cpu(dev->descriptor.idVendor); | 2213 | vendor = id->idVendor; |
1686 | product = le16_to_cpu(dev->descriptor.idProduct); | 2214 | product = id->idProduct; |
1687 | PDEBUG(D_PROBE, "probing %04x:%04x", vendor, product); | 2215 | PDEBUG(D_PROBE, "probing %04x:%04x", vendor, product); |
1688 | 2216 | ||
1689 | /* we don't handle multi-config cameras */ | 2217 | /* we don't handle multi-config cameras */ |
@@ -1703,6 +2231,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1703 | } | 2231 | } |
1704 | gspca_dev->dev = dev; | 2232 | gspca_dev->dev = dev; |
1705 | gspca_dev->iface = interface->bInterfaceNumber; | 2233 | gspca_dev->iface = interface->bInterfaceNumber; |
2234 | gspca_dev->nbalt = intf->num_altsetting; | ||
1706 | gspca_dev->sd_desc = sd_desc; | 2235 | gspca_dev->sd_desc = sd_desc; |
1707 | /* gspca_dev->users = 0; (done by kzalloc) */ | 2236 | /* gspca_dev->users = 0; (done by kzalloc) */ |
1708 | gspca_dev->nbufread = 2; | 2237 | gspca_dev->nbufread = 2; |
@@ -1724,6 +2253,9 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1724 | /* init video stuff */ | 2253 | /* init video stuff */ |
1725 | memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); | 2254 | memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); |
1726 | gspca_dev->vdev.dev = &dev->dev; | 2255 | gspca_dev->vdev.dev = &dev->dev; |
2256 | memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops); | ||
2257 | gspca_dev->vdev.fops = &gspca_dev->fops; | ||
2258 | gspca_dev->fops.owner = module; /* module protection */ | ||
1727 | ret = video_register_device(&gspca_dev->vdev, | 2259 | ret = video_register_device(&gspca_dev->vdev, |
1728 | VFL_TYPE_GRABBER, | 2260 | VFL_TYPE_GRABBER, |
1729 | video_nr); | 2261 | video_nr); |
@@ -1758,7 +2290,7 @@ void gspca_disconnect(struct usb_interface *intf) | |||
1758 | mutex_lock(&gspca_dev->queue_lock); | 2290 | mutex_lock(&gspca_dev->queue_lock); |
1759 | mutex_lock(&gspca_dev->usb_lock); | 2291 | mutex_lock(&gspca_dev->usb_lock); |
1760 | gspca_dev->streaming = 0; | 2292 | gspca_dev->streaming = 0; |
1761 | gspca_kill_transfer(gspca_dev); | 2293 | destroy_urbs(gspca_dev); |
1762 | mutex_unlock(&gspca_dev->usb_lock); | 2294 | mutex_unlock(&gspca_dev->usb_lock); |
1763 | mutex_unlock(&gspca_dev->queue_lock); | 2295 | mutex_unlock(&gspca_dev->queue_lock); |
1764 | while (gspca_dev->users != 0) { /* wait until fully closed */ | 2296 | while (gspca_dev->users != 0) { /* wait until fully closed */ |
@@ -1777,11 +2309,23 @@ EXPORT_SYMBOL(gspca_disconnect); | |||
1777 | /* -- module insert / remove -- */ | 2309 | /* -- module insert / remove -- */ |
1778 | static int __init gspca_init(void) | 2310 | static int __init gspca_init(void) |
1779 | { | 2311 | { |
2312 | #ifdef GSPCA_HLP | ||
2313 | int ret; | ||
2314 | |||
2315 | /* create /dev/gspca_hlp */ | ||
2316 | ret = misc_register(&hlp_device); | ||
2317 | if (ret < 0) | ||
2318 | err("misc_register err %d", ret); | ||
2319 | start_hlp(); /* try to start the helper process */ | ||
2320 | #endif | ||
1780 | info("main v%s registered", version); | 2321 | info("main v%s registered", version); |
1781 | return 0; | 2322 | return 0; |
1782 | } | 2323 | } |
1783 | static void __exit gspca_exit(void) | 2324 | static void __exit gspca_exit(void) |
1784 | { | 2325 | { |
2326 | #ifdef GSPCA_HLP | ||
2327 | misc_deregister(&hlp_device); | ||
2328 | #endif | ||
1785 | info("main deregistered"); | 2329 | info("main deregistered"); |
1786 | } | 2330 | } |
1787 | 2331 | ||
@@ -1791,7 +2335,8 @@ module_exit(gspca_exit); | |||
1791 | module_param_named(debug, gspca_debug, int, 0644); | 2335 | module_param_named(debug, gspca_debug, int, 0644); |
1792 | MODULE_PARM_DESC(debug, | 2336 | MODULE_PARM_DESC(debug, |
1793 | "Debug (bit) 0x01:error 0x02:probe 0x04:config" | 2337 | "Debug (bit) 0x01:error 0x02:probe 0x04:config" |
1794 | " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"); | 2338 | " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout" |
2339 | " 0x0100: v4l2"); | ||
1795 | 2340 | ||
1796 | module_param(comp_fac, int, 0644); | 2341 | module_param(comp_fac, int, 0644); |
1797 | MODULE_PARM_DESC(comp_fac, | 2342 | MODULE_PARM_DESC(comp_fac, |