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