Linux-2.6.12-rc2
[pandora-kernel.git] / Documentation / video4linux / CQcam.txt
1 c-qcam - Connectix Color QuickCam video4linux kernel driver
2
3 Copyright (C) 1999  Dave Forrest  <drf5n@virginia.edu>
4                     released under GNU GPL.
5
6 1999-12-08 Dave Forrest, written with kernel version 2.2.12 in mind
7
8
9 Table of Contents
10
11 1.0 Introduction
12 2.0 Compilation, Installation, and Configuration
13 3.0 Troubleshooting
14 4.0 Future Work / current work arounds
15 9.0 Sample Program, v4lgrab
16 10.0 Other Information
17
18
19 1.0 Introduction
20
21   The file ../drivers/char/c-qcam.c is a device driver for the
22 Logitech (nee Connectix) parallel port interface color CCD camera.
23 This is a fairly inexpensive device for capturing images.  Logitech
24 does not currently provide information for developers, but many people
25 have engineered several solutions for non-Microsoft use of the Color
26 Quickcam.
27
28 1.1 Motivation
29
30   I spent a number of hours trying to get my camera to work, and I
31 hope this document saves you some time.  My camera will not work with
32 the 2.2.13 kernel as distributed, but with a few patches to the
33 module, I was able to grab some frames. See 4.0, Future Work.
34
35
36
37 2.0 Compilation, Installation, and Configuration
38
39   The c-qcam depends on parallel port support, video4linux, and the
40 Color Quickcam.  It is also nice to have the parallel port readback
41 support enabled. I enabled these as modules during the kernel
42 configuration.  The appropriate flags are:
43
44     CONFIG_PRINTER       M    for lp.o, parport.o parport_pc.o modules
45     CONFIG_PNP_PARPORT   M for autoprobe.o IEEE1284 readback module
46     CONFIG_PRINTER_READBACK M for parport_probe.o IEEE1284 readback module
47     CONFIG_VIDEO_DEV     M    for videodev.o video4linux module
48     CONFIG_VIDEO_CQCAM   M    for c-qcam.o  Color Quickcam module 
49
50   With these flags, the kernel should compile and install the modules.
51 To record and monitor the compilation, I use:
52
53  (make zlilo ; \
54   make modules; \
55   make modules_install ; 
56   depmod -a ) &>log &
57  less log  # then a capital 'F' to watch the progress
58   
59 But that is my personal preference.
60
61 2.2 Configuration
62  
63   The configuration requires module configuration and device
64 configuration.  I like kmod or kerneld process with the
65 /etc/modprobe.conf file so the modules can automatically load/unload as
66 they are used.  The video devices could already exist, be generated
67 using MAKEDEV, or need to be created.  The following sections detail
68 these procedures.
69
70
71 2.1 Module Configuration  
72
73   Using modules requires a bit of work to install and pass the
74 parameters.  Understand that entries in /etc/modprobe.conf of:
75
76    alias parport_lowlevel parport_pc
77    options parport_pc io=0x378 irq=none
78    alias char-major-81 videodev
79    alias char-major-81-0 c-qcam
80
81 will cause the kmod/modprobe to do certain things.  If you are
82 using kmod, then a request for a 'char-major-81-0' will cause
83 the 'c-qcam' module to load.  If you have other video sources with
84 modules, you might want to assign the different minor numbers to
85 different modules.
86
87 2.2 Device Configuration
88
89   At this point, we need to ensure that the device files exist.
90 Video4linux used the /dev/video* files, and we want to attach the
91 Quickcam to one of these.
92
93    ls -lad /dev/video*  # should produce a list of the video devices
94
95 If the video devices do not exist, you can create them with:
96
97   su
98   cd /dev
99   for ii in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
100     mknod video$ii c 81 $ii   # char-major-81-[0-16]
101     chown root.root video$ii  # owned by root
102     chmod 600 video$ii        # read/writable by root only
103   done
104
105   Lots of people connect video0 to video and bttv, but you might want
106 your c-qcam to mean something more:
107
108    ln -s video0 c-qcam  # make /dev/c-qcam a working file
109    ln -s c-qcam video   # make /dev/c-qcam your default video source
110
111   But these are conveniences.  The important part is to make the proper
112 special character files with the right major and minor numbers.  All
113 of the special device files are listed in ../devices.txt.  If you
114 would like the c-qcam readable by non-root users, you will need to
115 change the permissions.
116
117 3.0 Troubleshooting
118
119   If the sample program below, v4lgrab, gives you output then
120 everything is working.
121
122     v4lgrab | wc # should give you a count of characters
123
124   Otherwise, you have some problem.
125
126   The c-qcam is IEEE1284 compatible, so if you are using the proc file
127 system (CONFIG_PROC_FS), the parallel printer support
128 (CONFIG_PRINTER), the IEEE 1284 system,(CONFIG_PRINTER_READBACK), you
129 should be able to read some identification from your quickcam with
130
131          modprobe -v parport
132          modprobe -v parport_probe
133          cat /proc/parport/PORTNUMBER/autoprobe
134 Returns:
135   CLASS:MEDIA;
136   MODEL:Color QuickCam 2.0;
137   MANUFACTURER:Connectix;
138
139   A good response to this indicates that your color quickcam is alive
140 and well.  A common problem is that the current driver does not
141 reliably detect a c-qcam, even though one is attached.  In this case,
142
143      modprobe -v c-qcam     
144 or
145      insmod -v c-qcam
146
147   Returns a message saying "Device or resource busy"  Development is
148 currently underway, but a workaround is to patch the module to skip
149 the detection code and attach to a defined port.  Check the
150 video4linux mailing list and archive for more current information.
151
152 3.1 Checklist:
153
154   Can you get an image?
155             v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm
156
157   Is a working c-qcam connected to the port? 
158             grep ^ /proc/parport/?/autoprobe
159
160   Do the /dev/video* files exist?  
161             ls -lad /dev/video
162
163   Is the c-qcam module loaded?     
164             modprobe -v c-qcam ; lsmod
165
166   Does the camera work with alternate programs? cqcam, etc?
167
168
169
170
171 4.0 Future Work / current workarounds
172
173   It is hoped that this section will soon become obsolete, but if it
174 isn't, you might try patching the c-qcam module to add a parport=xxx
175 option as in the bw-qcam module so you can specify the parallel port:
176
177        insmod -v c-qcam parport=0  
178
179 And bypass the detection code, see ../../drivers/char/c-qcam.c and
180 look for the 'qc_detect' code and call.
181
182   Note that there is work in progress to change the video4linux API,
183 this work is documented at the video4linux2 site listed below.
184
185
186 9.0 --- A sample program using v4lgrabber, 
187
188 This program is a simple image grabber that will copy a frame from the
189 first video device, /dev/video0 to standard output in portable pixmap
190 format (.ppm)  Using this like: 'v4lgrab | convert - c-qcam.jpg'
191 produced this picture of me at 
192     http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
193
194 -------------------- 8< ---------------- 8< -----------------------------
195
196 /* Simple Video4Linux image grabber. */
197 /*
198  *      Video4Linux Driver Test/Example Framegrabbing Program
199  *
200  *      Compile with:
201  *              gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
202  *      Use as:
203  *              v4lgrab >image.ppm
204  *
205  *      Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>  
206  *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c 
207  *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
208  *
209  */
210
211 #include <unistd.h>
212 #include <sys/types.h>
213 #include <sys/stat.h>
214 #include <fcntl.h>
215 #include <stdio.h>
216 #include <sys/ioctl.h>
217 #include <stdlib.h>
218
219 #include <linux/types.h>
220 #include <linux/videodev.h>
221
222 #define FILE "/dev/video0"
223
224 /* Stole this from tvset.c */
225
226 #define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
227 {                                                                       \
228         switch (format)                                                 \
229         {                                                               \
230                 case VIDEO_PALETTE_GREY:                                \
231                         switch (depth)                                  \
232                         {                                               \
233                                 case 4:                                 \
234                                 case 6:                                 \
235                                 case 8:                                 \
236                                         (r) = (g) = (b) = (*buf++ << 8);\
237                                         break;                          \
238                                                                         \
239                                 case 16:                                \
240                                         (r) = (g) = (b) =               \
241                                                 *((unsigned short *) buf);      \
242                                         buf += 2;                       \
243                                         break;                          \
244                         }                                               \
245                         break;                                          \
246                                                                         \
247                                                                         \
248                 case VIDEO_PALETTE_RGB565:                              \
249                 {                                                       \
250                         unsigned short tmp = *(unsigned short *)buf;    \
251                         (r) = tmp&0xF800;                               \
252                         (g) = (tmp<<5)&0xFC00;                          \
253                         (b) = (tmp<<11)&0xF800;                         \
254                         buf += 2;                                       \
255                 }                                                       \
256                 break;                                                  \
257                                                                         \
258                 case VIDEO_PALETTE_RGB555:                              \
259                         (r) = (buf[0]&0xF8)<<8;                         \
260                         (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
261                         (b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
262                         buf += 2;                                       \
263                         break;                                          \
264                                                                         \
265                 case VIDEO_PALETTE_RGB24:                               \
266                         (r) = buf[0] << 8; (g) = buf[1] << 8;           \
267                         (b) = buf[2] << 8;                              \
268                         buf += 3;                                       \
269                         break;                                          \
270                                                                         \
271                 default:                                                \
272                         fprintf(stderr,                                 \
273                                 "Format %d not yet supported\n",        \
274                                 format);                                \
275         }                                                               \
276 }                                               
277
278 int get_brightness_adj(unsigned char *image, long size, int *brightness) {
279   long i, tot = 0;
280   for (i=0;i<size*3;i++)
281     tot += image[i];
282   *brightness = (128 - tot/(size*3))/3;
283   return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
284 }
285
286 int main(int argc, char ** argv)
287 {
288   int fd = open(FILE, O_RDONLY), f;
289   struct video_capability cap;
290   struct video_window win;
291   struct video_picture vpic;
292
293   unsigned char *buffer, *src;
294   int bpp = 24, r, g, b;
295   unsigned int i, src_depth;
296
297   if (fd < 0) {
298     perror(FILE);
299     exit(1);
300   }
301
302   if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
303     perror("VIDIOGCAP");
304     fprintf(stderr, "(" FILE " not a video4linux device?)\n");
305     close(fd);
306     exit(1);
307   }
308
309   if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
310     perror("VIDIOCGWIN");
311     close(fd);
312     exit(1);
313   }
314
315   if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
316     perror("VIDIOCGPICT");
317     close(fd);
318     exit(1);
319   }
320
321   if (cap.type & VID_TYPE_MONOCHROME) {
322     vpic.depth=8;
323     vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
324     if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
325       vpic.depth=6;
326       if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
327         vpic.depth=4;
328         if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
329           fprintf(stderr, "Unable to find a supported capture format.\n");
330           close(fd);
331           exit(1);
332         }
333       }
334     }
335   } else {
336     vpic.depth=24;
337     vpic.palette=VIDEO_PALETTE_RGB24;
338     
339     if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
340       vpic.palette=VIDEO_PALETTE_RGB565;
341       vpic.depth=16;
342       
343       if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
344         vpic.palette=VIDEO_PALETTE_RGB555;
345         vpic.depth=15;
346         
347         if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
348           fprintf(stderr, "Unable to find a supported capture format.\n");
349           return -1;
350         }
351       }
352     }
353   }
354   
355   buffer = malloc(win.width * win.height * bpp);
356   if (!buffer) {
357     fprintf(stderr, "Out of memory.\n");
358     exit(1);
359   }
360   
361   do {
362     int newbright;
363     read(fd, buffer, win.width * win.height * bpp);
364     f = get_brightness_adj(buffer, win.width * win.height, &newbright);
365     if (f) {
366       vpic.brightness += (newbright << 8);
367       if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
368         perror("VIDIOSPICT");
369         break;
370       }
371     }
372   } while (f);
373
374   fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
375
376   src = buffer;
377
378   for (i = 0; i < win.width * win.height; i++) {
379     READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
380     fputc(r>>8, stdout);
381     fputc(g>>8, stdout);
382     fputc(b>>8, stdout);
383   }
384     
385   close(fd);
386   return 0;
387 }
388 -------------------- 8< ---------------- 8< -----------------------------
389
390
391 10.0 --- Other Information
392
393 Use the ../../Maintainers file, particularly the  VIDEO FOR LINUX and PARALLEL
394 PORT SUPPORT sections
395
396 The video4linux page:
397   http://roadrunner.swansea.linux.org.uk/v4l.shtml
398
399 The video4linux2 page:
400   http://millennium.diads.com/bdirks/v4l2.htm
401
402 Some web pages about the quickcams:
403    http://www.dkfz-heidelberg.de/Macromol/wedemann/mini-HOWTO-cqcam.html
404
405    http://www.crynwr.com/qcpc/            QuickCam Third-Party Drivers
406    http://www.crynwr.com/qcpc/re.html     Some Reverse Engineering
407    http://cse.unl.edu/~cluening/gqcam/    v4l client
408    http://phobos.illtel.denver.co.us/pub/qcread/ doesn't use v4l
409    ftp://ftp.cs.unm.edu/pub/chris/quickcam/   Has lots of drivers
410    http://www.cs.duke.edu/~reynolds/quickcam/ Has lots of information
411
412