V4L/DVB (5206): Usbvision: set alternate interface modification
authorThierry MERLE <thierry.merle@free.fr>
Wed, 7 Feb 2007 13:14:38 +0000 (10:14 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Wed, 21 Feb 2007 15:35:19 +0000 (13:35 -0200)
- usb alternate selection modified to get the biggest endpoint packet size.
- fix sysfs get values for brightness/contrast/hue/saturation

Signed-off-by: Thierry MERLE <thierry.merle@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/usbvision/Kconfig
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/usbvision/usbvision.h

index fc24ef05b3f31cf527b6fc850423cae317ad224b..c43a5d8990918bbffb510dbecfe47600360a392b 100644 (file)
@@ -1,6 +1,6 @@
 config VIDEO_USBVISION
        tristate "USB video devices based on Nogatech NT1003/1004/1005"
-       depends on I2C && VIDEO_V4L2
+       depends on I2C && VIDEO_V4L2 && USB
        select VIDEO_TUNER
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        ---help---
index d4fcd5736ba9d7cbe8bd9f44e1ced7ce91b8861c..f2154dc072e211d5829fe7865f6aaeea4f8e594e 100644 (file)
@@ -2361,6 +2361,32 @@ int usbvision_setup(struct usb_usbvision *usbvision,int format)
        return USBVISION_IS_OPERATIONAL(usbvision);
 }
 
+int usbvision_set_alternate(struct usb_usbvision *dev)
+{
+       int errCode, prev_alt = dev->ifaceAlt;
+       int i;
+
+       dev->ifaceAlt=0;
+       for(i=0;i< dev->num_alt; i++)
+               if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->ifaceAlt])
+                       dev->ifaceAlt=i;
+
+       if (dev->ifaceAlt != prev_alt) {
+               dev->isocPacketSize = dev->alt_max_pkt_size[dev->ifaceAlt];
+               PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize);
+               errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt);
+               if (errCode < 0) {
+                       err ("cannot change alternate number to %d (error=%i)",
+                                                       dev->ifaceAlt, errCode);
+                       return errCode;
+               }
+       }
+
+       PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isocPacketSize);
+
+       return 0;
+}
+
 /*
  * usbvision_init_isoc()
  *
@@ -2378,15 +2404,13 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
        scratch_reset(usbvision);
 
        /* Alternate interface 1 is is the biggest frame size */
-       errCode = usb_set_interface(dev, usbvision->iface, usbvision->ifaceAltActive);
+       errCode = usbvision_set_alternate(usbvision);
        if (errCode < 0) {
                usbvision->last_error = errCode;
                return -EBUSY;
        }
 
        regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
-       usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
-       PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
 
        usbvision->usb_bandwidth = regValue >> 1;
        PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
@@ -2472,8 +2496,9 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
        if (!usbvision->remove_pending) {
 
                /* Set packet size to 0 */
+               usbvision->ifaceAlt=0;
                errCode = usb_set_interface(usbvision->dev, usbvision->iface,
-                                     usbvision->ifaceAltInactive);
+                                           usbvision->ifaceAlt);
                if (errCode < 0) {
                        err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
                        usbvision->last_error = errCode;
index cfbfda47ec4fae0188b90187c457025942a43060..ae5f42562c0c410fff2ed53b120efa1f618d484d 100644 (file)
@@ -230,7 +230,7 @@ static ssize_t show_hue(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
 
@@ -243,7 +243,7 @@ static ssize_t show_contrast(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
 
@@ -256,7 +256,7 @@ static ssize_t show_brightness(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
 
@@ -269,7 +269,7 @@ static ssize_t show_saturation(struct class_device *cd, char *buf)
        ctrl.value = 0;
        if(usbvision->user)
                call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value >> 8);
+       return sprintf(buf, "%d\n", ctrl.value);
 }
 static CLASS_DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
 
@@ -776,8 +776,8 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOC_G_CTRL:
                {
                        struct v4l2_control *ctrl = arg;
-                       PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
                        call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+                       PDEBUG(DBG_IOCTL,"VIDIOC_G_CTRL id=%x value=%x",ctrl->id,ctrl->value);
                        return 0;
                }
                case VIDIOC_S_CTRL:
@@ -1243,6 +1243,13 @@ static int usbvision_radio_open(struct inode *inode, struct file *file)
                        }
                }
 
+               /* Alternate interface 1 is is the biggest frame size */
+               errCode = usbvision_set_alternate(usbvision);
+               if (errCode < 0) {
+                       usbvision->last_error = errCode;
+                       return -EBUSY;
+               }
+
                // If so far no errors then we shall start the radio
                usbvision->radio = 1;
                call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type);
@@ -1274,6 +1281,11 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
 
        down(&usbvision->lock);
 
+       /* Set packet size to 0 */
+       usbvision->ifaceAlt=0;
+       errCode = usb_set_interface(usbvision->dev, usbvision->iface,
+                                   usbvision->ifaceAlt);
+
        usbvision_audio_off(usbvision);
        usbvision->radio=0;
        usbvision->user--;
@@ -1765,15 +1777,17 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision)
  */
 static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid)
 {
-       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf));
+       struct usb_interface *uif;
        __u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
        const struct usb_host_interface *interface;
        struct usb_usbvision *usbvision = NULL;
        const struct usb_endpoint_descriptor *endpoint;
-       int model;
+       int model,i;
 
        PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
                                        dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+
        /* Is it an USBVISION video dev? */
        model = 0;
        for(model = 0; usbvision_device_data[model].idVendor; model++) {
@@ -1800,7 +1814,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
        endpoint = &interface->endpoint[1].desc;
        if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) {
                err("%s: interface %d. has non-ISO endpoint!", __FUNCTION__, ifnum);
-               err("%s: Endpoint attribures %d", __FUNCTION__, endpoint->bmAttributes);
+               err("%s: Endpoint attributes %d", __FUNCTION__, endpoint->bmAttributes);
                return -ENODEV;
        }
        if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
@@ -1827,6 +1841,28 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
 
        down(&usbvision->lock);
 
+       /* compute alternate max packet sizes */
+       uif = dev->actconfig->interface[0];
+
+       usbvision->num_alt=uif->num_altsetting;
+       PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt);
+       usbvision->alt_max_pkt_size = kmalloc(32*
+                                             usbvision->num_alt,GFP_KERNEL);
+       if (usbvision->alt_max_pkt_size == NULL) {
+               err("usbvision: out of memory!\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < usbvision->num_alt ; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
+                                     wMaxPacketSize);
+               usbvision->alt_max_pkt_size[i] =
+                       (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i,
+                      usbvision->alt_max_pkt_size[i]);
+       }
+
+
        usbvision->nr = usbvision_nr++;
 
        usbvision->have_tuner = usbvision_device_data[model].Tuner;
@@ -1839,8 +1875,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
        usbvision->DevModel = model;
        usbvision->remove_pending = 0;
        usbvision->iface = ifnum;
-       usbvision->ifaceAltInactive = 0;
-       usbvision->ifaceAltActive = 1;
+       usbvision->ifaceAlt = 0;
        usbvision->video_endp = endpoint->bEndpointAddress;
        usbvision->isocPacketSize = 0;
        usbvision->usb_bandwidth = 0;
index 0e2b5569986097f816e8fcd5ff2b1a9e825cb33f..ad6afd3e42a423c1177692189e0356625135a49a 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/list.h>
 #include <linux/usb.h>
+#include <linux/i2c.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <linux/videodev2.h>
@@ -396,8 +397,11 @@ struct usb_usbvision {
 
        /* Device structure */
        struct usb_device *dev;
+       /* usb transfer */
+       int num_alt;            /* Number of alternative settings */
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
        unsigned char iface;                                            /* Video interface number */
-       unsigned char ifaceAltActive, ifaceAltInactive;                 /* Alt settings */
+       unsigned char ifaceAlt;                 /* Alt settings */
        unsigned char Vin_Reg2_Preset;
        struct semaphore lock;
        struct timer_list powerOffTimer;
@@ -502,6 +506,7 @@ int usbvision_setup(struct usb_usbvision *usbvision,int format);
 int usbvision_init_isoc(struct usb_usbvision *usbvision);
 int usbvision_restart_isoc(struct usb_usbvision *usbvision);
 void usbvision_stop_isoc(struct usb_usbvision *usbvision);
+int usbvision_set_alternate(struct usb_usbvision *dev);
 
 int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel);
 int usbvision_audio_off(struct usb_usbvision *usbvision);