home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / usbd0906.zip / usb_20020906.zip / usbcalls / samples / ultracam / ultracam.cpp next >
C/C++ Source or Header  |  2001-11-15  |  45KB  |  1,468 lines

  1. /* -*- linux-c -*-
  2.  *
  3.  * USB NB (Ultraport) Camera driver
  4.  *
  5.  * Original source by Dmitri
  6.  * Updated by Karl Gutwin <karl@gutwin.org>
  7.  * Updated by Jakob Lichtenberg <jl@itu.dk>
  8.  * Thanks to axel grossklaus <axel@nomaden.org>
  9.  
  10. #include <linux/kernel.h>
  11. #include <linux/sched.h>
  12. #include <linux/wrapper.h>
  13. #include <linux/module.h>
  14. #include <linux/init.h>
  15. */
  16.  
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <conio.h>
  22. #define INCL_DOS
  23. #include <os2.h>
  24. #include "..\..\usbcalls.h"
  25. #include "usbvideo.h"
  26.  
  27.  
  28. #define    ULTRACAM_VENDOR_ID    0x0461
  29. #define    ULTRACAM_PRODUCT_ID    0x0813
  30.  
  31. #define MAX_CAMERAS        4    /* How many devices we allow to connect */
  32.  
  33. /*
  34.  * This structure lives in uvd_t->user field.
  35.  */
  36. typedef struct
  37. {
  38.   int initialized;  /* Had we already sent init sequence? */
  39.   int camera_model; /* What type of IBM camera we got? */
  40.   int has_hdr;
  41.   int bytes_in;         /* bytes remaining to read before drop */
  42.   int invert;           /* shall we invert the picture? */
  43.  
  44.   int rbar, gbar, bbar; /* mean vals for rgb, used for auto wb */
  45.   int projected_whitebal;
  46.   int frames_since_adjust;
  47.   int ybar;
  48.  
  49.  
  50. } ultracam_t;
  51. #define    ULTRACAM_T(uvd)    ((ultracam_t *)((uvd)->user_data))
  52.  
  53. usbvideo_t *cams = NULL;
  54.  
  55. static int debug = 9;
  56.  
  57. static int ultracam_is_backward(uvd_t *uvd);
  58. static void ultracam_set_white_balance(uvd_t *uvd);
  59.  
  60. static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
  61.  
  62. static const int min_canvasWidth  = 8;
  63. static const int min_canvasHeight = 4;
  64.  
  65. static int whitebal = -1; /* auto whitebal */
  66. static int wbmaxdelt = 1;
  67.  
  68. #define SHARPNESS_MIN    0
  69. #define SHARPNESS_MAX    4
  70. static int sharpness = 3; /* Low noise, good details */
  71.  
  72. /*
  73.  * Here we define several initialization variables. They may
  74.  * be used to automatically set color, hue, brightness and
  75.  * contrast to desired values. This is particularly useful in
  76.  * case of webcams (which have no controls and no on-screen
  77.  * output) and also when a client V4L software is used that
  78.  * does not have some of those controls. In any case it's
  79.  * good to have startup values as options.
  80.  *
  81.  * These values are all in [0..255] range. This simplifies
  82.  * operation. Note that actual values of V4L variables may
  83.  * be scaled up (as much as << 8). User can see that only
  84.  * on overlay output, however, or through a V4L client.
  85.  */
  86. static int init_brightness = 128;
  87. static int init_contrast = 192;
  88. static int init_sat = 10;
  89. static int init_hue = 180;
  90.  
  91.  
  92. #define MODULE_PARM(X,Y)
  93. #define MODULE_PARM_DESC(X,Y)
  94.  
  95. static int brite = 0;
  96. MODULE_PARM(brite, "i");
  97. MODULE_PARM_DESC(brite, "y adjust: (-255)-(255) (default=0)");
  98.  
  99. static unsigned short hs_0b = 0x002e;
  100. static unsigned short hs_0c = 0x00d6;
  101. static unsigned short hs_0d = 0x00fc;
  102. static unsigned short hs_0e = 0x00f1;
  103. static unsigned short hs_0f = 0x00da;
  104. static unsigned short hs_10 = 0x0036;
  105.  
  106. MODULE_PARM(hs_0b, "h");
  107. MODULE_PARM(hs_0c, "h");
  108. MODULE_PARM(hs_0d, "h");
  109. MODULE_PARM(hs_0e, "h");
  110. MODULE_PARM(hs_0f, "h");
  111. MODULE_PARM(hs_10, "h");
  112.  
  113. static unsigned short wb_51 = 0xff00;
  114. static unsigned short wb_52 = 0xff00;
  115. static unsigned short wb_53 = 0xff00;
  116. static unsigned short wb_11 = 0xff00;
  117. static unsigned short wb_12 = 0xff00;
  118. static unsigned short wb_13 = 0xff00;
  119.  
  120. MODULE_PARM(wb_51, "h");
  121. MODULE_PARM(wb_52, "h");
  122. MODULE_PARM(wb_53, "h");
  123. MODULE_PARM(wb_11, "h");
  124. MODULE_PARM(wb_12, "h");
  125. MODULE_PARM(wb_13, "h");
  126.  
  127. static int yuv = 0;
  128. MODULE_PARM(yuv, "i");
  129.  
  130. MODULE_PARM(debug, "i");
  131. MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
  132. MODULE_PARM(flags, "i");
  133. MODULE_PARM_DESC(flags,
  134.                  "Bitfield: 0=VIDIOCSYNC, "
  135.                  "1=B/W, "
  136.                  "2=show hints, "
  137.                  "3=show stats, "
  138.                  "4=test pattern, "
  139.                  "5=separate frames, "
  140.                  "6=clean frames");
  141. MODULE_PARM(whitebal, "i");
  142. MODULE_PARM_DESC(whitebal, "White balance: 0-48 (0:bluish, 48:reddish) or -1: automatic(default)");
  143. MODULE_PARM(wbmaxdelt, "i");
  144. MODULE_PARM_DESC(wbmaxdelt, "White balance maximum delta: 1-48 (1:slow, 48:fast) (default=1)");
  145. MODULE_PARM(sharpness, "i");
  146. MODULE_PARM_DESC(sharpness, "Sharpness: 0=smooth, 4=sharp (default=3)");
  147.  
  148. MODULE_PARM(init_brightness, "i");
  149. MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128) or -1: automatic");
  150. MODULE_PARM(init_contrast, "i");
  151. MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
  152. MODULE_PARM(init_sat, "i");
  153. MODULE_PARM_DESC(init_sat, "Saturation preconfiguration: 0-20 (default=10)");
  154. MODULE_PARM(init_hue, "i");
  155. MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-360 (default=180)");
  156.  
  157.  
  158. #if 0
  159.  
  160.  
  161.  
  162. /*
  163.  * ultracam_postProcess()
  164.  *
  165.  * Does various and sundried things to the image once it's been
  166.  * read in.
  167.  *
  168.  */
  169. static void ultracam_postProcess(uvd_t *uvd, usbvideo_frame_t *frame)
  170. {
  171.   ultracam_t *ucam;
  172.   char tmp[6];
  173.   int delt;
  174.  
  175.   if ((uvd == NULL) || (frame == NULL))
  176.     return;
  177.  
  178.   if ((VIDEOSIZE_X(frame->request) == 0) || (VIDEOSIZE_Y(frame->request) == 0))
  179.     return;
  180.  
  181.   ucam = ULTRACAM_T(uvd);
  182.  
  183.   ucam->rbar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request));
  184.   ucam->gbar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request));
  185.   ucam->bbar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request));
  186.   ucam->ybar /= (VIDEOSIZE_X(frame->request)*VIDEOSIZE_Y(frame->request));
  187.  
  188.   ucam->frames_since_adjust++;
  189.  
  190.   if (ucam->frames_since_adjust > 10)
  191.   { /* module param! */
  192.     ucam->frames_since_adjust = 0;
  193.  
  194.     if (whitebal < 0)
  195.     {
  196.       /* Auto white balance:
  197.        * I noticed that on one end of the white balance scale, 
  198.        * everything looks very blue (low, 0 end). On the other
  199.        * end, everything looks very red (high, 48 end). Therefore,
  200.        * this simple algorithm takes the difference between the
  201.        * average red and blue values, divides that by two,
  202.        * and changes the white balance by that much.
  203.        *
  204.        * delt is the estimated distance between where we are
  205.        * and where we need to be, white-balancy speaking. Since
  206.        * always jumping by size delt can cause radical color
  207.        * shifts (and because I'm a patient guy) we restrict the
  208.        * upper range of delt to wbmaxdelt, a module parameter.
  209.        * For quicker responses, increase the value of wbmaxdelt.
  210.        * 
  211.        * -Karl
  212.        * 
  213.        * PS. I know next to nothing about color or imaging... if
  214.        * someone out there knows a better solution than this, let
  215.        * me know! Thanks...
  216.        */
  217.  
  218.       delt = ((ucam->bbar - ucam->rbar)>>1);
  219.  
  220.       if (delt > wbmaxdelt)
  221.         delt = wbmaxdelt;
  222.       else if ((delt < 0) && (-delt > wbmaxdelt))
  223.         delt = -wbmaxdelt;
  224.  
  225.       ucam->projected_whitebal += delt;
  226.       RESTRICT_TO_RANGE(ucam->projected_whitebal, 0, 48);
  227.  
  228.       if (debug > 0)
  229.         printf("Autoadjusting whitebal to %d",ucam->projected_whitebal);
  230.       ultracam_set_white_balance(uvd);
  231.     }
  232.  
  233.   }
  234.  
  235.   /* Optionally display statistics on the screen */
  236.   if (uvd->flags & FLAGS_OVERLAY_STATS)
  237.   {
  238.     usbvideo_OverlayStats(uvd, frame);
  239.  
  240.     sprintf(tmp, "wb%3d", ucam->projected_whitebal);
  241.     usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 100, tmp);
  242.  
  243.     sprintf(tmp, "r %3d", ucam->rbar);
  244.     usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 116, tmp);
  245.     sprintf(tmp, "g %3d", ucam->gbar);
  246.     usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 124, tmp);
  247.     sprintf(tmp, "b %3d", ucam->bbar);
  248.     usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 132, tmp);
  249.  
  250.     sprintf(tmp, "y %3d", ucam->ybar);
  251.     usbvideo_OverlayString(uvd, frame, (VIDEOSIZE_X(frame->request) - 30), 148, tmp);
  252.   }
  253.  
  254.  
  255. }
  256.  
  257.  
  258.  
  259.  
  260.  
  261. /*
  262.  * ultracam_find_header()
  263.  *
  264.  * Locate one of supported header markers in the queue.
  265.  * Once found, remove all preceding bytes AND the marker (8 bytes)
  266.  * from the data pump queue. Whatever follows must be video lines.
  267.  *
  268.  * History:
  269.  * 5/16/01  Created.
  270.  */
  271. static ParseState_t ultracam_find_header(uvd_t *uvd, usbvideo_frame_t *frame)
  272. {
  273.   ultracam_t *ucam;
  274.  
  275.   if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES))
  276.   {
  277.     err("ibmcam_find_header: Illegal frame %d.", uvd->curframe);
  278.     return scan_EndParse;
  279.   }
  280.  
  281.   ucam = ULTRACAM_T(uvd);
  282.   assert(ucam != NULL);
  283.   ucam->has_hdr = 0;
  284.   /* and start looking for header */
  285.  
  286.   while (RingQueue_GetLength(&uvd->dp) >= 8)
  287.   {
  288.     if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
  289.         (RING_QUEUE_PEEK(&uvd->dp, 1) == 0x01) &&
  290.         (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x19) &&
  291.         (RING_QUEUE_PEEK(&uvd->dp, 3) == 0x00) &&
  292.         (RING_QUEUE_PEEK(&uvd->dp, 5) == 0x00) &&
  293.         (RING_QUEUE_PEEK(&uvd->dp, 6) == 0x00) &&
  294.         (RING_QUEUE_PEEK(&uvd->dp, 7) == 0x40))
  295.     {
  296.   #if 0                /* This code helps to detect new frame markers */
  297.       printf("Header sig: 00 01 19 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 4));
  298.   #endif
  299.       frame->header = RING_QUEUE_PEEK(&uvd->dp, 7);
  300.       if ((frame->header == 0x40))
  301.       {
  302.   #if 0
  303.         printf("Header found.");
  304.   #endif
  305.         RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 8);
  306.         ucam->bytes_in = 7;
  307.         ucam->has_hdr = 1;
  308.         ucam->invert = ultracam_is_backward(uvd);
  309.         ucam->rbar = ucam->gbar = ucam->bbar = 0;
  310.         break;
  311.       }
  312.     }
  313.     /* If we are still here then this doesn't look like a header */
  314.     RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
  315.   }
  316.  
  317.   if (!ucam->has_hdr)
  318.   {
  319.     if (uvd->debug > 2)
  320.       printf("Skipping frame, no header");
  321.     return scan_EndParse;
  322.   }
  323.  
  324.   /* Header found */
  325.   ucam->has_hdr = 1;
  326.   uvd->stats.header_count++;
  327.   frame->scanstate = ScanState_Lines;
  328.   frame->curline = 0;
  329.  
  330.   if (flags & FLAGS_FORCE_TESTPATTERN)
  331.   {
  332.     usbvideo_TestPattern(uvd, 1, 1);
  333.     return scan_NextFrame;
  334.   }
  335.   return scan_Continue;
  336. }
  337.  
  338. /*
  339.  * For some unknown reason, the Ultraport camera sticks a fluke byte into
  340.  * the bytestream every 640 bytes. This produces dotted lines on the
  341.  * picture, and when left unadjusted, skewed frames.
  342.  * This routine simply keeps track of how much we've dequeued so far,
  343.  * and drops the 640th byte of the stream.
  344.  * -Karl
  345.  */
  346. static int ultracam_Dequeue(uvd_t *uvd, unsigned char *buf, int req)
  347. {
  348.   ultracam_t *ucam;
  349.   int left;
  350.   ucam = ULTRACAM_T(uvd);
  351.  
  352.   left = (639 - ucam->bytes_in);
  353.   if (req > left)
  354.   {
  355.     RingQueue_Dequeue(&uvd->dp, buf, left);
  356.     RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
  357.     ucam->bytes_in = 0;
  358.     /* mmmm... recursion... <drool> */
  359.     ultracam_Dequeue(uvd, (buf + left), (req - left));
  360.   }
  361.   else
  362.   {
  363.     ucam->bytes_in += req;
  364.     RingQueue_Dequeue(&uvd->dp, buf, req);
  365.   } 
  366.  
  367.   return req;
  368. }
  369.  
  370. /*
  371.  * ultracam_parse_lines()
  372.  *
  373.  * Parse one line (interlaced) from the buffer, put
  374.  * decoded RGB value into the current frame buffer
  375.  * and add the written number of bytes (RGB) to
  376.  * the *pcopylen.
  377.  *
  378.  * History:
  379.  * 16-May-2001 Created.
  380.  */
  381.  
  382. static ParseState_t ultracam_parse_lines(uvd_t *uvd, usbvideo_frame_t *frame)
  383. {
  384.   /*
  385.    * Okay. Data seems to look like this:
  386.    *
  387.    * |----luma ----|-chroma -|
  388.    * |-------------+---------|
  389.    * |YYYYYYYY(320)|UUUU(160)|\
  390.    * |YYYYYYYY(320)|VVVV(160)| 240 lines
  391.    * |....     ... |  ...    |/
  392.    * |_____________|_________|
  393.    *
  394.    * The chroma is overlapped over four pixels to fill out
  395.    * the data.
  396.    */
  397.  
  398.   #if 1
  399.   unsigned char buf[(320*3) + 10];
  400.   unsigned char *yl[2], *ul, *vl;
  401.   int tX, tY;
  402.   int i, j;
  403.   unsigned char r, g, b, y, u, v;
  404.  
  405.   tX = 320;
  406.   tY = 240;
  407.  
  408.   /* We're actually going to process two lines at once.
  409.    * Each chroma byte has to be duplicated over four luma
  410.    * bytes. However, in the process of getting the entire 
  411.    * chroma set, we end up reading in -two- luma lines.
  412.    * So... we process them all - it's quicker.
  413.    * (on my system, this is faster than Windows! :)
  414.    * -Karl
  415.    */
  416.  
  417.   if (RingQueue_GetLength(&uvd->dp) < ((tX * 3)))
  418.     return scan_Out;
  419.  
  420.   ultracam_Dequeue(uvd, buf, (tX * 3)); 
  421.   /*  RingQueue_Dequeue(&uvd->dp, buf, (tX * 3)); */
  422.  
  423.   if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
  424.     return scan_NextFrame;
  425.  
  426.   assert(frame->data != NULL);
  427.   yl[0] = buf;
  428.   vl    = (yl[0] + tX);
  429.   yl[1] = (vl    + (tX >> 1));
  430.   ul    = (yl[1] + tX);
  431.  
  432.   for (j = 0; j < 2; j++)
  433.   {
  434.     for (i = 0; i < VIDEOSIZE_X(frame->request); i++)
  435.     {
  436.       /* At some point, I would like to scale the video to fit
  437.        * the requested window, rather than ignoring the size
  438.        * request.
  439.        */
  440.       if (i < tX)
  441.       {
  442.         y = yl[j][i];
  443.         u = ul[(i>>1)];
  444.         v = vl[(i>>1)];
  445.  
  446.         /* invert around 128 (signed/unsigned conflict?) */
  447.         y += ((y<128)?128:-128);
  448.         u += ((u<128)?128:-128);
  449.         v += ((v<128)?128:-128);
  450.  
  451.         y += brite;
  452.       }
  453.       else
  454.         y = u = v = 0;
  455.  
  456.       if (flags & FLAGS_MONOCHROME)
  457.       {
  458.         switch (yuv)
  459.         {
  460.           case 2:
  461.             r = g = b = v;
  462.             break;
  463.           case 1:
  464.             r = g = b = u;
  465.             break;
  466.           case 0:
  467.           default:
  468.             r = g = b = y;
  469.         }
  470.       }
  471.       else
  472.       {
  473.         YUV_TO_RGB_BY_THE_BOOK(y, u, v, r, g, b);
  474.       }
  475.       /* this is the slow way to put pixels. if you need speed,
  476.        * check out how the IBM cam driver does it.
  477.        */
  478.       if (ULTRACAM_T(uvd)->invert)
  479.       {
  480.         RGB24_PUTPIXEL(frame, (VIDEOSIZE_X(frame->request)-i-1), (VIDEOSIZE_Y(frame->request)-frame->curline-3), r, g, b);
  481.       }
  482.       else
  483.       {
  484.         RGB24_PUTPIXEL(frame, i, frame->curline, r, g, b);
  485.       }
  486.  
  487.       ULTRACAM_T(uvd)->ybar += y;
  488.       ULTRACAM_T(uvd)->rbar += r;
  489.       ULTRACAM_T(uvd)->gbar += g;
  490.       ULTRACAM_T(uvd)->bbar += b;
  491.     }
  492.     frame->curline++;
  493.   }
  494.  
  495.   if (frame->curline >= VIDEOSIZE_Y(frame->request))
  496.     return scan_NextFrame;
  497.   else
  498.     return scan_Continue;
  499.  
  500.   #else
  501.  
  502.   int n;
  503.   unsigned char buf;
  504.  
  505.   /* Try to move data from queue into frame buffer */
  506.   n = RingQueue_GetLength(&uvd->dp);
  507.   if (n > 0)
  508.   {
  509.     int m;
  510.     /* See how much spare we have left */
  511.     m = uvd->max_frame_size - frame->seqRead_Length;
  512.     if (n > (m/3))
  513.       n = (m/3);
  514.     /* Now move that much data into frame buffer */
  515.     while (n > 0)
  516.     {
  517.       ultracam_Dequeue(uvd, &buf, 1);
  518.       n--;
  519.       frame->data[frame->seqRead_Length] = buf;
  520.       frame->seqRead_Length++;
  521.       frame->data[frame->seqRead_Length] = buf;
  522.       frame->seqRead_Length++;
  523.       frame->data[frame->seqRead_Length] = buf;
  524.       frame->seqRead_Length++;
  525.     }
  526.   }
  527.   /* See if we filled the frame */
  528.   if (frame->seqRead_Length >= uvd->max_frame_size)
  529.   {
  530.     frame->frameState = FrameState_Done;
  531.     uvd->curframe = -1;
  532.     uvd->stats.frame_num++;
  533.     return scan_NextFrame;
  534.   }
  535.  
  536.   return scan_Continue;
  537.  
  538.   #endif
  539. }
  540.  
  541.  
  542.  
  543. /*
  544.  * ultracam_ProcessIsocData()
  545.  *
  546.  * Generic routine to parse the ring queue data. It employs either
  547.  * ultracam_find_header() or ultracam_parse_lines() to do most
  548.  * of work.
  549.  *
  550.  * 02-Nov-2000 First (mostly dummy) version.
  551.  * 06-Nov-2000 Rewrote to dump all data into frame.
  552.  * 16-May-2001 Rewrote to use find_header and parse_lines.
  553.  */
  554. void ultracam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame)
  555. {
  556.   /*  int n; */
  557.   ParseState_t pstate;
  558.  
  559.   assert(uvd != NULL);
  560.   assert(frame != NULL);
  561.  
  562.   while (1)
  563.   {
  564.     pstate = scan_Out;
  565.     if (frame->scanstate == ScanState_Scanning)
  566.     {
  567.       pstate = ultracam_find_header(uvd, frame);
  568.     }
  569.     else if (frame->scanstate == ScanState_Lines)
  570.     {
  571.       pstate = ultracam_parse_lines(uvd, frame);
  572.     }
  573.  
  574.     if (pstate == scan_Continue)
  575.       continue;
  576.     else if ((pstate == scan_NextFrame) || (pstate == scan_Out))
  577.       break;
  578.     else
  579.       return;
  580.   }
  581.  
  582.   if (pstate == scan_NextFrame)
  583.   {
  584.     frame->frameState = FrameState_Done;
  585.     uvd->curframe = -1;
  586.     uvd->stats.frame_num++;
  587.   }
  588.  
  589. }
  590. #endif
  591.  
  592. /*
  593.  * ultracam_veio()
  594.  *
  595.  * History:
  596.  * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
  597.  */
  598.  
  599. #define HZ 1000
  600. #define usb_rcvctrlpipe(X,Y) Y
  601. #define usb_control_msg(h,P,R,Rt,V,I,D,L,T) UsbCtrlMessage( h, Rt, R, V, I, L, D, T)
  602.  
  603. static int ultracam_veio(
  604.                         uvd_t *uvd,
  605.                         unsigned char req,
  606.                         unsigned short value,
  607.                         unsigned short index,
  608.                         unsigned char *is_out)
  609. {
  610.   static const char proc[] = "ultracam_veio";
  611.   #if 0
  612.   unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
  613.   #endif
  614.   int i;
  615.  
  616.   if (!CAMERA_IS_OPERATIONAL(uvd))
  617.     return 0;
  618.  
  619.   if (is_out)
  620.   {
  621.     i = usb_control_msg(
  622.                        uvd->dev,
  623.                        usb_rcvctrlpipe(uvd->dev, 0),
  624.                        req,
  625.                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  626.                        value,
  627.                        index,
  628.                        is_out,
  629.                        2,
  630.                        HZ);
  631.   #if 0
  632.     printf("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
  633.          "(req=$%02x val=$%04x ind=$%04x)",
  634.          cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
  635.          req, value, index);
  636.   #endif
  637.   }
  638.   else
  639.   {
  640.     i = usb_control_msg(
  641.                        uvd->dev,
  642.                        usb_sndctrlpipe(uvd->dev, 0),
  643.                        req,
  644.                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  645.                        value,
  646.                        index,
  647.                        NULL,
  648.                        0,
  649.                        HZ);
  650.   }
  651.   if (i )
  652.   {
  653.     printf("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
  654.         proc, i);
  655.     uvd->last_error = i;
  656.   }
  657.   return i;
  658. }
  659.  
  660. #define usb_set_interface(H,I,S) UsbInterfaceSetAltSetting(H,I,S)
  661.  
  662. static int ultracam_alternateSetting(uvd_t *uvd, int setting)
  663. {
  664.   static const char proc[] = "ultracam_alternateSetting";
  665.   int i;
  666.   i = usb_set_interface(uvd->dev, uvd->iface, setting);
  667.   if (i )
  668.   {
  669.     printf("%s: usb_set_interface error\n", proc);
  670.     uvd->last_error = i;
  671.     return -1;//EBUSY;
  672.   }
  673.   return 0;
  674. }
  675.  
  676. /*
  677.  * ultracam_calculate_fps()
  678.  */
  679. static int ultracam_calculate_fps(uvd_t *uvd)
  680. {
  681.   /* camera does not tell me, so I guess, no? */
  682.   return 30; /* YEAH RIGHT! more like 5... */
  683. }
  684.  
  685. /*
  686.  * ultracam_adjust_contrast()
  687.  */
  688. static void ultracam_adjust_contrast(uvd_t *uvd)
  689. {
  690. }
  691.  
  692. /*
  693.  * ultracam_set_white_balance()
  694.  */
  695. static void ultracam_set_white_balance(uvd_t *uvd)
  696. {
  697.   int wb;
  698.   /* white balance codes to send to cam (sniffed from Windows) */
  699.   unsigned short *wbp;
  700.   unsigned short whitebalcodes[49 * 6] = {
  701.     0x0034, 0x003f, 0x00da, 0x00ff, 0x0002, 0x00f5, 
  702.     0x0035, 0x003f, 0x00d6, 0x00ff, 0x0002, 0x00f5, 
  703.     0x0036, 0x003f, 0x00d3, 0x00ff, 0x0002, 0x00f5, 
  704.     0x0037, 0x003f, 0x00cf, 0x00ff, 0x0002, 0x00f5, 
  705.     0x0038, 0x003f, 0x00cc, 0x00ff, 0x0002, 0x00f5, 
  706.     0x0038, 0x003f, 0x00c8, 0x00ff, 0x0002, 0x00f5, 
  707.     0x0039, 0x003f, 0x00c5, 0x00ff, 0x0002, 0x00f5, 
  708.     0x003a, 0x003f, 0x00c1, 0x00ff, 0x0002, 0x00f5, 
  709.     0x003b, 0x003f, 0x00be, 0x0000, 0x0002, 0x00f6, 
  710.     0x003c, 0x003f, 0x00ba, 0x0000, 0x0002, 0x00f6, 
  711.     0x003d, 0x003f, 0x00b6, 0x0000, 0x0002, 0x00f6, 
  712.     0x003e, 0x003f, 0x00b3, 0x0000, 0x0002, 0x00f6, 
  713.     0x003f, 0x003f, 0x00af, 0x0001, 0x0002, 0x00f6, 
  714.     0x003f, 0x003f, 0x00ac, 0x0001, 0x0002, 0x00f6, 
  715.     0x0040, 0x003f, 0x00a8, 0x0001, 0x0002, 0x00f6, 
  716.     0x0041, 0x003f, 0x00a5, 0x0001, 0x0002, 0x00f6, 
  717.     0x0042, 0x003f, 0x00a1, 0x0001, 0x0002, 0x00f6, 
  718.     0x0045, 0x003f, 0x009f, 0x0001, 0x0002, 0x00f6, 
  719.     0x0049, 0x003f, 0x009d, 0x0001, 0x0002, 0x00f6, 
  720.     0x004c, 0x003f, 0x009b, 0x0000, 0x0002, 0x00f7, 
  721.     0x004f, 0x003f, 0x009a, 0x0000, 0x0003, 0x00f7, 
  722.     0x0053, 0x003f, 0x0098, 0x00ff, 0x0003, 0x00f7, 
  723.     0x0056, 0x003f, 0x0096, 0x00ff, 0x0003, 0x00f7, 
  724.     0x0059, 0x003f, 0x0094, 0x00ff, 0x0003, 0x00f7, 
  725.     0x005d, 0x003f, 0x0092, 0x00ff, 0x0003, 0x00f8, 
  726.     0x0060, 0x003f, 0x0090, 0x00ff, 0x0003, 0x00f8, 
  727.     0x0063, 0x003f, 0x008e, 0x00ff, 0x0003, 0x00f8, 
  728.     0x0066, 0x003f, 0x008c, 0x00fe, 0x0003, 0x00f8, 
  729.     0x006a, 0x003f, 0x008b, 0x00fe, 0x0004, 0x00f8, 
  730.     0x006d, 0x003f, 0x0089, 0x00fe, 0x0004, 0x00f8, 
  731.     0x0070, 0x003f, 0x0087, 0x00fe, 0x0004, 0x00f9, 
  732.     0x0074, 0x003f, 0x0085, 0x00fd, 0x0004, 0x00f9, 
  733.     0x0077, 0x003f, 0x0083, 0x00fd, 0x0004, 0x00f9, 
  734.     0x0078, 0x003f, 0x007f, 0x00fd, 0x0004, 0x00f9, 
  735.     0x007a, 0x003f, 0x007b, 0x00fd, 0x0004, 0x00fa, 
  736.     0x007b, 0x003f, 0x0077, 0x00fc, 0x0004, 0x00fa, 
  737.     0x007d, 0x003f, 0x0073, 0x00fc, 0x0004, 0x00fa, 
  738.     0x007e, 0x003f, 0x006f, 0x00fc, 0x0003, 0x00fa, 
  739.     0x007f, 0x003f, 0x006b, 0x00fc, 0x0003, 0x00fb, 
  740.     0x0081, 0x003f, 0x0067, 0x00fb, 0x0003, 0x00fb, 
  741.     0x0082, 0x0040, 0x0064, 0x00fb, 0x0003, 0x00fb, 
  742.     0x0083, 0x0040, 0x0060, 0x00fb, 0x0003, 0x00fb, 
  743.     0x0085, 0x0040, 0x005c, 0x00fb, 0x0003, 0x00fc, 
  744.     0x0086, 0x0040, 0x0058, 0x00fa, 0x0003, 0x00fc, 
  745.     0x0088, 0x0040, 0x0054, 0x00fa, 0x0003, 0x00fc, 
  746.     0x0089, 0x0040, 0x0050, 0x00fa, 0x0002, 0x00fc, 
  747.     0x008a, 0x0040, 0x004c, 0x00fa, 0x0002, 0x00fd, 
  748.     0x008c, 0x0040, 0x0048, 0x00f9, 0x0002, 0x00fd, 
  749.     0x008d, 0x0040, 0x0044, 0x00f9, 0x0002, 0x00fd 
  750.   };
  751.   /* I'm trying to figure out what
  752.    * these codes actually mean. Some hints may
  753.    * include rgb or yuv gain within the camera
  754.    * itself, but it doesn't make a whole lot of
  755.    * sense, since some values change a lot, some
  756.    * hardly change at all, and none is precisely
  757.    * linear or even suggests a coordinating function
  758.    * (Yes, I plotted the values out. They're not
  759.    * linear.)
  760.    *
  761.    * Any ideas?
  762.    * -Karl
  763.    */
  764.  
  765.   RESTRICT_TO_RANGE(whitebal, -1, 48);
  766.  
  767.   if (whitebal >= 0)
  768.     wb = whitebal;
  769.   else
  770.     wb = ULTRACAM_T(uvd)->projected_whitebal;
  771.  
  772.   wbp = whitebalcodes + (wb*6);
  773.  
  774.   ultracam_veio(uvd, 0x01, ((wb_51==0xff00)?*wbp:wb_51), 0x0051, NULL); wbp++;
  775.   ultracam_veio(uvd, 0x01, ((wb_52==0xff00)?*wbp:wb_52), 0x0052, NULL); wbp++;
  776.   ultracam_veio(uvd, 0x01, ((wb_53==0xff00)?*wbp:wb_53), 0x0053, NULL); wbp++;
  777.   ultracam_veio(uvd, 0x01, ((wb_11==0xff00)?*wbp:wb_11), 0x0011, NULL); wbp++;
  778.   ultracam_veio(uvd, 0x01, ((wb_12==0xff00)?*wbp:wb_12), 0x0012, NULL); wbp++;
  779.   ultracam_veio(uvd, 0x01, ((wb_13==0xff00)?*wbp:wb_13), 0x0013, NULL);
  780.  
  781. }
  782.  
  783. /*
  784.  * ultracam_set_sharpness()
  785.  *
  786.  * Cameras have internal smoothing feature. It is controlled by value in
  787.  * range [0..4], where 0 is most smooth and 4 is most sharp (raw image, I guess).
  788.  * Recommended value is 3. 
  789.  */
  790. static void ultracam_set_sharpness(uvd_t *uvd)
  791. {
  792.   unsigned char buf[2];
  793.   unsigned short sharps[SHARPNESS_MAX + 1] = { 0x0004, 0x0024, 0x0064, 0x00a4, 0x00e4};
  794.  
  795.   RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
  796.   ultracam_veio(uvd, 0x01, 0x0000, 0x0001, buf);
  797.   ultracam_veio(uvd, 0x01, sharps[sharpness], 0x0001, NULL);
  798.  
  799. }
  800.  
  801. /*
  802.  * ultracam_set_brightness()
  803.  *
  804.  * This procedure changes brightness of the picture.
  805.  */
  806. static void ultracam_set_brightness(uvd_t *uvd)
  807. {
  808. }
  809.  
  810. static void ultracam_set_hue(uvd_t *uvd)
  811. {
  812. }
  813.  
  814.  
  815.  
  816.  
  817. /*
  818.  * ultracam_adjust_picture()
  819.  *
  820.  * This procedure gets called from V4L interface to update picture settings.
  821.  * Here we change brightness and contrast.
  822.  */
  823. static void ultracam_adjust_picture(uvd_t *uvd)
  824. {
  825.   ultracam_adjust_contrast(uvd);
  826.   ultracam_set_brightness(uvd);
  827.   ultracam_set_hue(uvd);
  828. }
  829.  
  830. /*
  831.  * ultracam_video_stop()
  832.  *
  833.  * This code tells camera to stop streaming. The interface remains
  834.  * configured and bandwidth - claimed.
  835.  */
  836. static void ultracam_video_stop(uvd_t *uvd)
  837. {
  838.   /* I think it's this... */
  839.   ultracam_veio(uvd, 0x02, 0x0000, 0x0001, NULL);
  840.   ultracam_alternateSetting(uvd, 0x00);
  841.   ultracam_veio(uvd, 0x01, 0x0000, 0x0001, NULL);
  842.   ultracam_veio(uvd, 0x02, 0x0003, 0x0000, NULL);
  843.   ultracam_veio(uvd, 0x02, 0x0000, 0x0005, NULL);
  844.  
  845. }
  846.  
  847. /*
  848.  * ultracam_reinit_iso()
  849.  *
  850.  * This procedure sends couple of commands to the camera and then
  851.  * resets the video pipe. This sequence was observed to reinit the
  852.  * camera or, at least, to initiate ISO data stream.
  853.  */
  854. static void ultracam_reinit_iso(uvd_t *uvd, int do_stop)
  855. {
  856. }
  857.  
  858. static void ultracam_video_start(uvd_t *uvd)
  859. {
  860.   //    ultracam_change_lighting_conditions(uvd);
  861.   /* this is doing no good here... looks like 
  862.    * sharpness is set on camera init.
  863.         ultracam_set_sharpness(uvd);
  864.    */
  865.  
  866.   ultracam_reinit_iso(uvd, 0);
  867. }
  868.  
  869. #define usb_clear_halt(H,E) UsbEndpointClearHalt(H,E)
  870. static int ultracam_resetPipe(uvd_t *uvd)
  871. {
  872.   usb_clear_halt(uvd->dev, uvd->video_endp);
  873.   return 0;
  874. }
  875.  
  876.  
  877. static int ultracam_is_backward(uvd_t *uvd)
  878. {
  879.   unsigned char buf[2];
  880.   buf[0] = 0x00;
  881.   buf[1] = 0x00;
  882.   ultracam_veio(uvd, 0x02, 0x0000, 0x000b, buf);
  883.   if (buf[1] == 0x05)
  884.   {
  885.     if (debug > 2)
  886.       printf("Camera is facing forward  [%02x %02x]\n",buf[0],buf[1]);
  887.     return 0;
  888.   }
  889.   else
  890.   {
  891.     if (debug > 2)
  892.       printf("Camera is facing backward [%02x %02x]\n",buf[0],buf[1]);
  893.     return 1;
  894.   }
  895. }
  896.  
  897. /*
  898.  * Return negative code on failure, 0 on success.
  899.  */
  900. static int ultracam_setup_on_open(uvd_t *uvd)
  901. {
  902.   unsigned char buf[2];
  903.  
  904.   int setup_ok = 0; /* Success by default */
  905.  
  906.   ULTRACAM_T(uvd)->projected_whitebal = 20;
  907.  
  908.   /* Send init sequence only once, it's large! */
  909.   if (!ULTRACAM_T(uvd)->initialized)
  910.   {
  911.     ultracam_alternateSetting(uvd, 0x04);
  912.     ultracam_alternateSetting(uvd, 0x00);
  913.     ultracam_veio(uvd, 0x02, 0x0004, 0x000b, NULL);
  914.     ultracam_veio(uvd, 0x02, 0x0001, 0x0005, NULL);
  915.     ultracam_veio(uvd, 0x02, 0x8000, 0x0000, NULL);
  916.     ultracam_veio(uvd, 0x00, 0x0000, 0x0000, NULL);
  917.     ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, NULL);
  918.     ultracam_veio(uvd, 0x00, 0x0000, 0x0002, NULL);
  919.     ultracam_veio(uvd, 0x00, 0x000c, 0x0003, NULL);
  920.     ultracam_veio(uvd, 0x00, 0x000b, 0x0004, NULL);
  921.     ultracam_veio(uvd, 0x00, 0x0000, 0x0005, NULL);
  922.     ultracam_veio(uvd, 0x00, 0x0000, 0x0006, NULL);
  923.     ultracam_veio(uvd, 0x00, 0x0079, 0x0007, NULL);
  924.     ultracam_veio(uvd, 0x00, 0x003b, 0x0008, NULL);
  925.     ultracam_veio(uvd, 0x00, 0x0002, 0x000f, NULL);
  926.     ultracam_veio(uvd, 0x00, 0x0001, 0x0010, NULL);
  927.     ultracam_veio(uvd, 0x00, 0x0000, 0x0011, NULL);
  928.     ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, NULL);
  929.     ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, NULL);
  930.     ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, NULL);
  931.     ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, NULL);
  932.     ultracam_veio(uvd, 0x01, 0x0010, 0x0002, NULL);
  933.     ultracam_veio(uvd, 0x01, 0x0066, 0x0007, NULL);
  934.     ultracam_veio(uvd, 0x01, 0x000b, 0x0008, NULL);
  935.     ultracam_veio(uvd, 0x01, 0x0034, 0x0009, NULL);
  936.     ultracam_veio(uvd, 0x01, 0x0000, 0x000a, NULL);
  937.     ultracam_veio(uvd, 0x01, 0x002e, 0x000b, NULL);
  938.     ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, NULL);
  939.     ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, NULL);
  940.     ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, NULL);
  941.     ultracam_veio(uvd, 0x01, 0x00da, 0x000f, NULL);
  942.     ultracam_veio(uvd, 0x01, 0x0036, 0x0010, NULL);
  943.     ultracam_veio(uvd, 0x01, 0x000b, 0x0011, NULL);
  944.     ultracam_veio(uvd, 0x01, 0x0001, 0x0012, NULL);
  945.     ultracam_veio(uvd, 0x01, 0x0000, 0x0013, NULL);
  946.     ultracam_veio(uvd, 0x01, 0x0000, 0x0014, NULL);
  947.     ultracam_veio(uvd, 0x01, 0x0087, 0x0051, NULL);
  948.     ultracam_veio(uvd, 0x01, 0x0040, 0x0052, NULL);
  949.     ultracam_veio(uvd, 0x01, 0x0058, 0x0053, NULL);
  950.     ultracam_veio(uvd, 0x01, 0x0040, 0x0054, NULL);
  951.     ultracam_veio(uvd, 0x01, 0x0000, 0x0040, NULL);
  952.     ultracam_veio(uvd, 0x01, 0x0010, 0x0041, NULL);
  953.     ultracam_veio(uvd, 0x01, 0x0020, 0x0042, NULL);
  954.     ultracam_veio(uvd, 0x01, 0x0030, 0x0043, NULL);
  955.     ultracam_veio(uvd, 0x01, 0x0040, 0x0044, NULL);
  956.     ultracam_veio(uvd, 0x01, 0x0050, 0x0045, NULL);
  957.     ultracam_veio(uvd, 0x01, 0x0060, 0x0046, NULL);
  958.     ultracam_veio(uvd, 0x01, 0x0070, 0x0047, NULL);
  959.     ultracam_veio(uvd, 0x01, 0x0080, 0x0048, NULL);
  960.     ultracam_veio(uvd, 0x01, 0x0090, 0x0049, NULL);
  961.     ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, NULL);
  962.     ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, NULL);
  963.     ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, NULL);
  964.     ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, NULL);
  965.     ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, NULL);
  966.     ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, NULL);
  967.     ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, NULL);
  968.     ultracam_veio(uvd, 0x01, 0x0000, 0x0056, NULL);
  969.     ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, NULL);
  970.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, NULL);
  971.     ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL);
  972.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  973.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  974.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  975.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  976.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  977.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  978.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  979.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  980.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  981.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  982.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  983.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  984.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  985.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  986.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  987.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  988.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  989.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  990.     ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, NULL);
  991.     ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, NULL);
  992.     ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL);
  993.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  994.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  995.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  996.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  997.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  998.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  999.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1000.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1001.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1002.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1003.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1004.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1005.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1006.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1007.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1008.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1009.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1010.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1011.     ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, NULL);
  1012.     ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, NULL);
  1013.     ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL);
  1014.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL);
  1015.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL);
  1016.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL);
  1017.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL);
  1018.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL);
  1019.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL);
  1020.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1021.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL);
  1022.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL);
  1023.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL);
  1024.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL);
  1025.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL);
  1026.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL);
  1027.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1028.     ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, NULL);
  1029.     ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, NULL);
  1030.     ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL);
  1031.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL);
  1032.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL);
  1033.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL);
  1034.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL);
  1035.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL);
  1036.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL);
  1037.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1038.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, NULL);
  1039.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, NULL);
  1040.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, NULL);
  1041.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, NULL);
  1042.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, NULL);
  1043.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, NULL);
  1044.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, NULL);
  1045.     ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, NULL);
  1046.     ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, NULL);
  1047.     ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL);
  1048.  
  1049.     /* command mode? */
  1050.     ultracam_veio(uvd, 0x02, 0xc040, 0x0001, NULL);
  1051.  
  1052.     /* read in hue/sat? */
  1053.     ultracam_veio(uvd, 0x01, 0x0000, 0x0008, buf);
  1054.     printf("hs_read: 0x08 -- 0x%x\n", buf[0]);
  1055.     ultracam_veio(uvd, 0x01, 0x0000, 0x0009, buf);
  1056.     printf("hs_read: 0x09 -- 0x%x\n", buf[0]);
  1057.     ultracam_veio(uvd, 0x01, 0x0000, 0x000a, buf);
  1058.     printf("hs_read: 0x0a -- 0x%x\n", buf[0]);
  1059.     ultracam_veio(uvd, 0x01, 0x0000, 0x000b, buf);
  1060.     printf("hs_read: 0x0b -- 0x%x\n", buf[0]);
  1061.     ultracam_veio(uvd, 0x01, 0x0000, 0x000c, buf);
  1062.     printf("hs_read: 0x0c -- 0x%x\n", buf[0]);
  1063.     ultracam_veio(uvd, 0x01, 0x0000, 0x000d, buf);
  1064.     printf("hs_read: 0x0d -- 0x%x\n", buf[0]);
  1065.     ultracam_veio(uvd, 0x01, 0x0000, 0x000e, buf);
  1066.     printf("hs_read: 0x0e -- 0x%x\n", buf[0]);
  1067.     ultracam_veio(uvd, 0x01, 0x0000, 0x000f, buf);
  1068.     printf("hs_read: 0x0f -- 0x%x\n", buf[0]);
  1069.     ultracam_veio(uvd, 0x01, 0x0000, 0x0010, buf);
  1070.     printf("hs_read: 0x10 -- 0x%x\n", buf[0]);
  1071.  
  1072.     /* hue/saturation */
  1073.     ultracam_veio(uvd, 0x01, 0x000b, 0x0008, NULL);
  1074.     ultracam_veio(uvd, 0x01, 0x0034, 0x0009, NULL);
  1075.     ultracam_veio(uvd, 0x01, 0x0000, 0x000a, NULL);
  1076.  
  1077.     ultracam_veio(uvd, 0x01, hs_0b, 0x000b, NULL);
  1078.     ultracam_veio(uvd, 0x01, hs_0c, 0x000c, NULL);
  1079.     ultracam_veio(uvd, 0x01, hs_0d, 0x000d, NULL);
  1080.     ultracam_veio(uvd, 0x01, hs_0e, 0x000e, NULL);
  1081.     ultracam_veio(uvd, 0x01, hs_0f, 0x000f, NULL);
  1082.     ultracam_veio(uvd, 0x01, hs_10, 0x0010, NULL);
  1083.  
  1084.     /* sharpness
  1085.        ultracam_veio(uvd, 0x01, 0x0000, 0x0001, buf);
  1086.        ultracam_veio(uvd, 0x01, 0x0064, 0x0001, NULL);
  1087.     */
  1088.     ultracam_set_sharpness(uvd);
  1089.  
  1090.     /* white balance */
  1091.     ultracam_set_white_balance(uvd);
  1092.     /*
  1093.       ultracam_veio(uvd, 0x01, wb_51, 0x0051, NULL);
  1094.       ultracam_veio(uvd, 0x01, wb_52, 0x0052, NULL);
  1095.       ultracam_veio(uvd, 0x01, wb_53, 0x0053, NULL);
  1096.       ultracam_veio(uvd, 0x01, wb_11, 0x0011, NULL);
  1097.       ultracam_veio(uvd, 0x01, wb_12, 0x0012, NULL);
  1098.       ultracam_veio(uvd, 0x01, wb_13, 0x0013, NULL);
  1099.     */
  1100.  
  1101.  
  1102.     /* here I have >>>>>>    0x0007  (unknown setting?) */
  1103.     ultracam_veio(uvd, 0x00, 0x0009, 0x0011, NULL);
  1104.  
  1105.     ultracam_veio(uvd, 0x00, 0x0000, 0x0001, NULL);
  1106.     ultracam_veio(uvd, 0x00, 0x0000, 0x0000, NULL);
  1107.  
  1108.     /* on my system, these look like this:
  1109.      *                 0x00  0x001b  0x00c1
  1110.      *                 0x00  0x00e0  0x00c2
  1111.      *                 0x00  0x0000  0x00ca
  1112.      * some unknown values?
  1113.      * -Karl
  1114.      */
  1115.     ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, NULL);
  1116.     ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, NULL);
  1117.     ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, NULL);
  1118.  
  1119.     ultracam_alternateSetting(uvd, 0x04);
  1120.     ultracam_veio(uvd, 0x02, 0x0000, 0x0001, NULL);
  1121.     ultracam_veio(uvd, 0x02, 0x0000, 0x0001, NULL);
  1122.     ultracam_veio(uvd, 0x02, 0x0000, 0x0006, NULL);
  1123.  
  1124.     /* resolution */
  1125.     ultracam_veio(uvd, 0x02, 0x9000, 0x0007, NULL);
  1126.  
  1127.     /* turn on camera? */
  1128.     ultracam_veio(uvd, 0x02, 0x0042, 0x0001, NULL);
  1129.  
  1130.     ultracam_is_backward(uvd);
  1131.     ultracam_resetPipe(uvd);
  1132.     ULTRACAM_T(uvd)->initialized = (setup_ok != 0);
  1133.  
  1134.   }
  1135.   return setup_ok;
  1136. }
  1137.  
  1138. static void ultracam_configure_video(uvd_t *uvd)
  1139. {
  1140.   if (uvd == NULL)
  1141.     return;
  1142.  
  1143.   RESTRICT_TO_RANGE(init_brightness, 0, 255);
  1144.   RESTRICT_TO_RANGE(init_contrast, 0, 255);
  1145.   RESTRICT_TO_RANGE(init_sat, 0, 20);
  1146.   RESTRICT_TO_RANGE(init_hue, 0, 360);
  1147.   RESTRICT_TO_RANGE(wbmaxdelt, 1, 48);
  1148.  
  1149.   memset(&uvd->vpic, 0, sizeof(uvd->vpic));
  1150.   memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
  1151.  
  1152.   uvd->vpic.colour = init_sat << 8;
  1153.   uvd->vpic.hue = init_hue << 8;
  1154.   uvd->vpic.brightness = init_brightness << 8;
  1155.   uvd->vpic.contrast = init_contrast << 8;
  1156.   uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
  1157.   uvd->vpic.depth = 24;
  1158.   uvd->vpic.palette = VIDEO_PALETTE_RGB24;
  1159.  
  1160.   memset(&uvd->vcap, 0, sizeof(uvd->vcap));
  1161.   strcpy(uvd->vcap.name, "IBM Ultraport Camera");
  1162.   uvd->vcap.type = VID_TYPE_CAPTURE;
  1163.   uvd->vcap.channels = 1;
  1164.   uvd->vcap.audios = 0;
  1165.   uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
  1166.   uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
  1167.   uvd->vcap.minwidth = min_canvasWidth;
  1168.   uvd->vcap.minheight = min_canvasHeight;
  1169.  
  1170.   memset(&uvd->vchan, 0, sizeof(uvd->vchan));
  1171.   uvd->vchan.flags = 0;
  1172.   uvd->vchan.tuners = 0;
  1173.   uvd->vchan.channel = 0;
  1174.   uvd->vchan.type = VIDEO_TYPE_CAMERA;
  1175.   strcpy(uvd->vchan.name, "Camera");
  1176. }
  1177.  
  1178. /*
  1179.  * ultracam_probe()
  1180.  *
  1181.  * This procedure queries device descriptor and accepts the interface
  1182.  * if it looks like our camera.
  1183.  *
  1184.  * History:
  1185.  * 12-Nov-2000 Reworked to comply with new probe() signature.
  1186.  * 23-Jan-2001 Added compatibility with 2.2.x kernels.
  1187.  */
  1188.  
  1189.  
  1190.  
  1191. #if 0
  1192. static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum
  1193. #else
  1194. #define  MOD_INC_USE_COUNT
  1195. #define  MOD_DEC_USE_COUNT
  1196.  
  1197. uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams)
  1198. {
  1199.   uvd_t* Dev;
  1200.   Dev = (uvd_t*)malloc(sizeof(uvd_t));
  1201.   memset(Dev, 0, sizeof(uvd_t));
  1202.   Dev->user_data = (ultracam_t*) malloc(sizeof(ultracam_t));
  1203.   memset(Dev->user_data, 0, sizeof(ultracam_t));
  1204.  
  1205.   return Dev;
  1206. }
  1207.  
  1208. static void *ultracam_os2init(USBHANDLE dev, unsigned int ifnum
  1209. #endif
  1210.   #if defined(usb_device_id_ver)
  1211.                             ,const struct usb_device_id *devid
  1212.   #endif
  1213.                            )
  1214. {
  1215.   uvd_t *uvd = NULL;
  1216.   int i, nas;
  1217.   int actInterface=7, inactInterface=0, maxPS=0x3ff; // Hardcode values from report
  1218.   unsigned char video_ep = 0x81;
  1219.  
  1220.   if (debug >= 1)
  1221.     printf("ultracam_probe(%p,%u.)", dev, ifnum);
  1222.  
  1223. #if 0 
  1224.  
  1225.   /* We don't handle multi-config cameras */
  1226.   if (dev->descriptor.bNumConfigurations != 1)
  1227.     return NULL;
  1228.  
  1229.   /* Is it an IBM camera? */
  1230.   if ((dev->descriptor.idVendor != ULTRACAM_VENDOR_ID) ||
  1231.       (dev->descriptor.idProduct != ULTRACAM_PRODUCT_ID))
  1232.     return NULL;
  1233.  
  1234.   printf("IBM Ultra camera found (rev. 0x%04x)", dev->descriptor.bcdDevice);
  1235.  
  1236.   /* Validate found interface: must have one ISO endpoint */
  1237.   nas = dev->actconfig->interface[ifnum].num_altsetting;
  1238.   if (debug > 0)
  1239.     printf("Number of alternate settings=%d.", nas);
  1240.   if (nas < 8)
  1241.   {
  1242.     err("Too few alternate settings for this camera!");
  1243.     return NULL;
  1244.   }
  1245.  
  1246.   /* Validate all alternate settings */
  1247.   for (i=0; i < nas; i++)
  1248.   {
  1249.     const struct usb_interface_descriptor *interface;
  1250.     const struct usb_endpoint_descriptor *endpoint;
  1251.  
  1252.     interface = &dev->actconfig->interface[ifnum].altsetting[i];
  1253.     if (interface->bNumEndpoints != 1)
  1254.     {
  1255.       printf("Interface %d. has %u. endpoints!",
  1256.           ifnum, (unsigned)(interface->bNumEndpoints));
  1257.       return NULL;
  1258.     }
  1259.     endpoint = &interface->endpoint[0];
  1260.     if (video_ep == 0)
  1261.       video_ep = endpoint->bEndpointAddress;
  1262.     else if (video_ep != endpoint->bEndpointAddress)
  1263.     {
  1264.       printf("Alternate settings have different endpoint addresses!");
  1265.       return NULL;
  1266.     }
  1267.     if ((endpoint->bmAttributes & 0x03) != 0x01)
  1268.     {
  1269.       printf("Interface %d. has non-ISO endpoint!", ifnum);
  1270.       return NULL;
  1271.     }
  1272.     if ((endpoint->bEndpointAddress & 0x80) == 0)
  1273.     {
  1274.       printf("Interface %d. has ISO OUT endpoint!", ifnum);
  1275.       return NULL;
  1276.     }
  1277.     if (endpoint->wMaxPacketSize == 0)
  1278.     {
  1279.       if (inactInterface < 0)
  1280.         inactInterface = i;
  1281.       else
  1282.       {
  1283.         printf("More than one inactive alt. setting!");
  1284.         return NULL;
  1285.       }
  1286.     }
  1287.     else
  1288.     {
  1289.       if (actInterface < 0)
  1290.       {
  1291.         actInterface = i;
  1292.         maxPS = endpoint->wMaxPacketSize;
  1293.         if (debug > 0)
  1294.           printf("Active setting=%d. maxPS=%d.", i, maxPS);
  1295.       }
  1296.       else
  1297.       {
  1298.         /* Got another active alt. setting */
  1299.         if (maxPS < endpoint->wMaxPacketSize)
  1300.         {
  1301.           /* This one is better! */
  1302.           actInterface = i;
  1303.           maxPS = endpoint->wMaxPacketSize;
  1304.           if (debug > 0)
  1305.           {
  1306.             printf("Even better ctive setting=%d. maxPS=%d.",
  1307.                  i, maxPS);
  1308.           }
  1309.         }
  1310.       }
  1311.     }
  1312.   }
  1313.   if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0))
  1314.   {
  1315.     printf("Failed to recognize the camera!");
  1316.     return NULL;
  1317.   }
  1318.  
  1319.   /* Code below may sleep, need to lock module while we are here */
  1320. #endif
  1321.   MOD_INC_USE_COUNT;
  1322.   uvd = usbvideo_AllocateDevice(cams);
  1323.  
  1324.   if (uvd != NULL)
  1325.   {
  1326.     /* Here uvd is a fully allocated uvd_t object */
  1327.     uvd->flags = flags;
  1328.     uvd->debug = debug;
  1329.     uvd->dev = dev;
  1330.     uvd->iface = ifnum;
  1331.     uvd->ifaceAltInactive = inactInterface;
  1332.     uvd->ifaceAltActive = actInterface;
  1333.     uvd->video_endp = video_ep;
  1334.     uvd->iso_packet_len = maxPS;
  1335.     uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
  1336.     uvd->defaultPalette = VIDEO_PALETTE_RGB24;
  1337.     uvd->canvas = VIDEOSIZE(320, 240);  /* FIXME */
  1338.     uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/
  1339.  
  1340.     /* Initialize ibmcam-specific data */
  1341.     assert(ULTRACAM_T(uvd) != NULL);
  1342.     ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */
  1343.     ULTRACAM_T(uvd)->initialized = 0;
  1344.     ULTRACAM_T(uvd)->bytes_in = 0;
  1345.  
  1346.     ultracam_configure_video(uvd);
  1347.  
  1348.     i = 0;//usbvideo_RegisterVideoDevice(uvd);
  1349.     if (i != 0)
  1350.     {
  1351.       printf("usbvideo_RegisterVideoDevice() failed.");
  1352.       uvd = NULL;
  1353.     }
  1354.   }
  1355.   MOD_DEC_USE_COUNT;
  1356.   return uvd;
  1357. }
  1358.  
  1359.  
  1360. #if 0
  1361. /*
  1362.  * ultracam_init()
  1363.  *
  1364.  * This code is run to initialize the driver.
  1365.  */
  1366. static int __init ultracam_init(void)
  1367. {
  1368.   usbvideo_cb_t cbTbl;
  1369.   memset(&cbTbl, 0, sizeof(cbTbl));
  1370.   cbTbl.probe = ultracam_probe;
  1371.   cbTbl.setupOnOpen = ultracam_setup_on_open;
  1372.   cbTbl.videoStart = ultracam_video_start;
  1373.   cbTbl.videoStop = ultracam_video_stop;
  1374.   cbTbl.processData = ultracam_ProcessIsocData;
  1375.   cbTbl.postProcess = ultracam_postProcess;
  1376.   cbTbl.adjustPicture = ultracam_adjust_picture;
  1377.   cbTbl.getFPS = ultracam_calculate_fps;
  1378.   return usbvideo_register(
  1379.                           &cams,
  1380.                           MAX_CAMERAS,
  1381.                           sizeof(ultracam_t),
  1382.                           "ultracam",
  1383.                           &cbTbl,
  1384.                           THIS_MODULE);
  1385. }
  1386.  
  1387. static void __exit ultracam_cleanup(void)
  1388. {
  1389.   usbvideo_Deregister(&cams);
  1390. }
  1391.  
  1392.   #if defined(usb_device_id_ver)
  1393.  
  1394. static __devinitdata struct usb_device_id id_table[] = {
  1395.   { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID)},
  1396.   {}  /* Terminating entry */
  1397. };
  1398. MODULE_DEVICE_TABLE(usb, id_table);
  1399.  
  1400.   #endif /* defined(usb_device_id_ver) */
  1401.  
  1402. module_init(ultracam_init);
  1403. module_exit(ultracam_cleanup);
  1404.  
  1405. #endif
  1406.  
  1407. //////////////////////////////////////////
  1408. ////////// OS/2 RING 3 Test APP //////////
  1409. //////////////////////////////////////////
  1410.  
  1411. void main(int argc, char *argv[])
  1412. {
  1413.   USBHANDLE hDev;
  1414.   APIRET rc;
  1415.   uvd_t *pCam;
  1416.  
  1417.   rc = UsbOpen( &hDev,    
  1418.                 ULTRACAM_VENDOR_ID,
  1419.                 ULTRACAM_PRODUCT_ID,
  1420.                 USB_ANY_PRODUCTVERSION, // or try 0x0103
  1421.                 USB_OPEN_FIRST_UNUSED);
  1422.   if(!rc)
  1423.   {
  1424.     printf("Open OK\n");
  1425.     pCam = (uvd_t*)ultracam_os2init(hDev, 0);
  1426.     if(pCam)
  1427.     {
  1428.       char ch;
  1429.       printf( "Chose Action:\n"
  1430.               " Get Camera (P)osition\n"
  1431.               " (S)etup Camera\n"
  1432.               " Sta(r)t Video\n"
  1433.               " S(t)op Video\n"
  1434.               " E(x)it\n");
  1435.       while(1)
  1436.       {
  1437.         ch = getch();
  1438.         switch(ch)
  1439.         {
  1440.           case 'p':
  1441.           case 'P':
  1442.             ultracam_is_backward(pCam);
  1443.             break;
  1444.           case 's':
  1445.           case 'S':
  1446.             ultracam_setup_on_open(pCam);
  1447.             break;
  1448.           case 'r':
  1449.           case 'R':
  1450.             ultracam_video_start(pCam);
  1451.             break;
  1452.           case 't':
  1453.           case 'T':
  1454.             ultracam_video_stop(pCam);
  1455.             break;
  1456.         }
  1457.         if((ch=='x') || (ch=='X'))
  1458.           break;
  1459.       }
  1460.     }
  1461.     UsbClose(hDev);
  1462.   }
  1463.   else
  1464.     printf("Camera Not found (rc=%d)\r\n",rc);
  1465.  
  1466. }
  1467.  
  1468.