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