diff -urN qce-ga-0.40d/Makefile.qcamshot qce-ga-0.40d.new/Makefile.qcamshot --- qce-ga-0.40d/Makefile.qcamshot Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/Makefile.qcamshot Tue Feb 3 23:55:31 2004 @@ -0,0 +1,19 @@ +# Makefile for qcamshot +# +PREFIX ?= /usr/local +BINDIR ?= ${PREFIX}/bin +MANDIR ?= ${PREFIX}/man + +PROG = qcamshot +SRCS = qcamshot.c linux_usbif.c quickcam.c pb0100.c hdcs.c vv6410.c + +MAN = ${PROG}.1 + +CFLAGS += -Wall + +LDFLAGS += -Wall + +clean: cleanprog + rm -f *~ *.orig ${PROG}.cat1 + +.include diff -urN qce-ga-0.40d/Makefile.qcamview qce-ga-0.40d.new/Makefile.qcamview --- qce-ga-0.40d/Makefile.qcamview Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/Makefile.qcamview Tue Feb 3 23:55:31 2004 @@ -0,0 +1,22 @@ +# Makefile for qcamview +# +PREFIX ?= /usr/local +BINDIR ?= ${PREFIX}/bin +MANDIR ?= ${PREFIX}/man + +PROG = qcamview +SRCS = qcamview.c linux_usbif.c quickcam.c pb0100.c hdcs.c vv6410.c gui.c +MAN = ${PROG}.1 + +GTKCFLAGS != gtk12-config --cflags +IMLIBCFLAGS != imlib-config --cflags-gdk +CFLAGS += -Wall ${GTKCFLAGS} ${IMLIBCFLAGS} + +GTKLDFLAGS != gtk12-config --libs +IMLIBLDFLAGS!= imlib-config --libs-gdk +LDFLAGS += -Wall ${GTKLDFLAGS} ${IMLIBLDFLAGS} + +clean: cleanprog + rm -f *~ *.orig ${PROG}.cat1 + +.include diff -urN qce-ga-0.40d/README.BSD qce-ga-0.40d.new/README.BSD --- qce-ga-0.40d/README.BSD Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/README.BSD Wed Feb 4 00:02:39 2004 @@ -0,0 +1,118 @@ + USB Quickcam webcam Image Capture Programs 0.04 for NetBSD/FreeBSD + + This patches written by Takafumi Mizuno + +Logitech Quickcam Express USB Utilities for NetBSD/FreeBSD +----------------------------------------------- + +1. What is it? + qcamshot ... simple image capture program ( output stdout PPM file ) + qcamview ... sequential image capture program like animation( about 3fps ) + + Programs are required Linux device driver source. Those programs are not device + driver. They are image capture programs via ugen(4). + +2. What cameras are supported? + + Vendor Device Product Name(Sensor name) + ------ ------ ---------------------------------- + 0x046d 0x0870 Qcam Express QV-30(HDCS1000) + 0x046d 0x0870 Qcam for Notebook QV-300N(HDCS1020) + +3. How to compile? + a) Check your system. + qcam**** requred below; + hardware: + - UHCI + libraries: + - gtk+-1.2.?? ( I tested 1.2.10 ) + - imlib 1.9.?? ( I tested 1.9.14 ) + OS: + NetBSD/i386 + FreeBSD-5.x + + b) Download Linux qce-ga driver "qce-ga-0.40d.tar.gz" from http://qce-ga.sourceforge.net/ + and extract. + + % cd ${WORK} + % tar -zxvf ${YOUR_DOWNLOAD_DIR}/qce-ga-0.40d.tar.gz + + b) Get patches for *BSD. + from http://www2.starcat.ne.jp/~takam/bsd/qce-ga-bsd-0.04.patch.gz + + % wget http://www2.starcat.ne.jp/~takam/bsd/qce-ga-bsd-0.04.patch.gz + + c) Apply patches. + % gzip -dc qce-ga-bsd-0.04.patch.gz | patch -p0 + + d) Do make. + % cd qce-ga-0.40d + % make -f Makefile.qcamshot + % su root -c 'make -f Makefile.qcamshot install' + % make -f Makefile.qcamview + % su root -c 'make -f Makefile.qcamview install' + + +3. How to use? +3.1. qcamshot + a) Usage + % qcamshot [devname] + + Write captured image on standard output. The image format is PPM. + + for Example. + % qcamshot > output.ppm + + b) Command line options. + [devname] specify ugen device name. ex. /dev/ugen0.00 + + If no device file is specified, the program will cycle through the + /dev/ugen0, /dev/ugen1, ... devices until it finds an attached target camera. + +3.2. qcamview + a) Usage + % qcamview [devname] + + b) Command line options. + [devname] specify ugen device name. ex. /dev/ugen0.00 + + If no device name is specified, the program will cycle through the + /dev/ugen0, /dev/ugen1, ... devices until it finds an attached target camera. + + +----------------------------------------------- +References: + GNU/Linux OS Driver for the Quickcam Express + http://qce-ga.sourceforge.net/ + + OV511/OV511+ Capture for FreeBSD/NetBSD + http://ovtvid-bsd.sourceforge.net/ + + Image Processing Program by Linux(Japanese only!) + author Iio Jun, ohmsha publising. ISBN 4-274-94623-1 +----------------------------------------------- +Problems and Questions: + a) Low performance, because those programs aren't device driver. + + b) Programs require buffers to no purpose. + + c) Programs doesn't work on FreeBSD-stable(4.x) yet. Why? + + d) Programs doesn't work on NetBSD/macppc yet. Why? Endian problem? +----------------------------------------------- +----------------------------------------------- +History: +2003-02-27 0.01 First release +2003-11-22 0.02 Bug fix, that qcamshot said + USB_GET_INTERFACE_DESC: Invalid argument +2004-01-28 0.03 add FreeBSD 5.x support, Bug fix memory leak of qcamview +2004-02-03 0.04 corrected miss for appling a contributed patch ( excuse me... ) +----------------------------------------------- +Credits: +Thanks to GNU/Linux OS Driver for the Quickcam Express developers. +Thanks to Suzuki for debug opening endpoint bug on FreeBSD. +Thanks to Gerald Davies for the qcamview FreeBSD patch +Thanks to everyone who has tested this program and given me feedback on it. + +----------------------------------------------- +written by Takafumi Mizuno \ No newline at end of file diff -urN qce-ga-0.40d/gui.c qce-ga-0.40d.new/gui.c --- qce-ga-0.40d/gui.c Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/gui.c Tue Feb 3 23:55:31 2004 @@ -0,0 +1,128 @@ +/* + * USB Quickcam Video Camera Sequential Image Capture Program for NetBSD/FreeBSD + * qcamview - Sequential image capture program. + * gui.[ch] GUI and callback functions + * + * Copyright (C) 2003-2004 Takafumi Mizuno + * + * Reference: Image Processing Program by Linux, author Iio Jun, ohmsha publishing + * ISBN:4-274-94623-1 ( Japanese Only! ) + */ +#include +#include + +#include "gui.h" +#include "quickcam.h" +#define _QCAMVIEW_ +#include "qcamshot.h" + +/* 100ms */ +#define INTERVAL 100 + +/* display area */ +static GdkImlibImage *im = NULL; + +/* backing store pixmap area */ +static GdkPixmap *pixmap = NULL; + +/* interval timer tag */ +static gint ttag; + +/* set GUI */ +void gui_config(void) +{ + GtkWidget *main_window; + GtkWidget *aspframe; + GtkWidget *drawing_area; + + /* Top level Main Window */ + main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_signal_connect(GTK_OBJECT(main_window), "destroy", + GTK_SIGNAL_FUNC(gtk_main_quit), NULL); + + /* aspect frame */ + aspframe = gtk_aspect_frame_new(NULL,0.5,0.5,1.0,TRUE); + gtk_frame_set_shadow_type(GTK_FRAME(aspframe), GTK_SHADOW_NONE); + + im = get_new_frame(im); + + /* display area */ + drawing_area = gtk_drawing_area_new(); + gtk_drawing_area_size(GTK_DRAWING_AREA(drawing_area), + im ->rgb_width, im->rgb_height); + gtk_container_add(GTK_CONTAINER(main_window), aspframe); + gtk_container_add(GTK_CONTAINER(aspframe), drawing_area); + + /* signal configure */ + gtk_signal_connect(GTK_OBJECT(main_window), "destroy", + GTK_SIGNAL_FUNC(gtk_main_quit), NULL); + gtk_signal_connect(GTK_OBJECT(drawing_area), "expose_event", + GTK_SIGNAL_FUNC(exposed), NULL); + gtk_signal_connect(GTK_OBJECT(drawing_area), "configure_event", + GTK_SIGNAL_FUNC(configured), NULL); + gtk_widget_set_events(drawing_area, GDK_EXPOSURE_MASK); + + /* timer set */ + ttag = gtk_timeout_add(INTERVAL, (GtkFunction)update_screen, + (gpointer)drawing_area); + + /* display */ + gtk_widget_show_all(main_window); + return; +} + +/* configure(e.g. resize) event */ +gint configured(GtkWidget *widget, GdkEventConfigure *event) +{ + gint w, h; + + w = widget->allocation.width; + h = widget->allocation.height; + gdk_imlib_render(im, w, h); + + /* create new pixmap from new size image */ + if ( pixmap ) gdk_imlib_free_pixmap(pixmap); + pixmap = gdk_imlib_move_image(im); + + return TRUE; +} + +/* exposed event */ +int exposed(GtkWidget *widget, GdkEventExpose *event) +{ + if (pixmap) gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + pixmap, + event->area.x, event->area.y, + event->area.x, event->area.y, + event->area.width, event->area.height); + return TRUE; +} + +gint update_screen(GtkWidget *widget) +{ + GdkEventExpose e; + GdkImlibImage *oldim; + + e.type = GDK_EXPOSE; + e.window = widget->window; + e.area.x = 0; e.area.y = 0; + e.area.width = widget->allocation.width; + e.area.height = widget->allocation.height; + e.send_event = 0; e.count = 0; + + if ( e.window != NULL ) { + oldim = im; + im = get_new_frame(im); + if ( im == NULL ) { + /* do nothing */ + im = oldim; + return TRUE; + } + configured(widget, NULL); + exposed(widget, &e); + } + + return TRUE; + +} diff -urN qce-ga-0.40d/gui.h qce-ga-0.40d.new/gui.h --- qce-ga-0.40d/gui.h Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/gui.h Tue Feb 3 23:55:31 2004 @@ -0,0 +1,12 @@ +#ifndef _GUI_H_ +#define _GUI_H_ + +/* prototype declaration */ +void gui_config(void); + +gint configured(GtkWidget *, GdkEventConfigure *); +int exposed(GtkWidget *, GdkEventExpose *); +gint update_screen(GtkWidget *); + + +#endif /* _GUI_H_ */ diff -urN qce-ga-0.40d/linux_usbif.c qce-ga-0.40d.new/linux_usbif.c --- qce-ga-0.40d/linux_usbif.c Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/linux_usbif.c Tue Feb 3 23:55:31 2004 @@ -0,0 +1,83 @@ +/* + * linux_usbif.c - Linux API; usb_control_msg() usb_set_interface() + * usb_set_configuration() + * Copyright (C) 2003 Takafumi Mizuno + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include "linux_usbif.h" + +/* Linux API rapper */ + +int usb_control_msg(struct usb_device *dev, unsigned int pipe, + u_int8_t request, u_int8_t requesttype, + u_int16_t value, u_int16_t index, void *data, u_int16_t size, int timeout) +{ + /* XXX pipe and timeout is dummy */ + struct usb_ctl_request ur; + + ur.ucr_request.bRequest = request; + ur.ucr_request.bmRequestType = requesttype; + USETW(ur.ucr_request.wValue, value); + USETW(ur.ucr_request.wIndex, index); + USETW(ur.ucr_request.wLength, size); + ur.ucr_data = data; + ur.ucr_flags = 0; + ur.ucr_actlen = 0; + + if (ioctl(dev->fd, USB_DO_REQUEST, &ur) < 0) { + return -1; + } + + return 0; + +} + +int usb_set_configuration(struct usb_device *dev, int configuration) +{ + if (ioctl(dev->fd, USB_SET_CONFIG, &configuration) < 0) { + perror("USB_SET_CONFIG"); + return -1; + } + return 0; +} + +int usb_set_interface(struct usb_device *dev, int ifnum, int alternate) +{ + /* XXX ifnum is dummy */ + struct usb_alt_interface alt; /* interface/alternate selection */ + + alt.uai_config_index = USB_CURRENT_CONFIG_INDEX; + alt.uai_interface_index = 0; + alt.uai_alt_no = alternate; + if (ioctl(dev->fd, USB_SET_ALTINTERFACE, &alt) < 0) { + perror("USB_SET_ALTINTERFACE"); + return -1; + } + return 0; +} diff -urN qce-ga-0.40d/linux_usbif.h qce-ga-0.40d.new/linux_usbif.h --- qce-ga-0.40d/linux_usbif.h Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/linux_usbif.h Tue Feb 3 23:55:31 2004 @@ -0,0 +1,99 @@ +#ifndef __LINUX_USBIF__H +#define __LINUX_USBIF__H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define USB_DIR_OUT UT_WRITE +#define USB_DIR_IN UT_READ +#define USB_TYPE_VENDOR UT_VENDOR +#define USB_RECIP_DEVICE UT_DEVICE +#define USB_RECIP_INTERFACE UT_INTERFACE +#define USB_RECIP_ENDPOINT UT_ENDPOINT +#define USB_RECIP_OTHER UT_OTHER + +#define HZ 1000 /* dummy */ + +/* dummy */ +#define usb_sndctrlpipe(a,b) (b) +#define usb_rcvctrlpipe(a,b) (b) + +typedef u_int8_t u8; +typedef u_int16_t u16; +typedef u_int32_t u32; +typedef u_int8_t __u8; +typedef u_int16_t __u16; +typedef int32_t __s32; +typedef u_int32_t __u32; + +#define printk(fmt,args...) fprintf(stderr,fmt,##args) +#define kmalloc(siz,opt) malloc(siz) +#define kfree(pt) free(pt) + +/* fake $kernel_source_top/include/linux/???.h */ +/* I referenced 2.4.?? */ +#define LINUX_VERSION_CODE 0x020400 +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) + +struct devinfo{ + uint8_t class; + uint8_t subclass; + uint8_t protocol; + uint8_t bNumConfigurations; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; +}; + +struct usb_device { + int fd; + int efd; + char epdevname[FILENAME_MAX]; + struct devinfo descriptor; + struct usb_config_desc configdesc; + struct usb_config_desc *actconfig; + struct usb_interface_desc interfacedesc; + struct usb_endpoint_desc endpointdesc; +}; + +/* fake $kernel_source_top/include/linux/a.out.h */ +/* original size = 0x400 too small!? */ +#define PAGE_SIZE 0x800 + +/* fake $kernel_source_top/include/linux/usb.h */ +int usb_control_msg(struct usb_device *dev, unsigned int pipe, + u_int8_t request, u_int8_t requesttype, + u_int16_t value, u_int16_t index, void *data, u_int16_t size, int timeout); + +int usb_set_configuration(struct usb_device *dev, int configuration); +int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); + +/* from $kernel_source_top/include/linux/kernel.h */ +#define KERN_EMERG "<0>" /* system is unusable */ +#define KERN_ALERT "<1>" /* action must be taken immediately */ +#define KERN_CRIT "<2>" /* critical conditions */ +#define KERN_ERR "<3>" /* error conditions */ +#define KERN_WARNING "<4>" /* warning conditions */ +#define KERN_NOTICE "<5>" /* normal but significant condition */ +#define KERN_INFO "<6>" /* informational */ +#define KERN_DEBUG "<7>" /* debug-level messages */ + +/* XXX */ +#define MODULE_PARM(a,b) +#define MODULE_PARM_DESC(a,b) +#define MODULE_DESCRIPTION(a) +#define MODULE_AUTHOR(a) +#define MODULE_LICENSE(a) +#define MODULE_DEVICE_TABLE(a,b) + + +#endif /* __LINUX_USBIF__H */ diff -urN qce-ga-0.40d/qcamshot.1 qce-ga-0.40d.new/qcamshot.1 --- qce-ga-0.40d/qcamshot.1 Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/qcamshot.1 Wed Feb 4 00:17:06 2004 @@ -0,0 +1,67 @@ +.\"/*- +.\" * Copyright (c) 2003-2004 Mizuno Takafumi +.\" * All rights reserved. +.\" * +.\" * Redistribution and use in source and binary forms, with or without +.\" * modification, are permitted provided that the following conditions +.\" * are met: +.\" * 1. Redistributions of source code must retain the above copyright +.\" * notice, this list of conditions and the following disclaimer. +.\" * 2. Redistributions in binary form must reproduce the above copyright +.\" * notice, this list of conditions and the following disclaimer in the +.\" * documentation and/or other materials provided with the distribution. +.\" * +.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" * SUCH DAMAGE. +.\" * +.\" */ +.Dd February 4, 2004 +.Dt qcamshot 1 +.Os +.Sh NAME +.Nm qcamshot +.Nd simple image capture program for Qcam Express +.Sh SYNOPSIS +.Nm qcamshot +.Op /dev/ugen?.00 +.Sh DESCRIPTION +.Nm +is a simple program to capture image for USB Qcam Express. +.Pp +The captured image is PPM format as 352x288 size. It is written to the standard output. +.Pp +The following options are supported: +.Bl -tag -width indent +.It /dev/ugen?.00 +Specifies the ugen device name. If no device name is specified, +the program will cycle through the /dev/ugen0.00, /dev/ugen1.00, ... +devices until it finds an attached target camera. +.El +.Sh EXAMPLES +qcamshot \*[Gt] output.ppm +.Sh SEE ALSO +.Xr ugen 4 +.Sh WEBPAGE OF PORTING FOR BSD +http://www2.starcat.ne.jp/~takam/bsd/NetBSD.html#qcam +.Sh REFERENCE +Linux qce-ga driver; http://qce-ga.sourceforge.net/ +.Sh SUPPORT CAMERAS +.Bl -tag -width indent -compact +.It Pa Vendor Device Product_Name(Sensor_name) +.It 0x046d 0x0870 Qcam Express QV-30(HDCS1000) +.It 0x046d 0x0870 Qcam for Notebook QV-300N(HDCS1020) +.El +.Sh AUTHORS +.An Mizuno Takafumi + + + diff -urN qce-ga-0.40d/qcamshot.c qce-ga-0.40d.new/qcamshot.c --- qce-ga-0.40d/qcamshot.c Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/qcamshot.c Wed Feb 4 00:22:56 2004 @@ -0,0 +1,581 @@ +/* + * USB Quickcam Video Camera Image Capture Program for NetBSD/FreeBSD, version 0.04 + * qcamshot - Simple image capture program. + * Copyright (C) 2003-2004 Takafumi Mizuno + * + * Portions of this program were modeled after or adapted from the + * USB Quickcam Express dirver for Linux by many people; see + * http://qce-ga.sourceforge.net/ for more information. + * + * This program is free software; you can redistribute it and/or modify + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "linux_usbif.h" +#include "quickcam.h" /* Control register of the STV0600 ASIC */ +#include "helper.h" + +#include "pb0100.h" +#include "hdcs.h" +#include "vv6410.h" + +#include "qcamshot.h" + +struct usb_device usbdev; +struct usb_quickcam *quickcam; + +char dev[FILENAME_MAX]; + +#define REQ_FRAMES 10 +#define RAW_DAT_BUFSIZE (REQ_FRAMES*FRAMES_PER_DESC*FRAME_SIZE_PER_DESC) + +#define SEARCH_FRAMES 3 /* why 3? */ +#define STORE_BUFSIZE (RAW_DAT_BUFSIZE*SEARCH_FRAMES) + +static unsigned char storebuf[STORE_BUFSIZE]; +static unsigned char grabbuf[RAW_DAT_BUFSIZE]; +static unsigned char rgb[BAYER_FRAME_SIZE*4]; /* 4= RGB and work area */ +/* #define DEBUG_GRAB */ + +static int quickcam_grab(void); +static void outputppm(unsigned char *, int, int); + +int main(int argc, char *argv[]) +{ + int i = 0; + + /* + * check option + */ + if (argc == 1) { + /* search Quickcam */ + for ( i = 0; i < 15; ++i ) { +#ifdef __FreeBSD__ + sprintf(dev, "/dev/ugen%d", i); +#else + sprintf(dev, "/dev/ugen%d.00", i); +#endif + if ( (usbdev.fd = open(dev, O_RDWR)) < 0 ) { + continue; + } + if ( (quickcam = (struct usb_quickcam *)quickcam_probe(&usbdev)) == NULL ) { + close(usbdev.fd); + usbdev.fd = -1; + continue; + } else { + break; + } + } + } else { + if ( argv[1][0] != '/' ) { + fprintf(stderr, "usage: %s [device-name]\n", argv[0]); + fprintf(stderr, " [device-name] must be started slash \'/\' character.\n"); + exit(1); + } + strncpy(dev, argv[1], FILENAME_MAX-1); + if ( (usbdev.fd = open(dev, O_RDWR)) < 0 ) { + err(1, "%s", dev); + } else { + if ( (quickcam = (struct usb_quickcam *)quickcam_probe(&usbdev)) == NULL ) { + close(usbdev.fd); + usbdev.fd = -1; + } + } + } + + if ( usbdev.fd < 0 ) { + fprintf(stderr, "Not found Quickcam, or Permission denied\n"); + exit(1); + } + + quickcam_open(quickcam); + + /* open endpoint (endpoint 1) */ +#ifdef __FreeBSD__ + sprintf(usbdev.epdevname, "%s.1", dev); +#else + sprintf(usbdev.epdevname, "%s.01", strtok(dev,".")); +#endif + if ((usbdev.efd = open(usbdev.epdevname, O_RDONLY)) < 0) { + perror(usbdev.epdevname); + quickcam_close(quickcam); + close(usbdev.fd); + exit(1); + } + + memset(storebuf, 0, STORE_BUFSIZE); + memset(grabbuf, 0, RAW_DAT_BUFSIZE); + memset(rgb, 0, BAYER_FRAME_SIZE*4); + + if ( usb_quickcam_start(quickcam) < 0) { + fprintf(stderr, "can\'t quickcam start\n"); + } else { + +#define EXPOSURE_TIME 20 + for ( i = 0; i < EXPOSURE_TIME; i++ ) { + if ( quickcam_grab() != 0 ) { + break; + } + if ( (i%2) == 0) fprintf(stderr, " Say cheese! after %2d\r", (EXPOSURE_TIME-i)/2 ); + } + if ( i == EXPOSURE_TIME ) outputppm(rgb, QUICKCAM_WIDTH, QUICKCAM_HEIGHT); + } + + fprintf(stderr, "Closing Qcam Express....."); + close(usbdev.efd); + quickcam_close(quickcam); /* do free(quickcam) */ + close(usbdev.fd); + fprintf(stderr, "Done.\n"); + + return 0; +} + +/* Read raw-data from Quickcam and convert to RGB24 + * reference qce-linux-driver + * quickcam_parse_store() quickcam_parse_data() + */ +static int quickcam_grab(void) +{ + int i, cur_len; + unsigned char *isodat, *rawdat; + ssize_t readlen; + int totalsize; /* total iso-packet data */ + int tot_len; /* total grabbing data */ + unsigned char type1, type2; + int frag_len; + enum { SEARCH_HEAD, GRABBING_DAT, FOUND_TAIL} state; + int framesize; + + long ii; + unsigned long mid_value=0; + unsigned long mid_value_line=0; + int xx=0; + int yy=0; + int xd=0; + int copylen=0; + unsigned char *o; + unsigned char *data; + int skiph; + int startw, endw; + + /* Use sensor information to get the framesize */ + if (quickcam->sensor_ctrl.mode==1) + framesize = qcmin(BAYER_FRAME_SIZE, + (quickcam->sensor_ctrl.width* + quickcam->sensor_ctrl.height)*2); + else + framesize = qcmin(BAYER_FRAME_SIZE, + quickcam->sensor_ctrl.width* + quickcam->sensor_ctrl.height); + + /* get iso packet */ + totalsize = 0; + isodat = storebuf; + totalsize = 0; + for ( i = 0; i < (REQ_FRAMES*FRAMES_PER_DESC*SEARCH_FRAMES); i++ ) { + readlen = read(usbdev.efd, (void *)isodat, FRAME_SIZE_PER_DESC); + isodat += readlen; + totalsize += readlen; + } + + /* fail safe */ + if ( totalsize > STORE_BUFSIZE) { + fprintf(stderr,"buffer overflow\n"); + return -1; + } + + /* grab raw RGB data from isopacket */ + tot_len = 0; +#ifdef DEBUG_GRAB + fprintf(stderr, "total size = %d\n", totalsize); +#endif + isodat = storebuf; + rawdat = grabbuf; + state = SEARCH_HEAD; /* enum { SEARCH_HEAD, GRABBING_DAT, FOUND_TAIL} */ + for ( cur_len = 0; cur_len < totalsize; cur_len++ ) { + type1 = isodat[cur_len]; + type2 = isodat[cur_len+1]; + frag_len=isodat[cur_len+2]<<8 | isodat[cur_len+3]; + if(type1==0x80 || type1==0xC0) { + if(type2==1 || type2==5) { /* a frame begins - see if we can capture it. */ + if ( state == SEARCH_HEAD ) { + state = GRABBING_DAT; +#ifdef DEBUG_GRAB + fprintf(stderr, "found head\n"); +#endif + cur_len += 3; + continue; + } else if ( state == GRABBING_DAT ) { + /* restart */ +#ifdef DEBUG_GRAB + fprintf(stderr, "found header again...restart\n"); +#endif + state = GRABBING_DAT; + tot_len = 0; + rawdat = grabbuf; + cur_len += 3; + continue; + } else { + /* cant find FOUND_TAIL, grabbing abort */ +#ifdef DEBUG_GRAB + fprintf(stderr,"not found head, grabbing abort\n"); +#endif + state = FOUND_TAIL; + break; + } + } else if(type2==2 || type2==6) { /* a frame end */ + if ( state == GRABBING_DAT ) { + state = FOUND_TAIL; +#ifdef DEBUG_GRAB + fprintf(stderr, "found tail\n"); +#endif + break; + } else { + /* ignore */ + cur_len += 3; + continue; + } + } + } else if(type1==0x02 || type1==0x42) { /* data chunk */ + if ( state != GRABBING_DAT ) { + cur_len += 3; + continue; + } + if ( tot_len + frag_len > BAYER_FRAME_SIZE) { +#ifdef DEBUG_GRAB + fprintf(stderr, "buffer overflow, grabbing abort\n"); +#endif + state = FOUND_TAIL; + break; + } + memcpy((void *)rawdat, (void *)&isodat[cur_len+4], frag_len); + rawdat += frag_len; + tot_len += frag_len; + cur_len += (frag_len + 3); + } + /* other ignore */ + } + + if ( state != FOUND_TAIL ) { + fprintf(stderr, "grabbing error: grabbing size = %d\n", tot_len); + return -1; + } + + /* grabbing sucess ?: total size %d\n", tot_len); */ + if ( tot_len != framesize ) { +#ifdef DEBUG_GRAB + fprintf(stderr,"warring some packet lost\n"); +#endif + tot_len = framesize; + } +#ifdef DEBUG_GRAB + else { + fprintf(stderr, "grabbing sucess total size %d\n", tot_len); + } +#endif + +#define addblue 0 +#define addgreen 1 +#define addred 2 + /* need cleaning ... */ +#define XH QUICKCAM_HEIGHT +#define XW QUICKCAM_WIDTH +#define SW quickcam->sensor_ctrl.width + + /* calculate data to skip for the VV6410 sensor */ + if (mode) { + skiph = (quickcam->sensor_ctrl.height-(XH/2))/2; + startw = (quickcam->sensor_ctrl.width-(XW/2))/2; + } else { + skiph = (quickcam->sensor_ctrl.height-XH)/2; + startw = (quickcam->sensor_ctrl.width-XW)/2; + } + if (skiph<0) skiph=0; + if (startw<0) startw=0; + endw = quickcam->sensor_ctrl.width-startw; + + /* difference from original linux driver as follow; */ + /* frame->storedata ==> grabbuf */ + /* frame->storelength ==> tot_len */ + /* frame->data ==> rgb */ + /* frame->scanlength ==> N/A */ + + /* skip fisrt and last lines if needed */ + data = grabbuf+(skiph*quickcam->sensor_ctrl.width); + for (ii=skiph*quickcam->sensor_ctrl.width; + iisensor_ctrl.width); + ii++) { + + /* + * Skip line data when needed. + */ + if ((ii%quickcam->sensor_ctrl.widthsensor_ctrl.width>=endw && startw)) { + data++; + continue; + } + + /* + * For HDCS Sensors: + * Camera is G1R1 G2R2 G3R3... + * B4G4 B5G5 B6G6... + * Video is B4G1R1 B4G1R1 + * B4G4R1 B4G4R1 + * For Photobit... + */ + + if (yy>XH) + yy=XH; + + if (mode) { + o=((unsigned char*)rgb)+3*xd+(XW*3*yy); + xd++; + xd++; + } else { + o=((unsigned char*)rgb)+3*xx+(XW*3*yy); + } + + mid_value_line+=*data; + + if (interpolation == 1) { /* bilinear interpolation */ + if (!(yy&1)) { // even row + if (xx&1) { // odd column, red + *(o+addred)=*data; + if (yy == 0) { + if (xx == XW-1) { + *(o+addblue)=*(data+SW-1); + *(o+addgreen)=(*(data-1) + *(data+SW))/2; + } else { + *(o+addblue)=(*(data+SW-1) + *(data+SW+1))/2; + *(o+addgreen)=(*(data-1) + *(data+1) + *(data+SW))/3; + } + } else { + if (xx == XW-1) { + *(o+addblue)=(*(data-SW-1) + *(data+SW-1))/2; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+SW))/3; + } else { + *(o+addblue)=(*(data-SW-1) + *(data-SW+1) + *(data+SW-1) + *(data+SW+1))/4; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+1) + *(data+SW))/4; + } + } + if (mode) { + } + } else { // green + if (yy == 0) { + if (xx == 0) { + *(o+addred)=*(data+1); + *(o+addblue)=*(data+SW); + } else { + *(o+addred)=(*(data-1) + *(data+1))/2; + *(o+addblue)=*(data+SW); + } + } else { + if (xx == 0) { + *(o+addred)=*(data+1); + *(o+addblue)=(*(data-SW) + *(data+SW))/2; + } else { + *(o+addred)=(*(data-1) + *(data+1))/2; + *(o+addblue)=(*(data-SW) + *(data+SW))/2; + } + } + *(o+addgreen)=*data; + if (mode) { + } + } + } else { + if (xx&1) { // odd column green + if (yy == XH-1) { + if (xx == XW-1) { + *(o+addred)=*(data-SW); + *(o+addblue)=*(data-1); + } else { + *(o+addred)=*(data-SW); + *(o+addblue)=(*(data-1) + *(data+1))/2; + } + } else { + if (xx == XW-1) { + *(o+addred)=(*(data-SW) + *(data+SW))/2; + *(o+addblue)=*(data-1); + } else { + *(o+addred)=(*(data-SW) + *(data+SW))/2; + *(o+addblue)=(*(data-1) + *(data+1))/2; + } + } + *(o+addgreen)=*data; + if (mode) { + } + } else { //blue + *(o+addblue)=*data; + if (yy == XH-1) { + if (xx == 0) { + *(o+addred)=*(data-SW+1); + *(o+addgreen)=(*(data-SW) + *(data+1))/2; + } else { + *(o+addred)=(*(data-SW-1) + *(data-SW+1))/2; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+1))/3; + } + } else { + if (xx == 0) { + *(o+addred)=(*(data-SW+1) + *(data+SW+1))/2; + *(o+addgreen)=(*(data-SW) + *(data+1) + *(data+SW))/3; + } else { + *(o+addred)=(*(data-SW-1) + *(data-SW+1) + *(data+SW-1) + *(data+SW+1))/4; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+1) + *(data+SW))/4; + } + } + if (mode) { + } + } + } + } else { /* not bilinear interpolation */ + if (!(yy&1)) { // even row + if (xx&1) { // odd column, red + *(o+addred)=*data; + *(o+addred-3)=*data; + *(o+addred+3*(XW))=*data; + *(o+addred+3*(XW-1))=*data; + if (mode) { + *(o+addred+3)=*data; + *(o+addred-6)=*data; + *(o+addred+3*(XW+1))=*data; + *(o+addred+3*(XW-2))=*data; + } + } else { // green + *(o+1)=*data; + *(o+1+3)=*data; + if (mode) { + *(o+1+6)=*data; + if (xd>2) + *(o+1-3)=*data; + } + } + } else { + if (xx&1) { // odd column green + *(o+1)=*data; + *(o+1-3)=*data; + if (mode) { + *(o+1+3)=*data; + *(o+1-6)=*data; + *(o+1+6)=*data; // last would be missing. + } + } else { //blue + *(o+addblue)=*data; + *(o+addblue+3)=*data; + *(o+addblue+3*(XW))=*data; + *(o+addblue+3*(XW-1))=*data; + if (mode) { + *(o+addblue+6)=*data; + *(o+addblue+3*(XW+1))=*data; + *(o+addblue-6)=*data; + *(o+addblue+3*(XW-2))=*data; + } + } + } + } + + xx++; + copylen ++; + + if (xx==XW || (xx==XW/2 && mode)) { + if (mode) + mid_value += (mid_value_line/(XW/2)); + else + mid_value += (mid_value_line/XW); + mid_value_line = 0; + xx=0; + xd = 0; + yy++; + if (yy>=XH) { + break; + } + } + data++; + } + + /* + * the frame is done, the exposure should + * be set here (We are the waked-up process) + */ + if (yy>=XH || (yy>=XH/2 && mode)) { + if (quickcam->sensor_ctrl.mode==2) { + mid_value = mid_value/(yy/2); + } else { + mid_value = mid_value/yy; + } + usb_quickcam_set_exposure(quickcam,mid_value); + } + + /* if mode=2 we have only 1/2 of the enlargement */ + if (quickcam->sensor_ctrl.mode==2) { + data = rgb; + for (i=XH/2;i>1;i--) { + memcpy(&data[i*6*XW],&data[i*3*XW],XW*3); + memcpy(&data[i*6*XW-3*XW],&data[i*3*XW],XW*3); + } + copylen = copylen *2; + } + + if (mode) { + copylen = copylen *2; + } + /* frame->scanlength = (copylen*6)/2; */// yes but how to compute partial pixels!. + + /* RGB -> BGR */ + if(tobgr) + { + char c; + char *p = rgb; + int i = QUICKCAM_WIDTH * QUICKCAM_HEIGHT; + while(--i) + { + c = p[0]; + p[0] = p[2]; + p[2] = c; + p += 3; + } + } + + return 0; + +} + +static void outputppm(unsigned char *target, int width, int height) +{ + int i; + + if ( target == NULL || width <= 0 || height <= 0 ) return; + + printf("P6\n"); + printf("%d %d 255 ", width, height); + + for ( i = 0; i < (width*height*3); i+=3 ) { + printf("%c%c%c", + target[i], + target[i+1], + target[i+2]); + } + + return; +} diff -urN qce-ga-0.40d/qcamshot.h qce-ga-0.40d.new/qcamshot.h --- qce-ga-0.40d/qcamshot.h Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/qcamshot.h Tue Feb 3 23:55:31 2004 @@ -0,0 +1,14 @@ +#ifndef _INC_QCAMSHOT_H_ +#define _INC_QCAMSHOT_H_ + +#define QUICKCAM_WIDTH 352 +#define QUICKCAM_HEIGHT 288 + +extern struct usb_device usbdev; +extern struct usb_quickcam *quickcam; + +#ifdef _QCAMVIEW_ +extern GdkImlibImage *get_new_frame(GdkImlibImage *); +#endif + +#endif /* _INC_QCAMSHOT_H_ */ diff -urN qce-ga-0.40d/qcamview.1 qce-ga-0.40d.new/qcamview.1 --- qce-ga-0.40d/qcamview.1 Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/qcamview.1 Wed Feb 4 00:17:09 2004 @@ -0,0 +1,65 @@ +.\"/*- +.\" * Copyright (c) 2003-2004 Mizuno Takafumi +.\" * All rights reserved. +.\" * +.\" * Redistribution and use in source and binary forms, with or without +.\" * modification, are permitted provided that the following conditions +.\" * are met: +.\" * 1. Redistributions of source code must retain the above copyright +.\" * notice, this list of conditions and the following disclaimer. +.\" * 2. Redistributions in binary form must reproduce the above copyright +.\" * notice, this list of conditions and the following disclaimer in the +.\" * documentation and/or other materials provided with the distribution. +.\" * +.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" * SUCH DAMAGE. +.\" * +.\" */ +.Dd February 4, 2004 +.Dt qcamview 1 +.Os +.Sh NAME +.Nm qcamview +.Nd sequential image capture and view program for Qcam Express +.Sh SYNOPSIS +.Nm qcamview +.Op /dev/ugen?.00 +.Sh DESCRIPTION +.Nm +is a sequential image capture and view program for USB Qcam Express. +.Pp +The captured image size is 352x288. +.Pp +The following options are supported: +.Bl -tag -width indent +.It /dev/ugen?.00 +Specifies the ugen device name. If no device name is specified, +the program will cycle through the /dev/ugen0.00, /dev/ugen1.00, ... +devices until it finds an attached target camera. +.El +.Sh SEE ALSO +.Xr ugen 4 +.Sh WEBPAGE OF PORTING FOR BSD +http://www2.starcat.ne.jp/~takam/bsd/NetBSD.html#qcam +.Sh REFERENCE +Linux qce-ga driver; http://qce-ga.sourceforge.net/ +.Sh SUPPORT CAMERAS +.Bl -tag -width indent -compact +.It Pa Vendor Device Product_Name(Sensor_name) +.It 0x046d 0x0870 Qcam Express QV-30(HDCS1000) +.It 0x046d 0x0870 Qcam for Notebook QV-300N(HDCS1020) +.El +.Sh AUTHORS +.An Mizuno Takafumi + + + diff -urN qce-ga-0.40d/qcamview.c qce-ga-0.40d.new/qcamview.c --- qce-ga-0.40d/qcamview.c Thu Jan 1 09:00:00 1970 +++ qce-ga-0.40d.new/qcamview.c Wed Feb 4 00:03:26 2004 @@ -0,0 +1,523 @@ +/* + * USB Quickcam Video Camera Sequential Image Capture Program for NetBSD/FreeBSD, version 0.04 + * qcamview - Sequential image capture program. + * Copyright (C) 2003-2004 Takafumi Mizuno + * + * This program is very referenced one book. see "gui.c" more detail. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "gui.h" + +#include "linux_usbif.h" +#include "quickcam.h" /* Control register of the STV0600 ASIC */ +#include "helper.h" + +#include "pb0100.h" +#include "hdcs.h" +#include "vv6410.h" + +#define _QCAMVIEW_ +#include "qcamshot.h" + +struct usb_device usbdev; +struct usb_quickcam *quickcam; + +char dev[FILENAME_MAX]; + +#define REQ_FRAMES 10 +#define RAW_DAT_BUFSIZE (REQ_FRAMES*FRAMES_PER_DESC*FRAME_SIZE_PER_DESC) + +static unsigned char storebuf[RAW_DAT_BUFSIZE*3]; +static unsigned char grabbuf[RAW_DAT_BUFSIZE]; +static unsigned char rgb[BAYER_FRAME_SIZE*4]; /* 4= 0RGB */ + +GdkImlibImage *get_new_frame(GdkImlibImage *); + +int main(int argc, char *argv[]) +{ + int i = 0; + + gtk_init(&argc, &argv); + gdk_imlib_init(); + + /* + * check option + */ + if (argc == 1) { + /* search Quickcam */ + for ( i = 0; i < 15; ++i ) { +#ifdef __FreeBSD__ + sprintf(dev, "/dev/ugen%d", i); +#else + sprintf(dev, "/dev/ugen%d.00", i); +#endif + if ( (usbdev.fd = open(dev, O_RDWR)) < 0 ) { + continue; + } + if ( (quickcam = (struct usb_quickcam *)quickcam_probe(&usbdev)) == NULL ) { + close(usbdev.fd); + usbdev.fd = -1; + continue; + } else { + break; + } + } + } else { + if ( argv[1][0] != '/' ) { + fprintf(stderr, "usage: %s [device-name]\n", argv[0]); + fprintf(stderr, " [device-name] must be started slash \'/\' character.\n"); + exit(1); + } + strncpy(dev, argv[1], FILENAME_MAX-1); + if ( (usbdev.fd = open(dev, O_RDWR)) < 0 ) { + err(1, "%s", dev); + } else { + if ( (quickcam = (struct usb_quickcam *)quickcam_probe(&usbdev)) == NULL ) { + close(usbdev.fd); + usbdev.fd = -1; + } + } + } + + if ( usbdev.fd < 0 ) { + fprintf(stderr, "Not found Quickcam, or Permission denied\n"); + exit(1); + } + + quickcam_open(quickcam); + + /* open endpoint (endpoint 1) */ +#ifdef __FreeBSD__ + sprintf(usbdev.epdevname, "%s.1", dev); +#else + sprintf(usbdev.epdevname, "%s.01", strtok(dev,".")); +#endif + if ((usbdev.efd = open(usbdev.epdevname, O_RDONLY)) < 0) { + perror(usbdev.epdevname); + quickcam_close(quickcam); + close(usbdev.fd); + exit(1); + } + + memset(storebuf, 0, RAW_DAT_BUFSIZE*3); + memset(grabbuf, 0, RAW_DAT_BUFSIZE); + memset(rgb, 0, BAYER_FRAME_SIZE*4); + + if ( usb_quickcam_start(quickcam) < 0) { + fprintf(stderr, "can\'t quickcam start\n"); + } else { + gui_config(); + gtk_main(); + } + + fprintf(stderr, "Closing Qcam Express....."); + close(usbdev.efd); + quickcam_close(quickcam); /* do free(quickcam) */ + close(usbdev.fd); + fprintf(stderr, "Done.\n"); + + return 0; +} + +/* Read raw-data from Quickcam and convert to RGB24 + * reference qce-linux-driver + * quickcam_parse_store() quickcam_parse_data() + */ +GdkImlibImage *get_new_frame(GdkImlibImage *current) +{ + int i, cur_len; + unsigned char *isodat, *rawdat; + ssize_t readlen; + int totalsize; /* total iso-packet data */ + int tot_len; /* total grabbing data */ + unsigned char type1, type2; + int frag_len; + enum { SEARCH_HEAD, GRABBING_DAT, FOUND_TAIL} state; + int framesize; + + long ii; + unsigned long mid_value=0; + unsigned long mid_value_line=0; + int xx=0; + int yy=0; + int xd=0; + int copylen=0; + unsigned char *o; + unsigned char *data; + int skiph; + int startw, endw; + + /* Use sensor information to get the framesize */ + if (quickcam->sensor_ctrl.mode==1) + framesize = qcmin(BAYER_FRAME_SIZE, + (quickcam->sensor_ctrl.width* + quickcam->sensor_ctrl.height)*2); + else + framesize = qcmin(BAYER_FRAME_SIZE, + quickcam->sensor_ctrl.width* + quickcam->sensor_ctrl.height); + + /* get iso packet (with margin) */ + totalsize = 0; + isodat = storebuf; + totalsize = 0; + for ( i = 0; i < (REQ_FRAMES*FRAMES_PER_DESC*3); i++ ) { + if ( (readlen = read(usbdev.efd, (void *)isodat, FRAME_SIZE_PER_DESC))<0 ) { + perror("Read"); + return NULL; + } + isodat += readlen; + totalsize += readlen; + } + + /* fail safe */ + if ( totalsize > RAW_DAT_BUFSIZE*3) { + fprintf(stderr,"!"); + return NULL; + } + + /* grab raw RGB data from isopacket */ + tot_len = 0; + isodat = storebuf; + rawdat = grabbuf; + state = SEARCH_HEAD; /* enum { SEARCH_HEAD, GRABBING_DAT, FOUND_TAIL} */ + for ( cur_len = 0; cur_len < totalsize; cur_len++ ) { + type1 = isodat[cur_len]; + type2 = isodat[cur_len+1]; + frag_len=isodat[cur_len+2]<<8 | isodat[cur_len+3]; + if(type1==0x80 || type1==0xC0) { + if(type2==1 || type2==5) { /* a frame begins - see if we can capture it. */ + if ( state == SEARCH_HEAD ) { + state = GRABBING_DAT; + cur_len += 3; + continue; + } else if ( state == GRABBING_DAT ) { + /* restart */ + state = GRABBING_DAT; + tot_len = 0; + rawdat = grabbuf; + cur_len += 3; + continue; + } else { + /* cant find FOUND_TAIL, grabbing abort */ + state = FOUND_TAIL; + break; + } + } else if(type2==2 || type2==6) { /* a frame end */ + if ( state == GRABBING_DAT ) { + state = FOUND_TAIL; + break; + } else { + /* ignore */ + cur_len += 3; + continue; + } + } + } else if(type1==0x02 || type1==0x42) { /* data chunk */ + if ( state != GRABBING_DAT ) { + cur_len += 3; + continue; + } + if ( tot_len + frag_len > BAYER_FRAME_SIZE) { + state = FOUND_TAIL; + break; + } + memcpy((void *)rawdat, (void *)&isodat[cur_len+4], frag_len); + rawdat += frag_len; + tot_len += frag_len; + cur_len += (frag_len + 3); + } + /* other ignore */ + } + + if ( state != FOUND_TAIL ) { + fprintf(stderr,"/"); + return NULL; + } + + /* grabbing sucess ?: total size %d\n", tot_len); */ + if ( tot_len != framesize ) { + tot_len = framesize; + } + + +#define addblue 0 +#define addgreen 1 +#define addred 2 + /* need cleaning ... */ +#define XH QUICKCAM_HEIGHT +#define XW QUICKCAM_WIDTH +#define SW quickcam->sensor_ctrl.width + + /* calculate data to skip for the VV6410 sensor */ + if (mode) { + skiph = (quickcam->sensor_ctrl.height-(XH/2))/2; + startw = (quickcam->sensor_ctrl.width-(XW/2))/2; + } else { + skiph = (quickcam->sensor_ctrl.height-XH)/2; + startw = (quickcam->sensor_ctrl.width-XW)/2; + } + if (skiph<0) skiph=0; + if (startw<0) startw=0; + endw = quickcam->sensor_ctrl.width-startw; + + /* difference original linux driver as follow; */ + /* frame->storedata ==> grabbuf */ + /* frame->storelength ==> tot_len */ + /* frame->data ==> rgb */ + /* frame->scanlength ==> N/A */ + + /* skip fisrt and last lines if needed */ + data = grabbuf+(skiph*quickcam->sensor_ctrl.width); + for (ii=skiph*quickcam->sensor_ctrl.width; + iisensor_ctrl.width); + ii++) { + + /* + * Skip line data when needed. + */ + if ((ii%quickcam->sensor_ctrl.widthsensor_ctrl.width>=endw && startw)) { + data++; + continue; + } + + /* + * For HDCS Sensors: + * Camera is G1R1 G2R2 G3R3... + * B4G4 B5G5 B6G6... + * Video is B4G1R1 B4G1R1 + * B4G4R1 B4G4R1 + * For Photobit... + */ + + if (yy>XH) + yy=XH; + + if (mode) { + o=((unsigned char*)rgb)+3*xd+(XW*3*yy); + xd++; + xd++; + } else { + o=((unsigned char*)rgb)+3*xx+(XW*3*yy); + } + + mid_value_line+=*data; + + if (interpolation == 1) { /* bilinear interpolation */ + if (!(yy&1)) { // even row + if (xx&1) { // odd column, red + *(o+addred)=*data; + if (yy == 0) { + if (xx == XW-1) { + *(o+addblue)=*(data+SW-1); + *(o+addgreen)=(*(data-1) + *(data+SW))/2; + } else { + *(o+addblue)=(*(data+SW-1) + *(data+SW+1))/2; + *(o+addgreen)=(*(data-1) + *(data+1) + *(data+SW))/3; + } + } else { + if (xx == XW-1) { + *(o+addblue)=(*(data-SW-1) + *(data+SW-1))/2; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+SW))/3; + } else { + *(o+addblue)=(*(data-SW-1) + *(data-SW+1) + *(data+SW-1) + *(data+SW+1))/4; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+1) + *(data+SW))/4; + } + } + if (mode) { + } + } else { // green + if (yy == 0) { + if (xx == 0) { + *(o+addred)=*(data+1); + *(o+addblue)=*(data+SW); + } else { + *(o+addred)=(*(data-1) + *(data+1))/2; + *(o+addblue)=*(data+SW); + } + } else { + if (xx == 0) { + *(o+addred)=*(data+1); + *(o+addblue)=(*(data-SW) + *(data+SW))/2; + } else { + *(o+addred)=(*(data-1) + *(data+1))/2; + *(o+addblue)=(*(data-SW) + *(data+SW))/2; + } + } + *(o+addgreen)=*data; + if (mode) { + } + } + } else { + if (xx&1) { // odd column green + if (yy == XH-1) { + if (xx == XW-1) { + *(o+addred)=*(data-SW); + *(o+addblue)=*(data-1); + } else { + *(o+addred)=*(data-SW); + *(o+addblue)=(*(data-1) + *(data+1))/2; + } + } else { + if (xx == XW-1) { + *(o+addred)=(*(data-SW) + *(data+SW))/2; + *(o+addblue)=*(data-1); + } else { + *(o+addred)=(*(data-SW) + *(data+SW))/2; + *(o+addblue)=(*(data-1) + *(data+1))/2; + } + } + *(o+addgreen)=*data; + if (mode) { + } + } else { //blue + *(o+addblue)=*data; + if (yy == XH-1) { + if (xx == 0) { + *(o+addred)=*(data-SW+1); + *(o+addgreen)=(*(data-SW) + *(data+1))/2; + } else { + *(o+addred)=(*(data-SW-1) + *(data-SW+1))/2; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+1))/3; + } + } else { + if (xx == 0) { + *(o+addred)=(*(data-SW+1) + *(data+SW+1))/2; + *(o+addgreen)=(*(data-SW) + *(data+1) + *(data+SW))/3; + } else { + *(o+addred)=(*(data-SW-1) + *(data-SW+1) + *(data+SW-1) + *(data+SW+1))/4; + *(o+addgreen)=(*(data-SW) + *(data-1) + *(data+1) + *(data+SW))/4; + } + } + if (mode) { + } + } + } + } else { /* not bilinear interpolation */ + if (!(yy&1)) { // even row + if (xx&1) { // odd column, red + *(o+addred)=*data; + *(o+addred-3)=*data; + *(o+addred+3*(XW))=*data; + *(o+addred+3*(XW-1))=*data; + if (mode) { + *(o+addred+3)=*data; + *(o+addred-6)=*data; + *(o+addred+3*(XW+1))=*data; + *(o+addred+3*(XW-2))=*data; + } + } else { // green + *(o+1)=*data; + *(o+1+3)=*data; + if (mode) { + *(o+1+6)=*data; + if (xd>2) + *(o+1-3)=*data; + } + } + } else { + if (xx&1) { // odd column green + *(o+1)=*data; + *(o+1-3)=*data; + if (mode) { + *(o+1+3)=*data; + *(o+1-6)=*data; + *(o+1+6)=*data; // last would be missing. + } + } else { //blue + *(o+addblue)=*data; + *(o+addblue+3)=*data; + *(o+addblue+3*(XW))=*data; + *(o+addblue+3*(XW-1))=*data; + if (mode) { + *(o+addblue+6)=*data; + *(o+addblue+3*(XW+1))=*data; + *(o+addblue-6)=*data; + *(o+addblue+3*(XW-2))=*data; + } + } + } + } + + xx++; + copylen ++; + + if (xx==XW || (xx==XW/2 && mode)) { + if (mode) + mid_value += (mid_value_line/(XW/2)); + else + mid_value += (mid_value_line/XW); + mid_value_line = 0; + xx=0; + xd = 0; + yy++; + if (yy>=XH) { + break; + } + } + data++; + } + + /* + * the frame is done, the exposure should + * be set here (We are the waked-up process) + */ + if (yy>=XH || (yy>=XH/2 && mode)) { + if (quickcam->sensor_ctrl.mode==2) { + mid_value = mid_value/(yy/2); + } else { + mid_value = mid_value/yy; + } + usb_quickcam_set_exposure(quickcam,mid_value); + } + + /* if mode=2 we have only 1/2 of the enlargement */ + if (quickcam->sensor_ctrl.mode==2) { + data = rgb; + for (i=XH/2;i>1;i--) { + memcpy(&data[i*6*XW],&data[i*3*XW],XW*3); + memcpy(&data[i*6*XW-3*XW],&data[i*3*XW],XW*3); + } + copylen = copylen *2; + } + + if (mode) { + copylen = copylen *2; + } + /* frame->scanlength = (copylen*6)/2; */// yes but how to compute partial pixels!. + + /* RGB -> BGR */ + if(tobgr) + { + char c; + char *p = rgb; + int i = QUICKCAM_WIDTH * QUICKCAM_HEIGHT; + while(--i) + { + c = p[0]; + p[0] = p[2]; + p[2] = c; + p += 3; + } + } + + if (current) gdk_imlib_kill_image(current); + return gdk_imlib_create_image_from_data(rgb, NULL, + QUICKCAM_WIDTH,QUICKCAM_HEIGHT); +} diff -urN qce-ga-0.40d/quickcam.c qce-ga-0.40d.new/quickcam.c --- qce-ga-0.40d/quickcam.c Mon Jan 27 18:41:03 2003 +++ qce-ga-0.40d.new/quickcam.c Wed Feb 4 00:03:29 2004 @@ -32,7 +32,7 @@ For any questions ask qce-ga-devel@lists.sourceforge.net! */ - +#if 0 /* Cuted by *BSD patch */ #include #include #include @@ -55,13 +55,25 @@ #include #include #include +#endif /* Cuted by *BSD patch */ + +#include +#include +#include +#include +#include +#include + +#include #include "quickcam.h" #include "pb0100.h" #include "hdcs.h" #include "vv6410.h" -#include "memory.h" +/*#include "memory.h"*//* Cuted by *BSD patch */ #include "helper.h" +#include "linux_usbif.h" + #ifndef MODULE #define DEBUGLEVEL 0 // put in your wanted value here @@ -106,11 +118,11 @@ static int debug = DEBUGLEVEL; static int keepexposure = 0; -static int tobgr = 0; +int tobgr = 1; -static int interpolation = 1; /* 1 = bilinear interpolation */ +int interpolation = 1; /* 1 = bilinear interpolation */ -static int mode = 0; /* normal or sub-sample (sub-sample to increase the speed) */ +int mode = 0; /* normal or sub-sample (sub-sample to increase the speed) */ /* gains allow the user decide the initial value of the gains */ static int rgain = 0; @@ -118,19 +130,20 @@ static int ggain = 0; static int bright= 32768; /* Zero gives black images with gnomemeeting */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5) +#if 0 /* Cuted by *BSD patch */ /* video_nr option allows to specify a certain /dev/videoX device */ /* (like /dev/video0 or /dev/video1 ...) */ /* for autodetect first available use video_nr=-1 (defaultvalue) */ /* (code reused from bttv driver http://bytesex.org/bttv/) */ static int video_nr = -1; -#endif +#endif /* Cuted by *BSD patch */ /* Video Size 352 x 288 x 4 bytes for 0RGB 32 bpp mode */ #define MAX_FRAME_SIZE (352 * 288 * 4) -#define VERSION "$Id: quickcam.c,v 1.111 2003/01/27 09:41:03 tuukkat Exp $" +#define VERSION "$Id: quickcam.c,v 1.111 2003/01/27 09:41:03 tuukkat Exp $" " + BSD patch 0.04" +#if 0 /* Cuted by *BSD patch */ static struct usb_driver quickcam_driver; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) @@ -143,6 +156,7 @@ MODULE_DEVICE_TABLE (usb, device_table); #endif +#endif /* Cuted by *BSD patch */ static struct sensor_data sensors [] = { /* name reg23 i2c_addr id_reg id l load */ @@ -154,6 +168,7 @@ { NULL } }; +#if 0 /* Cuted by *BSD patch */ /* * HexDump a string... */ @@ -175,12 +190,13 @@ if (k > 0) printk("%s\n", tmp); } +#endif /* Cuted by *BSD patch */ /* * /proc interface for our driver */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if 0 /* Cuted by *BSD patch */ #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) static struct proc_dir_entry *quickcam_proc_entry = NULL; @@ -297,7 +313,7 @@ } #endif -#endif +#endif /* Cuted by *BSD patch */ /* * I2C read registers of HDCS1000, the result will be in the STV0600 register 0x1410. @@ -305,7 +321,7 @@ static int usb_quickcam_i2c_in(struct usb_device *dev, int reg, unsigned char sensor_addr) { -char buff[35]; /* why 35 = 23 hex? */ +unsigned char buff[35]; /* why 35 = 23 hex? */ buff[0]=reg; @@ -313,7 +329,7 @@ buff[0x21]=0; // 1 value buff[0x22]=3; // Read cmd. - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + return usb_control_msg(dev, 0, 0x04, 0x40, 0x1400, 0, @@ -327,10 +343,10 @@ static int usb_quickcam_get_i2c(struct usb_device *dev, unsigned char sensor_addr, int reg, void *buf, int len) { if (usb_quickcam_i2c_in(dev,reg,sensor_addr)<0) { - printk("usb_quickcam_i2c_in failed\n"); + fprintf(stderr, "usb_quickcam_i2c_in failed\n"); return(-1); } - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + return usb_control_msg(dev, 0, 0x04, 0xC0, 0x1410, 0, buf, len, HZ); @@ -339,11 +355,11 @@ /* * Set register one byte */ -int usb_quickcam_set1(struct usb_device *dev, short reg, char val) +int usb_quickcam_set1(struct usb_device *dev, unsigned short reg, unsigned char val) { -char buff[1]; +unsigned char buff[1]; buff[0] = val; - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + return usb_control_msg(dev, 0, 0x04, 0x40, reg, 0, @@ -353,12 +369,12 @@ /* * Set register two byte */ -int usb_quickcam_set2(struct usb_device *dev, short reg, short val) +int usb_quickcam_set2(struct usb_device *dev, unsigned short reg, unsigned short val) { -char buff[2]; +unsigned char buff[2]; buff[0] = val&0xFF; buff[1] = (val>>8)&255; - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + return usb_control_msg(dev, 0, 0x04, 0x40, reg, 0, @@ -367,9 +383,9 @@ /* Send a command to the sensor */ -static int quickcam_usb_control_msg(struct usb_device *dev, char *buff) +static int quickcam_usb_control_msg(struct usb_device *dev, unsigned char *buff) { - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + return usb_control_msg(dev, 0, 0x04, 0x40, 0x400, 0, @@ -416,7 +432,7 @@ { int ret; i2cbuff->buff[0x20]=sensor_add; - i2cbuff->buff[0x21]=i2cbuff->length-1; + i2cbuff->buff[0x21]=(unsigned char)i2cbuff->length-1; i2cbuff->buff[0x22]=1; // Write cmd, 03 would be read. ret = quickcam_usb_control_msg(dev,i2cbuff->buff); usb_quickcam_i2c_new(i2cbuff); @@ -435,9 +451,9 @@ gg=qcmin(255,qcmax(1,(quickcam->gain*quickcam->green)>>7)); if (debug&DEBUGDATA) { - printk("usb_quickcam_set_gains: gain %d, red %d, blue %d, green %d\n", + fprintf(stderr,"usb_quickcam_set_gains: gain %d, red %d, blue %d, green %d\n", quickcam->gain,quickcam->red,quickcam->blue,quickcam->green); - printk("usb_quickcam_set_gains: gr %d, gb %d, gg %d\n",gr,gb,gg); + fprintf(stderr,"usb_quickcam_set_gains: gr %d, gb %d, gg %d\n",gr,gb,gg); } return quickcam->sensor_ctrl.set_gains(dev,gr,gb,gg); @@ -450,7 +466,7 @@ * And he says: "Auto-Exposure needs a bit more intelligence"! */ -static int usb_quickcam_set_exposure(struct usb_quickcam *quickcam, +int usb_quickcam_set_exposure(struct usb_quickcam *quickcam, long val) { int og=quickcam->gain; @@ -478,8 +494,8 @@ } if (debug&DEBUGDATA) { - printk("usb_quickcam_set_exposure: required %d, mesured %ld\n",brightness,val); - printk("usb_quickcam_set_exposure: gain %d shutter %d\n",quickcam->gain,quickcam->shutter_val); + fprintf(stderr,"usb_quickcam_set_exposure: required %d, mesured %ld\n",brightness,val); + fprintf(stderr,"usb_quickcam_set_exposure: gain %d shutter %d\n",quickcam->gain,quickcam->shutter_val); } if (os!=quickcam->shutter_val) quickcam->sensor_ctrl.set_shutter(dev,quickcam->shutter_val,0x100); @@ -488,8 +504,31 @@ return 0; } +/* Start camera and esable ISO-streaming *//* add */ +int usb_quickcam_start(struct usb_quickcam *quickcam) +{ + int ret=0; + + if (!quickcam->dev) + return 0; // nothing to do. + + // start current frame. + if ( quickcam->sensor_ctrl.start(quickcam->dev, + &(quickcam->sensor_ctrl))<0) { + ret = -1; + } + + // start ISO-streaming. + ret = usb_quickcam_set1(quickcam->dev, STV_ISO_ENABLE, 1); + + // ffprintf(stderr, "start current frame = %d\n",ret); + if (debug&DEBUGLOGIC) + fprintf(stderr,"usb_quickcam_start:%d\n",ret); + return ret; +} + /* Stop camera and disable ISO-streaming */ -static int usb_quickcam_stop(struct usb_quickcam *quickcam) +int usb_quickcam_stop(struct usb_quickcam *quickcam) { int ret=0; @@ -504,7 +543,7 @@ ret = quickcam->sensor_ctrl.stop(quickcam->dev, &(quickcam->sensor_ctrl)); if (debug&DEBUGLOGIC) - printk("usb_quickcam_stop:%d\n",ret); + fprintf(stderr,"usb_quickcam_stop:%d\n",ret); return ret; } @@ -513,10 +552,11 @@ */ static int quickcam_init_isoc(struct usb_quickcam *quickcam); static int quickcam_stop_isoc(struct usb_quickcam *quickcam); +#if 0 /* Cuted by *BSD patch */ static int usb_quickcam_upload_frame(struct usb_quickcam *quickcam) { if (debug&DEBUGLOGIC) - printk("usb_quickcam_upload_frame %d\n",quickcam->scanstate); + fprintf(stderr,"usb_quickcam_upload_frame %d\n",quickcam->scanstate); if (quickcam->scanstate==STATE_ERROR) { quickcam->grabbing = 0; @@ -1073,25 +1113,24 @@ } else quickcam->scratchlen = 0; } +#endif /* Cuted by *BSD patch */ /* * Start isoc */ static int quickcam_init_isoc(struct usb_quickcam *quickcam) { - struct urb *urb; - int fx, err; if (debug&DEBUGLOGIC) - printk("quickcam_init_isoc\n"); + fprintf(stderr,"quickcam_init_isoc\n"); /* Alternate interface 3 is is the biggest frame size */ /* JFC use 1: but do not know why */ if (usb_set_interface(quickcam->dev, quickcam->iface, 1) < 0) { - printk("usb_set_interface error\n"); + fprintf(stderr,"usb_set_interface error\n"); return -EBUSY; } - +#if 0 /* Cuted by *BSD patch */ /* We double buffer the Iso lists */ urb = usb_alloc_urb(FRAMES_PER_DESC); @@ -1149,8 +1188,9 @@ err); quickcam->streaming = 1; +#endif /* Cuted by *BSD patch */ if (debug&DEBUGLOGIC) - printk("quickcam_init_isoc finished\n"); + fprintf(stderr,"quickcam_init_isoc finished\n"); return 0; } @@ -1166,20 +1206,17 @@ return -1; if (quickcam->sensor_ctrl.set_size(quickcam->dev, mode)<0) { - printk("set_size sensor failed\n"); + fprintf(stderr,"set_size sensor failed\n"); return -1; } /* set the requested size (we should try to center it) */ if (quickcam->sensor_ctrl.set_window(quickcam->dev, 0, 0,width,height, &(quickcam->sensor_ctrl))<0) { - printk("set_window sensor failed\n"); + fprintf(stderr,"set_window sensor failed\n"); return(-1); } - quickcam->vwin.width = width; - quickcam->vwin.height = height; - quickcam->sizechanged = -1; // changed! return(0); } @@ -1192,11 +1229,11 @@ int quickcam_init_sensor(struct usb_quickcam *quickcam) { if (debug&DEBUGBASE) - printk("quickcam_init_sensor: init sensor\n"); + fprintf(stderr, "quickcam_init_sensor: init sensor\n"); if (quickcam->sensor_ctrl.init(quickcam->dev,mode, &rgain, &bgain, &ggain, &(quickcam->sensor_ctrl))<0) { - printk("Init sensor failed\n"); + fprintf(stderr,"Init sensor failed\n"); return(-1); } /* gain is the average of blue, green and red gain */ @@ -1207,11 +1244,11 @@ quickcam->red =qcmin(255,qcmax(2,rgain)); quickcam->green=qcmin(255,qcmax(2,ggain)); if (usb_quickcam_set_gains(quickcam)<0) { - printk("set_gains sensor failed\n"); + fprintf(stderr,"set_gains sensor failed\n"); return(-1); } if (quickcam->sensor_ctrl.set_shutter(quickcam->dev,quickcam->shutter_val,0x100)<0) { - printk("set_shutter sensor failed\n"); + fprintf(stderr,"set_shutter sensor failed\n"); return(-1); } /* Set the size otherwise the read() will fail */ @@ -1231,20 +1268,21 @@ if (!quickcam->dev) return -1; if (debug&DEBUGLOGIC) - printk("quickcam_stop_isoc\n"); + fprintf(stderr, "quickcam_stop_isoc\n"); /* Turn off continuous grab */ if (usb_quickcam_stop(quickcam) < 0) { - printk("usb_quickcam_stop error\n"); + fprintf(stderr,"usb_quickcam_stop error\n"); return -EBUSY; } /* Set packet size to 0 */ if (usb_set_interface(quickcam->dev, quickcam->iface, 0) < 0) { - printk("usb_set_interface error\n"); + fprintf(stderr,"usb_set_interface error\n"); return -EINVAL; } +#if 0 /* Cuted by *BSD patch */ quickcam->streaming = 0; /* make sure that the next is called */ @@ -1264,9 +1302,11 @@ usb_free_urb(quickcam->sbuf[0].urb); quickcam->sbuf[0].urb = NULL; } +#endif /* Cuted by *BSD patch */ return 0; } +#if 0 /* Cuted by *BSD patch */ /* * Start grabing a new frame it must be the one required otherwise the calling * process will be lost (it waits for the wrong frame!). @@ -1391,78 +1431,16 @@ return -EINVAL; } } +#endif /* Cuted by *BSD patch */ /* Video 4 Linux API */ -static int quickcam_open(struct video_device *dev, int flags) +int quickcam_open(struct usb_quickcam *quickcam) { int err = -EBUSY; - struct usb_quickcam *quickcam = (struct usb_quickcam *)dev; if (debug&DEBUGLOGIC) - printk("quickcam_open\n"); - down(&quickcam->lock); - if (quickcam->user) - goto out_unlock; + fprintf(stderr,"quickcam_open\n"); - // Re-Setup internal video_picture - quickcam->vpic.hue = (rgain - bgain + 0xFF) << 7; - quickcam->vpic.colour = ggain; - quickcam->vpic.contrast = 32768; - quickcam->vpic.brightness = bright; - quickcam->vpic.whiteness = 0; - quickcam->vpic.palette = VIDEO_PALETTE_RGB24; - quickcam->vpic.depth = quickcam_get_depth(quickcam); - - // Re-Setup internal video_window - quickcam->vwin.x = 0; - quickcam->vwin.y = 0; - quickcam->vwin.chromakey = 0; - quickcam->vwin.flags = 30; /* 30 fps */ - - quickcam->frame[0].grabstate = FRAME_UNUSED; - quickcam->frame[1].grabstate = FRAME_UNUSED; - quickcam->streaming = 0; - quickcam->curframe = -1; - quickcam->scratchlen = 0; - quickcam->storestate=FRAME_STORE; - - err = -ENOMEM; - - /* Allocate memory for the frame buffers */ - quickcam->fbuf = rvmalloc(2 * MAX_FRAME_SIZE); - if (!quickcam->fbuf) - goto out_unlock; - - quickcam->frame[0].data = quickcam->fbuf; - quickcam->frame[1].data = quickcam->fbuf + MAX_FRAME_SIZE; - - quickcam->sbuf[0].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!quickcam->sbuf[0].data) - goto open_err_on0; - - quickcam->sbuf[1].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!quickcam->sbuf[1].data) - goto open_err_on1; - - quickcam->frame[0].storedata = vmalloc (BAYER_FRAME_SIZE); - if (!quickcam->frame[0].storedata) - goto open_err_on2; - - quickcam->frame[1].storedata = vmalloc (BAYER_FRAME_SIZE); - if (!quickcam->frame[1].storedata) - goto open_err_on3; - - /* - * Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used - * (when using read()). - */ - quickcam->frame[0].width = 352; - quickcam->frame[0].height = 288; - quickcam->frame[0].bytes_read = 0; - quickcam->frame[1].width = 352; - quickcam->frame[1].height = 288; - quickcam->frame[1].bytes_read = 0; - /* initialise the USB things */ err = quickcam_init_isoc(quickcam); if (err) @@ -1473,71 +1451,29 @@ if (err) goto open_err_init_sensor; - quickcam->user++; - quickcam->grabbing=0; // we are not grabbing. - quickcam->curframe=-1; // no frame in progress. - quickcam->readframe = -1; // no frame beeing read - - up(&quickcam->lock); - - MOD_INC_USE_COUNT; - if (debug&DEBUGLOGIC) - printk("quickcam_open successfull\n"); + fprintf(stderr,"quickcam_open successfull\n"); return 0; open_err_init_sensor: quickcam_stop_isoc(quickcam); open_err_init: - vfree (quickcam->frame[1].storedata); -open_err_on3: - vfree (quickcam->frame[0].storedata); -open_err_on2: - kfree (quickcam->sbuf[1].data); -open_err_on1: - kfree (quickcam->sbuf[0].data); -open_err_on0: - rvfree(quickcam->fbuf, 2 * MAX_FRAME_SIZE); - -out_unlock: - up(&quickcam->lock); if (debug&DEBUGLOGIC) - printk("quickcam_open failed\n"); + fprintf(stderr,"quickcam_open failed\n"); return err; } -static void quickcam_close(struct video_device *dev) +void quickcam_close(struct usb_quickcam *quickcam) { - struct usb_quickcam *quickcam = (struct usb_quickcam *)dev; if (debug&DEBUGLOGIC) - printk("quickcam_close\n"); - down(&quickcam->lock); - quickcam->user--; - - MOD_DEC_USE_COUNT; + fprintf(stderr,"quickcam_close\n"); quickcam_stop_isoc(quickcam); - quickcam->grabbing = 0; // not grabbing. - quickcam->readframe = -1; // no frame beeing read - quickcam->sizechanged = 0; // frame unchanged! - - rvfree(quickcam->fbuf, 2 * MAX_FRAME_SIZE); - kfree(quickcam->sbuf[1].data); - kfree(quickcam->sbuf[0].data); - - vfree(quickcam->frame[1].storedata); - vfree(quickcam->frame[0].storedata); - - up(&quickcam->lock); - - if (!quickcam->dev) { - video_unregister_device(&quickcam->vdev); - kfree(quickcam); - } } +#if 0 /* Cuted by *BSD patch */ static long quickcam_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) { return -EINVAL; @@ -2125,6 +2061,7 @@ ioctl: quickcam_ioctl, mmap: quickcam_mmap, }; +#endif /* Cuted by *BSD patch */ static int usb_quickcam_configure(struct usb_quickcam *quickcam) { @@ -2134,60 +2071,45 @@ /* Set altsetting 0 */ if (usb_set_interface(dev, quickcam->iface, 0) < 0) { - printk("usb_set_interface error\n"); + fprintf(stderr,"usb_set_interface error\n"); return -EBUSY; } if (usb_quickcam_set1(dev, STV_ISO_ENABLE, 0) < 0) { - printk("usb_quickcam_set1 STV_ISO_ENABLE(0) failed\n"); + fprintf(stderr,"usb_quickcam_set1 STV_ISO_ENABLE(0) failed\n"); return -EBUSY; } /* Probe for the sensor type. */ for (sensor = sensors; sensor->name; sensor++) { if (usb_quickcam_set1(dev, STV_REG23, sensor->reg23) < 0) { - printk("usb_quickcam_set1 STV_REG23 failed\n"); + fprintf(stderr,"usb_quickcam_set1 STV_REG23 failed\n"); return -EBUSY; } if (usb_quickcam_get_i2c(dev, sensor->i2c_addr, sensor->id_reg, id, sensor->length_id) < 0) { - printk("usb_quickcam_get_i2c error\n"); + fprintf(stderr,"usb_quickcam_get_i2c error\n"); return -EBUSY; } - printk("quickcam: probe of %s sensor = %02x %02x id: %02x\n", sensor->name, id[0], id[1],sensor->id); + fprintf(stderr,"quickcam: probe of %s sensor = %02x %02x id: %02x\n", sensor->name, id[0], id[1],sensor->id); if (id[sensor->length_id-1] == sensor->id) break; } if (!sensor->name) { - printk("quickcam: unsupported sensor\n"); + fprintf(stderr,"quickcam: unsupported sensor\n"); return -EBUSY; } - printk("quickcam: %s sensor detected\n", sensor->name); + fprintf(stderr,"quickcam: %s sensor detected\n", sensor->name); quickcam->sensor_name = sensor->name; quickcam->sensor_addr = sensor->i2c_addr; sensor->load(&quickcam->sensor_ctrl); - memcpy(&quickcam->vdev, &quickcam_template, sizeof(quickcam_template)); - - init_waitqueue_head(&quickcam->frame[0].wq); - init_waitqueue_head(&quickcam->frame[1].wq); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,5) - if (video_register_device(&quickcam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) -#else - if (video_register_device(&quickcam->vdev, VFL_TYPE_GRABBER) == -1) -#endif - { - printk("video_register_device failed\n"); - return -EBUSY; - } - // Disable data stream. if (usb_quickcam_set1(dev, STV_ISO_ENABLE, 0) < 0) { - printk("usb_quickcam_set1 STV_ISO_ENABLE(1) failed\n"); + fprintf(stderr,"usb_quickcam_set1 STV_ISO_ENABLE(1) failed\n"); goto error; } if (usb_quickcam_set1(dev, STV_REG23, 1) < 0) { /* I see no reason that the others failed if this one is OK */ - printk("usb_quickcam_set1 STV_REG23(1) failed\n"); + fprintf(stderr,"usb_quickcam_set1 STV_REG23(1) failed\n"); goto error; } @@ -2196,57 +2118,36 @@ if(bright<=0 || bright>=65535) bright=EXPO_VAL; quickcam->brightness = bright; quickcam->shutter_val= SHUTTER_VAL; - quickcam->scanstate = STATE_OK; quickcam->x = quickcam->yy=0; - quickcam->readframe = -1; - - // Setup internal video_picture - quickcam->vpic.hue = (rgain -bgain +0xFF) << 7; - quickcam->vpic.colour = ggain; - quickcam->vpic.contrast = 32768; - quickcam->vpic.brightness = bright; - quickcam->vpic.whiteness = 0; - quickcam->vpic.palette = VIDEO_PALETTE_RGB24; - quickcam->vpic.depth = quickcam_get_depth(quickcam); - - // Setup internal video_window - quickcam->vwin.x = 0; - quickcam->vwin.y = 0; - quickcam->vwin.chromakey = 0; - quickcam->vwin.flags = 30; /* 30 fps */ return 0; error: - video_unregister_device(&quickcam->vdev); - usb_driver_release_interface(&quickcam_driver, - &dev->actconfig->interface[0]); return -EBUSY; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static void *quickcam_probe(struct usb_device *dev, -unsigned int ifnum, const struct usb_device_id *id) -#else -static void *quickcam_probe(struct usb_device *dev, -unsigned int ifnum) -#endif +/* + * probe for NetBSD/FreeBSD + */ +void *quickcam_probe(struct usb_device *dev) { - struct usb_interface_descriptor *interface; + usb_device_descriptor_t ddesc; struct usb_quickcam *quickcam; + if (ioctl(dev->fd, USB_GET_DEVICE_DESC, &ddesc) < 0) { + perror("USB_GET_DEVICE_DESC"); + return NULL; + } + dev->descriptor.bNumConfigurations = ddesc.bNumConfigurations; + /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) return NULL; - interface = &dev->actconfig->interface[ifnum].altsetting[0]; - /* Is it a Quickcam? */ - printk("USB Quickcam Class %x SubClass %x idVendor %x idProduct %x\n", - interface->bInterfaceClass, interface->bInterfaceSubClass, - dev->descriptor.idVendor, dev->descriptor.idProduct); + dev->descriptor.idVendor = UGETW(ddesc.idVendor); + dev->descriptor.idProduct = UGETW(ddesc.idProduct); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,255) if (dev->descriptor.idVendor != 0x046d) return NULL; if (dev->descriptor.idProduct != 0x0840 && @@ -2254,42 +2155,43 @@ dev->descriptor.idProduct != 0x0870) return NULL; -#endif + dev->interfacedesc.uid_config_index = USB_CURRENT_CONFIG_INDEX; + dev->interfacedesc.uid_alt_index = USB_CURRENT_ALT_INDEX; + if (ioctl(dev->fd, USB_GET_INTERFACE_DESC, &dev->interfacedesc) < 0) { + perror("USB_GET_INTERFACE_DESC"); + return NULL; + } /* * Checking vendor/product is not enough * In case on Quickcam Web the audio is at class 1 and subclass 1/2. * ono /dev/dsp and one /dev/mixer */ - if (interface->bInterfaceClass != 0xFF) + if (dev->interfacedesc.uid_desc.bInterfaceClass != 0xFF) return NULL; - if (interface->bInterfaceSubClass != 0xFF) + if (dev->interfacedesc.uid_desc.bInterfaceSubClass != 0xFF) return NULL; /* We found a Quickcam */ - printk("USB Quickcam camera found using: %s\n", VERSION); + fprintf(stderr,"USB Quickcam camera found using: %s\n", VERSION); - if ((quickcam = kmalloc(sizeof(*quickcam), GFP_KERNEL)) == NULL) { - printk("couldn't kmalloc quickcam struct\n"); + if ((quickcam = malloc(sizeof(*quickcam))) == NULL) { + perror("couldn't kmalloc quickcam struct\n"); return NULL; } memset(quickcam, 0, sizeof(*quickcam)); quickcam->dev = dev; - quickcam->iface = interface->bInterfaceNumber; - - if (!usb_quickcam_configure(quickcam)) { - quickcam->user=0; - init_MUTEX(&quickcam->lock); /* to 1 == available */ - init_MUTEX(&quickcam->busy_lock); /* to 1 == available */ + quickcam->iface = dev->interfacedesc.uid_desc.bInterfaceNumber; /* not use */ + if (usb_quickcam_configure(quickcam) == 0) { return quickcam; } else { - kfree(quickcam); + free(quickcam); return NULL; } } - +#if 0 /* Cuted by *BSD patch */ static void quickcam_disconnect(struct usb_device *dev, void *ptr) { struct usb_quickcam *quickcam = (struct usb_quickcam *) ptr; @@ -2374,3 +2276,4 @@ module_init(usb_quickcam_init); module_exit(usb_quickcam_cleanup); +#endif /* Cuted by *BSD patch */ diff -urN qce-ga-0.40d/quickcam.h qce-ga-0.40d.new/quickcam.h --- qce-ga-0.40d/quickcam.h Mon Dec 9 18:59:30 2002 +++ qce-ga-0.40d.new/quickcam.h Tue Feb 3 23:55:31 2004 @@ -1,9 +1,13 @@ #ifndef __LINUX_QUICKCAM_H #define __LINUX_QUICKCAM_H +/* from quickcam Linux driver quickcam.h */ +#include "linux_usbif.h" +#if 0 /* Cuted by *BSD patch */ #include #include #include +#endif #define _QUICKCAM_ISOPIPE 0x81 #define SHUTTER_VAL 0x80 @@ -51,6 +55,7 @@ #define QUICKCAM_NUMFRAMES 2 #define QUICKCAM_NUMSBUF 2 +#if 0 /* Cuted by *BSD patch */ /* scanstate */ enum { STATE_OK, // Ok. @@ -72,7 +77,6 @@ FRAME_ERROR, /* Something bad happened while processing */ }; - struct usb_device; struct quickcam_sbuf { @@ -85,6 +89,7 @@ char *name; int supported; }; +#endif /* Cuted by *BSD patch */ /* * Structure filled in for each of the types of sensor (HDCS, PB0100) @@ -119,54 +124,12 @@ unsigned char buff[35]; }; -struct quickcam_frame { - - char *data; /* Frame buffer */ - long scanlength; /* uncompressed, raw data length of frame */ - - char *storedata; /* Bayer data */ - long storelength; /* len of received data */ - - int width; /* Width application is expecting */ - int height; /* Height */ - -// int hdrwidth; /* Width the frame actually is */ -// int hdrheight; /* Height */ - - volatile int grabstate; /* State of grabbing */ - - long bytes_read; /* amount of scanlength that has been read from *data */ - - wait_queue_head_t wq; /* Processes waiting */ -}; - struct usb_quickcam { - struct video_device vdev; /* This _must_ be in the beginning of the structure! */ - - struct video_picture vpic; - struct video_window vwin; - /* Device structure */ struct usb_device *dev; - /* For /proc interface */ - struct proc_dir_entry *proc_entry; - unsigned char iface; - struct semaphore lock; - int user; /* user count for exclusive use */ - - int streaming; /* Are we streaming Isochronous? */ - int grabbing; /* Are we grabbing? */ - int readframe; /* the frame we are reading. */ - - int scanstate; /* state of the automaton */ - - int storestate; /* indicated that we have to wait for the end */ - - int sizechanged; /* indicated size changes */ - int yy; int x; @@ -181,20 +144,6 @@ char *sensor_name; /* for /proc */ unsigned char sensor_addr; /* hdcs and photobit have different addr */ - - char *fbuf; /* Videodev buffer area */ - - int curframe; - struct quickcam_frame frame[QUICKCAM_NUMFRAMES]; /* Double buffering */ - - struct quickcam_sbuf sbuf[QUICKCAM_NUMSBUF]; /* Double buffering */ - - /* Scratch space from the Isochronous pipe */ - unsigned char scratch[SCRATCH_BUF_SIZE]; - int scratchlen; - - struct semaphore busy_lock; /* guard against SMP multithreading */ - struct sensorctrl sensor_ctrl; /* specific routines for a sensor */ }; @@ -203,7 +152,7 @@ struct sensor_data { char *name; - int reg23; + unsigned int reg23; unsigned char i2c_addr; int id_reg; unsigned char id; @@ -229,12 +178,19 @@ unsigned char sensor_add); /* USB interface chip control */ -int usb_quickcam_set1(struct usb_device *dev, short reg, char val); -int usb_quickcam_set2(struct usb_device *dev, short reg, short val); +int usb_quickcam_set1(struct usb_device *dev, unsigned short reg, unsigned char val); +int usb_quickcam_set2(struct usb_device *dev, unsigned short reg, unsigned short val); -/* conversion routines */ -int IsSupported(int format); -void quickcam_convert_image(struct quickcam_frame *frame, int format); -char *FormatName(int format); +/* for main */ +extern void *quickcam_probe(struct usb_device *); +extern int usb_quickcam_start(struct usb_quickcam *quickcam); /* add */ +extern int usb_quickcam_stop(struct usb_quickcam *quickcam); +extern int quickcam_open(struct usb_quickcam *quickcam); +extern void quickcam_close(struct usb_quickcam *quickcam); +extern int usb_quickcam_set_exposure(struct usb_quickcam *quickcam, long val); + +extern int tobgr; +extern int interpolation; +extern int mode; #endif