*BSD News Article 93263


Return to BSD News archive

Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!news.unimelb.edu.au!munnari.OZ.AU!news.ecn.uoknor.edu!feed1.news.erols.com!cpk-news-hub1.bbnplanet.com!news.bbnplanet.com!ais.net!uunet!in2.uu.net!204.147.226.2!quack!quack.kfu.com!nsayer
From: nsayer@quack.kfu.com (Nick Sayer)
Newsgroups: comp.unix.bsd.freebsd.misc
Subject: Re: fbsd and quickcams
Date: 10 Apr 1997 01:13:07 GMT
Organization: The Duck Pond public unix - http://www.kfu.com/
Lines: 439
Message-ID: <5iher3$mpe$1@phoenix.kfu.com>
References: <5hk7ss$a5l$1@news.nyu.edu>
NNTP-Posting-Host: quack.kfu.com
X-Newsreader: NN version 6.5.1 (NOV)
Xref: euryale.cc.adfa.oz.au comp.unix.bsd.freebsd.misc:38852

vmy8634@omicron.acf.nyu.edu ( ) writes:

>anyone have any experience at all with attaching quickcams to freebsd
>boxes?  i'm looking for someone to point me in the right direction here. 

>thanks a lot.

The kernel driver does not work with the color quickcam. There is
a userlevel thing that does. You need to port it, since it is really
Linux-ware. The port is _really_ easy, though.

Look around on the net for qcam-0.7c-4.

Apply this, then add the new file qcam-FreeBSD.c (it is below).
This patch fixes some bugs, adds some flags so you can fiddle with
the hue, saturation, etc.

*** oqcam/Makefile	Fri Oct 11 09:38:36 1996
--- qcam-0.7c/Makefile	Tue Nov 12 01:48:23 1996
***************
*** 10,17 ****
  # Using -O2 or -O6 slows xqcam down ~10%.  Using the -g flag makes no
  # measurable speed difference.
  
! CFLAGS=-Wall -O
! DEFINES=-DCONFIG_FILE=\"$(CONFFILE)\" #-DDEBUG #-DNEWDETECT
  
  LDFLAGS=$(CFLAGS)
  
--- 10,17 ----
  # Using -O2 or -O6 slows xqcam down ~10%.  Using the -g flag makes no
  # measurable speed difference.
  
! CFLAGS=-I/usr/X11R6/include -Wall -g
! DEFINES=-DCONFIG_FILE=\"$(CONFFILE)\" -DNEWDETECT #-DDEBUG
  
  LDFLAGS=$(CFLAGS)
  
***************
*** 64,71 ****
  	$(CC) $(LDFLAGS) -o probeqcam probeqcam.o -L. -lqcam
  
  libqcam.a: qcam-os.o qcam-lib.o
! 	rm -f libqcam.a
! 	ar rcs $@ $^ 
  
  
  install:: all
--- 64,71 ----
  	$(CC) $(LDFLAGS) -o probeqcam probeqcam.o -L. -lqcam
  
  libqcam.a: qcam-os.o qcam-lib.o
! 	ar ruv $@ qcam-os.o qcam-lib.o
! 	ranlib $@
  
  
  install:: all
*** oqcam/qcam-lib.c	Fri Oct 18 19:56:45 1996
--- qcam-0.7c/qcam-lib.c	Tue Nov 12 01:31:15 1996
***************
*** 394,399 ****
--- 394,405 ----
        if (qc_setbitdepth(q, dummy) == 1) BADENTRY("bpp");
      } else if (sscanf(buf, " brightness %d", &dummy) == 1) {
        if (qc_setbrightness(q, dummy) == 1) BADENTRY("brightness");
+     } else if (sscanf(buf, " saturation %d", &dummy) == 1) {
+       if (qc_setsaturation(q, dummy) == 1) BADENTRY("saturation");
+     } else if (sscanf(buf, " hue %d", &dummy) == 1) {
+       if (qc_sethue(q, dummy) == 1) BADENTRY("hue");
+     } else if (sscanf(buf, " blacklevel %d", &dummy) == 1) {
+       if (qc_setblacklevel(q, dummy) == 1) BADENTRY("blacklevel");
      } else if (sscanf(buf, " whitebal %d", &dummy) == 1) {
        if (qc_setwhitebal(q, dummy) == 1) BADENTRY("whitebal");
      } else if (sscanf(buf, " contrast %d", &dummy) == 1) {
***************
*** 583,591 ****
  #ifdef NEWDETECT
    int i, n1, n2, s1, s2, cmd;
  
!   write_lpcontrol(q, 0xf);
!   write_lpcontrol(q, 0xb);
!   write_lpcontrol(q, 0xf);
  
    write_lpdata(q, QC_SEND_VERSION);
    write_lpcontrol(q, 6);
--- 589,597 ----
  #ifdef NEWDETECT
    int i, n1, n2, s1, s2, cmd;
  
!   write_lpcontrol(q, 0xf); usleep(1000);
!   write_lpcontrol(q, 0xb); usleep(1000);
!   write_lpcontrol(q, 0xf); usleep(1000);
  
    write_lpdata(q, QC_SEND_VERSION);
    write_lpcontrol(q, 6);
***************
*** 669,677 ****
        break;
    }
  
!   write_lpcontrol(q, 0xf); usleep(1);
!   write_lpcontrol(q, 0xb); usleep(1);
!   write_lpcontrol(q, 0xf); usleep(1);
    qc_command(q, QC_SEND_VERSION);
    q->cam_version = qc_readparam(q);
    if (q->cam_version == QCAM_COLOR) q->bpp = 24;
--- 675,683 ----
        break;
    }
  
!   write_lpcontrol(q, 0xf); usleep(1000);
!   write_lpcontrol(q, 0xb); usleep(1000);
!   write_lpcontrol(q, 0xf); usleep(1000);
    qc_command(q, QC_SEND_VERSION);
    q->cam_version = qc_readparam(q);
    if (q->cam_version == QCAM_COLOR) q->bpp = 24;
***************
*** 758,764 ****
      qc_command(q, q->speed);
    }
  
! #if 0 /* This doesn't seem to work that well for me. --kenny */
    while (qc_checkstatus(q) & 0x80) {
        usleep(10000);
    }
--- 764,770 ----
      qc_command(q, q->speed);
    }
  
! #if 1 /* This doesn't seem to work that well for me. --kenny */
    while (qc_checkstatus(q) & 0x80) {
        usleep(10000);
    }
***************
*** 1024,1030 ****
            bytes = qc_readbytes(q, buffer);
            assert(bytes > 0);
            for (k = 0; k < bytes; k++) {
!             ret[i*(pixels_per_line*bytes_per_pixel) + (j*3) + k] = buffer[k];
            }
          }
          (void)qc_readbytes(q, 0);
--- 1030,1036 ----
            bytes = qc_readbytes(q, buffer);
            assert(bytes > 0);
            for (k = 0; k < bytes; k++) {
!             ret[i*(pixels_per_line*bytes_per_pixel) + (j*bits_per_xfer/8) + k] = buffer[k];
            }
          }
          (void)qc_readbytes(q, 0);
*** oqcam/qcam.c	Wed Oct  9 12:36:15 1996
--- qcam-0.7c/qcam.c	Tue Nov 12 16:44:56 1996
***************
*** 72,77 ****
--- 72,78 ----
    exit(1);
  }
  
+ #if 1
  /* Calculate average pixel value for entire image */
  
  int pixel_avg(struct qcam *q, scanbuf *scan)
***************
*** 98,103 ****
--- 99,129 ----
    return (sum / count);
  }
  
+ #else
+ /* Calculate average pixel value for middle 9th of image */
+ 
+ int pixel_avg(struct qcam *q, scanbuf *scan)
+ {
+   int x,y,sum=0,count=0,j;
+ 
+ #define NUM_PIXELS(x) ((x)/q->transfer_scale)
+ #define OFFSET(x,y) ((y)*NUM_PIXELS(q->width)+(x))
+ 
+   for (x=NUM_PIXELS(q->width)/3 ; x<NUM_PIXELS(q->width) *2/3 ; x++)
+     for (y=NUM_PIXELS(q->height)/3 ; y<NUM_PIXELS(q->height) *2/3 ; y++)
+       if (q->cam_version == 0x10)
+         { /* COLOR */
+           for (j=0;j<3;j++)
+             sum+=scan[3*OFFSET(x,y)+j], count++;
+         }
+       else
+         { /* BW */
+           sum+=scan[OFFSET(x,y)], count++;
+         }
+   return ( sum/count );
+ }
+ #endif
+ 
  /* Return false(0) if exposure is correct, otherwise adjust the
   * brightness and return true(1).
   */
***************
*** 127,133 ****
  	  brightness_cur,luminance_avg, luminance_target );
  #endif
  
!   if (luminance_dif == 0) {
      return 0;
    } else if (luminance_dif > 0) {
      brightness_adj = luminance_dif / 2 + 1;
--- 153,159 ----
  	  brightness_cur,luminance_avg, luminance_target );
  #endif
  
!   if (abs(luminance_dif) <= 2) {
      return 0;
    } else if (luminance_dif > 0) {
      brightness_adj = luminance_dif / 2 + 1;
***************
*** 140,145 ****
--- 166,176 ----
    /* Adjusted brightness is out of range ..
     * throw in the towel ... auto-exposure has failed!
     */
+   if (brightness_new<1)
+     brightness_new=1;
+   if (brightness_new>250)
+     brightness_new=250;
+ 
    if (qc_setbrightness(q, brightness_new)) {
      fprintf(stderr, "Autoexposure failed!\n");
      return 0;
***************
*** 174,179 ****
--- 205,212 ----
    }
  
    q=qc_init();
+ 
+ argc--;argv++;
  
    /* unpleasant pre-search for -f option */
    found = 0;
*** oqcam/xqcam.c	Fri Oct 18 19:56:49 1996
--- qcam-0.7c/xqcam.c	Tue Nov 12 00:35:51 1996
***************
*** 300,311 ****
    fprintf(stderr,"      -y height  Set height\n");
    fprintf(stderr,"      -p port    Set port\n");
    fprintf(stderr,"      -B bpp     Set bits per pixel\n");
- 
    fprintf(stderr,"      -c val     Set contrast\n");
    fprintf(stderr,"      -w val     Set white balance\n");
    fprintf(stderr,"      -W         Auto-set white balance\n");
!   fprintf(stderr,"      -b val     Set brightness\n");
    fprintf(stderr,"      -s val     Set scaling factor (1, 2, or 4)\n");
    fprintf(stderr,"      -t val     Set top line of scan\n");
    fprintf(stderr,"      -l val     Set left column of scan\n");
    fprintf(stderr,"      -V         Show version information\n");
--- 300,313 ----
    fprintf(stderr,"      -y height  Set height\n");
    fprintf(stderr,"      -p port    Set port\n");
    fprintf(stderr,"      -B bpp     Set bits per pixel\n");
    fprintf(stderr,"      -c val     Set contrast\n");
    fprintf(stderr,"      -w val     Set white balance\n");
    fprintf(stderr,"      -W         Auto-set white balance\n");
!   fprintf(stderr,"      -b val     Set brightness (integration time)\n");
!   fprintf(stderr,"      -d val     Set black balance\n");
    fprintf(stderr,"      -s val     Set scaling factor (1, 2, or 4)\n");
+   fprintf(stderr,"      -H val     Set hue\n");
+   fprintf(stderr,"      -S val     Set saturation\n");
    fprintf(stderr,"      -t val     Set top line of scan\n");
    fprintf(stderr,"      -l val     Set left column of scan\n");
    fprintf(stderr,"      -V         Show version information\n");
***************
*** 313,318 ****
--- 315,321 ----
    fprintf(stderr,"      -C         Use private colormap\n");
    fprintf(stderr,"      -r         Release the lock after each scan\n");
    fprintf(stderr,"      -u         Force unidirectional mode\n");
+   fprintf(stderr,"      -h         Show usage (this message)\n");
  
  }
  
***************
*** 344,350 ****
  
    /* Read command line */
  
!   while((arg=getopt(argc,argv,"WhCvx:y:p:b:B:c:d:t:l:s:S:w:Vru"))>0) { 
      switch (arg) {
      case 'x':
        q->width=atoi(optarg);
--- 347,353 ----
  
    /* Read command line */
  
!   while((arg=getopt(argc,argv,"WhCvH:x:y:p:b:B:c:d:t:l:s:S:w:Vru"))>0) { 
      switch (arg) {
      case 'x':
        q->width=atoi(optarg);
***************
*** 358,363 ****
--- 361,369 ----
        break;
      case 'B':
        q->bpp=atoi(optarg);
+       break;
+     case 'H':
+       q->hue=atoi(optarg);
        break;
      case 'b':
        q->brightness=atoi(optarg);



qcam-FreeBSD.h is an empty file. Touch it to keep the Makefile happy.

Here's qcam-FreeBSD.c:
----- cut here -----
/* qcam-FreeBSD.c -- FreeBSD-specific routines for accessing QuickCam */


#include <stdio.h>
#include <unistd.h>
#include <signal.h>

#include <sys/time.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <machine/cpufunc.h>

#include "qcam.h"

int read_lpstatus(struct qcam *q) { return inb(q->port+1); }
int read_lpcontrol(struct qcam *q) { return inb(q->port+2); }
int read_lpdata(struct qcam *q) { return inb(q->port); }
void write_lpdata(struct qcam *q, int d) { outb(q->port,d); }
void write_lpcontrol(struct qcam *q, int d) { outb(q->port+2,d); }

FILE *IO = NULL;

int enable_ports(struct qcam *q) 
{
  if(q->port<0x278) return 1; /* Better safe than sorry */
  if(q->port>0x3bc) return 1; 
  if (IO!=NULL)
    return 0; /* Already got it */
  IO=fopen("/dev/io","r+"); /* Simply opening /dev/io allows I/O instructions */
  return (IO==NULL);
}

int disable_ports(struct qcam *q)
{
  if (IO==NULL)
    return 0;
  fclose(IO);
  IO=NULL;
  return 0;
}

/* Lock port. */

FILE *lockfile = NULL;

void nolockexit()
{
  fprintf(stderr,"Cannot establish lock after 30 seconds.\n");
  exit(1);
}

int qc_lock(struct qcam *q)
{
  char fnam[64];

  if (lockfile!=NULL)
    return 0; /* already locked */

  sprintf(fnam,"/tmp/LCK.qcam-0x%x",q->port);
  lockfile=fopen(fnam,"w");
  if (lockfile==NULL)
    return -1;

  signal(SIGALRM,nolockexit);
  alarm(30);
  if (flock(fileno(lockfile),LOCK_EX)<0)
    return -1;
  alarm(0);
  signal(SIGALRM,SIG_DFL);

  return 0;
}

/* Unlock port */

int qc_unlock(struct qcam *q)
{
  if (lockfile==NULL)
    return 0;

  fclose(lockfile); /* close releases an flock */
  lockfile=NULL;
  return 0;
}

/* Probe for camera.  Returns 0 if found, 1 if not found, sets
   q->port.*/

int qc_probe(struct qcam *q)
{
  int ioports[]={0x378, 0x278, 0x3bc,0};
  int i=0;

  /* Attempt to get permission to access IO ports.  Must be root */

  while(ioports[i]!=0) {
    q->port=ioports[i++];

    if (qc_open(q)) {
      perror("Can't get I/O permission");
      exit(1);
    }

    if(qc_detect(q)) {
      fprintf(stderr,"QuickCam detected at 0x%x\n",q->port);
      qc_close(q);
      return(0);
    }
    else
    qc_close(q);
  }

  return 1;
}

----- ereh tuc -----
-- 
Nick Sayer <nsayer@quack.kfu.com>  | TRUE GIANTS OF HISTORY #102
N6QQQ @ N0ARY.#NORCAL.CA.USA.NOAM  | 
+1 408 249 9630, log in as 'guest' |     Edwin Armstrong
URL: http://www.kfu.com/~nsayer/   |     Radio Pioneer