Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
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