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