# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.575   -> 1.576  
#       drivers/usb/konicawc.c  1.2     -> 1.3    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/04/01      [EMAIL PROTECTED]      1.576
# [PATCH] Update to konicawc driver
# 
# This patch against 2.5.7 fixes an oops and a memleak in the konicawc driver
# and also adds an option to set the FPS.
# --------------------------------------------
#
diff -Nru a/drivers/usb/konicawc.c b/drivers/usb/konicawc.c
--- a/drivers/usb/konicawc.c    Wed Apr  3 16:39:12 2002
+++ b/drivers/usb/konicawc.c    Wed Apr  3 16:39:12 2002
@@ -1,5 +1,5 @@
 /*
- * $Id: konicawc.c,v 1.12 2002/02/07 23:18:53 spse Exp $
+ * $Id$
  *
  * konicawc.c - konica webcam driver
  *
@@ -18,17 +18,18 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-#define DEBUG
-
 #include "usbvideo.h"
 
 #define MAX_BRIGHTNESS 108
 #define MAX_CONTRAST   108
 #define MAX_SATURATION 108
 #define MAX_SHARPNESS  108
-#define MAX_WHITEBAL   363
+#define MAX_WHITEBAL   372
+#define MAX_SPEED      6
+#define MAX_CAMERAS    1
 
-#define MAX_CAMERAS 1
+#define DRIVER_VERSION "v1.1"
+#define DRIVER_DESC    "Konica Webcam driver"
 
 enum ctrl_req {
        SetWhitebal     = 0x01,
@@ -40,7 +41,7 @@
 
 
 enum frame_sizes {
-       SIZE_160X130    = 0,
+       SIZE_160X136    = 0,
        SIZE_176X144    = 1,
        SIZE_320X240    = 2,
 };
@@ -53,12 +54,30 @@
 
 static int debug;
 static enum frame_sizes size;  
+static int speed = 6;          /* Speed (fps) 0 (slowest) to 6 (fastest) */
 static int brightness =        MAX_BRIGHTNESS/2;
 static int contrast =  MAX_CONTRAST/2;
 static int saturation =        MAX_SATURATION/2;
 static int sharpness = MAX_SHARPNESS/2;
 static int whitebal =  3*(MAX_WHITEBAL/4);
 
+static int speed_to_interface[] = { 1, 0, 3, 2, 4, 5, 6 };
+
+/* These FPS speeds are from the windows config box. They are
+ * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
+ * real fps.
+ */
+
+static int speed_to_fps[3][7] = { { 24, 40, 48, 60, 72, 80, 100 },
+                                 { 18, 30, 36, 45, 54, 60, 75  },
+                                 { 6,  10, 12, 15, 18, 20, 25  } };
+
+
+static int camera_sizes[][2] = { { 160, 136 },
+                                { 176, 144 },
+                                { 320, 240 },
+                                { } /* List terminator */
+};
 
 struct konicawc {
        u8 brightness;          /* camera uses 0 - 9, x11 for real value */
@@ -66,12 +85,12 @@
        u8 saturation;          /* as above */
        u8 sharpness;           /* as above */
        u8 white_bal;           /* 0 - 33, x11 for real value */
-       u8 fps;                 /* Stored as fps * 3 */
+       u8 speed;               /* Stored as 0 - 6, used as index in speed_to_* 
+(above) */
        u8 size;                /* Frame Size */
        int height;
        int width;
-       struct urb *sts_urb[USBVIDEO_NUMFRAMES];
-       u8 sts_buf[USBVIDEO_NUMFRAMES][FRAMES_PER_DESC];
+       struct urb *sts_urb[USBVIDEO_NUMSBUF];
+       u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC];
        struct urb *last_data_urb;
        int lastframe;
 };
@@ -97,19 +116,19 @@
 
        konicawc_set_misc(uvd, 0x2, 0, 0x0b);
        dbg("setting brightness to %d (%d)", cam->brightness,
-           cam->brightness*11);
+           cam->brightness * 11);
        konicawc_set_value(uvd, cam->brightness, SetBrightness);
        dbg("setting white balance to %d (%d)", cam->white_bal,
-           cam->white_bal*11);
+           cam->white_bal * 11);
        konicawc_set_value(uvd, cam->white_bal, SetWhitebal);
        dbg("setting contrast to %d (%d)", cam->contrast,
-           cam->contrast*11);
-       konicawc_set_value(uvd, cam->brightness, SetBrightness);
+           cam->contrast * 11);
+       konicawc_set_value(uvd, cam->contrast, SetContrast);
        dbg("setting saturation to %d (%d)", cam->saturation,
-           cam->saturation*11);
+           cam->saturation * 11);
        konicawc_set_value(uvd, cam->saturation, SetSaturation);
        dbg("setting sharpness to %d (%d)", cam->sharpness,
-           cam->sharpness*11);
+           cam->sharpness * 11);
        konicawc_set_value(uvd, cam->sharpness, SetSharpness);
        dbg("setting size %d", cam->size);
        switch(cam->size) {
@@ -131,6 +150,30 @@
 }
 
 
+static void konicawc_adjust_picture(uvd_t *uvd)
+{
+       struct konicawc *cam = (struct konicawc *)uvd->user_data;
+
+       dbg("new brightness: %d", uvd->vpic.brightness);
+       uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? 
+MAX_BRIGHTNESS : uvd->vpic.brightness;
+       if(cam->brightness != uvd->vpic.brightness / 11) {
+          cam->brightness = uvd->vpic.brightness / 11;
+          dbg("setting brightness to %d (%d)", cam->brightness,
+              cam->brightness * 11);
+          konicawc_set_value(uvd, cam->brightness, SetBrightness);
+       }
+
+       dbg("new contrast: %d", uvd->vpic.contrast);
+       uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : 
+uvd->vpic.contrast;
+       if(cam->contrast != uvd->vpic.contrast / 11) {
+               cam->contrast = uvd->vpic.contrast / 11;
+               dbg("setting contrast to %d (%d)", cam->contrast,
+                   cam->contrast * 11);
+               konicawc_set_value(uvd, cam->contrast, SetContrast);
+       }
+}
+
+
 static int konicawc_compress_iso(uvd_t *uvd, struct urb *dataurb, struct urb *stsurb)
 {
        char *cdata;
@@ -138,7 +181,7 @@
        unsigned char *status = stsurb->transfer_buffer;
        int keep = 0, discard = 0, bad = 0;
        static int buttonsts = 0;
-       
+
        for (i = 0; i < dataurb->number_of_packets; i++) {
                int button = buttonsts;
                unsigned char sts;
@@ -228,7 +271,7 @@
        int i, len = 0;
        uvd_t *uvd = urb->context;
        struct konicawc *cam = (struct konicawc *)uvd->user_data;
- 
+
        /* We don't want to do anything if we are about to be removed! */
        if (!CAMERA_IS_OPERATIONAL(uvd))
                return;
@@ -236,7 +279,6 @@
        if (urb->actual_length > 32) {
                cam->last_data_urb = urb;
                return;
-
        }
 
        if (!uvd->streaming) {
@@ -244,7 +286,7 @@
                        info("Not streaming, but interrupt!");
                return;
        }
-       
+
        uvd->stats.urb_count++;
        if (urb->actual_length <= 0)
                goto urb_done_with;
@@ -329,7 +371,8 @@
                }
        }
 
-
+       cam->last_data_urb = NULL;
+       
        /* Link URBs into a ring so that they invoke each other infinitely */
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
                if ((i+1) < USBVIDEO_NUMSBUF) {
@@ -362,11 +405,14 @@
 static void konicawc_stop_data(uvd_t *uvd)
 {
        int i, j;
-       struct konicawc *cam = (struct konicawc *)uvd->user_data;
+       struct konicawc *cam;
 
        if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
                return;
 
+       cam = (struct konicawc *)uvd->user_data;
+       cam->last_data_urb = NULL;
+
        /* Unschedule all of the iso td's */
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
                j = usb_unlink_urb(uvd->sbuf[i].urb);
@@ -476,9 +522,9 @@
 static int konicawc_calculate_fps(uvd_t *uvd)
 {
        struct konicawc *t = uvd->user_data;
-       dbg("");
+       dbg("fps = %d", speed_to_fps[t->size][t->speed]/3);
 
-       return (t->fps)/3;
+       return speed_to_fps[t->size][t->speed]/3;
 }
 
 
@@ -515,10 +561,10 @@
        uvd->vcap.type = VID_TYPE_CAPTURE;
        uvd->vcap.channels = 1;
        uvd->vcap.audios = 0;
-       uvd->vcap.maxwidth = cam->width;
-       uvd->vcap.maxheight = cam->height;
-       uvd->vcap.minwidth = cam->width;
-       uvd->vcap.minheight = cam->height;
+       uvd->vcap.minwidth = camera_sizes[cam->size][0];
+       uvd->vcap.minheight = camera_sizes[cam->size][1];
+       uvd->vcap.maxwidth = camera_sizes[cam->size][0];
+       uvd->vcap.maxheight = camera_sizes[cam->size][1];
 
        memset(&uvd->vchan, 0, sizeof(uvd->vchan));
        uvd->vchan.flags = 0 ;
@@ -540,7 +586,7 @@
 }
 
 
-static void *konicawc_probe(struct usb_device *dev, unsigned int ifnum ,const struct 
usb_device_id *devid)
+static void *konicawc_probe(struct usb_device *dev, unsigned int ifnum, const struct 
+usb_device_id *devid)
 {
        uvd_t *uvd = NULL;
        int i, nas;
@@ -555,6 +601,7 @@
                return NULL;
 
        info("Konica Webcam (rev. 0x%04x)", dev->descriptor.bcdDevice);
+       RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
 
        /* Validate found interface: must have one ISO endpoint */
        nas = dev->actconfig->interface[ifnum].num_altsetting;
@@ -600,56 +647,58 @@
                                return NULL;
                        }
                } else {
-                       if (actInterface < 0) {
+                       if (i == speed_to_interface[speed]) {
+                               /* This one is the requested one */
                                actInterface = i;
                                maxPS = endpoint->wMaxPacketSize;
-                               if (debug > 0)
-                                       info("Active setting=%d. maxPS=%d.",
+                               if (debug > 0) {
+                                       info("Selecting requested active setting=%d. 
+maxPS=%d.",
                                             i, maxPS);
-                       } else {
-                               /* Got another active alt. setting */
-                               if (maxPS < endpoint->wMaxPacketSize) {
-                                       /* This one is better! */
-                                       actInterface = i;
-                                       maxPS = endpoint->wMaxPacketSize;
-                                       if (debug > 0) {
-                                               info("Even better active setting=%d. 
maxPS=%d.",
-                                                    i, maxPS);
-                                       }
                                }
                        }
                }
        }
+       if(actInterface == -1) {
+               err("Cant find required endpoint");
+               return NULL;
+       }
+
 
        /* Code below may sleep, need to lock module while we are here */
        MOD_INC_USE_COUNT;
        uvd = usbvideo_AllocateDevice(cams);
        if (uvd != NULL) {
-               struct konicawc *konicawc_data = (struct konicawc *)(uvd->user_data);
+               struct konicawc *cam = (struct konicawc *)(uvd->user_data);
                /* Here uvd is a fully allocated uvd_t object */
-
                for(i = 0; i < USBVIDEO_NUMSBUF; i++) {
-                       konicawc_data->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, 
GFP_KERNEL);
+                       cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
+                       if(cam->sts_urb[i] == NULL) {
+                               while(i--) {
+                                       usb_free_urb(cam->sts_urb[i]);
+                               }
+                               err("cant allocate urbs");
+                               return NULL;
+                       }
                }
-
+               cam->speed = speed;
                switch(size) {
-               case SIZE_160X130:
+               case SIZE_160X136:
                default:
-                       konicawc_data->height = 136;
-                       konicawc_data->width = 160;
-                       konicawc_data->size = SIZE_160X130;
+                       cam->height = 136;
+                       cam->width = 160;
+                       cam->size = SIZE_160X136;
                        break;
 
                case SIZE_176X144:
-                       konicawc_data->height = 144;
-                       konicawc_data->width = 176;
-                       konicawc_data->size = SIZE_176X144;
+                       cam->height = 144;
+                       cam->width = 176;
+                       cam->size = SIZE_176X144;
                        break;
 
                case SIZE_320X240:
-                       konicawc_data->height = 240;
-                       konicawc_data->width = 320;
-                       konicawc_data->size = SIZE_320X240;
+                       cam->height = 240;
+                       cam->width = 320;
+                       cam->size = SIZE_320X240;
                        break;
                }
 
@@ -663,14 +712,14 @@
                uvd->iso_packet_len = maxPS;
                uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P;
                uvd->defaultPalette = VIDEO_PALETTE_YUV420P;
-               uvd->canvas = VIDEOSIZE(konicawc_data->width, konicawc_data->height);
+               uvd->canvas = VIDEOSIZE(cam->width, cam->height);
                uvd->videosize = uvd->canvas;
 
                /* Initialize konicawc specific data */
                konicawc_configure_video(uvd);
 
                i = usbvideo_RegisterVideoDevice(uvd);
-               uvd->max_frame_size = (konicawc_data->width * konicawc_data->height * 
3)/2;
+               uvd->max_frame_size = (cam->width * cam->height * 3)/2;
                if (i != 0) {
                        err("usbvideo_RegisterVideoDevice() failed.");
                        uvd = NULL;
@@ -681,9 +730,28 @@
 }
 
 
+static void konicawc_free_uvd(uvd_t *uvd)
+{
+       int i;
+       struct konicawc *cam = (struct konicawc *)uvd->user_data;
+
+       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+               usb_free_urb(cam->sts_urb[i]);
+               cam->sts_urb[i] = NULL;
+       }
+}
+
+
+static struct usb_device_id id_table[] = {
+       { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */
+       { }  /* Terminating entry */
+};
+
+
 static int __init konicawc_init(void)
 {
        usbvideo_cb_t cbTbl;
+       info(DRIVER_DESC " " DRIVER_VERSION);
        memset(&cbTbl, 0, sizeof(cbTbl));
        cbTbl.probe = konicawc_probe;
        cbTbl.setupOnOpen = konicawc_setup_on_open;
@@ -691,6 +759,8 @@
        cbTbl.getFPS = konicawc_calculate_fps;
        cbTbl.startDataPump = konicawc_start_data;
        cbTbl.stopDataPump = konicawc_stop_data;
+       cbTbl.adjustPicture = konicawc_adjust_picture;
+       cbTbl.userFree = konicawc_free_uvd;
        return usbvideo_register(
                &cams,
                MAX_CAMERAS,
@@ -706,19 +776,14 @@
        usbvideo_Deregister(&cams);
 }
 
-#if defined(usb_device_id_ver)
-
-static __devinitdata struct usb_device_id id_table[] = {
-       { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */
-       { }  /* Terminating entry */
-};
 
 MODULE_DEVICE_TABLE(usb, id_table);
-#endif /* defined(usb_device_id_ver) */
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Simon Evans <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION("Konica Webcam driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_PARM(speed, "i");
+MODULE_PARM_DESC(speed, "FPS speed: 0 (slowest) - 6 (fastest)");
 MODULE_PARM(size, "i");
 MODULE_PARM_DESC(size, "Frame Size 0: 160x136 1: 176x144 2: 320x240");
 MODULE_PARM(brightness, "i");

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to