patch-2.3.99-pre1 linux/Documentation/video4linux/CQcam.txt

Next file: linux/Documentation/video4linux/bttv/README
Previous file: linux/Documentation/usb/ov511.txt
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.51/linux/Documentation/video4linux/CQcam.txt linux/Documentation/video4linux/CQcam.txt
@@ -0,0 +1,414 @@
+c-qcam - Connectix Color QuickCam video4linux kernel driver
+
+Copyright (C) 1999  Dave Forrest  <drf5n@virginia.edu>
+                    released under GNU GPL.
+
+1999-12-08 Dave Forrest, written with kernel version 2.2.12 in mind
+
+
+Table of Contents
+
+1.0 Introduction
+2.0 Compilation, Installation, and Configuration
+3.0 Troubleshooting
+4.0 Future Work / current work arounds
+9.0 Sample Program, v4lgrab
+10.0 Other Information
+
+
+1.0 Introduction
+
+  The file ../drivers/char/c-qcam.c is a device driver for the
+Logitech (nee Connectix) parallel port interface color CCD camera.
+This is a fairly inexpensive device for capturing images.  Logitech
+does not currently provide information for developers, but many people
+have engineered several solutions for non-Microsoft use of the Color
+Quickcam.
+
+1.1 Motivation
+
+  I spent a number of hours trying to get my camera to work, and I
+hope this document saves you some time.  My camera will not work with
+the 2.2.13 kernel as distributed, but with a few patches to the
+module, I was able to grab some frames. See 4.0, Future Work.
+
+
+
+2.0 Compilation, Installation, and Configuration
+
+  The c-qcam depends on parallel port support, video4linux, and the
+Color Quickcam.  It is also nice to have the parallel port readback
+support enabled. I enabled these as modules during the kernel
+configuration.  The appropriate flags are:
+
+    CONFIG_PRINTER       M    for lp.o, parport.o parport_pc.o modules
+    CONFIG_PNP_PARPORT   M for autoprobe.o IEEE1284 readback module
+    CONFIG_PRINTER_READBACK M for parport_probe.o IEEE1284 readback module
+    CONFIG_VIDEO_DEV     M    for videodev.o video4linux module
+    CONFIG_VIDEO_CQCAM   M    for c-qcam.o  Color Quickcam module 
+
+  With these flags, the kernel should compile and install the modules.
+To record and monitor the compilation, I use:
+
+ (make dep; \
+  make zlilo ; \
+  make modules; \
+  make modules_install ; 
+  depmod -a ) &>log &
+ less log  # then a capital 'F' to watch the progress
+  
+But that is my personal preference.
+
+2.2 Configuration
+ 
+  The configuration requires module configuration and device
+configuration.  I like kmod or kerneld process with the
+/etc/modules.conf file so the modules can automatically load/unload as
+they are used.  The video devices could already exist, be generated
+using MAKEDEV, or need to be created.  The following sections detail
+these procedures.
+
+
+2.1 Module Configuration  
+
+  Using modules requires a bit of work to install and pass the
+parameters.  Do read ../modules.txt, and understand that entries
+in /etc/modules.conf of:
+
+   alias parport_lowlevel parport_pc
+   options parport_pc io=0x378 irq=none
+   alias char-major-81 videodev
+   alias char-major-81-0 c-qcam
+
+will cause the kmod/kerneld/modprobe to do certain things.  If you are
+using kmod or kerneld, then a request for a 'char-major-81-0' will cause
+the 'c-qcam' module to load.  If you have other video sources with
+modules, you might want to assign the different minor numbers to
+different modules.
+
+2.2 Device Configuration
+
+  At this point, we need to ensure that the device files exist.
+Video4linux used the /dev/video* files, and we want to attach the
+Quickcam to one of these.
+
+   ls -lad /dev/video*  # should produce a list of the video devices
+
+If the video devices do not exist, you can create them with:
+
+  su
+  cd /dev
+  for ii in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
+    mknod video$ii c 81 $ii   # char-major-81-[0-16]
+    chown root.root video$ii  # owned by root
+    chmod 600 video$ii        # read/writable by root only
+  done
+
+  Lots of people connect video0 to video and bttv, but you might want
+your c-qcam to mean something more:
+
+   ln -s video0 c-qcam  # make /dev/c-qcam a working file
+   ln -s c-qcam video   # make /dev/c-qcam your default video source
+
+  But these are conveniences.  The important part is to make the proper
+special character files with the right major and minor numbers.  All
+of the special device files are listed in ../devices.txt.  If you
+would like the c-qcam readable by non-root users, you will need to
+change the permissions.
+
+3.0 Troubleshooting
+
+  If the sample program below, v4lgrab, gives you output then
+everything is working.
+
+    v4lgrab | wc # should give you a count of characters
+
+  Otherwise, you have some problem.
+
+  The c-qcam is IEEE1284 compatible, so if you are using the proc file
+system (CONFIG_PROC_FS), the parallel printer support
+(CONFIG_PRINTER), the IEEE 1284 sytem,(CONFIG_PRINTER_READBACK), you
+should be able to read some identification from your quickcam with
+
+         modprobe -v parport
+         modprobe -v parport_probe
+         cat /proc/parport/PORTNUMBER/autoprobe
+Returns:
+  CLASS:MEDIA;
+  MODEL:Color QuickCam 2.0;
+  MANUFACTURER:Connectix;
+
+  A good response to this indicates that your color quickcam is alive
+and well.  A common problem is that the current driver does not
+reliably detect a c-qcam, even though one is attached.  In this case,
+
+     modprobe -v c-qcam     
+or
+     insmod -v c-qcam
+
+  Returns a message saying "Device or resource busy"  Development is
+currently underway, but a workaround is to patch the module to skip
+the detection code and attach to a defined port.  Check the
+video4linux mailing list and archive for more current information.
+
+3.1 Checklist:
+
+  Can you get an image?
+            v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm
+
+  Is a working c-qcam connected to the port? 
+            grep ^ /proc/parport/?/autoprobe
+
+  Do the /dev/video* files exist?  
+            ls -lad /dev/video
+
+  Is the c-qcam module loaded?     
+            modprobe -v c-qcam ; lsmod
+
+  Does the camera work with alternate programs? cqcam, etc?
+
+
+
+
+4.0 Future Work / current workarounds
+
+  It is hoped that this section will soon become obsolete, but if it
+isn't, you might try patching the c-qcam module to add a parport=xxx
+option as in the bw-qcam module so you can specify the parallel port:
+
+       insmod -v c-qcam parport=0  
+
+And bypass the detection code, see ../../drivers/char/c-qcam.c and
+look for the 'qc_detect' code and call.
+
+  Note that there is work in progress to change the video4linux API,
+this work is documented at the video4linux2 site listed below.
+
+
+9.0 --- A sample program using v4lgrabber, 
+
+This program is a simple image grabber that will copy a frame from the
+first video device, /dev/video0 to standard output in portable pixmap
+format (.ppm)  Using this like: 'v4lgrab | convert - c-qcam.jpg'
+produced this picture of me at 
+    http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
+
+-------------------- 8< ---------------- 8< -----------------------------
+
+/* Simple Video4Linux image grabber. */
+/*
+ *	Video4Linux Driver Test/Example Framegrabbing Program
+ *
+ *	Compile with:
+ *		gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
+ *      Use as:
+ *              v4lgrab >image.ppm
+ *
+ *	Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>  
+ *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c 
+ *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+#define FILE "/dev/video0"
+
+/* Stole this from tvset.c */
+
+#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
+{                                                                       \
+        switch (format)                                                 \
+        {                                                               \
+                case VIDEO_PALETTE_GREY:                                \
+                        switch (depth)                                  \
+                        {                                               \
+                                case 4:                                 \
+                                case 6:                                 \
+                                case 8:                                 \
+                                        (r) = (g) = (b) = (*buf++ << 8);\
+                                        break;                          \
+                                                                        \
+                                case 16:                                \
+                                        (r) = (g) = (b) =               \
+                                                *((unsigned short *) buf);      \
+                                        buf += 2;                       \
+                                        break;                          \
+                        }                                               \
+                        break;                                          \
+                                                                        \
+                                                                        \
+                case VIDEO_PALETTE_RGB565:                              \
+                {                                                       \
+                        unsigned short tmp = *(unsigned short *)buf;    \
+                        (r) = tmp&0xF800;                               \
+                        (g) = (tmp<<5)&0xFC00;                          \
+                        (b) = (tmp<<11)&0xF800;                         \
+                        buf += 2;                                       \
+                }                                                       \
+                break;                                                  \
+                                                                        \
+                case VIDEO_PALETTE_RGB555:                              \
+                        (r) = (buf[0]&0xF8)<<8;                         \
+                        (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
+                        (b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
+                        buf += 2;                                       \
+                        break;                                          \
+                                                                        \
+                case VIDEO_PALETTE_RGB24:                               \
+                        (r) = buf[0] << 8; (g) = buf[1] << 8;           \
+                        (b) = buf[2] << 8;                              \
+                        buf += 3;                                       \
+                        break;                                          \
+                                                                        \
+                default:                                                \
+                        fprintf(stderr,                                 \
+                                "Format %d not yet supported\n",        \
+                                format);                                \
+        }                                                               \
+}                                               
+
+int get_brightness_adj(unsigned char *image, long size, int *brightness) {
+  long i, tot = 0;
+  for (i=0;i<size*3;i++)
+    tot += image[i];
+  *brightness = (128 - tot/(size*3))/3;
+  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
+}
+
+int main(int argc, char ** argv)
+{
+  int fd = open(FILE, O_RDONLY), f;
+  struct video_capability cap;
+  struct video_window win;
+  struct video_picture vpic;
+
+  unsigned char *buffer, *src;
+  int bpp = 24, r, g, b;
+  unsigned int i, src_depth;
+
+  if (fd < 0) {
+    perror(FILE);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
+    perror("VIDIOGCAP");
+    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
+    perror("VIDIOCGWIN");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
+    perror("VIDIOCGPICT");
+    close(fd);
+    exit(1);
+  }
+
+  if (cap.type & VID_TYPE_MONOCHROME) {
+    vpic.depth=8;
+    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.depth=6;
+      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+        vpic.depth=4;
+        if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+          fprintf(stderr, "Unable to find a supported capture format.\n");
+          close(fd);
+          exit(1);
+        }
+      }
+    }
+  } else {
+    vpic.depth=24;
+    vpic.palette=VIDEO_PALETTE_RGB24;
+    
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.palette=VIDEO_PALETTE_RGB565;
+      vpic.depth=16;
+      
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+        vpic.palette=VIDEO_PALETTE_RGB555;
+        vpic.depth=15;
+        
+        if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+          fprintf(stderr, "Unable to find a supported capture format.\n");
+          return -1;
+        }
+      }
+    }
+  }
+  
+  buffer = malloc(win.width * win.height * bpp);
+  if (!buffer) {
+    fprintf(stderr, "Out of memory.\n");
+    exit(1);
+  }
+  
+  do {
+    int newbright;
+    read(fd, buffer, win.width * win.height * bpp);
+    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
+    if (f) {
+      vpic.brightness += (newbright << 8);
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+        perror("VIDIOSPICT");
+        break;
+      }
+    }
+  } while (f);
+
+  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
+
+  src = buffer;
+
+  for (i = 0; i < win.width * win.height; i++) {
+    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
+    fputc(r>>8, stdout);
+    fputc(g>>8, stdout);
+    fputc(b>>8, stdout);
+  }
+    
+  close(fd);
+  return 0;
+}
+-------------------- 8< ---------------- 8< -----------------------------
+
+
+10.0 --- Other Information
+
+Use the ../../Maintainers file, particularly the  VIDEO FOR LINUX and PARALLEL
+PORT SUPPORT sections
+
+The video4linux page:
+  http://roadrunner.swansea.linux.org.uk/v4l.shtml
+
+The video4linux2 page:
+  http://millennium.diads.com/bdirks/v4l2.htm
+
+Some web pages about the quickcams:
+   http://www.dkfz-heidelberg.de/Macromol/wedemann/mini-HOWTO-cqcam.html
+
+   http://www.crynwr.com/qcpc/            QuickCam Third-Party Drivers
+   http://www.crynwr.com/qcpc/re.html     Some Reverse Engineering
+   http://cse.unl.edu/~cluening/gqcam/    v4l client
+   http://phobos.illtel.denver.co.us/pub/qcread/ doesn't use v4l
+   ftp://ftp.cs.unm.edu/pub/chris/quickcam/   Has lots of drivers
+   http://www.cs.duke.edu/~reynolds/quickcam/ Has lots of information
+
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)