diff -u usb-stock/Config.in usb/Config.in --- usb-stock/Config.in 2003-06-07 21:50:52.000000000 -0400 +++ usb/Config.in 2003-06-07 21:54:34.000000000 -0400 @@ -82,6 +82,7 @@ comment ' Video4Linux support is needed for USB Multimedia device support' else dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV + dep_tristate ' USB IBM Ultraport II Camera support' CONFIG_USB_ULTRACAM $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV dep_tristate ' USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV diff -u usb-stock/Makefile usb/Makefile --- usb-stock/Makefile 2003-06-07 21:51:08.000000000 -0400 +++ usb/Makefile 2003-06-07 21:55:04.000000000 -0400 @@ -72,7 +72,8 @@ obj-$(CONFIG_USB_AUDIO) += audio.o obj-$(CONFIG_USB_EMI26) += emi26.o obj-$(CONFIG_USB_MIDI) += usb-midi.o -obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o +obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o +obj-$(CONFIG_USB_ULTRACAM) += ultracam.o usbvideo.o obj-$(CONFIG_USB_PWC) += pwc.o obj-$(CONFIG_USB_DC2XX) += dc2xx.o obj-$(CONFIG_USB_MDC800) += mdc800.o diff -u usb-stock/ultracam.c usb/ultracam.c --- usb-stock/ultracam.c 2003-06-07 21:50:32.000000000 -0400 +++ usb/ultracam.c 2003-06-08 16:14:53.000000000 -0400 @@ -1,5 +1,11 @@ -/* - * USB NB Camera driver +/* -*- linux-c -*- + * + * USB NB (Ultraport) Camera driver + * + * Original source by Dmitri + * Updated by Karl Gutwin + * Updated by Jakob Lichtenberg + * Thanks to axel grossklaus */ #include @@ -16,33 +22,42 @@ #define MAX_CAMERAS 4 /* How many devices we allow to connect */ /* - * This structure lives in uvd->user field. + * This structure lives in uvd_t->user field. */ typedef struct { - int initialized; /* Had we already sent init sequence? */ - int camera_model; /* What type of IBM camera we got? */ - int has_hdr; + int initialized; /* Had we already sent init sequence? */ + int camera_model; /* What type of IBM camera we got? */ + int has_hdr; + int bytes_in; /* bytes remaining to read before drop */ + int invert; /* shall we invert the picture? */ + + int rbar, gbar, bbar; /* mean vals for rgb, used for auto wb */ + int projected_whitebal; + int frames_since_adjust; + int ybar; + + } ultracam_t; #define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data)) -static struct usbvideo *cams = NULL; +struct usbvideo *cams = NULL; + +static int debug = 9; -static int debug = 0; +static int ultracam_is_backward(struct uvd *uvd); +static void ultracam_set_white_balance(struct uvd *uvd); static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ static const int min_canvasWidth = 8; static const int min_canvasHeight = 4; -//static int lighting = 1; /* Medium */ +static int whitebal = -1; /* auto whitebal */ +static int wbmaxdelt = 1; #define SHARPNESS_MIN 0 -#define SHARPNESS_MAX 6 -//static int sharpness = 4; /* Low noise, good details */ - -#define FRAMERATE_MIN 0 -#define FRAMERATE_MAX 6 -static int framerate = -1; +#define SHARPNESS_MAX 4 +static int sharpness = 3; /* Low noise, good details */ /* * Here we define several initialization variables. They may @@ -60,9 +75,43 @@ */ static int init_brightness = 128; static int init_contrast = 192; -static int init_color = 128; -static int init_hue = 128; -static int hue_correction = 128; +static int init_sat = 10; +static int init_hue = 180; + +static int brite = 0; +MODULE_PARM(brite, "i"); +MODULE_PARM_DESC(brite, "y adjust: (-255)-(255) (default=0)"); + +static unsigned short hs_0b = 0x002e; +static unsigned short hs_0c = 0x00d6; +static unsigned short hs_0d = 0x00fc; +static unsigned short hs_0e = 0x00f1; +static unsigned short hs_0f = 0x00da; +static unsigned short hs_10 = 0x0036; + +MODULE_PARM(hs_0b, "h"); +MODULE_PARM(hs_0c, "h"); +MODULE_PARM(hs_0d, "h"); +MODULE_PARM(hs_0e, "h"); +MODULE_PARM(hs_0f, "h"); +MODULE_PARM(hs_10, "h"); + +static unsigned short wb_51 = 0xff00; +static unsigned short wb_52 = 0xff00; +static unsigned short wb_53 = 0xff00; +static unsigned short wb_11 = 0xff00; +static unsigned short wb_12 = 0xff00; +static unsigned short wb_13 = 0xff00; + +MODULE_PARM(wb_51, "h"); +MODULE_PARM(wb_52, "h"); +MODULE_PARM(wb_53, "h"); +MODULE_PARM(wb_11, "h"); +MODULE_PARM(wb_12, "h"); +MODULE_PARM(wb_13, "h"); + +static int yuv = 0; +MODULE_PARM(yuv, "i"); MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); @@ -75,40 +124,347 @@ "4=test pattern, " "5=separate frames, " "6=clean frames"); -MODULE_PARM(framerate, "i"); -MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); -MODULE_PARM(lighting, "i"); -MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light"); +MODULE_PARM(whitebal, "i"); +MODULE_PARM_DESC(whitebal, "White balance: 0-48 (0:bluish, 48:reddish) or -1: automatic(default)"); +MODULE_PARM(wbmaxdelt, "i"); +MODULE_PARM_DESC(wbmaxdelt, "White balance maximum delta: 1-48 (1:slow, 48:fast) (default=1)"); MODULE_PARM(sharpness, "i"); -MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)"); +MODULE_PARM_DESC(sharpness, "Sharpness: 0=smooth, 4=sharp (default=3)"); MODULE_PARM(init_brightness, "i"); -MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); +MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128) or -1: automatic"); MODULE_PARM(init_contrast, "i"); MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); -MODULE_PARM(init_color, "i"); -MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)"); +MODULE_PARM(init_sat, "i"); +MODULE_PARM_DESC(init_sat, "Saturation preconfiguration: 0-20 (default=10)"); MODULE_PARM(init_hue, "i"); -MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); -MODULE_PARM(hue_correction, "i"); -MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); +MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-360 (default=180)"); + +MODULE_AUTHOR ("Karl Gutwin"); +MODULE_DESCRIPTION ("IBM Ultracam I/II driver for Linux (c) 2000"); +MODULE_LICENSE("GPL"); /* - * ultracam_ProcessIsocData() + * ultracam_postProcess() * - * Generic routine to parse the ring queue data. It employs either - * ultracam_find_header() or ultracam_parse_lines() to do most - * of work. + * Does various things to the image once it's been + * read in. * - * 02-Nov-2000 First (mostly dummy) version. - * 06-Nov-2000 Rewrote to dump all data into frame. */ -void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) + +static void ultracam_postProcess(struct uvd *uvd, struct usbvideo_frame *frame) { - int n; + ultracam_t *ucam; + char tmp[6]; + int delt; + + if ((uvd == NULL) || (frame == NULL)) + return; + + if ((VIDEOSIZE_X(frame->request) == 0) || (VIDEOSIZE_Y(frame->request) == 0)) + return; + + ucam = ULTRACAM_T(uvd); + + ucam->rbar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request)); + ucam->gbar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request)); + ucam->bbar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request)); + ucam->ybar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request)); + + ucam->frames_since_adjust++; + + if (ucam->frames_since_adjust > 10) { /* module param! */ + ucam->frames_since_adjust = 0; + + if (whitebal < 0) { + /* Auto white balance: + * I noticed that on one end of the white balance scale, + * everything looks very blue (low, 0 end). On the other + * end, everything looks very red (high, 48 end). Therefore, + * this simple algorithm takes the difference between the + * average red and blue values, divides that by two, + * and changes the white balance by that much. + * + * delt is the estimated distance between where we are + * and where we need to be, white-balancy speaking. Since + * always jumping by size delt can cause radical color + * shifts (and because I'm a patient guy) we restrict the + * upper range of delt to wbmaxdelt, a module parameter. + * For quicker responses, increase the value of wbmaxdelt. + * + * -Karl + * + * PS. I know next to nothing about color or imaging... if + * someone out there knows a better solution than this, let + * me know! Thanks... + */ + + delt = ((ucam->bbar - ucam->rbar)>>1); + + if (delt > wbmaxdelt) + delt = wbmaxdelt; + else if ((delt < 0) && (-delt > wbmaxdelt)) + delt = -wbmaxdelt; + + ucam->projected_whitebal += delt; + RESTRICT_TO_RANGE(ucam->projected_whitebal, 0, 48); + + if (debug > 0) + info("Autoadjusting whitebal to %d",ucam->projected_whitebal); + ultracam_set_white_balance(uvd); + } + + } + + /* Optionally display statistics on the screen */ + if (uvd->flags & FLAGS_OVERLAY_STATS) { + usbvideo_OverlayStats(uvd, frame); + + sprintf(tmp, "wb%3d", ucam->projected_whitebal); + usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 100, tmp); + + sprintf(tmp, "r %3d", ucam->rbar); + usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 116, tmp); + sprintf(tmp, "g %3d", ucam->gbar); + usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 124, tmp); + sprintf(tmp, "b %3d", ucam->bbar); + usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 132, tmp); + + sprintf(tmp, "y %3d", ucam->ybar); + usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 148, tmp); + } + + +} - assert(uvd != NULL); - assert(frame != NULL); + + + + +/* + * ultracam_find_header() + * + * Locate one of supported header markers in the queue. + * Once found, remove all preceding bytes AND the marker (8 bytes) + * from the data pump queue. Whatever follows must be video lines. + * + * History: + * 5/16/01 Created. + */ +static enum ParseState ultracam_find_header(struct uvd *uvd, struct usbvideo_frame *frame) +{ + ultracam_t *ucam; + + if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) { + err("ibmcam_find_header: Illegal frame %d.", uvd->curframe); + return scan_EndParse; + } + + ucam = ULTRACAM_T(uvd); + assert(ucam != NULL); + ucam->has_hdr = 0; + /* and start looking for header */ + + while (RingQueue_GetLength(&uvd->dp) >= 8) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0x01) && + (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x19) && + (RING_QUEUE_PEEK(&uvd->dp, 3) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 5) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 6) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 7) == 0x40)) + { +#if 0 /* This code helps to detect new frame markers */ + info("Header sig: 00 01 19 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 4)); +#endif + frame->header = RING_QUEUE_PEEK(&uvd->dp, 7); + if ((frame->header == 0x40)) { +#if 0 + info("Header found."); +#endif + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 8); + ucam->bytes_in = 7; + ucam->has_hdr = 1; + ucam->invert = ultracam_is_backward(uvd); + ucam->rbar = ucam->gbar = ucam->bbar = 0; + break; + } + } + /* If we are still here then this doesn't look like a header */ + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + } + + if (!ucam->has_hdr) { + if (uvd->debug > 2) + info("Skipping frame, no header"); + return scan_EndParse; + } + + /* Header found */ + ucam->has_hdr = 1; + uvd->stats.header_count++; + frame->scanstate = ScanState_Lines; + frame->curline = 0; + + if (flags & FLAGS_FORCE_TESTPATTERN) { + usbvideo_TestPattern(uvd, 1, 1); + return scan_NextFrame; + } + return scan_Continue; +} + +/* + * For some unknown reason, the Ultraport camera sticks a fluke byte into + * the bytestream every 640 bytes. This produces dotted lines on the + * picture, and when left unadjusted, skewed frames. + * This routine simply keeps track of how much we've dequeued so far, + * and drops the 640th byte of the stream. + * -Karl + */ +static int ultracam_Dequeue(struct uvd *uvd, unsigned char *buf, int req) +{ + ultracam_t *ucam; + int left; + ucam = ULTRACAM_T(uvd); + + left = (639 - ucam->bytes_in); + if (req > left) { + RingQueue_Dequeue(&uvd->dp, buf, left); + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + ucam->bytes_in = 0; + /* mmmm... recursion... */ + ultracam_Dequeue(uvd, (buf + left), (req - left)); + } else { + ucam->bytes_in += req; + RingQueue_Dequeue(&uvd->dp, buf, req); + } + + return req; +} + +/* + * ultracam_parse_lines() + * + * Parse one line (interlaced) from the buffer, put + * decoded RGB value into the current frame buffer + * and add the written number of bytes (RGB) to + * the *pcopylen. + * + * History: + * 16-May-2001 Created. + */ + +static enum ParseState ultracam_parse_lines(struct uvd *uvd, struct usbvideo_frame *frame) +{ + /* + * Okay. Data seems to look like this: + * + * |----luma ----|-chroma -| + * |-------------+---------| + * |YYYYYYYY(320)|UUUU(160)|\ + * |YYYYYYYY(320)|VVVV(160)| 240 lines + * |.... ... | ... |/ + * |_____________|_________| + * + * The chroma is overlapped over four pixels to fill out + * the data. + */ + +#if 1 + unsigned char buf[(320*3) + 10]; + unsigned char *yl[2], *ul, *vl; + int tX, tY; + int i, j; + unsigned char r, g, b, y, u, v; + + tX = 320; + tY = 240; + + /* We're actually going to process two lines at once. + * Each chroma byte has to be duplicated over four luma + * bytes. However, in the process of getting the entire + * chroma set, we end up reading in -two- luma lines. + * So... we process them all - it's quicker. + * (on my system, this is faster than Windows! :) + * -Karl + */ + + if (RingQueue_GetLength(&uvd->dp) < ((tX * 3))) + return scan_Out; + + ultracam_Dequeue(uvd, buf, (tX * 3)); + /* RingQueue_Dequeue(&uvd->dp, buf, (tX * 3)); */ + + if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request)) + return scan_NextFrame; + + assert(frame->data != NULL); + yl[0] = buf; + vl = (yl[0] + tX); + yl[1] = (vl + (tX >> 1)); + ul = (yl[1] + tX); + + for (j = 0; j < 2; j++) { + for (i = 0; i < VIDEOSIZE_X(frame->request); i++) { + /* At some point, I would like to scale the video to fit + * the requested window, rather than ignoring the size + * request. + */ + if (i < tX) { + y = yl[j][i]; + u = ul[(i>>1)]; + v = vl[(i>>1)]; + + /* invert around 128 (signed/unsigned conflict?) */ + y += ((y<128)?128:-128); + u += ((u<128)?128:-128); + v += ((v<128)?128:-128); + + y += brite; + } else + y = u = v = 0; + + if (flags & FLAGS_MONOCHROME) { + switch (yuv) { + case 2: + r = g = b = v; + break; + case 1: + r = g = b = u; + break; + case 0: + default: + r = g = b = y; + } + } else { + YUV_TO_RGB_BY_THE_BOOK(y, u, v, r, g, b); + } + /* this is the slow way to put pixels. if you need speed, + * check out how the IBM cam driver does it. + */ + if (ULTRACAM_T(uvd)->invert) { + RGB24_PUTPIXEL(frame, (VIDEOSIZE_X(frame->request)-i-1), (VIDEOSIZE_Y(frame->request)-frame->curline-3), r, g, b); + } else { + RGB24_PUTPIXEL(frame, i, frame->curline, r, g, b); + } + + ULTRACAM_T(uvd)->ybar += y; + ULTRACAM_T(uvd)->rbar += r; + ULTRACAM_T(uvd)->gbar += g; + ULTRACAM_T(uvd)->bbar += b; + } + frame->curline++; + } + + if (frame->curline >= VIDEOSIZE_Y(frame->request)) + return scan_NextFrame; + else + return scan_Continue; + +#else + + int n; + unsigned char buf; /* Try to move data from queue into frame buffer */ n = RingQueue_GetLength(&uvd->dp); @@ -116,21 +472,76 @@ int m; /* See how much spare we have left */ m = uvd->max_frame_size - frame->seqRead_Length; - if (n > m) - n = m; + if (n > (m/3)) + n = (m/3); /* Now move that much data into frame buffer */ - RingQueue_Dequeue( - &uvd->dp, - frame->data + frame->seqRead_Length, - m); - frame->seqRead_Length += m; + while (n > 0) { + ultracam_Dequeue(uvd, &buf, 1); + n--; + frame->data[frame->seqRead_Length] = buf; + frame->seqRead_Length++; + frame->data[frame->seqRead_Length] = buf; + frame->seqRead_Length++; + frame->data[frame->seqRead_Length] = buf; + frame->seqRead_Length++; + } } /* See if we filled the frame */ if (frame->seqRead_Length >= uvd->max_frame_size) { frame->frameState = FrameState_Done; uvd->curframe = -1; uvd->stats.frame_num++; + return scan_NextFrame; } + + return scan_Continue; + +#endif +} + + + +/* + * ultracam_ProcessIsocData() + * + * Generic routine to parse the ring queue data. It employs either + * ultracam_find_header() or ultracam_parse_lines() to do most + * of work. + * + * 02-Nov-2000 First (mostly dummy) version. + * 06-Nov-2000 Rewrote to dump all data into frame. + * 16-May-2001 Rewrote to use find_header and parse_lines. + */ +void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) +{ + /* int n; */ + enum ParseState pstate; + + assert(uvd != NULL); + assert(frame != NULL); + + while (1) { + pstate = scan_Out; + if (frame->scanstate == ScanState_Scanning) { + pstate = ultracam_find_header(uvd, frame); + } else if (frame->scanstate == ScanState_Lines) { + pstate = ultracam_parse_lines(uvd, frame); + } + + if (pstate == scan_Continue) + continue; + else if ((pstate == scan_NextFrame) || (pstate == scan_Out)) + break; + else + return; + } + + if (pstate == scan_NextFrame) { + frame->frameState = FrameState_Done; + uvd->curframe = -1; + uvd->stats.frame_num++; + } + } /* @@ -144,16 +555,18 @@ unsigned char req, unsigned short value, unsigned short index, - int is_out) + unsigned char *is_out) { static const char proc[] = "ultracam_veio"; +#if 0 unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; +#endif int i; if (!CAMERA_IS_OPERATIONAL(uvd)) return 0; - if (!is_out) { + if (is_out) { i = usb_control_msg( uvd->dev, usb_rcvctrlpipe(uvd->dev, 0), @@ -161,14 +574,14 @@ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, - cp, - sizeof(cp), + is_out, + 2, HZ); -#if 1 +#if 0 info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " - "(req=$%02x val=$%04x ind=$%04x)", - cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], - req, value, index); + "(req=$%02x val=$%04x ind=$%04x)", + cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], + req, value, index); #endif } else { i = usb_control_msg( @@ -190,12 +603,26 @@ return i; } +static int ultracam_alternateSetting(struct uvd *uvd, int setting) +{ + static const char proc[] = "ultracam_alternateSetting"; + int i; + i = usb_set_interface(uvd->dev, uvd->iface, setting); + if (i < 0) { + err("%s: usb_set_interface error", proc); + uvd->last_error = i; + return -EBUSY; + } + return 0; +} + /* * ultracam_calculate_fps() */ static int ultracam_calculate_fps(struct uvd *uvd) { - return 3 + framerate*4 + framerate/2; + /* camera does not tell me, so I guess, no? */ + return 30; /* YEAH RIGHT! more like 5... */ } /* @@ -206,21 +633,112 @@ } /* - * ultracam_change_lighting_conditions() + * ultracam_set_white_balance() */ -static void ultracam_change_lighting_conditions(struct uvd *uvd) +static void ultracam_set_white_balance(struct uvd *uvd) { + int wb; + /* white balance codes to send to cam (sniffed from Windows) */ + unsigned short *wbp; + unsigned short whitebalcodes[49 * 6] = { + 0x0034, 0x003f, 0x00da, 0x00ff, 0x0002, 0x00f5, + 0x0035, 0x003f, 0x00d6, 0x00ff, 0x0002, 0x00f5, + 0x0036, 0x003f, 0x00d3, 0x00ff, 0x0002, 0x00f5, + 0x0037, 0x003f, 0x00cf, 0x00ff, 0x0002, 0x00f5, + 0x0038, 0x003f, 0x00cc, 0x00ff, 0x0002, 0x00f5, + 0x0038, 0x003f, 0x00c8, 0x00ff, 0x0002, 0x00f5, + 0x0039, 0x003f, 0x00c5, 0x00ff, 0x0002, 0x00f5, + 0x003a, 0x003f, 0x00c1, 0x00ff, 0x0002, 0x00f5, + 0x003b, 0x003f, 0x00be, 0x0000, 0x0002, 0x00f6, + 0x003c, 0x003f, 0x00ba, 0x0000, 0x0002, 0x00f6, + 0x003d, 0x003f, 0x00b6, 0x0000, 0x0002, 0x00f6, + 0x003e, 0x003f, 0x00b3, 0x0000, 0x0002, 0x00f6, + 0x003f, 0x003f, 0x00af, 0x0001, 0x0002, 0x00f6, + 0x003f, 0x003f, 0x00ac, 0x0001, 0x0002, 0x00f6, + 0x0040, 0x003f, 0x00a8, 0x0001, 0x0002, 0x00f6, + 0x0041, 0x003f, 0x00a5, 0x0001, 0x0002, 0x00f6, + 0x0042, 0x003f, 0x00a1, 0x0001, 0x0002, 0x00f6, + 0x0045, 0x003f, 0x009f, 0x0001, 0x0002, 0x00f6, + 0x0049, 0x003f, 0x009d, 0x0001, 0x0002, 0x00f6, + 0x004c, 0x003f, 0x009b, 0x0000, 0x0002, 0x00f7, + 0x004f, 0x003f, 0x009a, 0x0000, 0x0003, 0x00f7, + 0x0053, 0x003f, 0x0098, 0x00ff, 0x0003, 0x00f7, + 0x0056, 0x003f, 0x0096, 0x00ff, 0x0003, 0x00f7, + 0x0059, 0x003f, 0x0094, 0x00ff, 0x0003, 0x00f7, + 0x005d, 0x003f, 0x0092, 0x00ff, 0x0003, 0x00f8, + 0x0060, 0x003f, 0x0090, 0x00ff, 0x0003, 0x00f8, + 0x0063, 0x003f, 0x008e, 0x00ff, 0x0003, 0x00f8, + 0x0066, 0x003f, 0x008c, 0x00fe, 0x0003, 0x00f8, + 0x006a, 0x003f, 0x008b, 0x00fe, 0x0004, 0x00f8, + 0x006d, 0x003f, 0x0089, 0x00fe, 0x0004, 0x00f8, + 0x0070, 0x003f, 0x0087, 0x00fe, 0x0004, 0x00f9, + 0x0074, 0x003f, 0x0085, 0x00fd, 0x0004, 0x00f9, + 0x0077, 0x003f, 0x0083, 0x00fd, 0x0004, 0x00f9, + 0x0078, 0x003f, 0x007f, 0x00fd, 0x0004, 0x00f9, + 0x007a, 0x003f, 0x007b, 0x00fd, 0x0004, 0x00fa, + 0x007b, 0x003f, 0x0077, 0x00fc, 0x0004, 0x00fa, + 0x007d, 0x003f, 0x0073, 0x00fc, 0x0004, 0x00fa, + 0x007e, 0x003f, 0x006f, 0x00fc, 0x0003, 0x00fa, + 0x007f, 0x003f, 0x006b, 0x00fc, 0x0003, 0x00fb, + 0x0081, 0x003f, 0x0067, 0x00fb, 0x0003, 0x00fb, + 0x0082, 0x0040, 0x0064, 0x00fb, 0x0003, 0x00fb, + 0x0083, 0x0040, 0x0060, 0x00fb, 0x0003, 0x00fb, + 0x0085, 0x0040, 0x005c, 0x00fb, 0x0003, 0x00fc, + 0x0086, 0x0040, 0x0058, 0x00fa, 0x0003, 0x00fc, + 0x0088, 0x0040, 0x0054, 0x00fa, 0x0003, 0x00fc, + 0x0089, 0x0040, 0x0050, 0x00fa, 0x0002, 0x00fc, + 0x008a, 0x0040, 0x004c, 0x00fa, 0x0002, 0x00fd, + 0x008c, 0x0040, 0x0048, 0x00f9, 0x0002, 0x00fd, + 0x008d, 0x0040, 0x0044, 0x00f9, 0x0002, 0x00fd + }; + /* I'm trying to figure out what + * these codes actually mean. Some hints may + * include rgb or yuv gain within the camera + * itself, but it doesn't make a whole lot of + * sense, since some values change a lot, some + * hardly change at all, and none is precisely + * linear or even suggests a coordinating function + * (Yes, I plotted the values out. They're not + * linear.) + * + * Any ideas? + * -Karl + */ + + RESTRICT_TO_RANGE(whitebal, -1, 48); + + if (whitebal >= 0) + wb = whitebal; + else + wb = ULTRACAM_T(uvd)->projected_whitebal; + + wbp = whitebalcodes + (wb*6); + + ultracam_veio(uvd, 0x01, ((wb_51==0xff00)?*wbp:wb_51), 0x0051, NULL); wbp++; + ultracam_veio(uvd, 0x01, ((wb_52==0xff00)?*wbp:wb_52), 0x0052, NULL); wbp++; + ultracam_veio(uvd, 0x01, ((wb_53==0xff00)?*wbp:wb_53), 0x0053, NULL); wbp++; + ultracam_veio(uvd, 0x01, ((wb_11==0xff00)?*wbp:wb_11), 0x0011, NULL); wbp++; + ultracam_veio(uvd, 0x01, ((wb_12==0xff00)?*wbp:wb_12), 0x0012, NULL); wbp++; + ultracam_veio(uvd, 0x01, ((wb_13==0xff00)?*wbp:wb_13), 0x0013, NULL); + } /* * ultracam_set_sharpness() * - * Cameras model 1 have internal smoothing feature. It is controlled by value in - * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). - * Recommended value is 4. Cameras model 2 do not have this feature at all. + * Cameras have internal smoothing feature. It is controlled by value in + * range [0..4], where 0 is most smooth and 4 is most sharp (raw image, I guess). + * Recommended value is 3. */ static void ultracam_set_sharpness(struct uvd *uvd) { + unsigned char buf[2]; + unsigned short sharps[SHARPNESS_MAX + 1] = { 0x0004, 0x0024, 0x0064, 0x00a4, 0x00e4 }; + + RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); + ultracam_veio(uvd, 0x01, 0x0000, 0x0001, buf); + ultracam_veio(uvd, 0x01, sharps[sharpness], 0x0001, NULL); + } /* @@ -236,6 +754,9 @@ { } + + + /* * ultracam_adjust_picture() * @@ -257,6 +778,13 @@ */ static void ultracam_video_stop(struct uvd *uvd) { + /* I think it's this... */ + ultracam_veio(uvd, 0x02, 0x0000, 0x0001, NULL); + ultracam_alternateSetting(uvd, 0x00); + ultracam_veio(uvd, 0x01, 0x0000, 0x0001, NULL); + ultracam_veio(uvd, 0x02, 0x0003, 0x0000, NULL); + ultracam_veio(uvd, 0x02, 0x0000, 0x0005, NULL); + } /* @@ -272,8 +800,12 @@ static void ultracam_video_start(struct uvd *uvd) { - ultracam_change_lighting_conditions(uvd); - ultracam_set_sharpness(uvd); + // ultracam_change_lighting_conditions(uvd); + /* this is doing no good here... looks like + * sharpness is set on camera init. + ultracam_set_sharpness(uvd); + */ + ultracam_reinit_iso(uvd, 0); } @@ -283,17 +815,21 @@ return 0; } -static int ultracam_alternateSetting(struct uvd *uvd, int setting) + +static int ultracam_is_backward(struct uvd *uvd) { - static const char proc[] = "ultracam_alternateSetting"; - int i; - i = usb_set_interface(uvd->dev, uvd->iface, setting); - if (i < 0) { - err("%s: usb_set_interface error", proc); - uvd->last_error = i; - return -EBUSY; + unsigned char buf[2]; + + ultracam_veio(uvd, 0x02, 0x0000, 0x000b, buf); + if (buf[1] == 0x05) { + if (debug > 2) + info("Camera is facing forward [%02x %02x]",buf[0],buf[1]); + return 0; + } else { + if (debug > 2) + info("Camera is facing backward [%02x %02x]",buf[0],buf[1]); + return 1; } - return 0; } /* @@ -301,188 +837,237 @@ */ static int ultracam_setup_on_open(struct uvd *uvd) { + unsigned char buf[2]; + int setup_ok = 0; /* Success by default */ + + ULTRACAM_T(uvd)->projected_whitebal = 20; + /* Send init sequence only once, it's large! */ if (!ULTRACAM_T(uvd)->initialized) { ultracam_alternateSetting(uvd, 0x04); ultracam_alternateSetting(uvd, 0x00); - ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1); - ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1); - ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1); - ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1); - ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1); - ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1); - ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1); - ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1); - ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1); - ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1); - ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1); - ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1); - ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1); - ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1); - ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1); - ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1); - ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1); - ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1); - ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1); - ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1); - ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1); - ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1); - ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1); - ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1); - ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1); - ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); - ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0); - ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0); - ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); - ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); - ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); - ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); - ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); - ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); - ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); - ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); - ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0); - ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1); - ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1); - ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1); - ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1); - ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1); - ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1); - ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1); - ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); - ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1); - ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1); - ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1); + ultracam_veio(uvd, 0x02, 0x0004, 0x000b, NULL); + ultracam_veio(uvd, 0x02, 0x0001, 0x0005, NULL); + ultracam_veio(uvd, 0x02, 0x8000, 0x0000, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x0000, NULL); + ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x0002, NULL); + ultracam_veio(uvd, 0x00, 0x000c, 0x0003, NULL); + ultracam_veio(uvd, 0x00, 0x000b, 0x0004, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x0005, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x0006, NULL); + ultracam_veio(uvd, 0x00, 0x0079, 0x0007, NULL); + ultracam_veio(uvd, 0x00, 0x003b, 0x0008, NULL); + ultracam_veio(uvd, 0x00, 0x0002, 0x000f, NULL); + ultracam_veio(uvd, 0x00, 0x0001, 0x0010, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x0011, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, NULL); + ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, NULL); + ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, NULL); + ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, NULL); + ultracam_veio(uvd, 0x01, 0x0010, 0x0002, NULL); + ultracam_veio(uvd, 0x01, 0x0066, 0x0007, NULL); + ultracam_veio(uvd, 0x01, 0x000b, 0x0008, NULL); + ultracam_veio(uvd, 0x01, 0x0034, 0x0009, NULL); + ultracam_veio(uvd, 0x01, 0x0000, 0x000a, NULL); + ultracam_veio(uvd, 0x01, 0x002e, 0x000b, NULL); + ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, NULL); + ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, NULL); + ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, NULL); + ultracam_veio(uvd, 0x01, 0x00da, 0x000f, NULL); + ultracam_veio(uvd, 0x01, 0x0036, 0x0010, NULL); + ultracam_veio(uvd, 0x01, 0x000b, 0x0011, NULL); + ultracam_veio(uvd, 0x01, 0x0001, 0x0012, NULL); + ultracam_veio(uvd, 0x01, 0x0000, 0x0013, NULL); + ultracam_veio(uvd, 0x01, 0x0000, 0x0014, NULL); + ultracam_veio(uvd, 0x01, 0x0087, 0x0051, NULL); + ultracam_veio(uvd, 0x01, 0x0040, 0x0052, NULL); + ultracam_veio(uvd, 0x01, 0x0058, 0x0053, NULL); + ultracam_veio(uvd, 0x01, 0x0040, 0x0054, NULL); + ultracam_veio(uvd, 0x01, 0x0000, 0x0040, NULL); + ultracam_veio(uvd, 0x01, 0x0010, 0x0041, NULL); + ultracam_veio(uvd, 0x01, 0x0020, 0x0042, NULL); + ultracam_veio(uvd, 0x01, 0x0030, 0x0043, NULL); + ultracam_veio(uvd, 0x01, 0x0040, 0x0044, NULL); + ultracam_veio(uvd, 0x01, 0x0050, 0x0045, NULL); + ultracam_veio(uvd, 0x01, 0x0060, 0x0046, NULL); + ultracam_veio(uvd, 0x01, 0x0070, 0x0047, NULL); + ultracam_veio(uvd, 0x01, 0x0080, 0x0048, NULL); + ultracam_veio(uvd, 0x01, 0x0090, 0x0049, NULL); + ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, NULL); + ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, NULL); + ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, NULL); + ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, NULL); + ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, NULL); + ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, NULL); + ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, NULL); + ultracam_veio(uvd, 0x01, 0x0000, 0x0056, NULL); + ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, NULL); + ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, NULL); + ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, NULL); + ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL); + ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL); + + /* command mode? */ + ultracam_veio(uvd, 0x02, 0xc040, 0x0001, NULL); + + /* read in hue/sat? */ + ultracam_veio(uvd, 0x01, 0x0000, 0x0008, buf); + info("hs_read: 0x08 -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x0009, buf); + info("hs_read: 0x09 -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x000a, buf); + info("hs_read: 0x0a -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x000b, buf); + info("hs_read: 0x0b -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x000c, buf); + info("hs_read: 0x0c -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x000d, buf); + info("hs_read: 0x0d -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x000e, buf); + info("hs_read: 0x0e -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x000f, buf); + info("hs_read: 0x0f -- 0x%x", buf[0]); + ultracam_veio(uvd, 0x01, 0x0000, 0x0010, buf); + info("hs_read: 0x10 -- 0x%x", buf[0]); + + /* hue/saturation */ + ultracam_veio(uvd, 0x01, 0x000b, 0x0008, NULL); + ultracam_veio(uvd, 0x01, 0x0034, 0x0009, NULL); + ultracam_veio(uvd, 0x01, 0x0000, 0x000a, NULL); + + ultracam_veio(uvd, 0x01, hs_0b, 0x000b, NULL); + ultracam_veio(uvd, 0x01, hs_0c, 0x000c, NULL); + ultracam_veio(uvd, 0x01, hs_0d, 0x000d, NULL); + ultracam_veio(uvd, 0x01, hs_0e, 0x000e, NULL); + ultracam_veio(uvd, 0x01, hs_0f, 0x000f, NULL); + ultracam_veio(uvd, 0x01, hs_10, 0x0010, NULL); + + /* sharpness + ultracam_veio(uvd, 0x01, 0x0000, 0x0001, buf); + ultracam_veio(uvd, 0x01, 0x0064, 0x0001, NULL); + */ + ultracam_set_sharpness(uvd); + + /* white balance */ + ultracam_set_white_balance(uvd); + /* + ultracam_veio(uvd, 0x01, wb_51, 0x0051, NULL); + ultracam_veio(uvd, 0x01, wb_52, 0x0052, NULL); + ultracam_veio(uvd, 0x01, wb_53, 0x0053, NULL); + ultracam_veio(uvd, 0x01, wb_11, 0x0011, NULL); + ultracam_veio(uvd, 0x01, wb_12, 0x0012, NULL); + ultracam_veio(uvd, 0x01, wb_13, 0x0013, NULL); + */ + + + /* here I have >>>>>> 0x0007 (unknown setting?) */ + ultracam_veio(uvd, 0x00, 0x0009, 0x0011, NULL); + + ultracam_veio(uvd, 0x00, 0x0000, 0x0001, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x0000, NULL); + + /* on my system, these look like this: + * 0x00 0x001b 0x00c1 + * 0x00 0x00e0 0x00c2 + * 0x00 0x0000 0x00ca + * some unknown values? + * -Karl + */ + ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, NULL); + ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, NULL); + ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL); + ultracam_alternateSetting(uvd, 0x04); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1); - ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1); - ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1); - ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0); + ultracam_veio(uvd, 0x02, 0x0000, 0x0001, NULL); + ultracam_veio(uvd, 0x02, 0x0000, 0x0001, NULL); + ultracam_veio(uvd, 0x02, 0x0000, 0x0006, NULL); + + /* resolution */ + ultracam_veio(uvd, 0x02, 0x9000, 0x0007, NULL); + + /* turn on camera? */ + ultracam_veio(uvd, 0x02, 0x0042, 0x0001, NULL); + + ultracam_is_backward(uvd); ultracam_resetPipe(uvd); ULTRACAM_T(uvd)->initialized = (setup_ok != 0); + } return setup_ok; } @@ -494,14 +1079,14 @@ RESTRICT_TO_RANGE(init_brightness, 0, 255); RESTRICT_TO_RANGE(init_contrast, 0, 255); - RESTRICT_TO_RANGE(init_color, 0, 255); - RESTRICT_TO_RANGE(init_hue, 0, 255); - RESTRICT_TO_RANGE(hue_correction, 0, 255); + RESTRICT_TO_RANGE(init_sat, 0, 20); + RESTRICT_TO_RANGE(init_hue, 0, 360); + RESTRICT_TO_RANGE(wbmaxdelt, 1, 48); memset(&uvd->vpic, 0, sizeof(uvd->vpic)); memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); - uvd->vpic.colour = init_color << 8; + uvd->vpic.colour = init_sat << 8; uvd->vpic.hue = init_hue << 8; uvd->vpic.brightness = init_brightness << 8; uvd->vpic.contrast = init_contrast << 8; @@ -510,7 +1095,7 @@ uvd->vpic.palette = VIDEO_PALETTE_RGB24; memset(&uvd->vcap, 0, sizeof(uvd->vcap)); - strcpy(uvd->vcap.name, "IBM Ultra Camera"); + strcpy(uvd->vcap.name, "IBM Ultraport Camera"); uvd->vcap.type = VID_TYPE_CAPTURE; uvd->vcap.channels = 1; uvd->vcap.audios = 0; @@ -628,7 +1213,7 @@ MOD_INC_USE_COUNT; uvd = usbvideo_AllocateDevice(cams); if (uvd != NULL) { - /* Here uvd is a fully allocated uvd object */ + /* Here uvd is a fully allocated struct uvd object */ uvd->flags = flags; uvd->debug = debug; uvd->dev = dev; @@ -639,13 +1224,14 @@ uvd->iso_packet_len = maxPS; uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; uvd->defaultPalette = VIDEO_PALETTE_RGB24; - uvd->canvas = VIDEOSIZE(640, 480); /* FIXME */ + uvd->canvas = VIDEOSIZE(320, 240); /* FIXME */ uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/ /* Initialize ibmcam-specific data */ assert(ULTRACAM_T(uvd) != NULL); ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */ ULTRACAM_T(uvd)->initialized = 0; + ULTRACAM_T(uvd)->bytes_in = 0; ultracam_configure_video(uvd); @@ -659,11 +1245,12 @@ return uvd; } - -static struct usb_device_id id_table[] = { +static __devinitdata struct usb_device_id id_table[] = { { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, { } /* Terminating entry */ }; +MODULE_DEVICE_TABLE(usb, id_table); + /* * ultracam_init() @@ -679,7 +1266,7 @@ cbTbl.videoStart = ultracam_video_start; cbTbl.videoStop = ultracam_video_stop; cbTbl.processData = ultracam_ProcessIsocData; - cbTbl.postProcess = usbvideo_DeinterlaceFrame; + cbTbl.postProcess = ultracam_postProcess; cbTbl.adjustPicture = ultracam_adjust_picture; cbTbl.getFPS = ultracam_calculate_fps; return usbvideo_register( @@ -697,8 +1284,5 @@ usbvideo_Deregister(&cams); } -MODULE_DEVICE_TABLE(usb, id_table); -MODULE_LICENSE("GPL"); - module_init(ultracam_init); module_exit(ultracam_cleanup); diff -u usb-stock/usbvideo.c usb/usbvideo.c --- usb-stock/usbvideo.c 2003-06-08 16:20:19.000000000 -0400 +++ usb/usbvideo.c 2003-06-07 21:52:40.000000000 -0400 @@ -267,7 +267,7 @@ void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame, int x, int y, int ch) { - static const unsigned short digits[16] = { + static const unsigned short digits[36] = { 0xF6DE, /* 0 */ 0x2492, /* 1 */ 0xE7CE, /* 2 */ @@ -283,7 +283,27 @@ 0xF24E, /* c */ 0xD6DC, /* d */ 0xF34E, /* e */ - 0xF348 /* f */ + 0xF348, /* f */ + 0xf2de, /* g */ + 0xb7da, /* h */ + 0xe92e, /* i */ + 0xe92c, /* j */ + 0xb75a, /* k */ + 0x924e, /* l */ + 0xbeda, /* m */ + 0xd6da, /* n */ + 0x56d4, /* o */ + 0xf7c8, /* p */ + 0xf6fe, /* q */ + 0xf75a, /* r */ + 0x739c, /* s */ + 0xe924, /* t */ + 0xb6de, /* u */ + 0xb6d4, /* v */ + 0xb6fa, /* w */ + 0xb55a, /* x */ + 0xb524, /* y */ + 0xe54e /* z */ }; unsigned short digit; int ix, iy; @@ -293,9 +313,9 @@ if (ch >= '0' && ch <= '9') ch -= '0'; - else if (ch >= 'A' && ch <= 'F') + else if (ch >= 'A' && ch <= 'Z') ch = 10 + (ch - 'A'); - else if (ch >= 'a' && ch <= 'f') + else if (ch >= 'a' && ch <= 'z') ch = 10 + (ch - 'a'); else return; @@ -305,7 +325,7 @@ for (ix=0; ix < 3; ix++) { if (digit & 0x8000) { if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) { -/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); +/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xff, 0xff, 0xff); } } digit = digit << 1; @@ -403,51 +423,53 @@ } } - sprintf(tmp, "%8lx", uvd->stats.frame_num); + usbvideo_OverlayString(uvd, frame, qi_x1 + 8, qi_y1 + 2, "ring buffer fill"); + + sprintf(tmp, "%8lx fr", uvd->stats.frame_num); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8lx", uvd->stats.urb_count); + sprintf(tmp, "%8lx uc", uvd->stats.urb_count); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8lx", uvd->stats.urb_length); + sprintf(tmp, "%8lx ul", uvd->stats.urb_length); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8lx", uvd->stats.data_count); + sprintf(tmp, "%8lx dc", uvd->stats.data_count); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8lx", uvd->stats.header_count); + sprintf(tmp, "%8lx hc", uvd->stats.header_count); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8lx", uvd->stats.iso_skip_count); + sprintf(tmp, "%8lx is", uvd->stats.iso_skip_count); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8lx", uvd->stats.iso_err_count); + sprintf(tmp, "%8lx ie", uvd->stats.iso_err_count); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8x", uvd->vpic.colour); + sprintf(tmp, "%8x co", uvd->vpic.colour); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8x", uvd->vpic.hue); + sprintf(tmp, "%8x hu", uvd->vpic.hue); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8x", uvd->vpic.brightness >> 8); + sprintf(tmp, "%8x br", uvd->vpic.brightness >> 8); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8x", uvd->vpic.contrast >> 12); + sprintf(tmp, "%8x pi", uvd->vpic.contrast >> 12); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; - sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8); + sprintf(tmp, "%8d wh", uvd->vpic.whiteness >> 8); usbvideo_OverlayString(uvd, frame, x, y, tmp); y += y_diff; }