]>
Commit | Line | Data |
---|---|---|
96eb5089 | 1 | diff -urN linux-2.4.20.orig/Documentation/usb/philips.txt linux-2.4.20/Documentation/usb/philips.txt |
2 | --- linux-2.4.20.orig/Documentation/usb/philips.txt Mon Jan 6 22:16:06 2003 | |
3 | +++ linux-2.4.20/Documentation/usb/philips.txt Mon Dec 16 22:19:15 2002 | |
4 | @@ -1,13 +1,34 @@ | |
5 | -This file contains some additional information for the Philips webcams. | |
6 | -E-mail: webcam@smcc.demon.nl Last updated: 2001-09-24 | |
7 | - | |
8 | -The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/. | |
9 | -It contains a lot of extra information, a FAQ, and the binary plugin | |
10 | -'PWCX'. This plugin contains decompression routines that allow you to | |
11 | -use higher image sizes and framerates; in addition the webcam uses less | |
12 | -bandwidth on the USB bus (handy if you want to run more than 1 camera | |
13 | -simultaneously). These routines fall under an NDA, and may therefor not be | |
14 | -distributed as source; however, its use is completely optional. | |
15 | +This file contains some additional information for the Philips and OEM webcams. | |
16 | +E-mail: webcam@smcc.demon.nl Last updated: 2002-11-28 | |
17 | +Site: http://www.smcc.demon.nl/webcam/ | |
18 | +As of this moment, the following cameras are supported: | |
19 | + * Philips PCA645 | |
20 | + * Philips PCA646 | |
21 | + * Philips PCVC675 | |
22 | + * Philips PCVC680 | |
23 | + * Philips PCVC690 | |
24 | + * Philips PCVC730 | |
25 | + * Philips PCVC740 | |
26 | + * Philips PCVC750 | |
27 | + * Askey VC010 | |
28 | + * Creative Labs Webcam 5 | |
29 | + * Logitech QuickCam 3000 Pro | |
30 | + * Logitech QuickCam Notebook | |
31 | + * Logitech QuickCam 4000 Pro | |
32 | + * Logitech QuickCam Zoom | |
33 | + * Samsung MPC-C10 | |
34 | + * Samsung MPC-C30 | |
35 | + * Sotec Afina Eye | |
36 | + * Visionite VCS-UM100 | |
37 | + * Visionite VCS-UC300 | |
38 | + | |
39 | +The main webpage for the Philips driver is at the address above. It contains | |
40 | +a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin | |
41 | +contains decompression routines that allow you to use higher image sizes and | |
42 | +framerates; in addition the webcam uses less bandwidth on the USB bus (handy | |
43 | +if you want to run more than 1 camera simultaneously). These routines fall | |
44 | +under a NDA, and may therefor not be distributed as source; however, its use | |
45 | +is completely optional. | |
46 | ||
47 | You can build this code either into your kernel, or as a module. I recommend | |
48 | the latter, since it makes troubleshooting a lot easier. The built-in | |
49 | @@ -98,6 +119,9 @@ | |
50 | 750). For other cameras this command is silently ignored, and the LED | |
51 | cannot be controlled. | |
52 | ||
53 | + Finally: this parameters does not take effect UNTIL the first time you | |
54 | + open the camera device. Until then, the LED remains on. | |
55 | + | |
56 | dev_hint | |
57 | A long standing problem with USB devices is their dynamic nature: you | |
58 | never know what device a camera gets assigned; it depends on module load | |
59 | @@ -126,7 +150,7 @@ | |
60 | other cameras will get the first free | |
61 | available slot (see below). | |
62 | ||
63 | - dev_hint=645:1,680=2 The PCA645 camera will get /dev/video1, | |
64 | + dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1, | |
65 | and a PCVC680 /dev/video2. | |
66 | ||
67 | dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber | |
68 | @@ -176,6 +200,7 @@ | |
69 | ||
70 | 64 0x40 Show viewport and image sizes Off | |
71 | ||
72 | + 128 0x80 PWCX debugging Off | |
73 | ||
74 | For example, to trace the open() & read() fuctions, sum 8 + 4 = 12, | |
75 | so you would supply trace=12 during insmod or modprobe. If | |
76 | @@ -189,10 +214,10 @@ | |
77 | The fbufs, mbufs and trace parameters are global and apply to all connected | |
78 | cameras. Each camera has its own set of buffers. | |
79 | ||
80 | -size, fps, palette only specify defaults when you open() the device; this is | |
81 | -to accommodate some tools that don't set the size or colour palette. You can | |
82 | -change these settings after open() with the Video4Linux ioctl() calls. The | |
83 | -default of defaults is QCIF size at 10 fps, BGR order. | |
84 | +size and fps only specify defaults when you open() the device; this is to | |
85 | +accommodate some tools that don't set the size. You can change these | |
86 | +settings after open() with the Video4Linux ioctl() calls. The default of | |
87 | +defaults is QCIF size at 10 fps, YUV420 palette order. | |
88 | ||
89 | The compression parameter is semiglobal; it sets the initial compression | |
90 | preference for all camera's, but this parameter can be set per camera with | |
91 | @@ -200,4 +225,3 @@ | |
92 | ||
93 | All parameters are optional. | |
94 | ||
95 | - | |
96 | diff -urN linux-2.4.20.orig/drivers/usb/pwc-ctrl.c linux-2.4.20/drivers/usb/pwc-ctrl.c | |
97 | --- linux-2.4.20.orig/drivers/usb/pwc-ctrl.c Mon Jan 6 22:15:48 2003 | |
98 | +++ linux-2.4.20/drivers/usb/pwc-ctrl.c Mon Dec 16 22:19:15 2002 | |
99 | @@ -256,8 +256,10 @@ | |
100 | ||
101 | memcpy(buf, pEntry->mode, 3); | |
102 | ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); | |
103 | - if (ret < 0) | |
104 | + if (ret < 0) { | |
105 | + Debug("Failed to send video command... %d\n", ret); | |
106 | return ret; | |
107 | + } | |
108 | if (pEntry->compressed && pdev->decompressor != NULL) | |
109 | pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); | |
110 | ||
111 | @@ -444,8 +446,8 @@ | |
112 | Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames); | |
113 | else { | |
114 | Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); | |
115 | - return ret; | |
116 | } | |
117 | + return ret; | |
118 | } | |
119 | pdev->view.x = width; | |
120 | pdev->view.y = height; | |
121 | @@ -997,7 +999,7 @@ | |
122 | &buf, 1, HZ / 2); | |
123 | ||
124 | if (ret < 0) | |
125 | - return ret; | |
126 | + return ret; | |
127 | ||
128 | return (buf << 8); | |
129 | } | |
130 | @@ -1103,12 +1105,7 @@ | |
131 | buf[0] = on_value; | |
132 | buf[1] = off_value; | |
133 | ||
134 | - return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), | |
135 | - SET_STATUS_CTL, | |
136 | - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
137 | - LED_FORMATTER, | |
138 | - pdev->vcinterface, | |
139 | - &buf, 2, HZ / 2); | |
140 | + return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); | |
141 | } | |
142 | ||
143 | int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) | |
144 | @@ -1122,13 +1119,7 @@ | |
145 | return 0; | |
146 | } | |
147 | ||
148 | - ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), | |
149 | - GET_STATUS_CTL, | |
150 | - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | |
151 | - LED_FORMATTER, | |
152 | - pdev->vcinterface, | |
153 | - &buf, 2, HZ / 2); | |
154 | - | |
155 | + ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); | |
156 | if (ret < 0) | |
157 | return ret; | |
158 | *on_value = buf[0] * 100; | |
159 | @@ -1252,7 +1243,7 @@ | |
160 | int ret; | |
161 | unsigned char buf; | |
162 | ||
163 | - ret = RecvControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); | |
164 | + ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); | |
165 | if (ret < 0) | |
166 | return ret; | |
167 | return buf; | |
168 | @@ -1276,10 +1267,9 @@ | |
169 | int ret; | |
170 | unsigned char buf; | |
171 | ||
172 | - ret = RecvControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); | |
173 | + ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); | |
174 | if (ret < 0) | |
175 | return ret; | |
176 | -Debug("pwc_get_dynamic_noise = %d\n", buf); | |
177 | return buf; | |
178 | } | |
179 | ||
180 | @@ -1595,6 +1585,16 @@ | |
181 | break; | |
182 | } | |
183 | ||
184 | + case VIDIOCPWCGREALSIZE: | |
185 | + { | |
186 | + struct pwc_imagesize size; | |
187 | + | |
188 | + size.width = pdev->image.x; | |
189 | + size.height = pdev->image.y; | |
190 | + if (copy_to_user(arg, &size, sizeof(size))) | |
191 | + ret = -EFAULT; | |
192 | + break; | |
193 | + } | |
194 | ||
195 | default: | |
196 | ret = -ENOIOCTLCMD; | |
197 | diff -urN linux-2.4.20.orig/drivers/usb/pwc-if.c linux-2.4.20/drivers/usb/pwc-if.c | |
198 | --- linux-2.4.20.orig/drivers/usb/pwc-if.c Mon Jan 6 22:15:48 2003 | |
199 | +++ linux-2.4.20/drivers/usb/pwc-if.c Mon Dec 16 22:19:15 2002 | |
200 | @@ -42,11 +42,15 @@ | |
201 | - Alistar Moire: QuickCam 3000 Pro device/product ID | |
202 | - Tony Hoyle: Creative Labs Webcam 5 device/product ID | |
203 | - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged | |
204 | - - Jk Fang: SOTEC device/product ID | |
205 | + - Jk Fang: Sotec Afina Eye ID | |
206 | + - Xavier Roche: QuickCam Pro 4000 ID | |
207 | + - Jens Knudsen: QuickCam Zoom ID | |
208 | + - J. Debert: QuickCam for Notebooks ID | |
209 | */ | |
210 | ||
211 | #include <linux/errno.h> | |
212 | #include <linux/init.h> | |
213 | +#include <linux/mm.h> | |
214 | #include <linux/module.h> | |
215 | #include <linux/poll.h> | |
216 | #include <linux/slab.h> | |
217 | @@ -58,10 +62,6 @@ | |
218 | #include "pwc-ioctl.h" | |
219 | #include "pwc-uncompress.h" | |
220 | ||
221 | -#if !defined(MAP_NR) | |
222 | -#define MAP_NR(a) virt_to_page(a) | |
223 | -#endif | |
224 | - | |
225 | /* Function prototypes and driver templates */ | |
226 | ||
227 | /* hotplug device table support */ | |
228 | @@ -76,10 +76,13 @@ | |
229 | { USB_DEVICE(0x0471, 0x0311) }, | |
230 | { USB_DEVICE(0x0471, 0x0312) }, | |
231 | { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ | |
232 | - { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech */ | |
233 | + { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech QuickCam Pro 3000 */ | |
234 | + { USB_DEVICE(0x046D, 0x08b1) }, /* Logitech QuickCam Notebook Pro */ | |
235 | + { USB_DEVICE(0x046d, 0x08b2) }, /* Logitech QuickCam Pro 4000 */ | |
236 | + { USB_DEVICE(0x046d, 0x08b3) }, /* Logitech QuickCam Zoom */ | |
237 | { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ | |
238 | { USB_DEVICE(0x055D, 0x9001) }, | |
239 | - { USB_DEVICE(0x041E, 0x400C) }, /* Creative */ | |
240 | + { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ | |
241 | { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ | |
242 | { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ | |
243 | { USB_DEVICE(0x0d81, 0x1900) }, | |
244 | @@ -127,7 +130,7 @@ | |
245 | static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock); | |
246 | static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait); | |
247 | static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg); | |
248 | -static int pwc_video_mmap(struct video_device *dev, const char *adr, unsigned long size); | |
249 | +static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size); | |
250 | ||
251 | static struct video_device pwc_template = { | |
252 | owner: THIS_MODULE, | |
253 | @@ -238,7 +241,7 @@ | |
254 | int i; | |
255 | void *kbuf; | |
256 | ||
257 | - Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev); | |
258 | + Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); | |
259 | ||
260 | if (pdev == NULL) | |
261 | return -ENXIO; | |
262 | @@ -315,7 +318,7 @@ | |
263 | ||
264 | kbuf = NULL; | |
265 | ||
266 | - Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n"); | |
267 | + Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); | |
268 | return 0; | |
269 | } | |
270 | ||
271 | @@ -592,7 +595,7 @@ | |
272 | /* This gets called for the Isochronous pipe (video). This is done in | |
273 | * interrupt time, so it has to be fast, not crash, and not stall. Neat. | |
274 | */ | |
275 | -static void pwc_isoc_handler(struct urb *urb) | |
276 | +static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs) | |
277 | { | |
278 | struct pwc_device *pdev; | |
279 | int i, fst, flen; | |
280 | @@ -612,7 +615,7 @@ | |
281 | } | |
282 | #endif | |
283 | if (urb->status == -ENOENT || urb->status == -ECONNRESET) { | |
284 | - Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n"); | |
285 | + Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); | |
286 | return; | |
287 | } | |
288 | if (urb->status != -EINPROGRESS && urb->status != 0) { | |
289 | @@ -685,9 +688,22 @@ | |
290 | #if PWC_DEBUG | |
291 | Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); | |
292 | #endif | |
293 | - pdev->drop_frames = 2; | |
294 | + pdev->drop_frames += 2; | |
295 | pdev->vframes_error++; | |
296 | } | |
297 | + if ((ptr[0] ^ pdev->vmirror) & 0x01) { | |
298 | + if (ptr[0] & 0x01) | |
299 | + Info("Snapshot button pressed.\n"); | |
300 | + else | |
301 | + Info("Snapshot button released.\n"); | |
302 | + } | |
303 | + if ((ptr[0] ^ pdev->vmirror) & 0x02) { | |
304 | + if (ptr[0] & 0x02) | |
305 | + Info("Image is mirrored.\n"); | |
306 | + else | |
307 | + Info("Image is normal.\n"); | |
308 | + } | |
309 | + pdev->vmirror = ptr[0] & 0x03; | |
310 | /* Sometimes the trailer of the 730 is still sent as a 4 byte packet | |
311 | after a short frame; this condition is filtered out specifically. A 4 byte | |
312 | frame doesn't make sense anyway. | |
313 | @@ -704,7 +720,7 @@ | |
314 | /* In case we were instructed to drop the frame, do so silently. | |
315 | The buffer pointers are not updated either (but the counters are reset below). | |
316 | */ | |
317 | - if (pdev->drop_frames) | |
318 | + if (pdev->drop_frames > 0) | |
319 | pdev->drop_frames--; | |
320 | else { | |
321 | /* Check for underflow first */ | |
322 | @@ -740,10 +756,14 @@ | |
323 | } /* .. flen < last_packet_size */ | |
324 | pdev->vlast_packet_size = flen; | |
325 | } /* ..status == 0 */ | |
326 | -#ifdef PWC_DEBUG | |
327 | +#if PWC_DEBUG | |
328 | /* This is normally not interesting to the user, unless you are really debugging something */ | |
329 | - else | |
330 | - Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); | |
331 | + else { | |
332 | + static int iso_error = 0; | |
333 | + iso_error++; | |
334 | + if (iso_error < 20) | |
335 | + Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); | |
336 | + } | |
337 | #endif | |
338 | } | |
339 | if (awake) | |
340 | @@ -758,7 +778,6 @@ | |
341 | int i, j, ret; | |
342 | ||
343 | struct usb_interface_descriptor *idesc; | |
344 | - int cur_alt; | |
345 | ||
346 | if (pdev == NULL) | |
347 | return -EFAULT; | |
348 | @@ -766,12 +785,11 @@ | |
349 | return 0; | |
350 | pdev->vsync = 0; | |
351 | udev = pdev->udev; | |
352 | - | |
353 | + | |
354 | /* Get the current alternate interface, adjust packet size */ | |
355 | if (!udev->actconfig) | |
356 | return -EFAULT; | |
357 | - cur_alt = udev->actconfig->interface[0].act_altsetting; | |
358 | - idesc = &udev->actconfig->interface[0].altsetting[cur_alt]; | |
359 | + idesc = &udev->actconfig->interface[0].altsetting[pdev->valternate]; | |
360 | if (!idesc) | |
361 | return -EFAULT; | |
362 | ||
363 | @@ -783,12 +801,18 @@ | |
364 | break; | |
365 | } | |
366 | ||
367 | - if (pdev->vmax_packet_size < 0) { | |
368 | + if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { | |
369 | Err("Failed to find packet size for video endpoint in current alternate setting.\n"); | |
370 | return -ENFILE; /* Odd error, that should be noticable */ | |
371 | } | |
372 | ||
373 | + /* Set alternate interface */ | |
374 | ret = 0; | |
375 | + Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); | |
376 | + ret = usb_set_interface(pdev->udev, 0, pdev->valternate); | |
377 | + if (ret < 0) | |
378 | + return ret; | |
379 | + | |
380 | for (i = 0; i < MAX_ISO_BUFS; i++) { | |
381 | urb = usb_alloc_urb(ISO_FRAMES_PER_DESC); | |
382 | if (urb == NULL) { | |
383 | @@ -797,6 +821,7 @@ | |
384 | break; | |
385 | } | |
386 | pdev->sbuf[i].urb = urb; | |
387 | + Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); | |
388 | } | |
389 | if (ret) { | |
390 | /* De-allocate in reverse order */ | |
391 | @@ -808,8 +833,7 @@ | |
392 | } | |
393 | return ret; | |
394 | } | |
395 | - | |
396 | - | |
397 | + | |
398 | /* init URB structure */ | |
399 | for (i = 0; i < MAX_ISO_BUFS; i++) { | |
400 | urb = pdev->sbuf[i].urb; | |
401 | @@ -826,7 +850,7 @@ | |
402 | urb->number_of_packets = ISO_FRAMES_PER_DESC; | |
403 | for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { | |
404 | urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; | |
405 | - urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; | |
406 | + urb->iso_frame_desc[j].length = pdev->vmax_packet_size; | |
407 | } | |
408 | } | |
409 | ||
410 | @@ -836,11 +860,12 @@ | |
411 | if (ret) | |
412 | Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); | |
413 | else | |
414 | - Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n"); | |
415 | + Trace(TRACE_OPEN, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); | |
416 | } | |
417 | ||
418 | - /* data should stream in now */ | |
419 | + /* All is done... */ | |
420 | pdev->iso_init = 1; | |
421 | + Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); | |
422 | return 0; | |
423 | } | |
424 | ||
425 | @@ -848,21 +873,34 @@ | |
426 | { | |
427 | int i; | |
428 | ||
429 | + Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); | |
430 | if (pdev == NULL) | |
431 | return; | |
432 | - if (!pdev->iso_init) | |
433 | - return; | |
434 | + | |
435 | + /* Unlinking ISOC buffers one by one */ | |
436 | + for (i = 0; i < MAX_ISO_BUFS; i++) { | |
437 | + struct urb *urb; | |
438 | + | |
439 | + urb = pdev->sbuf[i].urb; | |
440 | + if (urb != 0) { | |
441 | + if (pdev->iso_init) { | |
442 | + Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); | |
443 | + usb_unlink_urb(urb); | |
444 | + } | |
445 | + Trace(TRACE_MEMORY, "Freeing URB\n"); | |
446 | + usb_free_urb(urb); | |
447 | + pdev->sbuf[i].urb = NULL; | |
448 | + } | |
449 | + } | |
450 | + | |
451 | /* Stop camera, but only if we are sure the camera is still there */ | |
452 | - if (!pdev->unplugged) | |
453 | + if (!pdev->unplugged) { | |
454 | + Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); | |
455 | usb_set_interface(pdev->udev, 0, 0); | |
456 | - /* Unlinking ISOC buffers one by one */ | |
457 | - for (i = MAX_ISO_BUFS - 1; i >= 0; i--) { | |
458 | - pdev->sbuf[i].urb->next = NULL; | |
459 | - usb_unlink_urb(pdev->sbuf[i].urb); | |
460 | - usb_free_urb(pdev->sbuf[i].urb); | |
461 | - pdev->sbuf[i].urb = NULL; | |
462 | } | |
463 | + | |
464 | pdev->iso_init = 0; | |
465 | + Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); | |
466 | } | |
467 | ||
468 | int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) | |
469 | @@ -876,11 +914,10 @@ | |
470 | ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); | |
471 | if (ret) /* That failed... restore old mode (we know that worked) */ | |
472 | ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); | |
473 | - else /* Set (new) alternate interface */ | |
474 | - ret = usb_set_interface(pdev->udev, 0, pdev->valternate); | |
475 | if (!ret) | |
476 | - ret = pwc_isoc_init(pdev); | |
477 | - pdev->drop_frames = 1; /* try to avoid garbage during switch */ | |
478 | + if (pwc_isoc_init(pdev) < 0) | |
479 | + Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); | |
480 | + pdev->drop_frames++; /* try to avoid garbage during switch */ | |
481 | return ret; | |
482 | } | |
483 | ||
484 | @@ -915,20 +952,19 @@ | |
485 | int i; | |
486 | struct pwc_device *pdev; | |
487 | ||
488 | - Trace(TRACE_OPEN, "video_open called(0x%p, 0%o).\n", vdev, mode); | |
489 | + Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); | |
490 | ||
491 | if (vdev == NULL) | |
492 | BUG(); | |
493 | pdev = (struct pwc_device *)vdev->priv; | |
494 | if (pdev == NULL) | |
495 | BUG(); | |
496 | + if (pdev->vopen) | |
497 | + return -EBUSY; | |
498 | ||
499 | down(&pdev->modlock); | |
500 | if (!pdev->usb_init) { | |
501 | Trace(TRACE_OPEN, "Doing first time initialization.\n"); | |
502 | - /* Reset camera */ | |
503 | - if (usb_set_interface(pdev->udev, 0, 0)) | |
504 | - Info("Failed to set alternate interface to 0.\n"); | |
505 | pdev->usb_init = 1; | |
506 | ||
507 | if (pwc_trace & TRACE_OPEN) { | |
508 | @@ -948,10 +984,10 @@ | |
509 | case 0x40: sensor_type = "UPA 1021 sensor"; break; | |
510 | case 0x100: sensor_type = "VGA sensor"; break; | |
511 | case 0x101: sensor_type = "PAL MR sensor"; break; | |
512 | - default: sensor_type = "unknown type of sensor"; break; | |
513 | + default: sensor_type = "unknown type of sensor"; break; | |
514 | } | |
515 | if (sensor_type != NULL) | |
516 | - Info("Thes %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); | |
517 | + Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i); | |
518 | } | |
519 | } | |
520 | ||
521 | @@ -1017,16 +1053,9 @@ | |
522 | return i; | |
523 | } | |
524 | ||
525 | - i = usb_set_interface(pdev->udev, 0, pdev->valternate); | |
526 | - if (i) { | |
527 | - Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i); | |
528 | - up(&pdev->modlock); | |
529 | - return -EINVAL; | |
530 | - } | |
531 | i = pwc_isoc_init(pdev); | |
532 | if (i) { | |
533 | Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); | |
534 | - MOD_DEC_USE_COUNT; | |
535 | up(&pdev->modlock); | |
536 | return i; | |
537 | } | |
538 | @@ -1039,7 +1068,7 @@ | |
539 | if (pdev->decompressor != NULL) | |
540 | pdev->decompressor->lock(); | |
541 | up(&pdev->modlock); | |
542 | - Trace(TRACE_OPEN, "video_open() returning 0.\n"); | |
543 | + Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); | |
544 | return 0; | |
545 | } | |
546 | ||
547 | @@ -1049,15 +1078,12 @@ | |
548 | struct pwc_device *pdev; | |
549 | int i; | |
550 | ||
551 | - Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev); | |
552 | + Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); | |
553 | ||
554 | pdev = (struct pwc_device *)vdev->priv; | |
555 | if (pdev->vopen == 0) | |
556 | Info("video_close() called on closed device?\n"); | |
557 | ||
558 | - /* Free isoc URBs */ | |
559 | - pwc_isoc_cleanup(pdev); | |
560 | - | |
561 | /* Dump statistics, but only if a reasonable amount of frames were | |
562 | processed (to prevent endless log-entries in case of snap-shot | |
563 | programs) | |
564 | @@ -1065,21 +1091,14 @@ | |
565 | if (pdev->vframe_count > 20) | |
566 | Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error); | |
567 | ||
568 | - if (pdev->unplugged) { | |
569 | - /* The device was unplugged or some other error occured */ | |
570 | - /* We unregister the video_device */ | |
571 | - Trace(TRACE_OPEN, "Delayed video device unregistered.\n"); | |
572 | - video_unregister_device(pdev->vdev); | |
573 | - } | |
574 | - else { | |
575 | - /* Normal close: stop isochronuous and interrupt endpoint */ | |
576 | - Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n"); | |
577 | - usb_set_interface(pdev->udev, 0, 0); | |
578 | + /* Free isoc URBs, stop camera */ | |
579 | + pwc_isoc_cleanup(pdev); | |
580 | ||
581 | + if (!pdev->unplugged) { | |
582 | /* Turn LEDs off */ | |
583 | if (pwc_set_leds(pdev, 0, 0) < 0) | |
584 | - Info("Failed to set LED on/off time..\n"); | |
585 | - /* Power down camere to save energy */ | |
586 | + Info("Failed to set LED on/off time.\n"); | |
587 | + /* Power down camera to save energy */ | |
588 | if (power_save) { | |
589 | i = pwc_camera_power(pdev, 0); | |
590 | if (i < 0) | |
591 | @@ -1097,6 +1116,7 @@ | |
592 | /* wake up _disconnect() routine */ | |
593 | if (pdev->unplugged) | |
594 | wake_up(&pdev->remove_ok); | |
595 | + Trace(TRACE_OPEN, "<< video_close()\n"); | |
596 | } | |
597 | ||
598 | /* | |
599 | @@ -1495,8 +1515,8 @@ | |
600 | set_current_state(TASK_RUNNING); | |
601 | return -ERESTARTSYS; | |
602 | } | |
603 | - schedule(); | |
604 | set_current_state(TASK_INTERRUPTIBLE); | |
605 | + schedule(); | |
606 | } | |
607 | remove_wait_queue(&pdev->frameq, &wait); | |
608 | set_current_state(TASK_RUNNING); | |
609 | @@ -1574,8 +1594,6 @@ | |
610 | Trace(TRACE_MEMORY, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size); | |
611 | pdev = vdev->priv; | |
612 | ||
613 | - /* FIXME - audit mmap during a read */ | |
614 | - /* Nemo: 9 months and 20 kernel revisions later I still don't know what you mean by this :-) */ | |
615 | pos = (unsigned long)pdev->image_data; | |
616 | while (size > 0) { | |
617 | page = kvirt_to_pa(pos); | |
618 | @@ -1691,10 +1709,25 @@ | |
619 | else if (vendor_id == 0x046d) { | |
620 | switch(product_id) { | |
621 | case 0x08b0: | |
622 | - Info("Logitech QuickCam 3000 Pro USB webcam detected.\n"); | |
623 | - name = "Logitech QuickCam 3000 Pro"; | |
624 | + Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); | |
625 | + name = "Logitech QuickCam Pro 3000"; | |
626 | type_id = 730; | |
627 | - break; | |
628 | + break; | |
629 | + case 0x08b1: | |
630 | + Info("Logitech QuickCam for Notebook Pro USB webcam detected.\n"); | |
631 | + name = "Logitech QuickCam Notebook Pro"; | |
632 | + type_id = 740; /* ?? unknown sensor */ | |
633 | + break; | |
634 | + case 0x08b2: | |
635 | + Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); | |
636 | + name = "Logitech QuickCam Pro 4000"; | |
637 | + type_id = 740; /* CCD sensor */ | |
638 | + break; | |
639 | + case 0x08b3: | |
640 | + Info("Logitech QuickCam Zoom USB webcam detected.\n"); | |
641 | + name = "Logitech QuickCam Zoom"; | |
642 | + type_id = 740; /* CCD sensor */ | |
643 | + break; | |
644 | default: | |
645 | return NULL; | |
646 | break; | |
647 | @@ -1868,6 +1901,8 @@ | |
648 | ||
649 | pdev->unplugged = 1; | |
650 | if (pdev->vdev != NULL) { | |
651 | + Trace(TRACE_PROBE, "Unregistering video device.\n"); | |
652 | + video_unregister_device(pdev->vdev); | |
653 | if (pdev->vopen) { | |
654 | Info("Disconnected while device/video is open!\n"); | |
655 | ||
656 | @@ -1895,8 +1930,6 @@ | |
657 | } | |
658 | else { | |
659 | /* Normal disconnect; remove from available devices */ | |
660 | - Trace(TRACE_PROBE, "Unregistering video device normally.\n"); | |
661 | - video_unregister_device(pdev->vdev); | |
662 | kfree(pdev->vdev); | |
663 | pdev->vdev = NULL; | |
664 | } | |
665 | @@ -1914,7 +1947,7 @@ | |
666 | ||
667 | ||
668 | /* *grunt* We have to do atoi ourselves :-( */ | |
669 | -static int pwc_atoi(char *s) | |
670 | +static int pwc_atoi(const char *s) | |
671 | { | |
672 | int k = 0; | |
673 | ||
674 | @@ -1959,7 +1992,7 @@ | |
675 | MODULE_PARM(dev_hint, "0-10s"); | |
676 | MODULE_PARM_DESC(dev_hint, "Device node hints"); | |
677 | ||
678 | -MODULE_DESCRIPTION("Philips USB webcam driver"); | |
679 | +MODULE_DESCRIPTION("Philips USB & OEM webcam driver"); | |
680 | MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>"); | |
681 | MODULE_LICENSE("GPL"); | |
682 | ||
683 | @@ -1969,7 +2002,7 @@ | |
684 | char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; | |
685 | ||
686 | Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n"); | |
687 | - Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30,\n"); | |
688 | + Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); | |
689 | Info("the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); | |
690 | ||
691 | if (fps) { | |
692 | @@ -2087,7 +2120,7 @@ | |
693 | device_hint[i].serial_number[k] = '\0'; | |
694 | } | |
695 | } | |
696 | -#ifdef PWC_DEBUG | |
697 | +#if PWC_DEBUG | |
698 | Debug("device_hint[%d]:\n", i); | |
699 | Debug(" type : %d\n", device_hint[i].type); | |
700 | Debug(" serial# : %s\n", device_hint[i].serial_number); | |
701 | diff -urN linux-2.4.20.orig/drivers/usb/pwc-ioctl.h linux-2.4.20/drivers/usb/pwc-ioctl.h | |
702 | --- linux-2.4.20.orig/drivers/usb/pwc-ioctl.h Mon Jan 6 22:15:48 2003 | |
703 | +++ linux-2.4.20/drivers/usb/pwc-ioctl.h Mon Dec 16 22:19:15 2002 | |
704 | @@ -18,12 +18,13 @@ | |
705 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
706 | */ | |
707 | ||
708 | -/* This is pwc-ioctl.h belonging to PWC 8.6 */ | |
709 | +/* This is pwc-ioctl.h belonging to PWC 8.10 */ | |
710 | ||
711 | /* | |
712 | Changes | |
713 | 2001/08/03 Alvarado Added ioctl constants to access methods for | |
714 | changing white balance and red/blue gains | |
715 | + 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE | |
716 | */ | |
717 | ||
718 | /* These are private ioctl() commands, specific for the Philips webcams. | |
719 | @@ -104,7 +105,12 @@ | |
720 | int led_off; /* Led off-time; range = 0..25000 */ | |
721 | }; | |
722 | ||
723 | - | |
724 | +/* Image size (used with GREALSIZE) */ | |
725 | +struct pwc_imagesize | |
726 | +{ | |
727 | + int width; | |
728 | + int height; | |
729 | +}; | |
730 | ||
731 | /* Restore user settings */ | |
732 | #define VIDIOCPWCRUSER _IO('v', 192) | |
733 | @@ -173,4 +179,7 @@ | |
734 | #define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) | |
735 | #define VIDIOCPWCGDYNNOISE _IOR('v', 209, int) | |
736 | ||
737 | + /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ | |
738 | +#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) | |
739 | + | |
740 | #endif | |
741 | diff -urN linux-2.4.20.orig/drivers/usb/pwc-uncompress.c linux-2.4.20/drivers/usb/pwc-uncompress.c | |
742 | --- linux-2.4.20.orig/drivers/usb/pwc-uncompress.c Mon Jan 6 22:15:48 2003 | |
743 | +++ linux-2.4.20/drivers/usb/pwc-uncompress.c Mon Dec 16 22:19:15 2002 | |
744 | @@ -77,7 +77,7 @@ | |
745 | { | |
746 | struct pwc_frame_buf *fbuf; | |
747 | int n, line, col, stride; | |
748 | - void *yuv, *image, *dst; | |
749 | + void *yuv, *image; | |
750 | u16 *src; | |
751 | u16 *dsty, *dstu, *dstv; | |
752 | ||
753 | @@ -114,19 +114,6 @@ | |
754 | to get the desired output format/size. | |
755 | */ | |
756 | switch (pdev->vpalette) { | |
757 | - case VIDEO_PALETTE_YUV420: | |
758 | - /* Calculate byte offsets per line in image & view */ | |
759 | - n = (pdev->image.x * 3) / 2; | |
760 | - col = (pdev->view.x * 3) / 2; | |
761 | - /* Offset into image */ | |
762 | - dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2; | |
763 | - for (line = 0; line < pdev->image.y; line++) { | |
764 | - memcpy(dst, yuv, n); | |
765 | - yuv += n; | |
766 | - dst += col; | |
767 | - } | |
768 | - break; | |
769 | - | |
770 | case VIDEO_PALETTE_YUV420P: | |
771 | /* | |
772 | * We do some byte shuffling here to go from the | |
773 | @@ -163,17 +150,20 @@ | |
774 | dstu += (stride >> 1); | |
775 | } | |
776 | break; | |
777 | + default: | |
778 | + Err("Unsupported palette!"); | |
779 | + break; | |
780 | } | |
781 | } | |
782 | else { | |
783 | /* Compressed; the decompressor routines will write the data | |
784 | - in interlaced or planar format immediately. | |
785 | + in planar format immediately. | |
786 | */ | |
787 | if (pdev->decompressor) | |
788 | pdev->decompressor->decompress( | |
789 | &pdev->image, &pdev->view, &pdev->offset, | |
790 | - yuv, image, | |
791 | - pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0, | |
792 | + yuv, image, | |
793 | + 1, | |
794 | pdev->decompress_data, pdev->vbandlength); | |
795 | else | |
796 | return -ENXIO; /* No such device or address: missing decompressor */ | |
797 | diff -urN linux-2.4.20.orig/drivers/usb/pwc.h linux-2.4.20/drivers/usb/pwc.h | |
798 | --- linux-2.4.20.orig/drivers/usb/pwc.h Mon Jan 6 22:15:48 2003 | |
799 | +++ linux-2.4.20/drivers/usb/pwc.h Mon Dec 16 22:19:15 2002 | |
800 | @@ -60,8 +60,8 @@ | |
801 | ||
802 | /* Version block */ | |
803 | #define PWC_MAJOR 8 | |
804 | -#define PWC_MINOR 6 | |
805 | -#define PWC_VERSION "8.6" | |
806 | +#define PWC_MINOR 8 | |
807 | +#define PWC_VERSION "8.8" | |
808 | #define PWC_NAME "pwc" | |
809 | ||
810 | /* Turn certain features on/off */ | |
811 | @@ -130,7 +130,7 @@ | |
812 | int vcinterface; /* video control interface */ | |
813 | int valternate; /* alternate interface needed */ | |
814 | int vframes, vsize; /* frames-per-second & size (see PSZ_*) */ | |
815 | - int vpalette; /* YUV, RGB24, RGB32, etc */ | |
816 | + int vpalette; /* YUV */ | |
817 | int vframe_count; /* received frames */ | |
818 | int vframes_dumped; /* counter for dumped frames */ | |
819 | int vframes_error; /* frames received in error */ | |
820 | @@ -140,7 +140,8 @@ | |
821 | int vbandlength; /* compressed band length; 0 is uncompressed */ | |
822 | char vsnapshot; /* snapshot mode */ | |
823 | char vsync; /* used by isoc handler */ | |
824 | - | |
825 | + char vmirror; /* for ToUCaM series */ | |
826 | + | |
827 | /* The image acquisition requires 3 to 4 steps: | |
828 | 1. data is gathered in short packets from the USB controller | |
829 | 2. data is synchronized and packed into a frame buffer |