/* * Sonix SN9C101 based webcam Image capture Program for NetBSD ver.0.2 * Copyright (C) 2004 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. * */ /* * Credits: * Special Thanks to Sonix SN9C102 based webcam driver Project developers. * * Thanks to Windows USb Sniffer Project developers. */ #include #include #include #include #include #include #include #include #include #include "sonix.h" /** Prototype definition **/ int dump_isoc(int); static void outputppm(unsigned char *, int, int); #define SONIX_ID 0x0c45 static struct usb_dev_info devslist [] = { { "Tama Electronic Corp. Z-102/Sweex USB MiniWebcam", SONIX_ID, 0x6005, 0x6005}, { NULL } }; static char dev[FILENAME_MAX]; static char epdevname[FILENAME_MAX]; #define IMAGE_SIZE (WIDTH*HEIGHT*DEPTH) #define STORE_BUFSIZE (IMAGE_SIZE*3) unsigned char isobuf[ISOBUF_SIZE]; /* raw isochronous transfer data packet */ unsigned char storebuf[STORE_BUFSIZE]; unsigned char scratch[IMAGE_SIZE]; /* image buffer */ int main(int argc, char *argv[]) { int i; int ret, retry; int fd = 0; int efd = 0; int id = -1; /* check option */ if (argc == 1) { for ( i = 0; i < 15; ++i ) { #ifdef __FreeBSD__ sprintf(dev, "/dev/ugen%d", i); #else sprintf(dev, "/dev/ugen%d.00", i); #endif if ( (fd = open(dev, O_RDWR)) < 0 ) { continue; } if ( (id = usbdev_probe(fd, devslist)) < 0 ) { close(fd); 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 ( (fd = open(dev, O_RDWR)) < 0 ) { err(1, "%s", dev); } else { if ( (id = usbdev_probe(fd, devslist)) < 0 ) { close(fd); fd = -1; } } } if (fd < 0) { fprintf(stderr, "Not found USB camera, or Permission denied\n"); return 1; } /* init */ ret = -1; for ( retry = 0; retry < 2; retry++ ) { if ( sonix_init(fd, id) >= 0 ) break; fprintf(stderr, "init fail, try again.\n"); } if ( retry == 2 ) goto BYE; fprintf(stderr, "init success\n"); memset((void *)isobuf, 0, ISOBUF_SIZE); memset((void *)storebuf, 0, STORE_BUFSIZE); memset((void *)scratch, 0, IMAGE_SIZE); /* open endpoint */ #ifdef __FreeBSD__ sprintf(epdevname, "%s.1", dev); #else sprintf(epdevname, "%s.01", strtok(dev,".")); #endif if ((efd = open(epdevname, O_RDONLY)) < 0) { perror(epdevname); goto BYE; } #define EXPOSURE_TIME 15 fprintf(stderr,"say cheese!"); for ( i = 0; i < EXPOSURE_TIME; i++ ) { fprintf(stderr,"...%d ",i); ret = dump_isoc(efd); if ((ret > 0) && (i > 9)) { fprintf(stderr,"\n"); bayer2rgb24(scratch, storebuf, ret); outputppm(scratch, WIDTH, HEIGHT); break; } } close(efd); BYE: close(fd); return ret; } int dump_isoc(int fd) { int offset; enum { FRAME_NONE = 0, FRAME_READING, FRAME_READY, FRAME_ERROR } frame_stat = FRAME_NONE; ssize_t grablen; ssize_t readlen; /* return value of read(2) */ unsigned char *isop; grablen = 0; for (;;) { isop = isobuf; readlen = read(fd, (void *)isop, ISOBUF_SIZE); if ( frame_stat == FRAME_READY ) { break; /* end */ } if ( readlen <= 0 ) { perror("read"); return -1; } if ( grablen + readlen > STORE_BUFSIZE ) { fprintf(stderr,"isoc read data overflow = %d\n", grablen); return -1; } if ( frame_stat != FRAME_READING ) { frame_stat = FRAME_NONE; /* search header */ offset = find_header(isop, readlen); if ( offset < 0 ) { /* igonore data */ continue; } if ((isop[offset+SNX_SEQ_OFFSET] != SNX_HDR_SOI) && (isop[offset+SNX_SEQ_OFFSET] != SNX_HDR_SOI2) ) { /* igonore data */ continue; } if ( (readlen-offset-SNX_SKIPHEADER_LEN) > 0 ) { memcpy(storebuf+grablen, (isop+offset+SNX_SKIPHEADER_LEN), (readlen-offset-SNX_SKIPHEADER_LEN)); } grablen = readlen - offset - SNX_SKIPHEADER_LEN; frame_stat = FRAME_READING; } else { /* search header on buffer head */ if ( (offset = find_header(isop, SNX_SKIPHEADER_LEN)) >= 0 ) { /* found header on buffer head */ if ((isop[offset+SNX_SEQ_OFFSET] == SNX_HDR_EOI) || (isop[offset+SNX_SEQ_OFFSET] == SNX_HDR_EOI2)) { /* end of image buffer */ frame_stat = FRAME_READY; break; } else { /* skip header */ isop += (offset+SNX_SKIPHEADER_LEN); readlen -= (offset+SNX_SKIPHEADER_LEN); } if ( readlen <= 0 ) continue; } /* search header on buffer tail */ if ( (offset = find_header(isop+readlen-SNX_SKIPHEADER_LEN, SNX_SKIPHEADER_LEN)) >= 0 ) { /* found header on buffer tail */ memcpy(storebuf+grablen, isop, readlen-SNX_SKIPHEADER_LEN); grablen += (readlen-SNX_SKIPHEADER_LEN); if ((isop[offset+SNX_SEQ_OFFSET] == SNX_HDR_EOI) || (isop[offset+SNX_SEQ_OFFSET] == SNX_HDR_EOI2)) { /* end of image buffer */ frame_stat = FRAME_READY; break; } } else { /* not found, copy all data */ memcpy(storebuf+grablen, isop, readlen); grablen += readlen; } } } return grablen; } static void outputppm(unsigned char *src, int width, int height) { int i; int totalsize; if ( src == NULL || width <= 0 || height <= 0 ) return; totalsize = ( (width*height*DEPTH) > IMAGE_SIZE ) ? IMAGE_SIZE : (width*height*DEPTH); printf("P6\n"); printf("%d %d 255 ", width, height); for ( i = 0; i < totalsize; i+=3 ) { printf("%c%c%c", src[i], src[i+1], src[i+2]); } return; }