The patch number 10297 was added via Mauro Carvalho Chehab <mche...@redhat.com>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        Linux Media Mailing List <linux-me...@vger.kernel.org>

------

From: Mauro Carvalho Chehab  <mche...@redhat.com>
merge: http://linuxtv.org/hg/~pinchartl/uvcvideo/


Priority: normal

Signed-off-by: Mauro Carvalho Chehab <mche...@redhat.com>


---

 linux/drivers/media/video/uvc/uvc_ctrl.c   |    2 
 linux/drivers/media/video/uvc/uvc_driver.c |   27 ++++--
 linux/drivers/media/video/uvc/uvc_status.c |   16 ---
 linux/drivers/media/video/uvc/uvc_v4l2.c   |   12 +-
 linux/drivers/media/video/uvc/uvc_video.c  |   93 +++++++++++----------
 linux/drivers/media/video/uvc/uvcvideo.h   |    7 -
 6 files changed, 81 insertions(+), 76 deletions(-)

diff -r abb4add20e7b -r 14a2ef98f994 linux/drivers/media/video/uvc/uvc_ctrl.c
--- a/linux/drivers/media/video/uvc/uvc_ctrl.c  Thu Jan 22 20:59:21 2009 -0200
+++ b/linux/drivers/media/video/uvc/uvc_ctrl.c  Thu Jan 22 21:04:48 2009 -0200
@@ -788,7 +788,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video
        memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
        v4l2_ctrl->id = mapping->id;
        v4l2_ctrl->type = mapping->v4l2_type;
-       strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
+       strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
        v4l2_ctrl->flags = 0;
 
        if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR))
diff -r abb4add20e7b -r 14a2ef98f994 linux/drivers/media/video/uvc/uvc_driver.c
--- a/linux/drivers/media/video/uvc/uvc_driver.c        Thu Jan 22 20:59:21 
2009 -0200
+++ b/linux/drivers/media/video/uvc/uvc_driver.c        Thu Jan 22 21:04:48 
2009 -0200
@@ -314,7 +314,7 @@ static int uvc_parse_format(struct uvc_d
                fmtdesc = uvc_format_by_guid(&buffer[5]);
 
                if (fmtdesc != NULL) {
-                       strncpy(format->name, fmtdesc->name,
+                       strlcpy(format->name, fmtdesc->name,
                                sizeof format->name);
                        format->fcc = fmtdesc->fcc;
                } else {
@@ -345,7 +345,7 @@ static int uvc_parse_format(struct uvc_d
                        return -EINVAL;
                }
 
-               strncpy(format->name, "MJPEG", sizeof format->name);
+               strlcpy(format->name, "MJPEG", sizeof format->name);
                format->fcc = V4L2_PIX_FMT_MJPEG;
                format->flags = UVC_FMT_FLAG_COMPRESSED;
                format->bpp = 0;
@@ -363,13 +363,13 @@ static int uvc_parse_format(struct uvc_d
 
                switch (buffer[8] & 0x7f) {
                case 0:
-                       strncpy(format->name, "SD-DV", sizeof format->name);
+                       strlcpy(format->name, "SD-DV", sizeof format->name);
                        break;
                case 1:
-                       strncpy(format->name, "SDL-DV", sizeof format->name);
+                       strlcpy(format->name, "SDL-DV", sizeof format->name);
                        break;
                case 2:
-                       strncpy(format->name, "HD-DV", sizeof format->name);
+                       strlcpy(format->name, "HD-DV", sizeof format->name);
                        break;
                default:
                        uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
@@ -379,7 +379,7 @@ static int uvc_parse_format(struct uvc_d
                        return -EINVAL;
                }
 
-               strncat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
+               strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
                        sizeof format->name);
 
                format->fcc = V4L2_PIX_FMT_DV;
@@ -1526,7 +1526,7 @@ static int uvc_register_video(struct uvc
        vdev->minor = -1;
        vdev->fops = &uvc_fops;
        vdev->release = video_device_release;
-       strncpy(vdev->name, dev->name, sizeof vdev->name);
+       strlcpy(vdev->name, dev->name, sizeof vdev->name);
 
        /* Set the driver data before calling video_register_device, otherwise
         * uvc_v4l2_open might race us.
@@ -1621,7 +1621,7 @@ static int uvc_probe(struct usb_interfac
        dev->quirks = id->driver_info | uvc_quirks_param;
 
        if (udev->product != NULL)
-               strncpy(dev->name, udev->product, sizeof dev->name);
+               strlcpy(dev->name, udev->product, sizeof dev->name);
        else
                snprintf(dev->name, sizeof dev->name,
                        "UVC Camera (%04x:%04x)",
@@ -1835,6 +1835,15 @@ static struct usb_device_id uvc_ids[] = 
          .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0 },
+       /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x058f,
+         .idProduct            = 0x3820,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
        /* Apple Built-In iSight */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1881,7 +1890,7 @@ static struct usb_device_id uvc_ids[] = 
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Asus F9SG */
+       /* Syntek (Asus F9SG) */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
          .idVendor             = 0x174f,
diff -r abb4add20e7b -r 14a2ef98f994 linux/drivers/media/video/uvc/uvc_status.c
--- a/linux/drivers/media/video/uvc/uvc_status.c        Thu Jan 22 20:59:21 
2009 -0200
+++ b/linux/drivers/media/video/uvc/uvc_status.c        Thu Jan 22 21:04:48 
2009 -0200
@@ -28,26 +28,19 @@
 #ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
 static int uvc_input_init(struct uvc_device *dev)
 {
-       struct usb_device *udev = dev->udev;
        struct input_dev *input;
-       char *phys = NULL;
        int ret;
 
        input = input_allocate_device();
        if (input == NULL)
                return -ENOMEM;
 
-       phys = kmalloc(6 + strlen(udev->bus->bus_name) + strlen(udev->devpath),
-                       GFP_KERNEL);
-       if (phys == NULL) {
-               ret = -ENOMEM;
-               goto error;
-       }
-       sprintf(phys, "usb-%s-%s", udev->bus->bus_name, udev->devpath);
+       usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));
+       strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
 
        input->name = dev->name;
-       input->phys = phys;
-       usb_to_input_id(udev, &input->id);
+       input->phys = dev->input_phys;
+       usb_to_input_id(dev->udev, &input->id);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
        input->dev.parent = &dev->intf->dev;
 #else
@@ -65,7 +58,6 @@ static int uvc_input_init(struct uvc_dev
 
 error:
        input_free_device(input);
-       kfree(phys);
        return ret;
 }
 
diff -r abb4add20e7b -r 14a2ef98f994 linux/drivers/media/video/uvc/uvc_v4l2.c
--- a/linux/drivers/media/video/uvc/uvc_v4l2.c  Thu Jan 22 20:59:21 2009 -0200
+++ b/linux/drivers/media/video/uvc/uvc_v4l2.c  Thu Jan 22 21:04:48 2009 -0200
@@ -55,7 +55,7 @@ static int uvc_v4l2_query_menu(struct uv
                return -EINVAL;
 
        menu_info = &mapping->menu_info[query_menu->index];
-       strncpy(query_menu->name, menu_info->name, 32);
+       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
        return 0;
 }
 
@@ -492,9 +492,9 @@ static long uvc_v4l2_do_ioctl(struct fil
                struct v4l2_capability *cap = arg;
 
                memset(cap, 0, sizeof *cap);
-               strncpy(cap->driver, "uvcvideo", sizeof cap->driver);
-               strncpy(cap->card, vdev->name, 32);
-               strncpy(cap->bus_info, video->dev->udev->bus->bus_name,
+               strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
+               strlcpy(cap->card, vdev->name, sizeof cap->card);
+               strlcpy(cap->bus_info, video->dev->udev->bus->bus_name,
                        sizeof cap->bus_info);
                cap->version = DRIVER_VERSION_NUMBER;
                if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -626,7 +626,7 @@ static long uvc_v4l2_do_ioctl(struct fil
 
                memset(input, 0, sizeof *input);
                input->index = index;
-               strncpy(input->name, iterm->name, sizeof input->name);
+               strlcpy(input->name, iterm->name, sizeof input->name);
                if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA)
                        input->type = V4L2_INPUT_TYPE_CAMERA;
                break;
@@ -688,7 +688,7 @@ static long uvc_v4l2_do_ioctl(struct fil
                fmt->flags = 0;
                if (format->flags & UVC_FMT_FLAG_COMPRESSED)
                        fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-               strncpy(fmt->description, format->name,
+               strlcpy(fmt->description, format->name,
                        sizeof fmt->description);
                fmt->description[sizeof fmt->description - 1] = 0;
                fmt->pixelformat = format->fcc;
diff -r abb4add20e7b -r 14a2ef98f994 linux/drivers/media/video/uvc/uvc_video.c
--- a/linux/drivers/media/video/uvc/uvc_video.c Thu Jan 22 20:59:21 2009 -0200
+++ b/linux/drivers/media/video/uvc/uvc_video.c Thu Jan 22 21:04:48 2009 -0200
@@ -703,27 +703,47 @@ static void uvc_free_urb_buffers(struct 
  * already allocated when resuming from suspend, in which case it will
  * return without touching the buffers.
  *
- * Return 0 on success or -ENOMEM when out of memory.
+ * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the
+ * system is too low on memory try successively smaller numbers of packets
+ * until allocation succeeds.
+ *
+ * Return the number of allocated packets on success or 0 when out of memory.
  */
 static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
-       unsigned int size)
-{
+       unsigned int size, unsigned int psize, gfp_t gfp_flags)
+{
+       unsigned int npackets;
        unsigned int i;
 
        /* Buffers are already allocated, bail out. */
        if (video->urb_size)
                return 0;
 
-       for (i = 0; i < UVC_URBS; ++i) {
-               video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
-                       size, GFP_KERNEL, &video->urb_dma[i]);
-               if (video->urb_buffer[i] == NULL) {
-                       uvc_free_urb_buffers(video);
-                       return -ENOMEM;
-               }
-       }
-
-       video->urb_size = size;
+       /* Compute the number of packets. Bulk endpoints might transfer UVC
+        * payloads accross multiple URBs.
+        */
+       npackets = DIV_ROUND_UP(size, psize);
+       if (npackets > UVC_MAX_PACKETS)
+               npackets = UVC_MAX_PACKETS;
+
+       /* Retry allocations until one succeed. */
+       for (; npackets > 1; npackets /= 2) {
+               for (i = 0; i < UVC_URBS; ++i) {
+                       video->urb_buffer[i] = usb_buffer_alloc(
+                               video->dev->udev, psize * npackets,
+                               gfp_flags | __GFP_NOWARN, &video->urb_dma[i]);
+                       if (!video->urb_buffer[i]) {
+                               uvc_free_urb_buffers(video);
+                               break;
+                       }
+               }
+
+               if (i == UVC_URBS) {
+                       video->urb_size = psize * npackets;
+                       return npackets;
+               }
+       }
+
        return 0;
 }
 
@@ -757,28 +777,18 @@ static int uvc_init_video_isoc(struct uv
 {
        struct urb *urb;
        unsigned int npackets, i, j;
-       __u16 psize;
-       __u32 size;
-
-       /* Compute the number of isochronous packets to allocate by dividing
-        * the maximum video frame size by the packet size. Limit the result
-        * to UVC_MAX_ISO_PACKETS.
-        */
+       u16 psize;
+       u32 size;
+
        psize = le16_to_cpu(ep->desc.wMaxPacketSize);
        psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-
        size = video->streaming->ctrl.dwMaxVideoFrameSize;
-       if (size > UVC_MAX_FRAME_SIZE)
-               return -EINVAL;
-
-       npackets = DIV_ROUND_UP(size, psize);
-       if (npackets > UVC_MAX_ISO_PACKETS)
-               npackets = UVC_MAX_ISO_PACKETS;
+
+       npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags);
+       if (npackets == 0)
+               return -ENOMEM;
 
        size = npackets * psize;
-
-       if (uvc_alloc_urb_buffers(video, size) < 0)
-               return -ENOMEM;
 
        for (i = 0; i < UVC_URBS; ++i) {
                urb = usb_alloc_urb(npackets, gfp_flags);
@@ -818,24 +828,19 @@ static int uvc_init_video_bulk(struct uv
        struct usb_host_endpoint *ep, gfp_t gfp_flags)
 {
        struct urb *urb;
-       unsigned int pipe, i;
-       __u16 psize;
-       __u32 size;
-
-       /* Compute the bulk URB size. Some devices set the maximum payload
-        * size to a value too high for memory-constrained devices. We must
-        * then transfer the payload accross multiple URBs. To be consistant
-        * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk
-        * URB.
-        */
+       unsigned int npackets, pipe, i;
+       u16 psize;
+       u32 size;
+
        psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;
        size = video->streaming->ctrl.dwMaxPayloadTransferSize;
        video->bulk.max_payload_size = size;
-       if (size > psize * UVC_MAX_ISO_PACKETS)
-               size = psize * UVC_MAX_ISO_PACKETS;
-
-       if (uvc_alloc_urb_buffers(video, size) < 0)
+
+       npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags);
+       if (npackets == 0)
                return -ENOMEM;
+
+       size = npackets * psize;
 
        if (usb_endpoint_dir_in(&ep->desc))
                pipe = usb_rcvbulkpipe(video->dev->udev,
diff -r abb4add20e7b -r 14a2ef98f994 linux/drivers/media/video/uvc/uvcvideo.h
--- a/linux/drivers/media/video/uvc/uvcvideo.h  Thu Jan 22 20:59:21 2009 -0200
+++ b/linux/drivers/media/video/uvc/uvcvideo.h  Thu Jan 22 21:04:48 2009 -0200
@@ -297,10 +297,8 @@ struct uvc_xu_control {
 
 /* Number of isochronous URBs. */
 #define UVC_URBS               5
-/* Maximum number of packets per isochronous URB. */
-#define UVC_MAX_ISO_PACKETS    40
-/* Maximum frame size in bytes, for sanity checking. */
-#define UVC_MAX_FRAME_SIZE     (16*1024*1024)
+/* Maximum number of packets per URB. */
+#define UVC_MAX_PACKETS                32
 /* Maximum number of video buffers. */
 #define UVC_MAX_VIDEO_BUFFERS  32
 /* Maximum status buffer size in bytes of interrupt URB. */
@@ -650,6 +648,7 @@ struct uvc_device {
        struct urb *int_urb;
        __u8 *status;
        struct input_dev *input;
+       char input_phys[64];
 
        /* Video Streaming interfaces */
        struct list_head streaming;


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/14a2ef98f994ae124bae99d769c3249ef95be151

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to