From a597fa78d374c57dcf9a9bac02472a530cd7e60a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 10 Jun 2011 12:23:30 -0300 Subject: [media] v4l: Add over-current and indicator flash fault bits Flash controllers can report over-current and indicator fault conditions. Define flash fault control bits for them. Signed-off-by: Laurent Pinchart Acked-by: Andy Shevchenko Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/linux/videodev2.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/videodev2.h') diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 4b752d5ee80e..3d62631839bc 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1682,6 +1682,8 @@ enum v4l2_flash_strobe_source { #define V4L2_FLASH_FAULT_TIMEOUT (1 << 1) #define V4L2_FLASH_FAULT_OVER_TEMPERATURE (1 << 2) #define V4L2_FLASH_FAULT_SHORT_CIRCUIT (1 << 3) +#define V4L2_FLASH_FAULT_OVER_CURRENT (1 << 4) +#define V4L2_FLASH_FAULT_INDICATOR (1 << 5) #define V4L2_CID_FLASH_CHARGE (V4L2_CID_FLASH_CLASS_BASE + 11) #define V4L2_CID_FLASH_READY (V4L2_CID_FLASH_CLASS_BASE + 12) -- cgit v1.2.3 From cc1d327232759647ea56725eab1c6b16c92d52fa Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 14 Nov 2011 08:48:18 -0300 Subject: [media] v4l: Add new alpha component control The V4L2_CID_ALPHA_COMPONENT control is intended for the video capture or memory-to-memory devices that are capable of setting up the per-pixel alpha component to some arbitrary value. It allows to set the alpha component for all pixels to an arbitrary value. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 11 ++++++++++ Documentation/DocBook/media/v4l/controls.xml | 25 ++++++++++++++++------ .../DocBook/media/v4l/pixfmt-packed-rgb.xml | 7 ++++-- drivers/media/video/v4l2-ctrls.c | 1 + include/linux/videodev2.h | 6 +++--- 5 files changed, 39 insertions(+), 11 deletions(-) (limited to 'include/linux/videodev2.h') diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 8b44a43f4542..12ba26262d32 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2379,6 +2379,17 @@ that used it. It was originally scheduled for removal in 2.6.35. +
+ V4L2 in Linux 3.3 + + + Added V4L2_CID_ALPHA_COMPONENT control + to the User controls class. + + + +
+
Relation of V4L2 to other Linux multimedia APIs diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index c0422c622337..a1be37897ad7 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -323,12 +323,6 @@ minimum value disables backlight compensation. Switch on or off the illuminator 1 or 2 of the device (usually a microscope). - - V4L2_CID_LASTP1 - - End of the predefined control IDs (currently -V4L2_CID_ILLUMINATORS_2 + 1). - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE integer @@ -345,6 +339,25 @@ and used as a hint to determine the number of OUTPUT buffers to pass to REQBUFS. The value is the minimum number of OUTPUT buffers that is necessary for hardware to work. + + V4L2_CID_ALPHA_COMPONENT + integer + Sets the alpha color component on the capture device or on + the capture buffer queue of a mem-to-mem device. When a mem-to-mem + device produces frame format that includes an alpha component + (e.g. packed RGB image formats) + and the alpha value is not defined by the mem-to-mem input data + this control lets you select the alpha component value of all + pixels. It is applicable to any pixel format that contains an alpha + component. + + + + V4L2_CID_LASTP1 + + End of the predefined control IDs (currently + V4L2_CID_ALPHA_COMPONENT + 1). + V4L2_CID_PRIVATE_BASE diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml index ba56536622f2..166c8d65e4f7 100644 --- a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml +++ b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml @@ -428,8 +428,11 @@ colorspace V4L2_COLORSPACE_SRGB. Bit 7 is the most significant bit. The value of a = alpha bits is undefined when reading from the driver, ignored when writing to the driver, except when alpha blending has been negotiated for a -Video Overlay or Video Output Overlay. +Video Overlay or +Video Output Overlay or when alpha component has been configured +for a Video Capture by means of V4L2_CID_ALPHA_COMPONENT + control. <constant>V4L2_PIX_FMT_BGR24</constant> 4 × 4 pixel diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 0f415dade05a..39266153499f 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -467,6 +467,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2"; case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Minimum Number of Capture Buffers"; case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Minimum Number of Output Buffers"; + case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; /* MPEG controls */ /* Keep the order of the 'case's the same as in videodev2.h! */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 3d62631839bc..2965906a02c9 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1204,10 +1204,10 @@ enum v4l2_colorfx { #define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE (V4L2_CID_BASE+39) #define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT (V4L2_CID_BASE+40) -/* last CID + 1 */ -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+41) +#define V4L2_CID_ALPHA_COMPONENT (V4L2_CID_BASE+41) -/* Minimum number of buffer neede by the device */ +/* last CID + 1 */ +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+42) /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- cgit v1.2.3 From fe3449a4aa4e62404cc1c57c945fd56152b2f877 Mon Sep 17 00:00:00 2001 From: Theodore Kilgore <kilgota@banach.math.auburn.edu> Date: Tue, 13 Dec 2011 18:09:15 -0300 Subject: [media] gspca: Add jl2005bcd sub driver Written by Theodore Kilgore With minor changes by Hans de Goede: -Code style fixes -Correct the verbose level on various PDEBUG messages -Make error messages use pr_err instead of PDEBUG -Document the jl20 pixel format Signed-off-by: Theodore Kilgore <kilgota@auburn.edu> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- Documentation/DocBook/media/v4l/pixfmt.xml | 5 + Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/Kconfig | 10 + drivers/media/video/gspca/Makefile | 2 + drivers/media/video/gspca/jl2005bcd.c | 554 +++++++++++++++++++++++++++++ include/linux/videodev2.h | 1 + 6 files changed, 573 insertions(+) create mode 100644 drivers/media/video/gspca/jl2005bcd.c (limited to 'include/linux/videodev2.h') diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index a33a4b22173b..9ddc57cb2ef9 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -890,6 +890,11 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm <entry>'M310'</entry> <entry>Compressed BGGR Bayer format used by the gspca driver.</entry> </row> + <row id="V4L2-PIX-FMT-JL2005BCD"> + <entry><constant>V4L2_PIX_FMT_JL2005BCD</constant></entry> + <entry>'JL20'</entry> + <entry>JPEG compressed RGGB Bayer format used by the gspca driver.</entry> + </row> <row id="V4L2-PIX-FMT-OV511"> <entry><constant>V4L2_PIX_FMT_OV511</constant></entry> <entry>'O511'</entry> diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 393815b62810..f2060f0dc02c 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -279,6 +279,7 @@ pac7302 093a:2628 Genius iLook 300 pac7302 093a:2629 Genious iSlim 300 pac7302 093a:262a Webcam 300k pac7302 093a:262c Philips SPC 230 NC +jl2005bcd 0979:0227 Various brands, 19 known cameras supported jeilinj 0979:0280 Sakar 57379 jeilinj 0979:0280 Sportscam DV15 zc3xx 0ac8:0302 Z-star Vimicro zc0302 diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 103af3fe5aa0..dfe268bfa4f8 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -77,6 +77,16 @@ config USB_GSPCA_JEILINJ To compile this driver as a module, choose M here: the module will be called gspca_jeilinj. +config USB_GSPCA_JL2005BCD + tristate "JL2005B/C/D USB V4L2 driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based the + JL2005B, JL2005C, or JL2005D chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_jl2005bcd. + config USB_GSPCA_KINECT tristate "Kinect sensor device USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index f345f494d0f3..79ebe46e1ad7 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o +obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o @@ -49,6 +50,7 @@ gspca_cpia1-objs := cpia1.o gspca_etoms-objs := etoms.o gspca_finepix-objs := finepix.o gspca_jeilinj-objs := jeilinj.o +gspca_jl2005bcd-objs := jl2005bcd.o gspca_kinect-objs := kinect.o gspca_konica-objs := konica.o gspca_mars-objs := mars.o diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c new file mode 100644 index 000000000000..53f58ef367cf --- /dev/null +++ b/drivers/media/video/gspca/jl2005bcd.c @@ -0,0 +1,554 @@ +/* + * Jeilin JL2005B/C/D library + * + * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define MODULE_NAME "jl2005bcd" + +#include <linux/workqueue.h> +#include <linux/slab.h> +#include "gspca.h" + + +MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); +MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define JL2005C_CMD_TIMEOUT 500 +#define JL2005C_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define JL2005C_MAX_TRANSFER 0x200 +#define FRAME_HEADER_LEN 16 + + +/* specific webcam descriptor */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + unsigned char firmware_id[6]; + const struct v4l2_pix_format *cap_mode; + /* Driver stuff */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; + u8 frame_brightness; + int block_size; /* block size of camera */ + int vga; /* 1 if vga cam, 0 if cif cam */ +}; + + +/* Camera has two resolution settings. What they are depends on model. */ +static const struct v4l2_pix_format cif_mode[] = { + {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 176 * 144, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; + +static const struct v4l2_pix_format vga_mode[] = { + {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; + +/* + * cam uses endpoint 0x03 to send commands, 0x84 for read commands, + * and 0x82 for bulk data transfer. + */ + +/* All commands are two bytes only */ +static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command) +{ + int retval; + + memcpy(gspca_dev->usb_buf, command, 2); + retval = usb_bulk_msg(gspca_dev->dev, + usb_sndbulkpipe(gspca_dev->dev, 3), + gspca_dev->usb_buf, 2, NULL, 500); + if (retval < 0) + pr_err("command write [%02x] error %d\n", + gspca_dev->usb_buf[0], retval); + return retval; +} + +/* Response to a command is one byte in usb_buf[0], only if requested. */ +static int jl2005c_read1(struct gspca_dev *gspca_dev) +{ + int retval; + + retval = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x84), + gspca_dev->usb_buf, 1, NULL, 500); + if (retval < 0) + pr_err("read command [0x%02x] error %d\n", + gspca_dev->usb_buf[0], retval); + return retval; +} + +/* Response appears in gspca_dev->usb_buf[0] */ +static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg) +{ + int retval; + + static u8 instruction[2] = {0x95, 0x00}; + /* put register to read in byte 1 */ + instruction[1] = reg; + /* Send the read request */ + retval = jl2005c_write2(gspca_dev, instruction); + if (retval < 0) + return retval; + retval = jl2005c_read1(gspca_dev); + + return retval; +} + +static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev) +{ + int i; + int retval; + int frame_brightness = 0; + + static u8 instruction[2] = {0x7f, 0x01}; + + retval = jl2005c_write2(gspca_dev, instruction); + if (retval < 0) + return retval; + + i = 0; + while (i < 20 && !frame_brightness) { + /* If we tried 20 times, give up. */ + retval = jl2005c_read_reg(gspca_dev, 0x7e); + if (retval < 0) + return retval; + frame_brightness = gspca_dev->usb_buf[0]; + retval = jl2005c_read_reg(gspca_dev, 0x7d); + if (retval < 0) + return retval; + i++; + } + PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]); + return retval; +} + +static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg, + unsigned char value) +{ + int retval; + u8 instruction[2]; + + instruction[0] = reg; + instruction[1] = value; + + retval = jl2005c_write2(gspca_dev, instruction); + if (retval < 0) + return retval; + + return retval; +} + +static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *)gspca_dev; + int i = 0; + int retval = -1; + unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f}; + + PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id"); + /* Read the first ID byte once for warmup */ + retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]); + PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]); + if (retval < 0) + return retval; + /* Now actually get the ID string */ + for (i = 0; i < 6; i++) { + retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]); + if (retval < 0) + return retval; + sd->firmware_id[i] = gspca_dev->usb_buf[0]; + } + PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x", + sd->firmware_id[0], + sd->firmware_id[1], + sd->firmware_id[2], + sd->firmware_id[3], + sd->firmware_id[4], + sd->firmware_id[5]); + return 0; +} + +static int jl2005c_stream_start_vga_lg + (struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x05, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x18}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x52}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + +static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x06, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x1a}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x52}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + +static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x05, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x30}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x42}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + +static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x06, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x32}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x42}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + + +static int jl2005c_stop(struct gspca_dev *gspca_dev) +{ + int retval; + + retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00); + return retval; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface the gspca usb_lock is + * used when performing the one USB control operation inside the workqueue, + * which tells the camera to close the stream. In practice the only thing + * which needs to be protected against is the usb_set_interface call that + * gspca makes during stream_off. Otherwise the camera doesn't provide any + * controls that the user could try to change. + */ +static void jl2005c_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + int bytes_left = 0; /* bytes remaining in current frame. */ + int data_len; /* size to use for the next read. */ + int header_read = 0; + unsigned char header_sig[2] = {0x4a, 0x4c}; + int act_len; + int packet_type; + int ret; + u8 *buffer; + + buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + if (!buffer) { + pr_err("Couldn't allocate USB buffer\n"); + goto quit_stream; + } + + while (gspca_dev->present && gspca_dev->streaming) { + /* Check if this is a new frame. If so, start the frame first */ + if (!header_read) { + mutex_lock(&gspca_dev->usb_lock); + ret = jl2005c_start_new_frame(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + if (ret < 0) + goto quit_stream; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, JL2005C_MAX_TRANSFER, &act_len, + JL2005C_DATA_TIMEOUT); + PDEBUG(D_PACK, + "Got %d bytes out of %d for header", + act_len, JL2005C_MAX_TRANSFER); + if (ret < 0 || act_len < JL2005C_MAX_TRANSFER) + goto quit_stream; + /* Check whether we actually got the first blodk */ + if (memcmp(header_sig, buffer, 2) != 0) { + pr_err("First block is not the first block\n"); + goto quit_stream; + } + /* total size to fetch is byte 7, times blocksize + * of which we already got act_len */ + bytes_left = buffer[0x07] * dev->block_size - act_len; + PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left); + /* We keep the header. It has other information, too.*/ + packet_type = FIRST_PACKET; + gspca_frame_add(gspca_dev, packet_type, + buffer, act_len); + header_read = 1; + } + while (bytes_left > 0 && gspca_dev->present) { + data_len = bytes_left > JL2005C_MAX_TRANSFER ? + JL2005C_MAX_TRANSFER : bytes_left; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, data_len, &act_len, + JL2005C_DATA_TIMEOUT); + if (ret < 0 || act_len < data_len) + goto quit_stream; + PDEBUG(D_PACK, + "Got %d bytes out of %d for frame", + data_len, bytes_left); + bytes_left -= data_len; + if (bytes_left == 0) { + packet_type = LAST_PACKET; + header_read = 0; + } else + packet_type = INTER_PACKET; + gspca_frame_add(gspca_dev, packet_type, + buffer, data_len); + } + } +quit_stream: + if (gspca_dev->present) { + mutex_lock(&gspca_dev->usb_lock); + jl2005c_stop(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + } + kfree(buffer); +} + + + + +/* This function is called at probe time */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam; + struct sd *sd = (struct sd *) gspca_dev; + + cam = &gspca_dev->cam; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 64; + cam->bulk = 1; + /* For the rest, the camera needs to be detected */ + jl2005c_get_firmware_id(gspca_dev); + /* Here are some known firmware IDs + * First some JL2005B cameras + * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam + * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B + * JL2005C cameras + * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512 + * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly + * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz + * + * Based upon this scanty evidence, we can detect a CIF camera by + * testing byte 0 for 0x4x. + */ + if ((sd->firmware_id[0] & 0xf0) == 0x40) { + cam->cam_mode = cif_mode; + cam->nmodes = ARRAY_SIZE(cif_mode); + sd->block_size = 0x80; + } else { + cam->cam_mode = vga_mode; + cam->nmodes = ARRAY_SIZE(vga_mode); + sd->block_size = 0x200; + } + + INIT_WORK(&sd->work_struct, jl2005c_dostream); + + return 0; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + return 0; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + + struct sd *sd = (struct sd *) gspca_dev; + sd->cap_mode = gspca_dev->cam.cam_mode; + + switch (gspca_dev->width) { + case 640: + PDEBUG(D_STREAM, "Start streaming at vga resolution"); + jl2005c_stream_start_vga_lg(gspca_dev); + break; + case 320: + PDEBUG(D_STREAM, "Start streaming at qvga resolution"); + jl2005c_stream_start_vga_small(gspca_dev); + break; + case 352: + PDEBUG(D_STREAM, "Start streaming at cif resolution"); + jl2005c_stream_start_cif_lg(gspca_dev); + break; + case 176: + PDEBUG(D_STREAM, "Start streaming at qcif resolution"); + jl2005c_stream_start_cif_small(gspca_dev); + break; + default: + pr_err("Unknown resolution specified\n"); + return -1; + } + + /* Start the workqueue function to do the streaming */ + sd->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(sd->work_thread, &sd->work_struct); + + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for sq905c_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); +} + + + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + /* .ctrls = none have been detected */ + /* .nctrls = ARRAY_SIZE(sd_ctrls), */ + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- module initialisation -- */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x0979, 0x0227)}, + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + return 0; +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 2965906a02c9..6bfaa767a817 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -401,6 +401,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ #define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */ #define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */ #define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ -- cgit v1.2.3 From 6c06108be53ca5e94d8b0e93883d534dd9079646 Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Thu, 5 Jan 2012 02:27:57 -0300 Subject: [media] V4L/DVB: v4l2-ioctl: integer overflow in video_usercopy() If ctrls->count is too high the multiplication could overflow and array_size would be lower than expected. Mauro and Hans Verkuil suggested that we cap it at 1024. That comes from the maximum number of controls with lots of room for expantion. $ grep V4L2_CID include/linux/videodev2.h | wc -l 211 Cc: stable <stable@vger.kernel.org> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/v4l2-ioctl.c | 4 ++++ include/linux/videodev2.h | 1 + 2 files changed, 5 insertions(+) (limited to 'include/linux/videodev2.h') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index e1da8fc9dd2f..639abeee3392 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -2226,6 +2226,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, struct v4l2_ext_controls *ctrls = parg; if (ctrls->count != 0) { + if (ctrls->count > V4L2_CID_MAX_CTRLS) { + ret = -EINVAL; + break; + } *user_ptr = (void __user *)ctrls->controls; *kernel_ptr = (void *)&ctrls->controls; *array_size = sizeof(struct v4l2_ext_control) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 6bfaa767a817..b2e1331ca76b 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1132,6 +1132,7 @@ struct v4l2_querymenu { #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 /* User-class control IDs defined by V4L2 */ +#define V4L2_CID_MAX_CTRLS 1024 #define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) #define V4L2_CID_USER_BASE V4L2_CID_BASE /* IDs reserved for driver specific controls */ -- cgit v1.2.3 From 0e8caaceff160ad821c83d798fc03812cb810560 Mon Sep 17 00:00:00 2001 From: Tomasz Stanislawski <t.stanislaws@samsung.com> Date: Wed, 10 Aug 2011 10:37:47 -0300 Subject: [media] v4l: add support for selection api This patch introduces new api for a precise control of cropping and composing features for video devices. The new ioctls are VIDIOC_S_SELECTION and VIDIOC_G_SELECTION. Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/v4l2-compat-ioctl32.c | 2 ++ drivers/media/video/v4l2-ioctl.c | 34 +++++++++++++++++++++++ include/linux/videodev2.h | 46 +++++++++++++++++++++++++++++++ include/media/v4l2-ioctl.h | 4 +++ 4 files changed, 86 insertions(+) (limited to 'include/linux/videodev2.h') diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index c68531b88279..af4419e6c658 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -985,6 +985,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_CROPCAP: case VIDIOC_G_CROP: case VIDIOC_S_CROP: + case VIDIOC_G_SELECTION: + case VIDIOC_S_SELECTION: case VIDIOC_G_JPEGCOMP: case VIDIOC_S_JPEGCOMP: case VIDIOC_QUERYSTD: diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 639abeee3392..072cfc1a166f 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -238,6 +238,8 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", + [_IOC_NR(VIDIOC_G_SELECTION)] = "VIDIOC_G_SELECTION", + [_IOC_NR(VIDIOC_S_SELECTION)] = "VIDIOC_S_SELECTION", [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", @@ -1571,6 +1573,38 @@ static long __video_do_ioctl(struct file *file, ret = ops->vidioc_s_crop(file, fh, p); break; } + case VIDIOC_G_SELECTION: + { + struct v4l2_selection *p = arg; + + if (!ops->vidioc_g_selection) + break; + + dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); + + ret = ops->vidioc_g_selection(file, fh, p); + if (!ret) + dbgrect(vfd, "", &p->r); + break; + } + case VIDIOC_S_SELECTION: + { + struct v4l2_selection *p = arg; + + if (!ops->vidioc_s_selection) + break; + + if (ret_prio) { + ret = ret_prio; + break; + } + + dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); + dbgrect(vfd, "", &p->r); + + ret = ops->vidioc_s_selection(file, fh, p); + break; + } case VIDIOC_CROPCAP: { struct v4l2_cropcap *p = arg; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index b2e1331ca76b..012a29604522 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -743,6 +743,48 @@ struct v4l2_crop { struct v4l2_rect c; }; +/* Hints for adjustments of selection rectangle */ +#define V4L2_SEL_FLAG_GE 0x00000001 +#define V4L2_SEL_FLAG_LE 0x00000002 + +/* Selection targets */ + +/* current cropping area */ +#define V4L2_SEL_TGT_CROP_ACTIVE 0 +/* default cropping area */ +#define V4L2_SEL_TGT_CROP_DEFAULT 1 +/* cropping bounds */ +#define V4L2_SEL_TGT_CROP_BOUNDS 2 +/* current composing area */ +#define V4L2_SEL_TGT_COMPOSE_ACTIVE 256 +/* default composing area */ +#define V4L2_SEL_TGT_COMPOSE_DEFAULT 257 +/* composing bounds */ +#define V4L2_SEL_TGT_COMPOSE_BOUNDS 258 +/* current composing area plus all padding pixels */ +#define V4L2_SEL_TGT_COMPOSE_PADDED 259 + +/** + * struct v4l2_selection - selection info + * @type: buffer type (do not use *_MPLANE types) + * @target: selection target, used to choose one of possible rectangles + * @flags: constraints flags + * @r: coordinates of selection window + * @reserved: for future use, rounds structure size to 64 bytes, set to zero + * + * Hardware may use multiple helper window to process a video stream. + * The structure is used to exchange this selection areas between + * an application and a driver. + */ +struct v4l2_selection { + __u32 type; + __u32 target; + __u32 flags; + struct v4l2_rect r; + __u32 reserved[9]; +}; + + /* * A N A L O G V I D E O S T A N D A R D */ @@ -2259,6 +2301,10 @@ struct v4l2_create_buffers { #define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) #define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) +/* Experimental selection API */ +#define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) +#define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) + /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 4d1c74ad4c84..3f5d60fc5df6 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -196,6 +196,10 @@ struct v4l2_ioctl_ops { struct v4l2_crop *a); int (*vidioc_s_crop) (struct file *file, void *fh, struct v4l2_crop *a); + int (*vidioc_g_selection) (struct file *file, void *fh, + struct v4l2_selection *s); + int (*vidioc_s_selection) (struct file *file, void *fh, + struct v4l2_selection *s); /* Compression ioctls */ int (*vidioc_g_jpegcomp) (struct file *file, void *fh, struct v4l2_jpegcompression *a); -- cgit v1.2.3