media: v4l2: import HTC v4l2 stack
HTC kernel version: villeu-jb-crc-3.4.10-ae8b65e
Change-Id: Ib3cf788a9931b4efa68380ff6adf6ea6359a9ef9
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 1baec83..0969f47 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -33,16 +33,6 @@
* Fixes:
*/
-/*
- * Video4linux 1/2 integration by Justin Schoeman
- * <justin@suntiger.ee.up.ac.za>
- * 2.4 PROCFS support ported from 2.4 kernels by
- * Iñaki García Etxebarria <garetxe@euskalnet.net>
- * Makefile fix by "W. Michael Petullo" <mike@flyn.org>
- * 2.4 devfs support ported from 2.4 kernels by
- * Dan Merillat <dan@merillat.org>
- * Added Gerd Knorrs v4l1 enhancements (Justin Schoeman)
- */
#include <linux/module.h>
#include <linux/types.h>
@@ -55,6 +45,7 @@
#include <linux/spi/spi.h>
#endif
#include <asm/uaccess.h>
+#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/div64.h>
@@ -69,21 +60,9 @@
MODULE_DESCRIPTION("misc helper functions for v4l2 device drivers");
MODULE_LICENSE("GPL");
-/*
- *
- * V 4 L 2 D R I V E R H E L P E R A P I
- *
- */
-/*
- * Video Standard Operations (contributed by Michael Schimek)
- */
-/* Helper functions for control handling */
-/* Check for correctness of the ctrl's value based on the data from
- struct v4l2_queryctrl and the available menu items. Note that
- menu_items may be NULL, in that case it is ignored. */
int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
const char * const *menu_items)
{
@@ -104,14 +83,10 @@
menu_items[ctrl->value][0] == '\0')
return -EINVAL;
}
- if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&
- (ctrl->value & ~qctrl->maximum))
- return -ERANGE;
return 0;
}
EXPORT_SYMBOL(v4l2_ctrl_check);
-/* Fill in a struct v4l2_queryctrl */
int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
{
const char *name;
@@ -132,10 +107,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_query_fill);
-/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
- the menu. The qctrl pointer may be NULL, in which case it is ignored.
- If menu_items is NULL, then the menu items are retrieved using
- v4l2_ctrl_get_menu. */
int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
const char * const *menu_items)
{
@@ -155,9 +126,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_query_menu);
-/* Fill in a struct v4l2_querymenu based on the specified array of valid
- menu items (terminated by V4L2_CTRL_MENU_IDS_END).
- Use this if there are 'holes' in the list of valid menu items. */
int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
{
const char * const *menu_items = v4l2_ctrl_get_menu(qmenu->id);
@@ -176,14 +144,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items);
-/* ctrl_classes points to an array of u32 pointers, the last element is
- a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
- Each array must be sorted low to high and belong to the same control
- class. The array of u32 pointers must also be sorted, from low class IDs
- to high class IDs.
-
- This function returns the first ID that follows after the given ID.
- When no more controls are available 0 is returned. */
u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
{
u32 ctrl_class = V4L2_CTRL_ID2CLASS(id);
@@ -192,34 +152,32 @@
if (ctrl_classes == NULL)
return 0;
- /* if no query is desired, then check if the ID is part of ctrl_classes */
+
if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) {
- /* find class */
+
while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class)
ctrl_classes++;
if (*ctrl_classes == NULL)
return 0;
pctrl = *ctrl_classes;
- /* find control ID */
+
while (*pctrl && *pctrl != id) pctrl++;
return *pctrl ? id : 0;
}
id &= V4L2_CTRL_ID_MASK;
- id++; /* select next control */
- /* find first class that matches (or is greater than) the class of
- the ID */
+ id++;
while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class)
ctrl_classes++;
- /* no more classes */
+
if (*ctrl_classes == NULL)
return 0;
pctrl = *ctrl_classes;
- /* find first ctrl within the class that is >= ID */
+
while (*pctrl && *pctrl < id) pctrl++;
if (*pctrl)
return *pctrl;
- /* we are at the end of the controls of the current class. */
- /* continue with next class if available */
+
+
ctrl_classes++;
if (*ctrl_classes == NULL)
return 0;
@@ -251,7 +209,7 @@
if (c->driver == NULL || c->driver->driver.name == NULL)
return 0;
len = strlen(c->driver->driver.name);
- /* legacy drivers have a ' suffix, don't try to match that */
+
if (len && c->driver->driver.name[len - 1] == '\'')
len--;
return len && !strncmp(c->driver->driver.name, match->name, len);
@@ -280,9 +238,7 @@
}
EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
-/* ----------------------------------------------------------------- */
-/* I2C Helper functions */
void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
@@ -290,12 +246,12 @@
{
v4l2_subdev_init(sd, ops);
sd->flags |= V4L2_SUBDEV_FL_IS_I2C;
- /* the owner is the same as the i2c_client's driver owner */
+
sd->owner = client->driver->driver.owner;
- /* i2c_client and v4l2_subdev point to one another */
+
v4l2_set_subdevdata(sd, client);
i2c_set_clientdata(client, sd);
- /* initialize name */
+
snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
client->driver->driver.name, i2c_adapter_id(client->adapter),
client->addr);
@@ -304,7 +260,6 @@
-/* Load an i2c sub-device. */
struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
struct i2c_adapter *adapter, struct i2c_board_info *info,
const unsigned short *probe_addrs)
@@ -316,38 +271,27 @@
request_module(I2C_MODULE_PREFIX "%s", info->type);
- /* Create the i2c client */
+
if (info->addr == 0 && probe_addrs)
client = i2c_new_probed_device(adapter, info, probe_addrs,
NULL);
else
client = i2c_new_device(adapter, info);
- /* Note: by loading the module first we are certain that c->driver
- will be set if the driver was found. If the module was not loaded
- first, then the i2c core tries to delay-load the module for us,
- and then c->driver is still NULL until the module is finally
- loaded. This delay-load mechanism doesn't work if other drivers
- want to use the i2c device, so explicitly loading the module
- is the best alternative. */
if (client == NULL || client->driver == NULL)
goto error;
- /* Lock the module so we can safely get the v4l2_subdev pointer */
+
if (!try_module_get(client->driver->driver.owner))
goto error;
sd = i2c_get_clientdata(client);
- /* Register with the v4l2_device which increases the module's
- use count as well. */
if (v4l2_device_register_subdev(v4l2_dev, sd))
sd = NULL;
- /* Decrease the module use count to match the first try_module_get. */
+
module_put(client->driver->driver.owner);
error:
- /* If we have a client but no subdev, then something went wrong and
- we must unregister the client. */
if (client && sd == NULL)
i2c_unregister_device(client);
return sd;
@@ -360,8 +304,6 @@
{
struct i2c_board_info info;
- /* Setup the i2c board info with the device type and
- the device address. */
memset(&info, 0, sizeof(info));
strlcpy(info.type, client_type, sizeof(info.type));
info.addr = addr;
@@ -370,7 +312,6 @@
}
EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
-/* Return i2c client address of v4l2_subdev. */
unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -379,8 +320,6 @@
}
EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr);
-/* Return a list of I2C tuner addresses to probe. Use only if the tuner
- addresses are unknown. */
const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
{
static const unsigned short radio_addrs[] = {
@@ -395,7 +334,7 @@
I2C_CLIENT_END
};
static const unsigned short tv_addrs[] = {
- 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */
+ 0x42, 0x43, 0x4a, 0x4b,
0x60, 0x61, 0x62, 0x63, 0x64,
I2C_CLIENT_END
};
@@ -414,23 +353,22 @@
}
EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
-#endif /* defined(CONFIG_I2C) */
+#endif
#if defined(CONFIG_SPI)
-/* Load a spi sub-device. */
void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
const struct v4l2_subdev_ops *ops)
{
v4l2_subdev_init(sd, ops);
sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
- /* the owner is the same as the spi_device's driver owner */
+
sd->owner = spi->dev.driver->owner;
- /* spi_device and v4l2_subdev point to one another */
+
v4l2_set_subdevdata(sd, spi);
spi_set_drvdata(spi, sd);
- /* initialize name */
+
strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name));
}
EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
@@ -456,17 +394,13 @@
sd = spi_get_drvdata(spi);
- /* Register with the v4l2_device which increases the module's
- use count as well. */
if (v4l2_device_register_subdev(v4l2_dev, sd))
sd = NULL;
- /* Decrease the module use count to match the first try_module_get. */
+
module_put(spi->dev.driver->owner);
error:
- /* If we have a client but no subdev, then something went wrong and
- we must unregister the client. */
if (spi && sd == NULL)
spi_unregister_device(spi);
@@ -474,23 +408,19 @@
}
EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
-#endif /* defined(CONFIG_SPI) */
+#endif
-/* Clamp x to be between min and max, aligned to a multiple of 2^align. min
- * and max don't have to be aligned, but there must be at least one valid
- * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples
- * of 16 between 17 and 31. */
static unsigned int clamp_align(unsigned int x, unsigned int min,
unsigned int max, unsigned int align)
{
- /* Bits that must be zero to be aligned */
+
unsigned int mask = ~((1 << align) - 1);
- /* Round to nearest aligned value */
+
if (align)
x = (x + (1 << (align - 1))) & mask;
- /* Clamp to aligned value of min and max */
+
if (x < min)
x = (min + ~mask) & mask;
else if (x > max)
@@ -499,20 +429,6 @@
return x;
}
-/* Bound an image to have a width between wmin and wmax, and height between
- * hmin and hmax, inclusive. Additionally, the width will be a multiple of
- * 2^walign, the height will be a multiple of 2^halign, and the overall size
- * (width*height) will be a multiple of 2^salign. The image may be shrunk
- * or enlarged to fit the alignment constraints.
- *
- * The width or height maximum must not be smaller than the corresponding
- * minimum. The alignments must not be so high there are no possible image
- * sizes within the allowed bounds. wmin and hmin must be at least 1
- * (don't use 0). If you don't care about a certain alignment, specify 0,
- * as 2^0 is 1 and one byte alignment is equivalent to no alignment. If
- * you only want to adjust downward, specify a maximum that's the same as
- * the initial value.
- */
void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
unsigned int walign,
u32 *h, unsigned int hmin, unsigned int hmax,
@@ -521,21 +437,21 @@
*w = clamp_align(*w, wmin, wmax, walign);
*h = clamp_align(*h, hmin, hmax, halign);
- /* Usually we don't need to align the size and are done now. */
+
if (!salign)
return;
- /* How much alignment do we have? */
+
walign = __ffs(*w);
halign = __ffs(*h);
- /* Enough to satisfy the image alignment? */
+
if (walign + halign < salign) {
- /* Max walign where there is still a valid width */
+
unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
- /* Max halign where there is still a valid height */
+
unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
- /* up the smaller alignment until we have enough */
+
do {
if (halign >= hmaxa ||
(walign <= halign && walign < wmaxa)) {
@@ -550,14 +466,6 @@
}
EXPORT_SYMBOL_GPL(v4l_bound_align_image);
-/**
- * v4l_fill_dv_preset_info - fill description of a digital video preset
- * @preset - preset value
- * @info - pointer to struct v4l2_dv_enum_preset
- *
- * drivers can use this helper function to fill description of dv preset
- * in info.
- */
int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info)
{
static const struct v4l2_dv_preset_info {
@@ -565,25 +473,25 @@
u16 height;
const char *name;
} dv_presets[] = {
- { 0, 0, "Invalid" }, /* V4L2_DV_INVALID */
- { 720, 480, "480p@59.94" }, /* V4L2_DV_480P59_94 */
- { 720, 576, "576p@50" }, /* V4L2_DV_576P50 */
- { 1280, 720, "720p@24" }, /* V4L2_DV_720P24 */
- { 1280, 720, "720p@25" }, /* V4L2_DV_720P25 */
- { 1280, 720, "720p@30" }, /* V4L2_DV_720P30 */
- { 1280, 720, "720p@50" }, /* V4L2_DV_720P50 */
- { 1280, 720, "720p@59.94" }, /* V4L2_DV_720P59_94 */
- { 1280, 720, "720p@60" }, /* V4L2_DV_720P60 */
- { 1920, 1080, "1080i@29.97" }, /* V4L2_DV_1080I29_97 */
- { 1920, 1080, "1080i@30" }, /* V4L2_DV_1080I30 */
- { 1920, 1080, "1080i@25" }, /* V4L2_DV_1080I25 */
- { 1920, 1080, "1080i@50" }, /* V4L2_DV_1080I50 */
- { 1920, 1080, "1080i@60" }, /* V4L2_DV_1080I60 */
- { 1920, 1080, "1080p@24" }, /* V4L2_DV_1080P24 */
- { 1920, 1080, "1080p@25" }, /* V4L2_DV_1080P25 */
- { 1920, 1080, "1080p@30" }, /* V4L2_DV_1080P30 */
- { 1920, 1080, "1080p@50" }, /* V4L2_DV_1080P50 */
- { 1920, 1080, "1080p@60" }, /* V4L2_DV_1080P60 */
+ { 0, 0, "Invalid" },
+ { 720, 480, "480p@59.94" },
+ { 720, 576, "576p@50" },
+ { 1280, 720, "720p@24" },
+ { 1280, 720, "720p@25" },
+ { 1280, 720, "720p@30" },
+ { 1280, 720, "720p@50" },
+ { 1280, 720, "720p@59.94" },
+ { 1280, 720, "720p@60" },
+ { 1920, 1080, "1080i@29.97" },
+ { 1920, 1080, "1080i@30" },
+ { 1920, 1080, "1080i@25" },
+ { 1920, 1080, "1080i@50" },
+ { 1920, 1080, "1080i@60" },
+ { 1920, 1080, "1080p@24" },
+ { 1920, 1080, "1080p@25" },
+ { 1920, 1080, "1080p@30" },
+ { 1920, 1080, "1080p@50" },
+ { 1920, 1080, "1080p@60" },
};
if (info == NULL || preset >= ARRAY_SIZE(dv_presets))
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 7da4657..6cbd317 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -18,49 +18,20 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/slab.h>
-#include <linux/export.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
#include <media/v4l2-dev.h>
-#define has_op(master, op) \
- (master->ops && master->ops->op)
-#define call_op(master, op) \
- (has_op(master, op) ? master->ops->op(master) : 0)
-
-/* Internal temporary helper struct, one for each v4l2_ext_control */
-struct v4l2_ctrl_helper {
- /* Pointer to the control reference of the master control */
- struct v4l2_ctrl_ref *mref;
- /* The control corresponding to the v4l2_ext_control ID field. */
+struct ctrl_helper {
+
struct v4l2_ctrl *ctrl;
- /* v4l2_ext_control index of the next control belonging to the
- same cluster, or 0 if there isn't any. */
- u32 next;
+ bool handled;
};
-/* Small helper function to determine if the autocluster is set to manual
- mode. */
-static bool is_cur_manual(const struct v4l2_ctrl *master)
-{
- return master->is_auto && master->cur.val == master->manual_mode_value;
-}
-
-/* Same as above, but this checks the against the new value instead of the
- current value. */
-static bool is_new_manual(const struct v4l2_ctrl *master)
-{
- return master->is_auto && master->val == master->manual_mode_value;
-}
-
-/* Returns NULL or a character pointer array containing the menu for
- the given control ID. The pointer array ends with a NULL pointer.
- An empty string signifies a menu entry that is invalid. This allows
- drivers to disable certain options if it is not supported. */
const char * const *v4l2_ctrl_get_menu(u32 id)
{
static const char * const mpeg_audio_sampling_freq[] = {
@@ -175,15 +146,6 @@
"16-bit CRC",
NULL
};
- static const char * const mpeg_audio_dec_playback[] = {
- "Auto",
- "Stereo",
- "Left",
- "Right",
- "Mono",
- "Swapped Stereo",
- NULL
- };
static const char * const mpeg_video_encoding[] = {
"MPEG-1",
"MPEG-2",
@@ -213,14 +175,13 @@
};
static const char * const mpeg_stream_vbi_fmt[] = {
"No VBI",
- "Private Packet, IVTV Format",
+ "Private packet, IVTV format",
NULL
};
static const char * const camera_power_line_frequency[] = {
"Disabled",
"50 Hz",
"60 Hz",
- "Auto",
NULL
};
static const char * const camera_exposure_auto[] = {
@@ -237,147 +198,18 @@
"Negative",
"Emboss",
"Sketch",
- "Sky Blue",
- "Grass Green",
- "Skin Whiten",
+ "Sky blue",
+ "Grass green",
+ "Skin whiten",
"Vivid",
NULL
};
static const char * const tune_preemphasis[] = {
- "No Preemphasis",
- "50 Microseconds",
- "75 Microseconds",
+ "No preemphasis",
+ "50 useconds",
+ "75 useconds",
NULL,
};
- static const char * const header_mode[] = {
- "Separate Buffer",
- "Joined With 1st Frame",
- NULL,
- };
- static const char * const multi_slice[] = {
- "Single",
- "Max Macroblocks",
- "Max Bytes",
- NULL,
- };
- static const char * const entropy_mode[] = {
- "CAVLC",
- "CABAC",
- NULL,
- };
- static const char * const mpeg_h264_level[] = {
- "1",
- "1b",
- "1.1",
- "1.2",
- "1.3",
- "2",
- "2.1",
- "2.2",
- "3",
- "3.1",
- "3.2",
- "4",
- "4.1",
- "4.2",
- "5",
- "5.1",
- NULL,
- };
- static const char * const h264_loop_filter[] = {
- "Enabled",
- "Disabled",
- "Disabled at Slice Boundary",
- NULL,
- };
- static const char * const h264_profile[] = {
- "Baseline",
- "Constrained Baseline",
- "Main",
- "Extended",
- "High",
- "High 10",
- "High 422",
- "High 444 Predictive",
- "High 10 Intra",
- "High 422 Intra",
- "High 444 Intra",
- "CAVLC 444 Intra",
- "Scalable Baseline",
- "Scalable High",
- "Scalable High Intra",
- "Multiview High",
- NULL,
- };
- static const char * const vui_sar_idc[] = {
- "Unspecified",
- "1:1",
- "12:11",
- "10:11",
- "16:11",
- "40:33",
- "24:11",
- "20:11",
- "32:11",
- "80:33",
- "18:11",
- "15:11",
- "64:33",
- "160:99",
- "4:3",
- "3:2",
- "2:1",
- "Extended SAR",
- NULL,
- };
- static const char * const mpeg_mpeg4_level[] = {
- "0",
- "0b",
- "1",
- "2",
- "3",
- "3b",
- "4",
- "5",
- NULL,
- };
- static const char * const mpeg4_profile[] = {
- "Simple",
- "Advanced Simple",
- "Core",
- "Simple Scalable",
- "Advanced Coding Efficency",
- NULL,
- };
-
- static const char * const flash_led_mode[] = {
- "Off",
- "Flash",
- "Torch",
- NULL,
- };
- static const char * const flash_strobe_source[] = {
- "Software",
- "External",
- NULL,
- };
-
- static const char * const jpeg_chroma_subsampling[] = {
- "4:4:4",
- "4:2:2",
- "4:2:0",
- "4:1:1",
- "4:1:0",
- "Gray",
- NULL,
- };
- static const char *const mpeg_video_intra_refresh_mode[] = {
- "No Intra Refresh",
- "AIR MBS",
- "AIR REF",
- "CIR MBS",
- NULL
- };
switch (id) {
case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
@@ -400,9 +232,6 @@
return mpeg_audio_emphasis;
case V4L2_CID_MPEG_AUDIO_CRC:
return mpeg_audio_crc;
- case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:
- case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK:
- return mpeg_audio_dec_playback;
case V4L2_CID_MPEG_VIDEO_ENCODING:
return mpeg_video_encoding;
case V4L2_CID_MPEG_VIDEO_ASPECT:
@@ -421,44 +250,17 @@
return colorfx;
case V4L2_CID_TUNE_PREEMPHASIS:
return tune_preemphasis;
- case V4L2_CID_FLASH_LED_MODE:
- return flash_led_mode;
- case V4L2_CID_FLASH_STROBE_SOURCE:
- return flash_strobe_source;
- case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
- return header_mode;
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
- return multi_slice;
- case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
- return entropy_mode;
- case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
- return mpeg_h264_level;
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
- return h264_loop_filter;
- case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
- return h264_profile;
- case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
- return vui_sar_idc;
- case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
- return mpeg_mpeg4_level;
- case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
- return mpeg4_profile;
- case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
- return jpeg_chroma_subsampling;
- case V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE:
- return mpeg_video_intra_refresh_mode;
default:
return NULL;
}
}
EXPORT_SYMBOL(v4l2_ctrl_get_menu);
-/* Return the control name. */
const char *v4l2_ctrl_get_name(u32 id)
{
switch (id) {
- /* USER controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+
+
case V4L2_CID_USER_CLASS: return "User Controls";
case V4L2_CID_BRIGHTNESS: return "Brightness";
case V4L2_CID_CONTRAST: return "Contrast";
@@ -498,12 +300,9 @@
case V4L2_CID_CHROMA_GAIN: return "Chroma Gain";
case V4L2_CID_ILLUMINATORS_1: return "Illuminator 1";
case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2";
- case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Min Number of Capture Buffers";
- case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Min 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! */
+
+
case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls";
case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type";
case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID";
@@ -525,8 +324,6 @@
case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute";
case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate";
case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate";
- case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: return "Audio Playback";
- case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: return "Audio Multilingual Playback";
case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding";
case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect";
case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames";
@@ -539,61 +336,9 @@
case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation";
case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute";
case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV";
- case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface";
- case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable";
- case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs";
- case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable";
- case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control";
- case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode";
- case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "Max Number of Reference Pics";
- case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP: return "H263 I-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H263_MIN_QP: return "H263 Minimum QP Value";
- case V4L2_CID_MPEG_VIDEO_H263_MAX_QP: return "H263 Maximum QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: return "H264 I-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: return "H264 Maximum QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: return "H264 Minimum QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: return "H264 8x8 Transform Enable";
- case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: return "H264 CPB Buffer Size";
- case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entropy Mode";
- case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I-Frame Period";
- case V4L2_CID_MPEG_VIDEO_H264_LEVEL: return "H264 Level";
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: return "H264 Loop Filter Alpha Offset";
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: return "H264 Loop Filter Beta Offset";
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: return "H264 Loop Filter Mode";
- case V4L2_CID_MPEG_VIDEO_H264_PROFILE: return "H264 Profile";
- case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT: return "Vertical Size of SAR";
- case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH: return "Horizontal Size of SAR";
- case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable";
- case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC";
- case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP: return "MPEG4 Minimum QP Value";
- case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP: return "MPEG4 Maximum QP Value";
- case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: return "MPEG4 Level";
- case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: return "MPEG4 Profile";
- case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: return "Quarter Pixel Search Enable";
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "Maximum Bytes in a Slice";
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice";
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method";
- case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size";
- case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS";
- case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count";
- case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION: return "Rotation";
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL: return "Rate Control";
- case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL: return "CABAC Model";
- case V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE:
- return "Intra Refresh Mode";
- case V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS: return "Intra Refresh AIR MBS";
- case V4L2_CID_MPEG_VIDC_VIDEO_AIR_REF: return "Intra Refresh AIR REF";
- case V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS: return "Intra Refresh CIR MBS";
- /* CAMERA controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+
+
case V4L2_CID_CAMERA_CLASS: return "Camera Controls";
case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure";
case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute";
@@ -614,8 +359,8 @@
case V4L2_CID_IRIS_ABSOLUTE: return "Iris, Absolute";
case V4L2_CID_IRIS_RELATIVE: return "Iris, Relative";
- /* FM Radio Modulator control */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+
+
case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls";
case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation";
case V4L2_CID_RDS_TX_PI: return "RDS Program ID";
@@ -625,7 +370,7 @@
case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled";
case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation";
- case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled";
+ case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled";
case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain";
case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
@@ -633,33 +378,10 @@
case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled";
case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation";
case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency";
- case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis";
+ case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings";
case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level";
case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor";
- /* Flash controls */
- case V4L2_CID_FLASH_CLASS: return "Flash Controls";
- case V4L2_CID_FLASH_LED_MODE: return "LED Mode";
- case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe Source";
- case V4L2_CID_FLASH_STROBE: return "Strobe";
- case V4L2_CID_FLASH_STROBE_STOP: return "Stop Strobe";
- case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe Status";
- case V4L2_CID_FLASH_TIMEOUT: return "Strobe Timeout";
- case V4L2_CID_FLASH_INTENSITY: return "Intensity, Flash Mode";
- case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, Torch Mode";
- case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator";
- case V4L2_CID_FLASH_FAULT: return "Faults";
- case V4L2_CID_FLASH_CHARGE: return "Charge";
- case V4L2_CID_FLASH_READY: return "Ready to Strobe";
-
- /* JPEG encoder controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
- case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls";
- case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling";
- case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval";
- case V4L2_CID_JPEG_COMPRESSION_QUALITY: return "Compression Quality";
- case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers";
-
default:
return NULL;
}
@@ -694,24 +416,12 @@
case V4L2_CID_PILOT_TONE_ENABLED:
case V4L2_CID_ILLUMINATORS_1:
case V4L2_CID_ILLUMINATORS_2:
- case V4L2_CID_FLASH_STROBE_STATUS:
- case V4L2_CID_FLASH_CHARGE:
- case V4L2_CID_FLASH_READY:
- case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
- case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
- case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
- case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
- case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
- case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
- case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
*type = V4L2_CTRL_TYPE_BOOLEAN;
*min = 0;
*max = *step = 1;
break;
case V4L2_CID_PAN_RESET:
case V4L2_CID_TILT_RESET:
- case V4L2_CID_FLASH_STROBE:
- case V4L2_CID_FLASH_STROBE_STOP:
*type = V4L2_CTRL_TYPE_BUTTON;
*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
*min = *max = *step = *def = 0;
@@ -727,8 +437,6 @@
case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
case V4L2_CID_MPEG_AUDIO_EMPHASIS:
case V4L2_CID_MPEG_AUDIO_CRC:
- case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:
- case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK:
case V4L2_CID_MPEG_VIDEO_ENCODING:
case V4L2_CID_MPEG_VIDEO_ASPECT:
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
@@ -737,21 +445,6 @@
case V4L2_CID_EXPOSURE_AUTO:
case V4L2_CID_COLORFX:
case V4L2_CID_TUNE_PREEMPHASIS:
- case V4L2_CID_FLASH_LED_MODE:
- case V4L2_CID_FLASH_STROBE_SOURCE:
- case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
- case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
- case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
- case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
- case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
- case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
- case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
- case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
- case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL:
- case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
*type = V4L2_CTRL_TYPE_MENU;
break;
case V4L2_CID_RDS_TX_PS_NAME:
@@ -762,39 +455,18 @@
case V4L2_CID_CAMERA_CLASS:
case V4L2_CID_MPEG_CLASS:
case V4L2_CID_FM_TX_CLASS:
- case V4L2_CID_FLASH_CLASS:
- case V4L2_CID_JPEG_CLASS:
*type = V4L2_CTRL_TYPE_CTRL_CLASS;
- /* You can neither read not write these */
+
*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
*min = *max = *step = *def = 0;
break;
case V4L2_CID_BG_COLOR:
- case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
- case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
- case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
- *type = V4L2_CTRL_TYPE_INTEGER;
+ *type = V4L2_CTRL_TYPE_INTEGER;
*step = 1;
*min = 0;
- /* Max is calculated as RGB888 that is 2^24 */
+
*max = 0xFFFFFF;
break;
- case V4L2_CID_FLASH_FAULT:
- case V4L2_CID_JPEG_ACTIVE_MARKER:
- *type = V4L2_CTRL_TYPE_BITMASK;
- break;
- case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
- case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
- *type = V4L2_CTRL_TYPE_INTEGER;
- *flags |= V4L2_CTRL_FLAG_READ_ONLY;
- break;
- case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
- case V4L2_CID_MPEG_VIDEO_DEC_PTS:
- *type = V4L2_CTRL_TYPE_INTEGER64;
- *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE;
- break;
default:
*type = V4L2_CTRL_TYPE_INTEGER;
break;
@@ -840,65 +512,22 @@
case V4L2_CID_ZOOM_RELATIVE:
*flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
break;
- case V4L2_CID_FLASH_STROBE_STATUS:
- case V4L2_CID_FLASH_READY:
- *flags |= V4L2_CTRL_FLAG_READ_ONLY;
- break;
}
}
EXPORT_SYMBOL(v4l2_ctrl_fill);
-/* Helper function to determine whether the control type is compatible with
- VIDIOC_G/S_CTRL. */
static bool type_is_int(const struct v4l2_ctrl *ctrl)
{
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER64:
case V4L2_CTRL_TYPE_STRING:
- /* Nope, these need v4l2_ext_control */
+
return false;
default:
return true;
}
}
-static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes)
-{
- memset(ev->reserved, 0, sizeof(ev->reserved));
- ev->type = V4L2_EVENT_CTRL;
- ev->id = ctrl->id;
- ev->u.ctrl.changes = changes;
- ev->u.ctrl.type = ctrl->type;
- ev->u.ctrl.flags = ctrl->flags;
- if (ctrl->type == V4L2_CTRL_TYPE_STRING)
- ev->u.ctrl.value64 = 0;
- else
- ev->u.ctrl.value64 = ctrl->cur.val64;
- ev->u.ctrl.minimum = ctrl->minimum;
- ev->u.ctrl.maximum = ctrl->maximum;
- if (ctrl->type == V4L2_CTRL_TYPE_MENU)
- ev->u.ctrl.step = 1;
- else
- ev->u.ctrl.step = ctrl->step;
- ev->u.ctrl.default_value = ctrl->default_value;
-}
-
-static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
-{
- struct v4l2_event ev;
- struct v4l2_subscribed_event *sev;
-
- if (list_empty(&ctrl->ev_subs))
- return;
- fill_event(&ev, ctrl, changes);
-
- list_for_each_entry(sev, &ctrl->ev_subs, node)
- if (sev->fh != fh ||
- (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))
- v4l2_event_queue_fh(sev->fh, &ev);
-}
-
-/* Helper function: copy the current control value back to the caller */
static int cur_to_user(struct v4l2_ext_control *c,
struct v4l2_ctrl *ctrl)
{
@@ -923,7 +552,6 @@
return 0;
}
-/* Helper function: copy the caller-provider value as the new control value */
static int user_to_new(struct v4l2_ext_control *c,
struct v4l2_ctrl *ctrl)
{
@@ -946,8 +574,6 @@
char last = ctrl->string[size - 1];
ctrl->string[size - 1] = 0;
- /* If the string was longer than ctrl->maximum,
- then return an error. */
if (strlen(ctrl->string) == ctrl->maximum && last)
return -ERANGE;
}
@@ -959,7 +585,6 @@
return 0;
}
-/* Helper function: copy the new control value back to the caller */
static int new_to_user(struct v4l2_ext_control *c,
struct v4l2_ctrl *ctrl)
{
@@ -984,62 +609,31 @@
return 0;
}
-/* Copy the new value to the current value. */
-static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
- bool update_inactive)
+static void new_to_cur(struct v4l2_ctrl *ctrl)
{
- bool changed = false;
-
if (ctrl == NULL)
return;
switch (ctrl->type) {
- case V4L2_CTRL_TYPE_BUTTON:
- changed = true;
- break;
case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
- changed = strcmp(ctrl->string, ctrl->cur.string);
+
strcpy(ctrl->cur.string, ctrl->string);
break;
case V4L2_CTRL_TYPE_INTEGER64:
- changed = ctrl->val64 != ctrl->cur.val64;
ctrl->cur.val64 = ctrl->val64;
break;
default:
- changed = ctrl->val != ctrl->cur.val;
ctrl->cur.val = ctrl->val;
break;
}
- if (update_inactive) {
- /* Note: update_inactive can only be true for auto clusters. */
- ctrl->flags &=
- ~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE);
- if (!is_cur_manual(ctrl->cluster[0])) {
- ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
- if (ctrl->cluster[0]->has_volatiles)
- ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
- }
- fh = NULL;
- }
- if (changed || update_inactive) {
- /* If a control was changed that was not one of the controls
- modified by the application, then send the event to all. */
- if (!ctrl->is_new)
- fh = NULL;
- send_event(fh, ctrl,
- (changed ? V4L2_EVENT_CTRL_CH_VALUE : 0) |
- (update_inactive ? V4L2_EVENT_CTRL_CH_FLAGS : 0));
- }
}
-/* Copy the current value to the new value */
static void cur_to_new(struct v4l2_ctrl *ctrl)
{
if (ctrl == NULL)
return;
switch (ctrl->type) {
case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
+
strcpy(ctrl->string, ctrl->cur.string);
break;
case V4L2_CTRL_TYPE_INTEGER64:
@@ -1051,8 +645,6 @@
}
}
-/* Return non-zero if one or more of the controls in the cluster has a new
- value that differs from the current value. */
static int cluster_changed(struct v4l2_ctrl *master)
{
int diff = 0;
@@ -1065,10 +657,10 @@
continue;
switch (ctrl->type) {
case V4L2_CTRL_TYPE_BUTTON:
- /* Button controls are always 'different' */
+
return 1;
case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
+
diff = strcmp(ctrl->string, ctrl->cur.string);
break;
case V4L2_CTRL_TYPE_INTEGER64:
@@ -1082,15 +674,16 @@
return diff;
}
-/* Validate integer-type control */
-static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval)
+static int validate_new(struct v4l2_ctrl *ctrl)
{
- s32 val = *pval;
+ s32 val = ctrl->val;
+ char *s = ctrl->string;
u32 offset;
+ size_t len;
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER:
- /* Round towards the closest legal value */
+
val += ctrl->step / 2;
if (val < ctrl->minimum)
val = ctrl->minimum;
@@ -1099,11 +692,11 @@
offset = val - ctrl->minimum;
offset = ctrl->step * (offset / ctrl->step);
val = ctrl->minimum + offset;
- *pval = val;
+ ctrl->val = val;
return 0;
case V4L2_CTRL_TYPE_BOOLEAN:
- *pval = !!val;
+ ctrl->val = !!ctrl->val;
return 0;
case V4L2_CTRL_TYPE_MENU:
@@ -1114,35 +707,11 @@
return -EINVAL;
return 0;
- case V4L2_CTRL_TYPE_BITMASK:
- *pval &= ctrl->maximum;
- return 0;
-
case V4L2_CTRL_TYPE_BUTTON:
case V4L2_CTRL_TYPE_CTRL_CLASS:
- *pval = 0;
+ ctrl->val64 = 0;
return 0;
- default:
- return -EINVAL;
- }
-}
-
-/* Validate a new control */
-static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
-{
- char *s = c->string;
- size_t len;
-
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_INTEGER:
- case V4L2_CTRL_TYPE_BOOLEAN:
- case V4L2_CTRL_TYPE_MENU:
- case V4L2_CTRL_TYPE_BITMASK:
- case V4L2_CTRL_TYPE_BUTTON:
- case V4L2_CTRL_TYPE_CTRL_CLASS:
- return validate_new_int(ctrl, &c->value);
-
case V4L2_CTRL_TYPE_INTEGER64:
return 0;
@@ -1164,7 +733,6 @@
return list_entry(node, struct v4l2_ctrl_ref, node)->ctrl->id;
}
-/* Set the handler's error code if it wasn't set earlier already */
static inline int handler_set_err(struct v4l2_ctrl_handler *hdl, int err)
{
if (hdl->error == 0)
@@ -1172,7 +740,6 @@
return err;
}
-/* Initialize the handler */
int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
unsigned nr_of_controls_hint)
{
@@ -1180,34 +747,30 @@
INIT_LIST_HEAD(&hdl->ctrls);
INIT_LIST_HEAD(&hdl->ctrl_refs);
hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
- hdl->buckets = kcalloc(hdl->nr_of_buckets, sizeof(hdl->buckets[0]),
- GFP_KERNEL);
+ hdl->buckets = kzalloc(sizeof(hdl->buckets[0]) * hdl->nr_of_buckets,
+ GFP_KERNEL);
hdl->error = hdl->buckets ? 0 : -ENOMEM;
return hdl->error;
}
EXPORT_SYMBOL(v4l2_ctrl_handler_init);
-/* Free all controls and control refs */
void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
{
struct v4l2_ctrl_ref *ref, *next_ref;
struct v4l2_ctrl *ctrl, *next_ctrl;
- struct v4l2_subscribed_event *sev, *next_sev;
if (hdl == NULL || hdl->buckets == NULL)
return;
mutex_lock(&hdl->lock);
- /* Free all nodes */
+
list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
list_del(&ref->node);
kfree(ref);
}
- /* Free all controls owned by the handler */
+
list_for_each_entry_safe(ctrl, next_ctrl, &hdl->ctrls, node) {
list_del(&ctrl->node);
- list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node)
- list_del(&sev->node);
kfree(ctrl);
}
kfree(hdl->buckets);
@@ -1218,12 +781,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_handler_free);
-/* For backwards compatibility: V4L2_CID_PRIVATE_BASE should no longer
- be used except in G_CTRL, S_CTRL, QUERYCTRL and QUERYMENU when dealing
- with applications that do not use the NEXT_CTRL flag.
-
- We just find the n-th private user control. It's O(N), but that should not
- be an issue in this particular case. */
static struct v4l2_ctrl_ref *find_private_ref(
struct v4l2_ctrl_handler *hdl, u32 id)
{
@@ -1231,8 +788,6 @@
id -= V4L2_CID_PRIVATE_BASE;
list_for_each_entry(ref, &hdl->ctrl_refs, node) {
- /* Search for private user controls that are compatible with
- VIDIOC_G/S_CTRL. */
if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER &&
V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) {
if (!type_is_int(ref->ctrl))
@@ -1245,7 +800,6 @@
return NULL;
}
-/* Find a control with the given ID. */
static struct v4l2_ctrl_ref *find_ref(struct v4l2_ctrl_handler *hdl, u32 id)
{
struct v4l2_ctrl_ref *ref;
@@ -1253,26 +807,25 @@
id &= V4L2_CTRL_ID_MASK;
- /* Old-style private controls need special handling */
+
if (id >= V4L2_CID_PRIVATE_BASE)
return find_private_ref(hdl, id);
bucket = id % hdl->nr_of_buckets;
- /* Simple optimization: cache the last control found */
+
if (hdl->cached && hdl->cached->ctrl->id == id)
return hdl->cached;
- /* Not in cache, search the hash */
+
ref = hdl->buckets ? hdl->buckets[bucket] : NULL;
while (ref && ref->ctrl->id != id)
ref = ref->next;
if (ref)
- hdl->cached = ref; /* cache it! */
+ hdl->cached = ref;
return ref;
}
-/* Find a control with the given ID. Take the handler's lock first. */
static struct v4l2_ctrl_ref *find_ref_lock(
struct v4l2_ctrl_handler *hdl, u32 id)
{
@@ -1286,7 +839,6 @@
return ref;
}
-/* Find a control with the given ID. */
struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
{
struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
@@ -1295,7 +847,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_find);
-/* Allocate a new v4l2_ctrl_ref and hook it into the handler. */
static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
struct v4l2_ctrl *ctrl)
{
@@ -1303,9 +854,9 @@
struct v4l2_ctrl_ref *new_ref;
u32 id = ctrl->id;
u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1;
- int bucket = id % hdl->nr_of_buckets; /* which bucket to use */
+ int bucket = id % hdl->nr_of_buckets;
- /* Automatically add the control class if it is not yet present. */
+
if (id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0))
return hdl->error;
@@ -1318,10 +869,6 @@
return handler_set_err(hdl, -ENOMEM);
new_ref->ctrl = ctrl;
if (ctrl->handler == hdl) {
- /* By default each control starts in a cluster of its own.
- new_ref->ctrl is basically a cluster array with one
- element, so that's perfect to use as the cluster pointer.
- But only do this for the handler that owns the control. */
ctrl->cluster = &new_ref->ctrl;
ctrl->ncontrols = 1;
}
@@ -1330,20 +877,16 @@
mutex_lock(&hdl->lock);
- /* Add immediately at the end of the list if the list is empty, or if
- the last element in the list has a lower ID.
- This ensures that when elements are added in ascending order the
- insertion is an O(1) operation. */
if (list_empty(&hdl->ctrl_refs) || id > node2id(hdl->ctrl_refs.prev)) {
list_add_tail(&new_ref->node, &hdl->ctrl_refs);
goto insert_in_hash;
}
- /* Find insert position in sorted list */
+
list_for_each_entry(ref, &hdl->ctrl_refs, node) {
if (ref->ctrl->id < id)
continue;
- /* Don't add duplicates */
+
if (ref->ctrl->id == id) {
kfree(new_ref);
goto unlock;
@@ -1353,7 +896,7 @@
}
insert_in_hash:
- /* Insert the control node in the hash */
+
new_ref->next = hdl->buckets[bucket];
hdl->buckets[bucket] = new_ref;
@@ -1362,7 +905,6 @@
return 0;
}
-/* Add a new control */
static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, const char *name, enum v4l2_ctrl_type type,
@@ -1375,19 +917,15 @@
if (hdl->error)
return NULL;
- /* Sanity checks */
+
if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
+ max < min ||
(type == V4L2_CTRL_TYPE_INTEGER && step == 0) ||
- (type == V4L2_CTRL_TYPE_BITMASK && max == 0) ||
(type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
(type == V4L2_CTRL_TYPE_STRING && max == 0)) {
handler_set_err(hdl, -ERANGE);
return NULL;
}
- if (type != V4L2_CTRL_TYPE_BITMASK && max < min) {
- handler_set_err(hdl, -ERANGE);
- return NULL;
- }
if ((type == V4L2_CTRL_TYPE_INTEGER ||
type == V4L2_CTRL_TYPE_MENU ||
type == V4L2_CTRL_TYPE_BOOLEAN) &&
@@ -1395,10 +933,6 @@
handler_set_err(hdl, -ERANGE);
return NULL;
}
- if (type == V4L2_CTRL_TYPE_BITMASK && ((def & ~max) || min || step)) {
- handler_set_err(hdl, -ERANGE);
- return NULL;
- }
if (type == V4L2_CTRL_TYPE_BUTTON)
flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -1414,7 +948,6 @@
}
INIT_LIST_HEAD(&ctrl->node);
- INIT_LIST_HEAD(&ctrl->ev_subs);
ctrl->handler = hdl;
ctrl->ops = ops;
ctrl->id = id;
@@ -1474,13 +1007,14 @@
type, min, max,
is_menu ? cfg->menu_skip_mask : step,
def, flags, qmenu, priv);
- if (ctrl)
+ if (ctrl) {
ctrl->is_private = cfg->is_private;
+ ctrl->is_volatile = cfg->is_volatile;
+ }
return ctrl;
}
EXPORT_SYMBOL(v4l2_ctrl_new_custom);
-/* Helper function for standard non-menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 min, s32 max, u32 step, s32 def)
@@ -1499,7 +1033,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_new_std);
-/* Helper function for standard menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 max, s32 mask, s32 def)
@@ -1521,7 +1054,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
-/* Add a control from another handler to this handler */
struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl,
struct v4l2_ctrl *ctrl)
{
@@ -1537,28 +1069,22 @@
}
EXPORT_SYMBOL(v4l2_ctrl_add_ctrl);
-/* Add the controls from another handler to our own. */
int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
struct v4l2_ctrl_handler *add)
{
- struct v4l2_ctrl_ref *ref;
+ struct v4l2_ctrl *ctrl;
int ret = 0;
- /* Do nothing if either handler is NULL or if they are the same */
+
if (!hdl || !add || hdl == add)
return 0;
if (hdl->error)
return hdl->error;
mutex_lock(&add->lock);
- list_for_each_entry(ref, &add->ctrl_refs, node) {
- struct v4l2_ctrl *ctrl = ref->ctrl;
-
- /* Skip handler-private controls. */
+ list_for_each_entry(ctrl, &add->ctrls, node) {
+
if (ctrl->is_private)
continue;
- /* And control classes */
- if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
- continue;
ret = handler_new_ref(hdl, ctrl);
if (ret)
break;
@@ -1568,104 +1094,56 @@
}
EXPORT_SYMBOL(v4l2_ctrl_add_handler);
-/* Cluster controls */
void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
{
- bool has_volatiles = false;
int i;
- /* The first control is the master control and it must not be NULL */
- BUG_ON(ncontrols == 0 || controls[0] == NULL);
+
+ BUG_ON(controls[0] == NULL);
for (i = 0; i < ncontrols; i++) {
if (controls[i]) {
controls[i]->cluster = controls;
controls[i]->ncontrols = ncontrols;
- if (controls[i]->flags & V4L2_CTRL_FLAG_VOLATILE)
- has_volatiles = true;
}
}
- controls[0]->has_volatiles = has_volatiles;
}
EXPORT_SYMBOL(v4l2_ctrl_cluster);
-void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
- u8 manual_val, bool set_volatile)
-{
- struct v4l2_ctrl *master = controls[0];
- u32 flag = 0;
- int i;
-
- v4l2_ctrl_cluster(ncontrols, controls);
- WARN_ON(ncontrols <= 1);
- WARN_ON(manual_val < master->minimum || manual_val > master->maximum);
- WARN_ON(set_volatile && !has_op(master, g_volatile_ctrl));
- master->is_auto = true;
- master->has_volatiles = set_volatile;
- master->manual_mode_value = manual_val;
- master->flags |= V4L2_CTRL_FLAG_UPDATE;
-
- if (!is_cur_manual(master))
- flag = V4L2_CTRL_FLAG_INACTIVE |
- (set_volatile ? V4L2_CTRL_FLAG_VOLATILE : 0);
-
- for (i = 1; i < ncontrols; i++)
- if (controls[i])
- controls[i]->flags |= flag;
-}
-EXPORT_SYMBOL(v4l2_ctrl_auto_cluster);
-
-/* Activate/deactivate a control. */
void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active)
{
- /* invert since the actual flag is called 'inactive' */
- bool inactive = !active;
- bool old;
-
if (ctrl == NULL)
return;
- if (inactive)
- /* set V4L2_CTRL_FLAG_INACTIVE */
- old = test_and_set_bit(4, &ctrl->flags);
+ if (!active)
+
+ set_bit(4, &ctrl->flags);
else
- /* clear V4L2_CTRL_FLAG_INACTIVE */
- old = test_and_clear_bit(4, &ctrl->flags);
- if (old != inactive)
- send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS);
+
+ clear_bit(4, &ctrl->flags);
}
EXPORT_SYMBOL(v4l2_ctrl_activate);
-/* Grab/ungrab a control.
- Typically used when streaming starts and you want to grab controls,
- preventing the user from changing them.
-
- Just call this and the framework will block any attempts to change
- these controls. */
void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed)
{
- bool old;
-
if (ctrl == NULL)
return;
- v4l2_ctrl_lock(ctrl);
if (grabbed)
- /* set V4L2_CTRL_FLAG_GRABBED */
- old = test_and_set_bit(1, &ctrl->flags);
+
+ set_bit(1, &ctrl->flags);
else
- /* clear V4L2_CTRL_FLAG_GRABBED */
- old = test_and_clear_bit(1, &ctrl->flags);
- if (old != grabbed)
- send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS);
- v4l2_ctrl_unlock(ctrl);
+
+ clear_bit(1, &ctrl->flags);
}
EXPORT_SYMBOL(v4l2_ctrl_grab);
-/* Log the control name and value */
static void log_ctrl(const struct v4l2_ctrl *ctrl,
const char *prefix, const char *colon)
{
+ int fl_inact = ctrl->flags & V4L2_CTRL_FLAG_INACTIVE;
+ int fl_grabbed = ctrl->flags & V4L2_CTRL_FLAG_GRABBED;
+
if (ctrl->flags & (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY))
return;
if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
@@ -1683,9 +1161,6 @@
case V4L2_CTRL_TYPE_MENU:
printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
break;
- case V4L2_CTRL_TYPE_BITMASK:
- printk(KERN_CONT "0x%08x", ctrl->cur.val);
- break;
case V4L2_CTRL_TYPE_INTEGER64:
printk(KERN_CONT "%lld", ctrl->cur.val64);
break;
@@ -1696,20 +1171,16 @@
printk(KERN_CONT "unknown type %d", ctrl->type);
break;
}
- if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
- V4L2_CTRL_FLAG_GRABBED |
- V4L2_CTRL_FLAG_VOLATILE)) {
- if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
- printk(KERN_CONT " inactive");
- if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
- printk(KERN_CONT " grabbed");
- if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
- printk(KERN_CONT " volatile");
- }
- printk(KERN_CONT "\n");
+ if (fl_inact && fl_grabbed)
+ printk(KERN_CONT " (inactive, grabbed)\n");
+ else if (fl_inact)
+ printk(KERN_CONT " (inactive)\n");
+ else if (fl_grabbed)
+ printk(KERN_CONT " (grabbed)\n");
+ else
+ printk(KERN_CONT "\n");
}
-/* Log all controls owned by the handler */
void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl,
const char *prefix)
{
@@ -1732,7 +1203,6 @@
}
EXPORT_SYMBOL(v4l2_ctrl_handler_log_status);
-/* Call s_ctrl for all controls owned by the handler */
int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
{
struct v4l2_ctrl *ctrl;
@@ -1748,29 +1218,33 @@
struct v4l2_ctrl *master = ctrl->cluster[0];
int i;
- /* Skip if this control was already handled by a cluster. */
- /* Skip button controls and read-only controls. */
- if (ctrl->done || ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
- (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
+
+ if (ctrl->done)
continue;
for (i = 0; i < master->ncontrols; i++) {
if (master->cluster[i]) {
cur_to_new(master->cluster[i]);
master->cluster[i]->is_new = 1;
- master->cluster[i]->done = true;
}
}
- ret = call_op(master, s_ctrl);
+
+
+ if (ctrl->type == V4L2_CTRL_TYPE_BUTTON ||
+ (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
+ continue;
+ ret = master->ops->s_ctrl(master);
if (ret)
break;
+ for (i = 0; i < master->ncontrols; i++)
+ if (master->cluster[i])
+ master->cluster[i]->done = true;
}
mutex_unlock(&hdl->lock);
return ret;
}
EXPORT_SYMBOL(v4l2_ctrl_handler_setup);
-/* Implement VIDIOC_QUERYCTRL */
int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
{
u32 id = qc->id & V4L2_CTRL_ID_MASK;
@@ -1782,24 +1256,18 @@
mutex_lock(&hdl->lock);
- /* Try to find it */
+
ref = find_ref(hdl, id);
if ((qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) && !list_empty(&hdl->ctrl_refs)) {
- /* Find the next control with ID > qc->id */
+
- /* Did we reach the end of the control list? */
+
if (id >= node2id(hdl->ctrl_refs.prev)) {
- ref = NULL; /* Yes, so there is no next control */
+ ref = NULL;
} else if (ref) {
- /* We found a control with the given ID, so just get
- the next one in the list. */
ref = list_entry(ref->node.next, typeof(*ref), node);
} else {
- /* No control with the given ID exists, so start
- searching for the next largest ID. We know there
- is one, otherwise the first 'if' above would have
- been true. */
list_for_each_entry(ref, &hdl->ctrl_refs, node)
if (id < ref->ctrl->id)
break;
@@ -1837,7 +1305,6 @@
}
EXPORT_SYMBOL(v4l2_subdev_queryctrl);
-/* Implement VIDIOC_QUERYMENU */
int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm)
{
struct v4l2_ctrl *ctrl;
@@ -1848,14 +1315,14 @@
return -EINVAL;
qm->reserved = 0;
- /* Sanity checks */
+
if (ctrl->qmenu == NULL ||
i < ctrl->minimum || i > ctrl->maximum)
return -EINVAL;
- /* Use mask to see if this menu item should be skipped */
+
if (ctrl->menu_skip_mask & (1 << i))
return -EINVAL;
- /* Empty menu items should also be skipped */
+
if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0')
return -EINVAL;
strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name));
@@ -1871,128 +1338,74 @@
-/* Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS:
- It is not a fully atomic operation, just best-effort only. After all, if
- multiple controls have to be set through multiple i2c writes (for example)
- then some initial writes may succeed while others fail. Thus leaving the
- system in an inconsistent state. The question is how much effort you are
- willing to spend on trying to make something atomic that really isn't.
-
- From the point of view of an application the main requirement is that
- when you call VIDIOC_S_EXT_CTRLS and some values are invalid then an
- error should be returned without actually affecting any controls.
-
- If all the values are correct, then it is acceptable to just give up
- in case of low-level errors.
-
- It is important though that the application can tell when only a partial
- configuration was done. The way we do that is through the error_idx field
- of struct v4l2_ext_controls: if that is equal to the count field then no
- controls were affected. Otherwise all controls before that index were
- successful in performing their 'get' or 'set' operation, the control at
- the given index failed, and you don't know what happened with the controls
- after the failed one. Since if they were part of a control cluster they
- could have been successfully processed (if a cluster member was encountered
- at index < error_idx), they could have failed (if a cluster member was at
- error_idx), or they may not have been processed yet (if the first cluster
- member appeared after error_idx).
-
- It is all fairly theoretical, though. In practice all you can do is to
- bail out. If error_idx == count, then it is an application bug. If
- error_idx < count then it is only an application bug if the error code was
- EBUSY. That usually means that something started streaming just when you
- tried to set the controls. In all other cases it is a driver/hardware
- problem and all you can do is to retry or bail out.
-
- Note that these rules do not apply to VIDIOC_TRY_EXT_CTRLS: since that
- never modifies controls the error_idx is just set to whatever control
- has an invalid value.
- */
-
-/* Prepare for the extended g/s/try functions.
- Find the controls in the control array and do some basic checks. */
static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_controls *cs,
- struct v4l2_ctrl_helper *helpers)
+ struct ctrl_helper *helpers,
+ bool try)
{
- struct v4l2_ctrl_helper *h;
- bool have_clusters = false;
u32 i;
- for (i = 0, h = helpers; i < cs->count; i++, h++) {
+ for (i = 0; i < cs->count; i++) {
struct v4l2_ext_control *c = &cs->controls[i];
- struct v4l2_ctrl_ref *ref;
struct v4l2_ctrl *ctrl;
u32 id = c->id & V4L2_CTRL_ID_MASK;
- cs->error_idx = i;
+ if (try)
+ cs->error_idx = i;
if (cs->ctrl_class && V4L2_CTRL_ID2CLASS(id) != cs->ctrl_class)
return -EINVAL;
- /* Old-style private controls are not allowed for
- extended controls */
if (id >= V4L2_CID_PRIVATE_BASE)
return -EINVAL;
- ref = find_ref_lock(hdl, id);
- if (ref == NULL)
+ ctrl = v4l2_ctrl_find(hdl, id);
+ if (ctrl == NULL)
return -EINVAL;
- ctrl = ref->ctrl;
if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
return -EINVAL;
- if (ctrl->cluster[0]->ncontrols > 1)
- have_clusters = true;
- if (ctrl->cluster[0] != ctrl)
- ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
- /* Store the ref to the master control of the cluster */
- h->mref = ref;
- h->ctrl = ctrl;
- /* Initially set next to 0, meaning that there is no other
- control in this helper array belonging to the same
- cluster */
- h->next = 0;
+ helpers[i].ctrl = ctrl;
+ helpers[i].handled = false;
}
-
- /* We are done if there were no controls that belong to a multi-
- control cluster. */
- if (!have_clusters)
- return 0;
-
- /* The code below figures out in O(n) time which controls in the list
- belong to the same cluster. */
-
- /* This has to be done with the handler lock taken. */
- mutex_lock(&hdl->lock);
-
- /* First zero the helper field in the master control references */
- for (i = 0; i < cs->count; i++)
- helpers[i].mref->helper = 0;
- for (i = 0, h = helpers; i < cs->count; i++, h++) {
- struct v4l2_ctrl_ref *mref = h->mref;
-
- /* If the mref->helper is set, then it points to an earlier
- helper that belongs to the same cluster. */
- if (mref->helper) {
- /* Set the next field of mref->helper to the current
- index: this means that that earlier helper now
- points to the next helper in the same cluster. */
- mref->helper->next = i;
- /* mref should be set only for the first helper in the
- cluster, clear the others. */
- h->mref = NULL;
- }
- /* Point the mref helper to the current helper struct. */
- mref->helper = h;
- }
- mutex_unlock(&hdl->lock);
return 0;
}
-/* Handles the corner case where cs->count == 0. It checks whether the
- specified control class exists. If that class ID is 0, then it checks
- whether there are any controls at all. */
+typedef int (*cluster_func)(struct v4l2_ext_control *c,
+ struct v4l2_ctrl *ctrl);
+
+static int cluster_walk(unsigned from,
+ struct v4l2_ext_controls *cs,
+ struct ctrl_helper *helpers,
+ cluster_func f)
+{
+ struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
+ int ret = 0;
+ int i;
+
+
+ for (i = from; !ret && i < cs->count; i++) {
+ struct v4l2_ctrl *ctrl = helpers[i].ctrl;
+
+ if (!helpers[i].handled && ctrl->cluster == cluster)
+ ret = f(&cs->controls[i], ctrl);
+ }
+ return ret;
+}
+
+static void cluster_done(unsigned from,
+ struct v4l2_ext_controls *cs,
+ struct ctrl_helper *helpers)
+{
+ struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
+ int i;
+
+
+ for (i = from; i < cs->count; i++)
+ if (helpers[i].ctrl->cluster == cluster)
+ helpers[i].handled = true;
+}
+
static int class_check(struct v4l2_ctrl_handler *hdl, u32 ctrl_class)
{
if (ctrl_class == 0)
@@ -2002,13 +1415,12 @@
-/* Get extended controls. Allocates the helpers array if needed. */
int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
{
- struct v4l2_ctrl_helper helper[4];
- struct v4l2_ctrl_helper *helpers = helper;
+ struct ctrl_helper helper[4];
+ struct ctrl_helper *helpers = helper;
int ret;
- int i, j;
+ int i;
cs->error_idx = cs->count;
cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);
@@ -2025,47 +1437,30 @@
return -ENOMEM;
}
- ret = prepare_ext_ctrls(hdl, cs, helpers);
- cs->error_idx = cs->count;
+ ret = prepare_ext_ctrls(hdl, cs, helpers, false);
for (i = 0; !ret && i < cs->count; i++)
if (helpers[i].ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
ret = -EACCES;
for (i = 0; !ret && i < cs->count; i++) {
- int (*ctrl_to_user)(struct v4l2_ext_control *c,
- struct v4l2_ctrl *ctrl) = cur_to_user;
- struct v4l2_ctrl *master;
+ struct v4l2_ctrl *ctrl = helpers[i].ctrl;
+ struct v4l2_ctrl *master = ctrl->cluster[0];
- if (helpers[i].mref == NULL)
+ if (helpers[i].handled)
continue;
- master = helpers[i].mref->ctrl;
cs->error_idx = i;
v4l2_ctrl_lock(master);
-
- /* g_volatile_ctrl will update the new control values */
- if ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
- (master->has_volatiles && !is_cur_manual(master))) {
- for (j = 0; j < master->ncontrols; j++)
- cur_to_new(master->cluster[j]);
- ret = call_op(master, g_volatile_ctrl);
- ctrl_to_user = new_to_user;
- }
- /* If OK, then copy the current (for non-volatile controls)
- or the new (for volatile controls) control values to the
- caller */
- if (!ret) {
- u32 idx = i;
-
- do {
- ret = ctrl_to_user(cs->controls + idx,
- helpers[idx].ctrl);
- idx = helpers[idx].next;
- } while (!ret && idx);
- }
+
+ if (ctrl->is_volatile && master->ops->g_volatile_ctrl)
+ ret = master->ops->g_volatile_ctrl(master);
+
+ if (!ret)
+ ret = cluster_walk(i, cs, helpers, cur_to_user);
v4l2_ctrl_unlock(master);
+ cluster_done(i, cs, helpers);
}
if (cs->count > ARRAY_SIZE(helper))
@@ -2080,26 +1475,19 @@
}
EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls);
-/* Helper function to get a single control */
static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
{
struct v4l2_ctrl *master = ctrl->cluster[0];
int ret = 0;
- int i;
if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
return -EACCES;
v4l2_ctrl_lock(master);
- /* g_volatile_ctrl will update the current control values */
- if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
- for (i = 0; i < master->ncontrols; i++)
- cur_to_new(master->cluster[i]);
- ret = call_op(master, g_volatile_ctrl);
- *val = ctrl->val;
- } else {
- *val = ctrl->cur.val;
- }
+
+ if (ctrl->is_volatile && master->ops->g_volatile_ctrl)
+ ret = master->ops->g_volatile_ctrl(master);
+ *val = ctrl->cur.val;
v4l2_ctrl_unlock(master);
return ret;
}
@@ -2124,7 +1512,7 @@
{
s32 val = 0;
- /* It's a driver bug if this happens. */
+
WARN_ON(!type_is_int(ctrl));
get_ctrl(ctrl, &val);
return val;
@@ -2132,105 +1520,105 @@
EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
-/* Core function that calls try/s_ctrl and ensures that the new value is
- copied to the current value on a set.
- Must be called with ctrl->handler->lock held. */
-static int try_or_set_cluster(struct v4l2_fh *fh,
- struct v4l2_ctrl *master, bool set)
+static int try_or_set_control_cluster(struct v4l2_ctrl *master, bool set)
{
- bool update_flag;
- int ret;
+ bool try = !set;
+ int ret = 0;
int i;
- /* Go through the cluster and either validate the new value or
- (if no new value was set), copy the current value to the new
- value, ensuring a consistent view for the control ops when
- called. */
- for (i = 0; i < master->ncontrols; i++) {
+ for (i = 0; !ret && i < master->ncontrols; i++) {
struct v4l2_ctrl *ctrl = master->cluster[i];
if (ctrl == NULL)
continue;
- if (!ctrl->is_new) {
- cur_to_new(ctrl);
+ if (ctrl->is_new) {
+ if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
+ return -EBUSY;
+
+
+ if (!set)
+ ret = validate_new(ctrl);
continue;
}
- /* Check again: it may have changed since the
- previous check in try_or_set_ext_ctrls(). */
- if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
- return -EBUSY;
+ try = true;
+ cur_to_new(ctrl);
}
- ret = call_op(master, try_ctrl);
+ if (!ret && master->ops->try_ctrl && try)
+ ret = master->ops->try_ctrl(master);
- /* Don't set if there is no change */
- if (ret || !set || !cluster_changed(master))
- return ret;
- ret = call_op(master, s_ctrl);
- if (ret)
- return ret;
-
- /* If OK, then make the new values permanent. */
- update_flag = is_cur_manual(master) != is_new_manual(master);
- for (i = 0; i < master->ncontrols; i++)
- new_to_cur(fh, master->cluster[i], update_flag && i > 0);
- return 0;
+
+ if (!ret && set && cluster_changed(master)) {
+ ret = master->ops->s_ctrl(master);
+
+ if (!ret)
+ for (i = 0; i < master->ncontrols; i++)
+ new_to_cur(master->cluster[i]);
+ }
+ return ret;
}
-/* Validate controls. */
-static int validate_ctrls(struct v4l2_ext_controls *cs,
- struct v4l2_ctrl_helper *helpers, bool set)
+static int try_or_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
+ struct v4l2_ext_controls *cs,
+ struct ctrl_helper *helpers,
+ bool set)
{
- unsigned i;
+ unsigned i, j;
int ret = 0;
cs->error_idx = cs->count;
for (i = 0; i < cs->count; i++) {
struct v4l2_ctrl *ctrl = helpers[i].ctrl;
- cs->error_idx = i;
+ if (!set)
+ cs->error_idx = i;
if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
return -EACCES;
- /* This test is also done in try_set_control_cluster() which
- is called in atomic context, so that has the final say,
- but it makes sense to do an up-front check as well. Once
- an error occurs in try_set_control_cluster() some other
- controls may have been set already and we want to do a
- best-effort to avoid that. */
if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
return -EBUSY;
- ret = validate_new(ctrl, &cs->controls[i]);
- if (ret)
- return ret;
}
- return 0;
+
+ for (i = 0; !ret && i < cs->count; i++) {
+ struct v4l2_ctrl *ctrl = helpers[i].ctrl;
+ struct v4l2_ctrl *master = ctrl->cluster[0];
+
+ cs->error_idx = i;
+
+ if (helpers[i].handled)
+ continue;
+
+ v4l2_ctrl_lock(ctrl);
+
+
+ for (j = 0; j < master->ncontrols; j++)
+ if (master->cluster[j])
+ master->cluster[j]->is_new = 0;
+
+ ret = cluster_walk(i, cs, helpers, user_to_new);
+
+ if (!ret)
+ ret = try_or_set_control_cluster(master, set);
+
+
+ if (!ret)
+ ret = cluster_walk(i, cs, helpers, new_to_user);
+
+ v4l2_ctrl_unlock(ctrl);
+ cluster_done(i, cs, helpers);
+ }
+ return ret;
}
-/* Obtain the current volatile values of an autocluster and mark them
- as new. */
-static void update_from_auto_cluster(struct v4l2_ctrl *master)
-{
- int i;
-
- for (i = 0; i < master->ncontrols; i++)
- cur_to_new(master->cluster[i]);
- if (!call_op(master, g_volatile_ctrl))
- for (i = 1; i < master->ncontrols; i++)
- if (master->cluster[i])
- master->cluster[i]->is_new = 1;
-}
-
-/* Try or try-and-set controls */
-static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
+static int try_set_ext_ctrls(struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_controls *cs,
bool set)
{
- struct v4l2_ctrl_helper helper[4];
- struct v4l2_ctrl_helper *helpers = helper;
- unsigned i, j;
+ struct ctrl_helper helper[4];
+ struct ctrl_helper *helpers = helper;
int ret;
+ int i;
cs->error_idx = cs->count;
cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);
@@ -2246,74 +1634,22 @@
if (!helpers)
return -ENOMEM;
}
- ret = prepare_ext_ctrls(hdl, cs, helpers);
- if (!ret)
- ret = validate_ctrls(cs, helpers, set);
- if (ret && set)
+ ret = prepare_ext_ctrls(hdl, cs, helpers, !set);
+ if (ret)
+ goto free;
+
+
+ ret = try_or_set_ext_ctrls(hdl, cs, helpers, false);
+ if (set)
cs->error_idx = cs->count;
- for (i = 0; !ret && i < cs->count; i++) {
- struct v4l2_ctrl *master;
- u32 idx = i;
-
- if (helpers[i].mref == NULL)
- continue;
-
- cs->error_idx = i;
- master = helpers[i].mref->ctrl;
- v4l2_ctrl_lock(master);
-
- /* Reset the 'is_new' flags of the cluster */
- for (j = 0; j < master->ncontrols; j++)
- if (master->cluster[j])
- master->cluster[j]->is_new = 0;
-
- /* For volatile autoclusters that are currently in auto mode
- we need to discover if it will be set to manual mode.
- If so, then we have to copy the current volatile values
- first since those will become the new manual values (which
- may be overwritten by explicit new values from this set
- of controls). */
- if (master->is_auto && master->has_volatiles &&
- !is_cur_manual(master)) {
- /* Pick an initial non-manual value */
- s32 new_auto_val = master->manual_mode_value + 1;
- u32 tmp_idx = idx;
-
- do {
- /* Check if the auto control is part of the
- list, and remember the new value. */
- if (helpers[tmp_idx].ctrl == master)
- new_auto_val = cs->controls[tmp_idx].value;
- tmp_idx = helpers[tmp_idx].next;
- } while (tmp_idx);
- /* If the new value == the manual value, then copy
- the current volatile values. */
- if (new_auto_val == master->manual_mode_value)
- update_from_auto_cluster(master);
- }
-
- /* Copy the new caller-supplied control values.
- user_to_new() sets 'is_new' to 1. */
- do {
- ret = user_to_new(cs->controls + idx, helpers[idx].ctrl);
- idx = helpers[idx].next;
- } while (!ret && idx);
-
- if (!ret)
- ret = try_or_set_cluster(fh, master, set);
-
- /* Copy the new values back to userspace. */
- if (!ret) {
- idx = i;
- do {
- ret = new_to_user(cs->controls + idx,
- helpers[idx].ctrl);
- idx = helpers[idx].next;
- } while (!ret && idx);
- }
- v4l2_ctrl_unlock(master);
+ if (!ret && set) {
+
+ for (i = 0; i < cs->count; i++)
+ helpers[i].handled = false;
+ ret = try_or_set_ext_ctrls(hdl, cs, helpers, true);
}
+free:
if (cs->count > ARRAY_SIZE(helper))
kfree(helpers);
return ret;
@@ -2321,146 +1657,75 @@
int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
{
- return try_set_ext_ctrls(NULL, hdl, cs, false);
+ return try_set_ext_ctrls(hdl, cs, false);
}
EXPORT_SYMBOL(v4l2_try_ext_ctrls);
-int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
- struct v4l2_ext_controls *cs)
+int v4l2_s_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
{
- return try_set_ext_ctrls(fh, hdl, cs, true);
+ return try_set_ext_ctrls(hdl, cs, true);
}
EXPORT_SYMBOL(v4l2_s_ext_ctrls);
int v4l2_subdev_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs)
{
- return try_set_ext_ctrls(NULL, sd->ctrl_handler, cs, false);
+ return try_set_ext_ctrls(sd->ctrl_handler, cs, false);
}
EXPORT_SYMBOL(v4l2_subdev_try_ext_ctrls);
int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs)
{
- return try_set_ext_ctrls(NULL, sd->ctrl_handler, cs, true);
+ return try_set_ext_ctrls(sd->ctrl_handler, cs, true);
}
EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls);
-/* Helper function for VIDIOC_S_CTRL compatibility */
-static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
+static int set_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
{
struct v4l2_ctrl *master = ctrl->cluster[0];
int ret;
int i;
- ret = validate_new_int(ctrl, val);
- if (ret)
- return ret;
+ if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
+ return -EACCES;
v4l2_ctrl_lock(ctrl);
- /* Reset the 'is_new' flags of the cluster */
+
for (i = 0; i < master->ncontrols; i++)
if (master->cluster[i])
master->cluster[i]->is_new = 0;
- /* For autoclusters with volatiles that are switched from auto to
- manual mode we have to update the current volatile values since
- those will become the initial manual values after such a switch. */
- if (master->is_auto && master->has_volatiles && ctrl == master &&
- !is_cur_manual(master) && *val == master->manual_mode_value)
- update_from_auto_cluster(master);
ctrl->val = *val;
ctrl->is_new = 1;
- ret = try_or_set_cluster(fh, master, true);
+ ret = try_or_set_control_cluster(master, false);
+ if (!ret)
+ ret = try_or_set_control_cluster(master, true);
*val = ctrl->cur.val;
v4l2_ctrl_unlock(ctrl);
return ret;
}
-int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
- struct v4l2_control *control)
+int v4l2_s_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
{
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
if (ctrl == NULL || !type_is_int(ctrl))
return -EINVAL;
- if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
- return -EACCES;
-
- return set_ctrl(fh, ctrl, &control->value);
+ return set_ctrl(ctrl, &control->value);
}
EXPORT_SYMBOL(v4l2_s_ctrl);
int v4l2_subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control)
{
- return v4l2_s_ctrl(NULL, sd->ctrl_handler, control);
+ return v4l2_s_ctrl(sd->ctrl_handler, control);
}
EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
{
- /* It's a driver bug if this happens. */
+
WARN_ON(!type_is_int(ctrl));
- return set_ctrl(NULL, ctrl, &val);
+ return set_ctrl(ctrl, &val);
}
EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
-
-void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev)
-{
- v4l2_ctrl_lock(ctrl);
- list_add_tail(&sev->node, &ctrl->ev_subs);
- if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS &&
- (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL)) {
- struct v4l2_event ev;
- u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
-
- if (!(ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY))
- changes |= V4L2_EVENT_CTRL_CH_VALUE;
- fill_event(&ev, ctrl, changes);
- v4l2_event_queue_fh(sev->fh, &ev);
- }
- v4l2_ctrl_unlock(ctrl);
-}
-EXPORT_SYMBOL(v4l2_ctrl_add_event);
-
-void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev)
-{
- v4l2_ctrl_lock(ctrl);
- list_del(&sev->node);
- v4l2_ctrl_unlock(ctrl);
-}
-EXPORT_SYMBOL(v4l2_ctrl_del_event);
-
-int v4l2_ctrl_log_status(struct file *file, void *fh)
-{
- struct video_device *vfd = video_devdata(file);
- struct v4l2_fh *vfh = file->private_data;
-
- if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev)
- v4l2_ctrl_handler_log_status(vfh->ctrl_handler,
- vfd->v4l2_dev->name);
- return 0;
-}
-EXPORT_SYMBOL(v4l2_ctrl_log_status);
-
-int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- if (sub->type == V4L2_EVENT_CTRL)
- return v4l2_event_subscribe(fh, sub, 0);
- return -EINVAL;
-}
-EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
-
-unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct v4l2_fh *fh = file->private_data;
-
- if (v4l2_event_pending(fh))
- return POLLPRI;
- poll_wait(file, &fh->wait, wait);
- return 0;
-}
-EXPORT_SYMBOL(v4l2_ctrl_poll);
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 70bec54..ba13a3e 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -26,6 +26,7 @@
#include <linux/kmod.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
+#include <asm/system.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
@@ -34,9 +35,6 @@
#define VIDEO_NUM_DEVICES 256
#define VIDEO_NAME "video4linux"
-/*
- * sysfs stuff
- */
static ssize_t show_index(struct device *cd,
struct device_attribute *attr, char *buf)
@@ -60,50 +58,36 @@
__ATTR_NULL
};
-/*
- * Active devices
- */
static struct video_device *video_device[VIDEO_NUM_DEVICES];
static DEFINE_MUTEX(videodev_lock);
static DECLARE_BITMAP(devnode_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES);
-/* Device node utility functions */
-/* Note: these utility functions all assume that vfl_type is in the range
- [0, VFL_TYPE_MAX-1]. */
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
-/* Return the bitmap corresponding to vfl_type. */
static inline unsigned long *devnode_bits(int vfl_type)
{
- /* Any types not assigned to fixed minor ranges must be mapped to
- one single bitmap for the purposes of finding a free node number
- since all those unassigned types use the same minor range. */
int idx = (vfl_type > VFL_TYPE_RADIO) ? VFL_TYPE_MAX - 1 : vfl_type;
return devnode_nums[idx];
}
#else
-/* Return the bitmap corresponding to vfl_type. */
static inline unsigned long *devnode_bits(int vfl_type)
{
return devnode_nums[vfl_type];
}
#endif
-/* Mark device node number vdev->num as used */
static inline void devnode_set(struct video_device *vdev)
{
set_bit(vdev->num, devnode_bits(vdev->vfl_type));
}
-/* Mark device node number vdev->num as unused */
static inline void devnode_clear(struct video_device *vdev)
{
clear_bit(vdev->num, devnode_bits(vdev->vfl_type));
}
-/* Try to find a free device node number in the range [from, to> */
static inline int devnode_find(struct video_device *vdev, int from, int to)
{
return find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
@@ -123,8 +107,8 @@
void video_device_release_empty(struct video_device *vdev)
{
- /* Do nothing */
- /* Only valid when the video_device struct is a static. */
+
+
}
EXPORT_SYMBOL(video_device_release_empty);
@@ -138,55 +122,40 @@
put_device(&vdev->dev);
}
-/* Called when the last user of the video device exits. */
static void v4l2_device_release(struct device *cd)
{
struct video_device *vdev = to_video_device(cd);
struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
mutex_lock(&videodev_lock);
- if (WARN_ON(video_device[vdev->minor] != vdev)) {
- /* should not happen */
+ if (video_device[vdev->minor] != vdev) {
mutex_unlock(&videodev_lock);
+
+ WARN_ON(1);
return;
}
- /* Free up this device for reuse */
+
video_device[vdev->minor] = NULL;
- /* Delete the cdev on this minor as well */
+
cdev_del(vdev->cdev);
- /* Just in case some driver tries to access this from
- the release() callback. */
vdev->cdev = NULL;
- /* Mark device node number as free */
+
devnode_clear(vdev);
mutex_unlock(&videodev_lock);
#if defined(CONFIG_MEDIA_CONTROLLER)
- if (v4l2_dev && v4l2_dev->mdev &&
+ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
vdev->vfl_type != VFL_TYPE_SUBDEV)
media_device_unregister_entity(&vdev->entity);
#endif
- /* Do not call v4l2_device_put if there is no release callback set.
- * Drivers that have no v4l2_device release callback might free the
- * v4l2_dev instance in the video_device release callback below, so we
- * must perform this check here.
- *
- * TODO: In the long run all drivers that use v4l2_device should use the
- * v4l2_device release callback. This check will then be unnecessary.
- */
- if (v4l2_dev && v4l2_dev->release == NULL)
- v4l2_dev = NULL;
-
- /* Release video_device and perform other
- cleanups as needed. */
vdev->release(vdev);
- /* Decrease v4l2_device refcount */
+
if (v4l2_dev)
v4l2_device_put(v4l2_dev);
}
@@ -198,12 +167,19 @@
struct video_device *video_devdata(struct file *file)
{
- return video_device[iminor(file->f_path.dentry->d_inode)];
+ struct video_device *vdev = NULL;
+ int index;
+
+ index = iminor(file->f_path.dentry->d_inode);
+
+ if(index < VIDEO_NUM_DEVICES)
+ vdev = video_device[index];
+
+ return vdev;
}
EXPORT_SYMBOL(video_devdata);
-/* Priority handling */
static inline bool prio_is_valid(enum v4l2_priority prio)
{
@@ -329,28 +305,6 @@
if (vdev->lock)
mutex_unlock(vdev->lock);
} else if (vdev->fops->ioctl) {
- /* This code path is a replacement for the BKL. It is a major
- * hack but it will have to do for those drivers that are not
- * yet converted to use unlocked_ioctl.
- *
- * There are two options: if the driver implements struct
- * v4l2_device, then the lock defined there is used to
- * serialize the ioctls. Otherwise the v4l2 core lock defined
- * below is used. This lock is really bad since it serializes
- * completely independent devices.
- *
- * Both variants suffer from the same problem: if the driver
- * sleeps, then it blocks all ioctls since the lock is still
- * held. This is very common for VIDIOC_DQBUF since that
- * normally waits for a frame to arrive. As a result any other
- * ioctl calls will proceed very, very slowly since each call
- * will have to wait for the VIDIOC_QBUF to finish. Things that
- * should take 0.01s may now take 10-20 seconds.
- *
- * The workaround is to *not* take the lock for VIDIOC_DQBUF.
- * This actually works OK for videobuf-based drivers, since
- * videobuf will take its own internal lock.
- */
static DEFINE_MUTEX(v4l2_ioctl_mutex);
struct mutex *m = vdev->v4l2_dev ?
&vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex;
@@ -400,21 +354,20 @@
return ret;
}
-/* Override for the open function */
static int v4l2_open(struct inode *inode, struct file *filp)
{
struct video_device *vdev;
int ret = 0;
- /* Check if the video device is available */
+
mutex_lock(&videodev_lock);
vdev = video_devdata(filp);
- /* return ENODEV if the video device has already been removed. */
+
if (vdev == NULL || !video_is_registered(vdev)) {
mutex_unlock(&videodev_lock);
return -ENODEV;
}
- /* and increase the device refcount */
+
video_get(vdev);
mutex_unlock(&videodev_lock);
if (vdev->fops->open) {
@@ -431,13 +384,12 @@
}
err:
- /* decrease the refcount in case of an error */
+
if (ret)
video_put(vdev);
return ret;
}
-/* Override for the release function */
static int v4l2_release(struct inode *inode, struct file *filp)
{
struct video_device *vdev = video_devdata(filp);
@@ -450,8 +402,6 @@
if (vdev->lock)
mutex_unlock(vdev->lock);
}
- /* decrease the refcount unconditionally since the release()
- return value is ignored. */
video_put(vdev);
return ret;
}
@@ -472,27 +422,12 @@
.llseek = no_llseek,
};
-/**
- * get_index - assign stream index number based on parent device
- * @vdev: video_device to assign index number to, vdev->parent should be assigned
- *
- * Note that when this is called the new device has not yet been registered
- * in the video_device array, but it was able to obtain a minor number.
- *
- * This means that we can always obtain a free stream index number since
- * the worst case scenario is that there are VIDEO_NUM_DEVICES - 1 slots in
- * use of the video_device array.
- *
- * Returns a free index number.
- */
static int get_index(struct video_device *vdev)
{
- /* This can be static since this function is called with the global
- videodev_lock held. */
static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES);
int i;
- /* Some drivers do not set the parent. In that case always return 0. */
+
if (vdev->parent == NULL)
return 0;
@@ -508,38 +443,6 @@
return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
}
-/**
- * __video_register_device - register video4linux devices
- * @vdev: video device structure we want to register
- * @type: type of device to register
- * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ...
- * -1 == first free)
- * @warn_if_nr_in_use: warn if the desired device node number
- * was already in use and another number was chosen instead.
- * @owner: module that owns the video device node
- *
- * The registration code assigns minor numbers and device node numbers
- * based on the requested type and registers the new device node with
- * the kernel.
- *
- * This function assumes that struct video_device was zeroed when it
- * was allocated and does not contain any stale date.
- *
- * An error is returned if no free minor or device node number could be
- * found, or if the registration of the device node failed.
- *
- * Zero is returned on success.
- *
- * Valid types are
- *
- * %VFL_TYPE_GRABBER - A frame grabber
- *
- * %VFL_TYPE_VBI - Vertical blank data (undecoded)
- *
- * %VFL_TYPE_RADIO - A radio card
- *
- * %VFL_TYPE_SUBDEV - A subdevice
- */
int __video_register_device(struct video_device *vdev, int type, int nr,
int warn_if_nr_in_use, struct module *owner)
{
@@ -549,19 +452,18 @@
int minor_cnt = VIDEO_NUM_DEVICES;
const char *name_base;
- /* A minor value of -1 marks this video device as never
- having been registered */
vdev->minor = -1;
- /* the release callback MUST be present */
- if (WARN_ON(!vdev->release))
+
+ WARN_ON(!vdev->release);
+ if (!vdev->release)
return -EINVAL;
- /* v4l2_fh support */
+
spin_lock_init(&vdev->fh_lock);
INIT_LIST_HEAD(&vdev->fh_list);
- /* Part 1: check device type */
+
switch (type) {
case VFL_TYPE_GRABBER:
name_base = "video";
@@ -588,19 +490,12 @@
vdev->parent = vdev->v4l2_dev->dev;
if (vdev->ctrl_handler == NULL)
vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler;
- /* If the prio state pointer is NULL, then use the v4l2_device
- prio state. */
if (vdev->prio == NULL)
vdev->prio = &vdev->v4l2_dev->prio;
}
- /* Part 2: find a free minor, device node number and device index. */
+
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
- /* Keep the ranges for the first four types for historical
- * reasons.
- * Newer devices (not yet in place) should use the range
- * of 128-191 and just pick the first free minor there
- * (new style). */
switch (type) {
case VFL_TYPE_GRABBER:
minor_offset = 0;
@@ -621,7 +516,7 @@
}
#endif
- /* Pick a device node number */
+
mutex_lock(&videodev_lock);
nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
if (nr == minor_cnt)
@@ -632,11 +527,9 @@
return -ENFILE;
}
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
- /* 1-on-1 mapping of device node number to minor number */
+
i = nr;
#else
- /* The device node number and minor numbers are independent, so
- we just find the first free minor number. */
for (i = 0; i < VIDEO_NUM_DEVICES; i++)
if (video_device[i] == NULL)
break;
@@ -650,12 +543,12 @@
vdev->num = nr;
devnode_set(vdev);
- /* Should not happen since we thought this minor was free */
+
WARN_ON(video_device[vdev->minor] != NULL);
vdev->index = get_index(vdev);
mutex_unlock(&videodev_lock);
- /* Part 3: Initialize the character device */
+
vdev->cdev = cdev_alloc();
if (vdev->cdev == NULL) {
ret = -ENOMEM;
@@ -671,7 +564,7 @@
goto cleanup;
}
- /* Part 4: register the device with sysfs */
+
vdev->dev.class = &video_class;
vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
if (vdev->parent)
@@ -682,26 +575,24 @@
printk(KERN_ERR "%s: device_register failed\n", __func__);
goto cleanup;
}
- /* Register the release callback that will be called when the last
- reference to the device goes away. */
vdev->dev.release = v4l2_device_release;
if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
name_base, nr, video_device_node_name(vdev));
- /* Increase v4l2_device refcount */
+
if (vdev->v4l2_dev)
v4l2_device_get(vdev->v4l2_dev);
#if defined(CONFIG_MEDIA_CONTROLLER)
- /* Part 5: Register the entity. */
+
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
vdev->vfl_type != VFL_TYPE_SUBDEV) {
vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
vdev->entity.name = vdev->name;
- vdev->entity.info.v4l.major = VIDEO_MAJOR;
- vdev->entity.info.v4l.minor = vdev->minor;
+ vdev->entity.v4l.major = VIDEO_MAJOR;
+ vdev->entity.v4l.minor = vdev->minor;
ret = media_device_register_entity(vdev->v4l2_dev->mdev,
&vdev->entity);
if (ret < 0)
@@ -710,7 +601,7 @@
__func__);
}
#endif
- /* Part 6: Activate this minor. The char device can now be used. */
+
set_bit(V4L2_FL_REGISTERED, &vdev->flags);
mutex_lock(&videodev_lock);
video_device[vdev->minor] = vdev;
@@ -724,38 +615,25 @@
cdev_del(vdev->cdev);
devnode_clear(vdev);
mutex_unlock(&videodev_lock);
- /* Mark this video device as never having been registered. */
+
vdev->minor = -1;
return ret;
}
EXPORT_SYMBOL(__video_register_device);
-/**
- * video_unregister_device - unregister a video4linux device
- * @vdev: the device to unregister
- *
- * This unregisters the passed device. Future open calls will
- * be met with errors.
- */
void video_unregister_device(struct video_device *vdev)
{
- /* Check if vdev was ever registered at all */
+
if (!vdev || !video_is_registered(vdev))
return;
mutex_lock(&videodev_lock);
- /* This must be in a critical section to prevent a race with v4l2_open.
- * Once this bit has been cleared video_get may never be called again.
- */
clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
mutex_unlock(&videodev_lock);
device_unregister(&vdev->dev);
}
EXPORT_SYMBOL(video_unregister_device);
-/*
- * Initialise video for linux
- */
static int __init videodev_init(void)
{
dev_t dev = MKDEV(VIDEO_MAJOR, 0);
@@ -787,7 +665,7 @@
unregister_chrdev_region(dev, VIDEO_NUM_DEVICES);
}
-subsys_initcall(videodev_init);
+module_init(videodev_init)
module_exit(videodev_exit)
MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -796,8 +674,3 @@
MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR);
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 1f203b8..5ae49af 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -18,11 +18,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioctl.h>
-#include <linux/module.h>
#include <linux/i2c.h>
-#include <linux/slab.h>
#if defined(CONFIG_SPI)
#include <linux/spi/spi.h>
#endif
@@ -40,15 +39,14 @@
mutex_init(&v4l2_dev->ioctl_lock);
v4l2_prio_init(&v4l2_dev->prio);
kref_init(&v4l2_dev->ref);
- get_device(dev);
v4l2_dev->dev = dev;
if (dev == NULL) {
- /* If dev == NULL, then name must be filled in by the caller */
+
WARN_ON(!v4l2_dev->name[0]);
return 0;
}
- /* Set name to driver name + device name if it is empty. */
+
if (!v4l2_dev->name[0])
snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
dev->driver->name, dev_name(dev));
@@ -96,7 +94,6 @@
if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
dev_set_drvdata(v4l2_dev->dev, NULL);
- put_device(v4l2_dev->dev);
v4l2_dev->dev = NULL;
}
EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
@@ -109,17 +106,13 @@
return;
v4l2_device_disconnect(v4l2_dev);
- /* Unregister subdevs */
+
list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
v4l2_device_unregister_subdev(sd);
#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
struct i2c_client *client = v4l2_get_subdevdata(sd);
- /* We need to unregister the i2c client explicitly.
- We cannot rely on i2c_del_adapter to always
- unregister clients for us, since if the i2c bus
- is a platform bus, then it is never deleted. */
if (client)
i2c_unregister_device(client);
continue;
@@ -146,11 +139,11 @@
#endif
int err;
- /* Check for valid input */
+
if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
return -EINVAL;
- /* Warn if we apparently re-register a subdev */
+
WARN_ON(sd->v4l2_dev != NULL);
if (!try_module_get(sd->owner))
@@ -165,7 +158,7 @@
}
}
- /* This just returns 0 if either of the two args is NULL */
+
err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
if (err) {
if (sd->internal_ops && sd->internal_ops->unregistered)
@@ -175,7 +168,7 @@
}
#if defined(CONFIG_MEDIA_CONTROLLER)
- /* Register the entity. */
+
if (v4l2_dev->mdev) {
err = media_device_register_entity(v4l2_dev->mdev, entity);
if (err < 0) {
@@ -187,6 +180,10 @@
}
#endif
+#if defined(CONFIG_MACH_DUMMY)
+ if (v4l2_dev->subdevs.prev == NULL)
+ return -EINVAL;
+#endif
spin_lock(&v4l2_dev->lock);
list_add_tail(&sd->list, &v4l2_dev->subdevs);
spin_unlock(&v4l2_dev->lock);
@@ -195,60 +192,31 @@
}
EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
-static void v4l2_device_release_subdev_node(struct video_device *vdev)
-{
- struct v4l2_subdev *sd = video_get_drvdata(vdev);
- sd->devnode = NULL;
- kfree(vdev);
-}
-
int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
{
struct video_device *vdev;
struct v4l2_subdev *sd;
int err;
- /* Register a device node for every subdev marked with the
- * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
- */
list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
continue;
- vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
- if (!vdev) {
- err = -ENOMEM;
- goto clean_up;
- }
-
- video_set_drvdata(vdev, sd);
+ vdev = &sd->devnode;
strlcpy(vdev->name, sd->name, sizeof(vdev->name));
vdev->v4l2_dev = v4l2_dev;
vdev->fops = &v4l2_subdev_fops;
- vdev->release = v4l2_device_release_subdev_node;
- vdev->ctrl_handler = sd->ctrl_handler;
+ vdev->release = video_device_release_empty;
err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
sd->owner);
- if (err < 0) {
- kfree(vdev);
- goto clean_up;
- }
+ if (err < 0)
+ return err;
#if defined(CONFIG_MEDIA_CONTROLLER)
- sd->entity.info.v4l.major = VIDEO_MAJOR;
- sd->entity.info.v4l.minor = vdev->minor;
+ sd->entity.v4l.major = VIDEO_MAJOR;
+ sd->entity.v4l.minor = vdev->minor;
#endif
- sd->devnode = vdev;
}
return 0;
-
-clean_up:
- list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
- if (!sd->devnode)
- break;
- video_unregister_device(sd->devnode);
- }
-
- return err;
}
EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
@@ -256,7 +224,7 @@
{
struct v4l2_device *v4l2_dev;
- /* return if it isn't registered */
+
if (sd == NULL || sd->v4l2_dev == NULL)
return;
@@ -274,7 +242,7 @@
if (v4l2_dev->mdev)
media_device_unregister_entity(&sd->entity);
#endif
- video_unregister_device(sd->devnode);
+ video_unregister_device(&sd->devnode);
module_put(sd->owner);
}
EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c
index f3d16ab..9a61197 100644
--- a/drivers/media/video/v4l2-event.c
+++ b/drivers/media/video/v4l2-event.c
@@ -22,43 +22,104 @@
* 02110-1301 USA
*/
+#include <linux/module.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-event.h>
-#include <media/v4l2-ctrls.h>
#include <linux/sched.h>
#include <linux/slab.h>
-#include <linux/export.h>
-static unsigned sev_pos(const struct v4l2_subscribed_event *sev, unsigned idx)
+int v4l2_event_init(struct v4l2_fh *fh)
{
- idx += sev->first;
- return idx >= sev->elems ? idx - sev->elems : idx;
+ fh->events = kzalloc(sizeof(*fh->events), GFP_KERNEL);
+ if (fh->events == NULL)
+ return -ENOMEM;
+
+ init_waitqueue_head(&fh->events->wait);
+
+ INIT_LIST_HEAD(&fh->events->free);
+ INIT_LIST_HEAD(&fh->events->available);
+ INIT_LIST_HEAD(&fh->events->subscribed);
+
+ fh->events->sequence = -1;
+
+ return 0;
}
+EXPORT_SYMBOL_GPL(v4l2_event_init);
+
+int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n)
+{
+ struct v4l2_events *events = fh->events;
+ unsigned long flags;
+
+ if (!events) {
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ while (events->nallocated < n) {
+ struct v4l2_kevent *kev;
+
+ kev = kzalloc(sizeof(*kev), GFP_KERNEL);
+ if (kev == NULL)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&fh->vdev->fh_lock, flags);
+ list_add_tail(&kev->list, &events->free);
+ events->nallocated++;
+ spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_event_alloc);
+
+#define list_kfree(list, type, member) \
+ while (!list_empty(list)) { \
+ type *hi; \
+ hi = list_first_entry(list, type, member); \
+ list_del(&hi->member); \
+ kfree(hi); \
+ }
+
+void v4l2_event_free(struct v4l2_fh *fh)
+{
+ struct v4l2_events *events = fh->events;
+
+ if (!events)
+ return;
+
+ list_kfree(&events->free, struct v4l2_kevent, list);
+ list_kfree(&events->available, struct v4l2_kevent, list);
+ list_kfree(&events->subscribed, struct v4l2_subscribed_event, list);
+
+ kfree(events);
+ fh->events = NULL;
+}
+EXPORT_SYMBOL_GPL(v4l2_event_free);
static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
{
+ struct v4l2_events *events = fh->events;
struct v4l2_kevent *kev;
unsigned long flags;
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- if (list_empty(&fh->available)) {
+ if (list_empty(&events->available)) {
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
return -ENOENT;
}
- WARN_ON(fh->navailable == 0);
+ WARN_ON(events->navailable == 0);
- kev = list_first_entry(&fh->available, struct v4l2_kevent, list);
- list_del(&kev->list);
- fh->navailable--;
+ kev = list_first_entry(&events->available, struct v4l2_kevent, list);
+ list_move(&kev->list, &events->free);
+ events->navailable--;
- kev->event.pending = fh->navailable;
+ kev->event.pending = events->navailable;
*event = kev->event;
- kev->sev->first = sev_pos(kev->sev, 1);
- kev->sev->in_use--;
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
@@ -68,18 +129,19 @@
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
int nonblocking)
{
+ struct v4l2_events *events = fh->events;
int ret;
if (nonblocking)
return __v4l2_event_dequeue(fh, event);
- /* Release the vdev lock while waiting */
+
if (fh->vdev->lock)
mutex_unlock(fh->vdev->lock);
do {
- ret = wait_event_interruptible(fh->wait,
- fh->navailable != 0);
+ ret = wait_event_interruptible(events->wait,
+ events->navailable != 0);
if (ret < 0)
break;
@@ -93,70 +155,20 @@
}
EXPORT_SYMBOL_GPL(v4l2_event_dequeue);
-/* Caller must hold fh->vdev->fh_lock! */
static struct v4l2_subscribed_event *v4l2_event_subscribed(
- struct v4l2_fh *fh, u32 type, u32 id)
+ struct v4l2_fh *fh, u32 type)
{
+ struct v4l2_events *events = fh->events;
struct v4l2_subscribed_event *sev;
assert_spin_locked(&fh->vdev->fh_lock);
- list_for_each_entry(sev, &fh->subscribed, list)
- if (sev->type == type && sev->id == id)
+ list_for_each_entry(sev, &events->subscribed, list) {
+ if (sev->type == type)
return sev;
-
- return NULL;
-}
-
-static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev,
- const struct timespec *ts)
-{
- struct v4l2_subscribed_event *sev;
- struct v4l2_kevent *kev;
- bool copy_payload = true;
-
- /* Are we subscribed? */
- sev = v4l2_event_subscribed(fh, ev->type, ev->id);
- if (sev == NULL)
- return;
-
- /* Increase event sequence number on fh. */
- fh->sequence++;
-
- /* Do we have any free events? */
- if (sev->in_use == sev->elems) {
- /* no, remove the oldest one */
- kev = sev->events + sev_pos(sev, 0);
- list_del(&kev->list);
- sev->in_use--;
- sev->first = sev_pos(sev, 1);
- fh->navailable--;
- if (sev->elems == 1) {
- if (sev->replace) {
- sev->replace(&kev->event, ev);
- copy_payload = false;
- }
- } else if (sev->merge) {
- struct v4l2_kevent *second_oldest =
- sev->events + sev_pos(sev, 0);
- sev->merge(&kev->event, &second_oldest->event);
- }
}
- /* Take one and fill it. */
- kev = sev->events + sev_pos(sev, sev->in_use);
- kev->event.type = ev->type;
- if (copy_payload)
- kev->event.u = ev->u;
- kev->event.id = ev->id;
- kev->event.timestamp = *ts;
- kev->event.sequence = fh->sequence;
- sev->in_use++;
- list_add_tail(&kev->list, &fh->available);
-
- fh->navailable++;
-
- wake_up_all(&fh->wait);
+ return NULL;
}
void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
@@ -169,103 +181,84 @@
spin_lock_irqsave(&vdev->fh_lock, flags);
- list_for_each_entry(fh, &vdev->fh_list, list)
- __v4l2_event_queue_fh(fh, ev, ×tamp);
+ list_for_each_entry(fh, &vdev->fh_list, list) {
+ struct v4l2_events *events = fh->events;
+ struct v4l2_kevent *kev;
+
+
+ if (!v4l2_event_subscribed(fh, ev->type))
+ continue;
+
+
+ events->sequence++;
+
+
+ if (list_empty(&events->free)) {
+
+ pr_err("%s, no free event queues", __func__);
+ continue;
+ }
+
+ kev = list_first_entry(&events->free, struct v4l2_kevent, list);
+ kev->event.type = ev->type;
+ kev->event.u = ev->u;
+ kev->event.timestamp = timestamp;
+ kev->event.sequence = events->sequence;
+ list_move_tail(&kev->list, &events->available);
+
+ events->navailable++;
+
+ wake_up_all(&events->wait);
+ }
spin_unlock_irqrestore(&vdev->fh_lock, flags);
}
EXPORT_SYMBOL_GPL(v4l2_event_queue);
-void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev)
-{
- unsigned long flags;
- struct timespec timestamp;
-
- ktime_get_ts(×tamp);
-
- spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- __v4l2_event_queue_fh(fh, ev, ×tamp);
- spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
-}
-EXPORT_SYMBOL_GPL(v4l2_event_queue_fh);
-
int v4l2_event_pending(struct v4l2_fh *fh)
{
- return fh->navailable;
+ if (!(fh) || !(fh)->events) return 0;
+ return fh->events->navailable;
}
EXPORT_SYMBOL_GPL(v4l2_event_pending);
-static void ctrls_replace(struct v4l2_event *old, const struct v4l2_event *new)
-{
- u32 old_changes = old->u.ctrl.changes;
-
- old->u.ctrl = new->u.ctrl;
- old->u.ctrl.changes |= old_changes;
-}
-
-static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new)
-{
- new->u.ctrl.changes |= old->u.ctrl.changes;
-}
-
int v4l2_event_subscribe(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub, unsigned elems)
+ struct v4l2_event_subscription *sub)
{
- struct v4l2_subscribed_event *sev, *found_ev;
- struct v4l2_ctrl *ctrl = NULL;
+ struct v4l2_events *events = fh->events;
+ struct v4l2_subscribed_event *sev;
unsigned long flags;
- unsigned i;
- if (sub->type == V4L2_EVENT_ALL)
- return -EINVAL;
-
- if (elems < 1)
- elems = 1;
- if (sub->type == V4L2_EVENT_CTRL) {
- ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
- if (ctrl == NULL)
- return -EINVAL;
+ if (fh->events == NULL) {
+ WARN_ON(1);
+ return -ENOMEM;
}
- if (!fh->vdev) {
- pr_err("%s: fh->vdev is NULL\n", __func__);
- return -EIO;
- }
-
- sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL);
+ sev = kmalloc(sizeof(*sev), GFP_KERNEL);
if (!sev)
return -ENOMEM;
- for (i = 0; i < elems; i++)
- sev->events[i].sev = sev;
- sev->type = sub->type;
- sev->id = sub->id;
- sev->flags = sub->flags;
- sev->fh = fh;
- sev->elems = elems;
- if (ctrl) {
- sev->replace = ctrls_replace;
- sev->merge = ctrls_merge;
- }
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
- if (!found_ev)
- list_add(&sev->list, &fh->subscribed);
+
+ if (v4l2_event_subscribed(fh, sub->type) == NULL) {
+ INIT_LIST_HEAD(&sev->list);
+ sev->type = sub->type;
+
+ list_add(&sev->list, &events->subscribed);
+ sev = NULL;
+ }
+
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
- /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
- if (found_ev)
- kfree(sev);
- else if (ctrl)
- v4l2_ctrl_add_event(ctrl, sev);
+ kfree(sev);
return 0;
}
EXPORT_SYMBOL_GPL(v4l2_event_subscribe);
-void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
+static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
{
- struct v4l2_event_subscription sub;
+ struct v4l2_events *events = fh->events;
struct v4l2_subscribed_event *sev;
unsigned long flags;
@@ -273,25 +266,21 @@
sev = NULL;
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- if (!list_empty(&fh->subscribed)) {
- sev = list_first_entry(&fh->subscribed,
- struct v4l2_subscribed_event, list);
- sub.type = sev->type;
- sub.id = sev->id;
+ if (!list_empty(&events->subscribed)) {
+ sev = list_first_entry(&events->subscribed,
+ struct v4l2_subscribed_event, list);
+ list_del(&sev->list);
}
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
- if (sev)
- v4l2_event_unsubscribe(fh, &sub);
+ kfree(sev);
} while (sev);
}
-EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe_all);
int v4l2_event_unsubscribe(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
struct v4l2_subscribed_event *sev;
unsigned long flags;
- int i;
if (sub->type == V4L2_EVENT_ALL) {
v4l2_event_unsubscribe_all(fh);
@@ -300,23 +289,11 @@
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
- sev = v4l2_event_subscribed(fh, sub->type, sub->id);
- if (sev != NULL) {
- /* Remove any pending events for this subscription */
- for (i = 0; i < sev->in_use; i++) {
- list_del(&sev->events[sev_pos(sev, i)].list);
- fh->navailable--;
- }
+ sev = v4l2_event_subscribed(fh, sub->type);
+ if (sev != NULL)
list_del(&sev->list);
- }
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
- if (sev && sev->type == V4L2_EVENT_CTRL) {
- struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id);
-
- if (ctrl)
- v4l2_ctrl_del_event(ctrl, sev);
- }
kfree(sev);
diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c
index bf5cd5b..1081a11 100644
--- a/drivers/media/video/v4l2-fh.c
+++ b/drivers/media/video/v4l2-fh.c
@@ -22,26 +22,27 @@
* 02110-1301 USA
*/
+#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/slab.h>
-#include <linux/export.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
-void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
+int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
{
fh->vdev = vdev;
- /* Inherit from video_device. May be overridden by the driver. */
- fh->ctrl_handler = vdev->ctrl_handler;
INIT_LIST_HEAD(&fh->list);
set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
fh->prio = V4L2_PRIORITY_UNSET;
- init_waitqueue_head(&fh->wait);
- INIT_LIST_HEAD(&fh->available);
- INIT_LIST_HEAD(&fh->subscribed);
- fh->sequence = -1;
+
+ if (vdev->ioctl_ops && vdev->ioctl_ops->vidioc_subscribe_event)
+ return v4l2_event_init(fh);
+
+ fh->events = NULL;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(v4l2_fh_init);
@@ -75,11 +76,6 @@
{
unsigned long flags;
- if (!fh->vdev) {
- pr_err("%s: fd->vdev is NULL\n", __func__);
- return;
- }
-
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
list_del_init(&fh->list);
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
@@ -92,8 +88,10 @@
{
if (fh->vdev == NULL)
return;
- v4l2_event_unsubscribe_all(fh);
+
fh->vdev = NULL;
+
+ v4l2_event_free(fh);
}
EXPORT_SYMBOL_GPL(v4l2_fh_exit);
diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c
index f447349..b991afd 100644
--- a/drivers/media/video/v4l2-int-device.c
+++ b/drivers/media/video/v4l2-int-device.c
@@ -26,7 +26,6 @@
#include <linux/list.h>
#include <linux/sort.h>
#include <linux/string.h>
-#include <linux/module.h>
#include <media/v4l2-int-device.h>
@@ -45,11 +44,11 @@
if (s->type != v4l2_int_type_slave)
continue;
- /* Slave is connected? */
+
if (s->u.slave->master)
continue;
- /* Slave wants to attach to master? */
+
if (s->u.slave->attach_to[0] != 0
&& strncmp(m->name, s->u.slave->attach_to,
V4L2NAMESIZE))
@@ -111,7 +110,6 @@
}
EXPORT_SYMBOL_GPL(v4l2_int_device_unregister);
-/* Adapted from search_extable in extable.c. */
static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd,
v4l2_int_ioctl_func *no_such_ioctl)
{
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 5b2ec1f..c45f285 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -16,7 +16,6 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/videodev2.h>
@@ -49,25 +48,10 @@
printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\
} while (0)
-/* Zero out the end of the struct pointed to by p. Everything after, but
- * not including, the specified field is cleared. */
#define CLEAR_AFTER_FIELD(p, field) \
memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
-#define have_fmt_ops(foo) ( \
- ops->vidioc_##foo##_fmt_vid_cap || \
- ops->vidioc_##foo##_fmt_vid_out || \
- ops->vidioc_##foo##_fmt_vid_cap_mplane || \
- ops->vidioc_##foo##_fmt_vid_out_mplane || \
- ops->vidioc_##foo##_fmt_vid_overlay || \
- ops->vidioc_##foo##_fmt_vbi_cap || \
- ops->vidioc_##foo##_fmt_vid_out_overlay || \
- ops->vidioc_##foo##_fmt_vbi_out || \
- ops->vidioc_##foo##_fmt_sliced_vbi_cap || \
- ops->vidioc_##foo##_fmt_sliced_vbi_out || \
- ops->vidioc_##foo##_fmt_type_private)
-
struct std_descr {
v4l2_std_id std;
const char *descr;
@@ -107,17 +91,11 @@
{ 0, "Unknown" }
};
-/* video4linux standard ID conversion to standard name
- */
const char *v4l2_norm_to_name(v4l2_std_id id)
{
u32 myid = id;
int i;
- /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
- 64 bit comparations. So, on that architecture, with some gcc
- variants, compilation fails. Currently, the max value is 30bit wide.
- */
BUG_ON(myid != id);
for (i = 0; standards[i].std; i++)
@@ -127,7 +105,6 @@
}
EXPORT_SYMBOL(v4l2_norm_to_name);
-/* Returns frame period for the given standard */
void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
{
if (id & V4L2_STD_525_60) {
@@ -140,8 +117,6 @@
}
EXPORT_SYMBOL(v4l2_video_std_frame_period);
-/* Fill in the fields of a v4l2_standard structure according to the
- 'id' and 'transmission' parameters. Returns negative on error. */
int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, const char *name)
{
@@ -153,8 +128,6 @@
}
EXPORT_SYMBOL(v4l2_video_std_construct);
-/* ----------------------------------------------------------------- */
-/* some arrays for pretty-printing debug messages of enum types */
const char *v4l2_field_names[] = {
[V4L2_FIELD_ANY] = "any",
@@ -193,8 +166,6 @@
#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
arr[a] : "unknown")
-/* ------------------------------------------------------------------ */
-/* debug help functions */
static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
[_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
@@ -238,8 +209,6 @@
[_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",
@@ -260,8 +229,6 @@
[_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
[_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
- [_IOC_NR(VIDIOC_DECODER_CMD)] = "VIDIOC_DECODER_CMD",
- [_IOC_NR(VIDIOC_TRY_DECODER_CMD)] = "VIDIOC_TRY_DECODER_CMD",
[_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
[_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
@@ -277,13 +244,9 @@
[_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT",
[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT",
[_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
- [_IOC_NR(VIDIOC_CREATE_BUFS)] = "VIDIOC_CREATE_BUFS",
- [_IOC_NR(VIDIOC_PREPARE_BUF)] = "VIDIOC_PREPARE_BUF",
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-/* Common ioctl debug function. This function can be used by
- external ioctl messages as well as internal V4L ioctl */
void v4l_printk_ioctl(unsigned int cmd)
{
char *dir, *type;
@@ -418,19 +381,14 @@
{
__u32 i;
- /* zero the reserved fields */
+
c->reserved[0] = c->reserved[1] = 0;
for (i = 0; i < c->count; i++)
c->controls[i].reserved2[0] = 0;
- /* V4L2_CID_PRIVATE_BASE cannot be used as control class
- when using extended controls.
- Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
- is it allowed for backwards compatibility.
- */
if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
return 0;
- /* Check that all controls are from the same control class. */
+
for (i = 0; i < c->count; i++) {
if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
c->error_idx = i;
@@ -496,6 +454,55 @@
return -EINVAL;
}
+static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
+ struct v4l2_format *f_mp)
+{
+ struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
+ const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
+
+ if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ else
+ return -EINVAL;
+
+ pix_mp->width = pix->width;
+ pix_mp->height = pix->height;
+ pix_mp->pixelformat = pix->pixelformat;
+ pix_mp->field = pix->field;
+ pix_mp->colorspace = pix->colorspace;
+ pix_mp->num_planes = 1;
+ pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
+ pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
+
+ return 0;
+}
+
+static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
+ struct v4l2_format *f_sp)
+{
+ const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
+ struct v4l2_pix_format *pix = &f_sp->fmt.pix;
+
+ if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ else
+ return -EINVAL;
+
+ pix->width = pix_mp->width;
+ pix->height = pix_mp->height;
+ pix->pixelformat = pix_mp->pixelformat;
+ pix->field = pix_mp->field;
+ pix->colorspace = pix_mp->colorspace;
+ pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
+ pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
+
+ return 0;
+}
+
static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
@@ -503,14 +510,14 @@
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
void *fh = file->private_data;
struct v4l2_fh *vfh = NULL;
+ struct v4l2_format f_copy;
int use_fh_prio = 0;
- long ret_prio = 0;
- long ret = -ENOTTY;
+ long ret = -EINVAL;
if (ops == NULL) {
printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
vfd->name);
- return ret;
+ return -EINVAL;
}
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
@@ -524,12 +531,43 @@
use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
}
- if (use_fh_prio)
- ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
+ if (use_fh_prio) {
+ switch (cmd) {
+ case VIDIOC_S_CTRL:
+ case VIDIOC_S_STD:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_S_OUTPUT:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_S_FREQUENCY:
+ case VIDIOC_S_FMT:
+ case VIDIOC_S_CROP:
+ case VIDIOC_S_AUDIO:
+ case VIDIOC_S_AUDOUT:
+ case VIDIOC_S_EXT_CTRLS:
+ case VIDIOC_S_FBUF:
+ case VIDIOC_S_PRIORITY:
+ case VIDIOC_S_DV_PRESET:
+ case VIDIOC_S_DV_TIMINGS:
+ case VIDIOC_S_JPEGCOMP:
+ case VIDIOC_S_MODULATOR:
+ case VIDIOC_S_PARM:
+ case VIDIOC_S_HW_FREQ_SEEK:
+ case VIDIOC_ENCODER_CMD:
+ case VIDIOC_OVERLAY:
+ case VIDIOC_REQBUFS:
+ case VIDIOC_STREAMON:
+ case VIDIOC_STREAMOFF:
+ ret = v4l2_prio_check(vfd->prio, vfh->prio);
+ if (ret)
+ goto exit_prio;
+ ret = -EINVAL;
+ break;
+ }
+ }
switch (cmd) {
- /* --- capabilities ------------------------------------------ */
+
case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = (struct v4l2_capability *)arg;
@@ -537,21 +575,18 @@
if (!ops->vidioc_querycap)
break;
- cap->version = LINUX_VERSION_CODE;
ret = ops->vidioc_querycap(file, fh, cap);
if (!ret)
dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
"version=0x%08x, "
- "capabilities=0x%08x, "
- "device_caps=0x%08x\n",
+ "capabilities=0x%08x\n",
cap->driver, cap->card, cap->bus_info,
cap->version,
- cap->capabilities,
- cap->device_caps);
+ cap->capabilities);
break;
}
- /* --- priority ------------------------------------------ */
+
case VIDIOC_G_PRIORITY:
{
enum v4l2_priority *p = arg;
@@ -571,55 +606,53 @@
enum v4l2_priority *p = arg;
if (!ops->vidioc_s_priority && !use_fh_prio)
- break;
+ break;
dbgarg(cmd, "setting priority to %d\n", *p);
if (ops->vidioc_s_priority)
ret = ops->vidioc_s_priority(file, fh, *p);
else
- ret = ret_prio ? ret_prio :
- v4l2_prio_change(&vfd->v4l2_dev->prio,
- &vfh->prio, *p);
+ ret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
break;
}
- /* --- capture ioctls ---------------------------------------- */
+
case VIDIOC_ENUM_FMT:
{
struct v4l2_fmtdesc *f = arg;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (likely(ops->vidioc_enum_fmt_vid_cap))
+ if (ops->vidioc_enum_fmt_vid_cap)
ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- if (likely(ops->vidioc_enum_fmt_vid_cap_mplane))
+ if (ops->vidioc_enum_fmt_vid_cap_mplane)
ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (likely(ops->vidioc_enum_fmt_vid_overlay))
+ if (ops->vidioc_enum_fmt_vid_overlay)
ret = ops->vidioc_enum_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (likely(ops->vidioc_enum_fmt_vid_out))
+ if (ops->vidioc_enum_fmt_vid_out)
ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (likely(ops->vidioc_enum_fmt_vid_out_mplane))
+ if (ops->vidioc_enum_fmt_vid_out_mplane)
ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
- if (likely(ops->vidioc_enum_fmt_type_private))
+ if (ops->vidioc_enum_fmt_type_private)
ret = ops->vidioc_enum_fmt_type_private(file,
fh, f);
break;
default:
break;
}
- if (likely (!ret))
+ if (!ret)
dbgarg(cmd, "index=%d, type=%d, flags=%d, "
"pixelformat=%c%c%c%c, description='%s'\n",
f->index, f->type, f->flags,
@@ -628,86 +661,126 @@
(f->pixelformat >> 16) & 0xff,
(f->pixelformat >> 24) & 0xff,
f->description);
- else if (ret == -ENOTTY &&
- (ops->vidioc_enum_fmt_vid_cap ||
- ops->vidioc_enum_fmt_vid_out ||
- ops->vidioc_enum_fmt_vid_cap_mplane ||
- ops->vidioc_enum_fmt_vid_out_mplane ||
- ops->vidioc_enum_fmt_vid_overlay ||
- ops->vidioc_enum_fmt_type_private))
- ret = -EINVAL;
break;
}
case VIDIOC_G_FMT:
{
struct v4l2_format *f = (struct v4l2_format *)arg;
- /* FIXME: Should be one dump per type */
+
dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (ops->vidioc_g_fmt_vid_cap)
+ if (ops->vidioc_g_fmt_vid_cap) {
ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
+ } else if (ops->vidioc_g_fmt_vid_cap_mplane) {
+ if (fmt_sp_to_mp(f, &f_copy))
+ break;
+ ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
+ &f_copy);
+ if (ret)
+ break;
+
+ if (f_copy.fmt.pix_mp.num_planes > 1) {
+ ret = -EBUSY;
+ break;
+ }
+
+ ret = fmt_mp_to_sp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- if (ops->vidioc_g_fmt_vid_cap_mplane)
+ if (ops->vidioc_g_fmt_vid_cap_mplane) {
ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
fh, f);
+ } else if (ops->vidioc_g_fmt_vid_cap) {
+ if (fmt_mp_to_sp(f, &f_copy))
+ break;
+ ret = ops->vidioc_g_fmt_vid_cap(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ ret = fmt_sp_to_mp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (likely(ops->vidioc_g_fmt_vid_overlay))
+ if (ops->vidioc_g_fmt_vid_overlay)
ret = ops->vidioc_g_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (ops->vidioc_g_fmt_vid_out)
+ if (ops->vidioc_g_fmt_vid_out) {
ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
+ } else if (ops->vidioc_g_fmt_vid_out_mplane) {
+ if (fmt_sp_to_mp(f, &f_copy))
+ break;
+ ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,
+ &f_copy);
+ if (ret)
+ break;
+
+ if (f_copy.fmt.pix_mp.num_planes > 1) {
+ ret = -EBUSY;
+ break;
+ }
+
+ ret = fmt_mp_to_sp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (ops->vidioc_g_fmt_vid_out_mplane)
+ if (ops->vidioc_g_fmt_vid_out_mplane) {
ret = ops->vidioc_g_fmt_vid_out_mplane(file,
fh, f);
+ } else if (ops->vidioc_g_fmt_vid_out) {
+ if (fmt_mp_to_sp(f, &f_copy))
+ break;
+ ret = ops->vidioc_g_fmt_vid_out(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ ret = fmt_sp_to_mp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
- if (likely(ops->vidioc_g_fmt_vid_out_overlay))
+ if (ops->vidioc_g_fmt_vid_out_overlay)
ret = ops->vidioc_g_fmt_vid_out_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
- if (likely(ops->vidioc_g_fmt_vbi_cap))
+ if (ops->vidioc_g_fmt_vbi_cap)
ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
- if (likely(ops->vidioc_g_fmt_vbi_out))
+ if (ops->vidioc_g_fmt_vbi_out)
ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
- if (likely(ops->vidioc_g_fmt_sliced_vbi_cap))
+ if (ops->vidioc_g_fmt_sliced_vbi_cap)
ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
- if (likely(ops->vidioc_g_fmt_sliced_vbi_out))
+ if (ops->vidioc_g_fmt_sliced_vbi_out)
ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
- if (likely(ops->vidioc_g_fmt_type_private))
+ if (ops->vidioc_g_fmt_type_private)
ret = ops->vidioc_g_fmt_type_private(file,
fh, f);
break;
}
- if (unlikely(ret == -ENOTTY && have_fmt_ops(g)))
- ret = -EINVAL;
break;
}
@@ -715,30 +788,49 @@
{
struct v4l2_format *f = (struct v4l2_format *)arg;
- if (!have_fmt_ops(s))
- break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
- ret = -EINVAL;
-
- /* FIXME: Should be one dump per type */
+
dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.pix);
v4l_print_pix_fmt(vfd, &f->fmt.pix);
- if (ops->vidioc_s_fmt_vid_cap)
+ if (ops->vidioc_s_fmt_vid_cap) {
ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
+ } else if (ops->vidioc_s_fmt_vid_cap_mplane) {
+ if (fmt_sp_to_mp(f, &f_copy))
+ break;
+ ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
+ &f_copy);
+ if (ret)
+ break;
+
+ if (f_copy.fmt.pix_mp.num_planes > 1) {
+ ret = -EBUSY;
+ WARN_ON(1);
+ break;
+ }
+
+ ret = fmt_mp_to_sp(&f_copy, f);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
- if (ops->vidioc_s_fmt_vid_cap_mplane)
+ if (ops->vidioc_s_fmt_vid_cap_mplane) {
ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
fh, f);
+ } else if (ops->vidioc_s_fmt_vid_cap &&
+ f->fmt.pix_mp.num_planes == 1) {
+ if (fmt_mp_to_sp(f, &f_copy))
+ break;
+ ret = ops->vidioc_s_fmt_vid_cap(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ ret = fmt_sp_to_mp(&f_copy, f);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
@@ -749,15 +841,42 @@
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.pix);
v4l_print_pix_fmt(vfd, &f->fmt.pix);
- if (ops->vidioc_s_fmt_vid_out)
+ if (ops->vidioc_s_fmt_vid_out) {
ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
+ } else if (ops->vidioc_s_fmt_vid_out_mplane) {
+ if (fmt_sp_to_mp(f, &f_copy))
+ break;
+ ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
+ &f_copy);
+ if (ret)
+ break;
+
+ if (f_copy.fmt.pix_mp.num_planes > 1) {
+ ret = -EBUSY;
+ WARN_ON(1);
+ break;
+ }
+
+ ret = fmt_mp_to_sp(&f_copy, f);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
- if (ops->vidioc_s_fmt_vid_out_mplane)
+ if (ops->vidioc_s_fmt_vid_out_mplane) {
ret = ops->vidioc_s_fmt_vid_out_mplane(file,
fh, f);
+ } else if (ops->vidioc_s_fmt_vid_out &&
+ f->fmt.pix_mp.num_planes == 1) {
+ if (fmt_mp_to_sp(f, &f_copy))
+ break;
+ ret = ops->vidioc_s_fmt_vid_out(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ ret = fmt_mp_to_sp(&f_copy, f);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
@@ -767,30 +886,29 @@
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (likely(ops->vidioc_s_fmt_vbi_cap))
+ if (ops->vidioc_s_fmt_vbi_cap)
ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (likely(ops->vidioc_s_fmt_vbi_out))
+ if (ops->vidioc_s_fmt_vbi_out)
ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (likely(ops->vidioc_s_fmt_sliced_vbi_cap))
+ if (ops->vidioc_s_fmt_sliced_vbi_cap)
ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (likely(ops->vidioc_s_fmt_sliced_vbi_out))
+ if (ops->vidioc_s_fmt_sliced_vbi_out)
ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
fh, f);
-
break;
case V4L2_BUF_TYPE_PRIVATE:
- /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
- if (likely(ops->vidioc_s_fmt_type_private))
+
+ if (ops->vidioc_s_fmt_type_private)
ret = ops->vidioc_s_fmt_type_private(file,
fh, f);
break;
@@ -801,99 +919,142 @@
{
struct v4l2_format *f = (struct v4l2_format *)arg;
- /* FIXME: Should be one dump per type */
+
dbgarg(cmd, "type=%s\n", prt_names(f->type,
v4l2_type_names));
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.pix);
- if (ops->vidioc_try_fmt_vid_cap)
+ if (ops->vidioc_try_fmt_vid_cap) {
ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
+ } else if (ops->vidioc_try_fmt_vid_cap_mplane) {
+ if (fmt_sp_to_mp(f, &f_copy))
+ break;
+ ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ if (f_copy.fmt.pix_mp.num_planes > 1) {
+ ret = -EBUSY;
+ WARN_ON(1);
+ break;
+ }
+ ret = fmt_mp_to_sp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
- if (ops->vidioc_try_fmt_vid_cap_mplane)
+ if (ops->vidioc_try_fmt_vid_cap_mplane) {
ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
fh, f);
+ } else if (ops->vidioc_try_fmt_vid_cap &&
+ f->fmt.pix_mp.num_planes == 1) {
+ if (fmt_mp_to_sp(f, &f_copy))
+ break;
+ ret = ops->vidioc_try_fmt_vid_cap(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ ret = fmt_sp_to_mp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
- if (likely(ops->vidioc_try_fmt_vid_overlay))
+ if (ops->vidioc_try_fmt_vid_overlay)
ret = ops->vidioc_try_fmt_vid_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.pix);
- if (ops->vidioc_try_fmt_vid_out)
+ if (ops->vidioc_try_fmt_vid_out) {
ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
+ } else if (ops->vidioc_try_fmt_vid_out_mplane) {
+ if (fmt_sp_to_mp(f, &f_copy))
+ break;
+ ret = ops->vidioc_try_fmt_vid_out_mplane(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ if (f_copy.fmt.pix_mp.num_planes > 1) {
+ ret = -EBUSY;
+ WARN_ON(1);
+ break;
+ }
+ ret = fmt_mp_to_sp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt(vfd, &f->fmt.pix);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
CLEAR_AFTER_FIELD(f, fmt.pix_mp);
- if (ops->vidioc_try_fmt_vid_out_mplane)
+ if (ops->vidioc_try_fmt_vid_out_mplane) {
ret = ops->vidioc_try_fmt_vid_out_mplane(file,
fh, f);
+ } else if (ops->vidioc_try_fmt_vid_out &&
+ f->fmt.pix_mp.num_planes == 1) {
+ if (fmt_mp_to_sp(f, &f_copy))
+ break;
+ ret = ops->vidioc_try_fmt_vid_out(file,
+ fh, &f_copy);
+ if (ret)
+ break;
+
+ ret = fmt_sp_to_mp(&f_copy, f);
+ }
if (!ret)
v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
CLEAR_AFTER_FIELD(f, fmt.win);
- if (likely(ops->vidioc_try_fmt_vid_out_overlay))
+ if (ops->vidioc_try_fmt_vid_out_overlay)
ret = ops->vidioc_try_fmt_vid_out_overlay(file,
fh, f);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (likely(ops->vidioc_try_fmt_vbi_cap))
+ if (ops->vidioc_try_fmt_vbi_cap)
ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
break;
case V4L2_BUF_TYPE_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.vbi);
- if (likely(ops->vidioc_try_fmt_vbi_out))
+ if (ops->vidioc_try_fmt_vbi_out)
ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (likely(ops->vidioc_try_fmt_sliced_vbi_cap))
+ if (ops->vidioc_try_fmt_sliced_vbi_cap)
ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
fh, f);
break;
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
CLEAR_AFTER_FIELD(f, fmt.sliced);
- if (likely(ops->vidioc_try_fmt_sliced_vbi_out))
+ if (ops->vidioc_try_fmt_sliced_vbi_out)
ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
fh, f);
break;
case V4L2_BUF_TYPE_PRIVATE:
- /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
- if (likely(ops->vidioc_try_fmt_type_private))
+
+ if (ops->vidioc_try_fmt_type_private)
ret = ops->vidioc_try_fmt_type_private(file,
fh, f);
break;
}
- if (unlikely(ret == -ENOTTY && have_fmt_ops(try)))
- ret = -EINVAL;
+
break;
}
- /* FIXME: Those buf reqs could be handled here,
- with some changes on videobuf to allow its header to be included at
- videodev2.h or being merged at videodev2.
- */
case VIDIOC_REQBUFS:
{
struct v4l2_requestbuffers *p = arg;
if (!ops->vidioc_reqbufs)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -959,10 +1120,6 @@
if (!ops->vidioc_overlay)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_overlay(file, fh, *i);
break;
@@ -988,10 +1145,6 @@
if (!ops->vidioc_s_fbuf)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
p->capability, p->flags, (unsigned long)p->base);
v4l_print_pix_fmt(vfd, &p->fmt);
@@ -1004,10 +1157,6 @@
if (!ops->vidioc_streamon)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamon(file, fh, i);
break;
@@ -1018,15 +1167,11 @@
if (!ops->vidioc_streamoff)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamoff(file, fh, i);
break;
}
- /* ---------- tv norms ---------- */
+
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *p = arg;
@@ -1034,14 +1179,8 @@
unsigned int index = p->index, i, j = 0;
const char *descr = "";
- if (id == 0)
- break;
- ret = -EINVAL;
-
- /* Return norm array in a canonical way */
+
for (i = 0; i <= index && id; i++) {
- /* last std value in the standards array is 0, so this
- while always ends there since (id & 0) == 0. */
while ((id & standards[j].std) != standards[j].std)
j++;
curr_id = standards[j].std;
@@ -1073,15 +1212,16 @@
{
v4l2_std_id *id = arg;
- /* Calls the specific handler */
+ ret = 0;
+
if (ops->vidioc_g_std)
ret = ops->vidioc_g_std(file, fh, id);
- else if (vfd->current_norm) {
- ret = 0;
+ else if (vfd->current_norm)
*id = vfd->current_norm;
- }
+ else
+ ret = -EINVAL;
- if (likely(!ret))
+ if (!ret)
dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
break;
}
@@ -1091,22 +1231,17 @@
dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
- if (!ops->vidioc_s_std)
- break;
-
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
- ret = -EINVAL;
norm = (*id) & vfd->tvnorms;
- if (vfd->tvnorms && !norm) /* Check if std is supported */
+ if (vfd->tvnorms && !norm)
break;
- /* Calls the specific handler */
- ret = ops->vidioc_s_std(file, fh, &norm);
+
+ if (ops->vidioc_s_std)
+ ret = ops->vidioc_s_std(file, fh, &norm);
+ else
+ ret = -EINVAL;
- /* Updates standard information */
+
if (ret >= 0)
vfd->current_norm = norm;
break;
@@ -1117,32 +1252,18 @@
if (!ops->vidioc_querystd)
break;
- /*
- * If nothing detected, it should return all supported
- * Drivers just need to mask the std argument, in order
- * to remove the standards that don't apply from the mask.
- * This means that tuners, audio and video decoders can join
- * their efforts to improve the standards detection
- */
- *p = vfd->tvnorms;
ret = ops->vidioc_querystd(file, fh, arg);
if (!ret)
dbgarg(cmd, "detected std=%08Lx\n",
(unsigned long long)*p);
break;
}
- /* ------ input switching ---------- */
- /* FIXME: Inputs can be handled inside videodev2 */
+
+
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *p = arg;
- /*
- * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
- * CAP_STD here based on ioctl handler provided by the
- * driver. If the driver doesn't support these
- * for a specific input, it must override these flags.
- */
if (ops->vidioc_s_std)
p->capabilities |= V4L2_IN_CAP_STD;
if (ops->vidioc_s_dv_preset)
@@ -1181,16 +1302,12 @@
if (!ops->vidioc_s_input)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_input(file, fh, *i);
break;
}
- /* ------ output switching ---------- */
+
case VIDIOC_ENUMOUTPUT:
{
struct v4l2_output *p = arg;
@@ -1198,12 +1315,6 @@
if (!ops->vidioc_enum_output)
break;
- /*
- * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
- * CAP_STD here based on ioctl handler provided by the
- * driver. If the driver doesn't support these
- * for a specific output, it must override these flags.
- */
if (ops->vidioc_s_std)
p->capabilities |= V4L2_OUT_CAP_STD;
if (ops->vidioc_s_dv_preset)
@@ -1237,23 +1348,17 @@
if (!ops->vidioc_s_output)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_output(file, fh, *i);
break;
}
- /* --- controls ---------------------------------------------- */
+
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *p = arg;
- if (vfh && vfh->ctrl_handler)
- ret = v4l2_queryctrl(vfh->ctrl_handler, p);
- else if (vfd->ctrl_handler)
+ if (vfd->ctrl_handler)
ret = v4l2_queryctrl(vfd->ctrl_handler, p);
else if (ops->vidioc_queryctrl)
ret = ops->vidioc_queryctrl(file, fh, p);
@@ -1273,9 +1378,7 @@
{
struct v4l2_control *p = arg;
- if (vfh && vfh->ctrl_handler)
- ret = v4l2_g_ctrl(vfh->ctrl_handler, p);
- else if (vfd->ctrl_handler)
+ if (vfd->ctrl_handler)
ret = v4l2_g_ctrl(vfd->ctrl_handler, p);
else if (ops->vidioc_g_ctrl)
ret = ops->vidioc_g_ctrl(file, fh, p);
@@ -1307,22 +1410,14 @@
struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl;
- if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
+ if (!vfd->ctrl_handler &&
!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
- if (vfh && vfh->ctrl_handler) {
- ret = v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);
- break;
- }
if (vfd->ctrl_handler) {
- ret = v4l2_s_ctrl(NULL, vfd->ctrl_handler, p);
+ ret = v4l2_s_ctrl(vfd->ctrl_handler, p);
break;
}
if (ops->vidioc_s_ctrl) {
@@ -1339,8 +1434,6 @@
ctrl.value = p->value;
if (check_ext_ctrls(&ctrls, 1))
ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
- else
- ret = -EINVAL;
break;
}
case VIDIOC_G_EXT_CTRLS:
@@ -1348,14 +1441,10 @@
struct v4l2_ext_controls *p = arg;
p->error_idx = p->count;
- if (vfh && vfh->ctrl_handler)
- ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
- else if (vfd->ctrl_handler)
+ if (vfd->ctrl_handler)
ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
- else if (ops->vidioc_g_ext_ctrls)
- ret = check_ext_ctrls(p, 0) ?
- ops->vidioc_g_ext_ctrls(file, fh, p) :
- -EINVAL;
+ else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
+ ret = ops->vidioc_g_ext_ctrls(file, fh, p);
else
break;
v4l_print_ext_ctrls(cmd, vfd, p, !ret);
@@ -1366,22 +1455,13 @@
struct v4l2_ext_controls *p = arg;
p->error_idx = p->count;
- if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
- !ops->vidioc_s_ext_ctrls)
+ if (!vfd->ctrl_handler && !ops->vidioc_s_ext_ctrls)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
v4l_print_ext_ctrls(cmd, vfd, p, 1);
- if (vfh && vfh->ctrl_handler)
- ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
- else if (vfd->ctrl_handler)
- ret = v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
+ if (vfd->ctrl_handler)
+ ret = v4l2_s_ext_ctrls(vfd->ctrl_handler, p);
else if (check_ext_ctrls(p, 0))
ret = ops->vidioc_s_ext_ctrls(file, fh, p);
- else
- ret = -EINVAL;
break;
}
case VIDIOC_TRY_EXT_CTRLS:
@@ -1389,27 +1469,20 @@
struct v4l2_ext_controls *p = arg;
p->error_idx = p->count;
- if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
- !ops->vidioc_try_ext_ctrls)
+ if (!vfd->ctrl_handler && !ops->vidioc_try_ext_ctrls)
break;
v4l_print_ext_ctrls(cmd, vfd, p, 1);
- if (vfh && vfh->ctrl_handler)
- ret = v4l2_try_ext_ctrls(vfh->ctrl_handler, p);
- else if (vfd->ctrl_handler)
+ if (vfd->ctrl_handler)
ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
else if (check_ext_ctrls(p, 0))
ret = ops->vidioc_try_ext_ctrls(file, fh, p);
- else
- ret = -EINVAL;
break;
}
case VIDIOC_QUERYMENU:
{
struct v4l2_querymenu *p = arg;
- if (vfh && vfh->ctrl_handler)
- ret = v4l2_querymenu(vfh->ctrl_handler, p);
- else if (vfd->ctrl_handler)
+ if (vfd->ctrl_handler)
ret = v4l2_querymenu(vfd->ctrl_handler, p);
else if (ops->vidioc_querymenu)
ret = ops->vidioc_querymenu(file, fh, p);
@@ -1423,7 +1496,7 @@
p->id, p->index);
break;
}
- /* --- audio ---------------------------------------------- */
+
case VIDIOC_ENUMAUDIO:
{
struct v4l2_audio *p = arg;
@@ -1461,10 +1534,6 @@
if (!ops->vidioc_s_audio)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
"mode=0x%x\n", p->index, p->name,
p->capability, p->mode);
@@ -1505,10 +1574,6 @@
if (!ops->vidioc_s_audout)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"mode=%d\n", p->index, p->name,
p->capability, p->mode);
@@ -1538,10 +1603,6 @@
if (!ops->vidioc_s_modulator)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
p->index, p->name, p->capability, p->rangelow,
@@ -1553,32 +1614,11 @@
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_g_crop && !ops->vidioc_g_selection)
+ if (!ops->vidioc_g_crop)
break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
-
- if (ops->vidioc_g_crop) {
- ret = ops->vidioc_g_crop(file, fh, p);
- } else {
- /* simulate capture crop using selection api */
- struct v4l2_selection s = {
- .type = p->type,
- };
-
- /* crop means compose for output devices */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
- else
- s.target = V4L2_SEL_TGT_CROP_ACTIVE;
-
- ret = ops->vidioc_g_selection(file, fh, &s);
-
- /* copying results to old structure on success */
- if (!ret)
- p->c = s.r;
- }
-
+ ret = ops->vidioc_g_crop(file, fh, p);
if (!ret)
dbgrect(vfd, "", &p->c);
break;
@@ -1587,108 +1627,23 @@
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_s_crop && !ops->vidioc_s_selection)
+ if (!ops->vidioc_s_crop)
break;
-
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
dbgrect(vfd, "", &p->c);
-
- if (ops->vidioc_s_crop) {
- ret = ops->vidioc_s_crop(file, fh, p);
- } else {
- /* simulate capture crop using selection api */
- struct v4l2_selection s = {
- .type = p->type,
- .r = p->c,
- };
-
- /* crop means compose for output devices */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
- else
- s.target = V4L2_SEL_TGT_CROP_ACTIVE;
-
- ret = ops->vidioc_s_selection(file, fh, &s);
- }
- 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);
+ ret = ops->vidioc_s_crop(file, fh, p);
break;
}
case VIDIOC_CROPCAP:
{
struct v4l2_cropcap *p = arg;
- /*FIXME: Should also show v4l2_fract pixelaspect */
- if (!ops->vidioc_cropcap && !ops->vidioc_g_selection)
+
+ if (!ops->vidioc_cropcap)
break;
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
- if (ops->vidioc_cropcap) {
- ret = ops->vidioc_cropcap(file, fh, p);
- } else {
- struct v4l2_selection s = { .type = p->type };
-
- /* obtaining bounds */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
- else
- s.target = V4L2_SEL_TGT_CROP_BOUNDS;
-
- ret = ops->vidioc_g_selection(file, fh, &s);
- if (ret)
- break;
- p->bounds = s.r;
-
- /* obtaining defrect */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
- else
- s.target = V4L2_SEL_TGT_CROP_DEFAULT;
-
- ret = ops->vidioc_g_selection(file, fh, &s);
- if (ret)
- break;
- p->defrect = s.r;
-
- /* setting trivial pixelaspect */
- p->pixelaspect.numerator = 1;
- p->pixelaspect.denominator = 1;
- }
-
+ ret = ops->vidioc_cropcap(file, fh, p);
if (!ret) {
dbgrect(vfd, "bounds ", &p->bounds);
dbgrect(vfd, "defrect ", &p->defrect);
@@ -1717,15 +1672,11 @@
if (!ops->vidioc_g_jpegcomp)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
"COM_len=%d, jpeg_markers=%d\n",
p->quality, p->APPn, p->APP_len,
p->COM_len, p->jpeg_markers);
- ret = ops->vidioc_s_jpegcomp(file, fh, p);
+ ret = ops->vidioc_s_jpegcomp(file, fh, p);
break;
}
case VIDIOC_G_ENC_INDEX:
@@ -1746,10 +1697,6 @@
if (!ops->vidioc_encoder_cmd)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = ops->vidioc_encoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1766,38 +1713,10 @@
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
break;
}
- case VIDIOC_DECODER_CMD:
- {
- struct v4l2_decoder_cmd *p = arg;
-
- if (!ops->vidioc_decoder_cmd)
- break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
- ret = ops->vidioc_decoder_cmd(file, fh, p);
- if (!ret)
- dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
- break;
- }
- case VIDIOC_TRY_DECODER_CMD:
- {
- struct v4l2_decoder_cmd *p = arg;
-
- if (!ops->vidioc_try_decoder_cmd)
- break;
- ret = ops->vidioc_try_decoder_cmd(file, fh, p);
- if (!ret)
- dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
- break;
- }
case VIDIOC_G_PARM:
{
struct v4l2_streamparm *p = arg;
- if (!ops->vidioc_g_parm && !vfd->current_norm)
- break;
if (ops->vidioc_g_parm) {
ret = check_fmt(ops, p->type);
if (ret)
@@ -1806,13 +1725,14 @@
} else {
v4l2_std_id std = vfd->current_norm;
- ret = -EINVAL;
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
break;
ret = 0;
if (ops->vidioc_g_std)
ret = ops->vidioc_g_std(file, fh, &std);
+ else if (std == 0)
+ ret = -EINVAL;
if (ret == 0)
v4l2_video_std_frame_period(std,
&p->parm.capture.timeperframe);
@@ -1827,10 +1747,6 @@
if (!ops->vidioc_s_parm)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1866,10 +1782,6 @@
if (!ops->vidioc_s_tuner)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1901,22 +1813,12 @@
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *p = arg;
- enum v4l2_tuner_type type;
if (!ops->vidioc_s_frequency)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
- type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
- V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
p->tuner, p->type, p->frequency);
- if (p->type != type)
- ret = -EINVAL;
- else
- ret = ops->vidioc_s_frequency(file, fh, p);
+ ret = ops->vidioc_s_frequency(file, fh, p);
break;
}
case VIDIOC_G_SLICED_VBI_CAP:
@@ -1926,7 +1828,7 @@
if (!ops->vidioc_g_sliced_vbi_cap)
break;
- /* Clear up to type, everything after type is zerod already */
+
memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
@@ -1939,13 +1841,7 @@
{
if (!ops->vidioc_log_status)
break;
- if (vfd->v4l2_dev)
- pr_info("%s: ================= START STATUS =================\n",
- vfd->v4l2_dev->name);
ret = ops->vidioc_log_status(file, fh);
- if (vfd->v4l2_dev)
- pr_info("%s: ================== END STATUS ==================\n",
- vfd->v4l2_dev->name);
break;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1994,10 +1890,6 @@
if (!ops->vidioc_s_hw_freq_seek)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd,
@@ -2102,10 +1994,6 @@
if (!ops->vidioc_s_dv_preset)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "preset=%d\n", p->preset);
ret = ops->vidioc_s_dv_preset(file, fh, p);
@@ -2141,10 +2029,6 @@
if (!ops->vidioc_s_dv_timings)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
switch (p->type) {
case V4L2_DV_BT_656_1120:
@@ -2252,47 +2136,20 @@
dbgarg(cmd, "type=0x%8.8x", sub->type);
break;
}
- case VIDIOC_CREATE_BUFS:
- {
- struct v4l2_create_buffers *create = arg;
-
- if (!ops->vidioc_create_bufs)
- break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
- ret = check_fmt(ops, create->format.type);
- if (ret)
- break;
-
- ret = ops->vidioc_create_bufs(file, fh, create);
-
- dbgarg(cmd, "count=%d @ %d\n", create->count, create->index);
- break;
- }
- case VIDIOC_PREPARE_BUF:
- {
- struct v4l2_buffer *b = arg;
-
- if (!ops->vidioc_prepare_buf)
- break;
- ret = check_fmt(ops, b->type);
- if (ret)
- break;
-
- ret = ops->vidioc_prepare_buf(file, fh, b);
-
- dbgarg(cmd, "index=%d", b->index);
- break;
- }
default:
+ {
+ bool valid_prio = true;
+
if (!ops->vidioc_default)
break;
- ret = ops->vidioc_default(file, fh, ret_prio >= 0, cmd, arg);
+ if (use_fh_prio)
+ valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
+ ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
break;
- } /* switch */
+ }
+ }
+exit_prio:
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
if (ret < 0) {
v4l_print_ioctl(vfd->name, cmd);
@@ -2303,12 +2160,9 @@
return ret;
}
-/* In some cases, only a few fields are used as input, i.e. when the app sets
- * "index" and then the driver fills in the rest of the structure for the thing
- * with that index. We only need to copy up the first non-input field. */
static unsigned long cmd_input_size(unsigned int cmd)
{
- /* Size of structure up to and including 'field' */
+
#define CMDINSIZE(cmd, type, field) \
case VIDIOC_##cmd: \
return offsetof(struct v4l2_##type, field) + \
@@ -2359,7 +2213,7 @@
break;
}
*user_ptr = (void __user *)buf->m.planes;
- *kernel_ptr = (void *)&buf->m.planes;
+ *kernel_ptr = (void **)&buf->m.planes;
*array_size = sizeof(struct v4l2_plane) * buf->length;
ret = 1;
}
@@ -2377,7 +2231,7 @@
break;
}
*user_ptr = (void __user *)ctrls->controls;
- *kernel_ptr = (void *)&ctrls->controls;
+ *kernel_ptr = (void **)&ctrls->controls;
*array_size = sizeof(struct v4l2_ext_control)
* ctrls->count;
ret = 1;
@@ -2402,12 +2256,12 @@
void __user *user_ptr = NULL;
void **kernel_ptr = NULL;
- /* Copy arguments into temp kernel buffer */
+
if (_IOC_DIR(cmd) != _IOC_NONE) {
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
parg = sbuf;
} else {
- /* too big to allocate from stack */
+
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
@@ -2421,11 +2275,11 @@
if (copy_from_user(parg, (void __user *)arg, n))
goto out;
- /* zero out anything we don't copy from userspace */
+
if (n < _IOC_SIZE(cmd))
memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
} else {
- /* read-only ioctl */
+
memset(parg, 0, _IOC_SIZE(cmd));
}
}
@@ -2436,12 +2290,6 @@
has_array_args = err;
if (has_array_args) {
- /*
- * When adding new types of array args, make sure that the
- * parent argument to ioctl (which contains the pointer to the
- * array) fits into sbuf (so that mbuf will still remain
- * unused up to here).
- */
mbuf = kmalloc(array_size, GFP_KERNEL);
err = -ENOMEM;
if (NULL == mbuf)
@@ -2452,10 +2300,10 @@
*kernel_ptr = mbuf;
}
- /* Handles IOCTL */
+
err = func(file, cmd, parg);
if (err == -ENOIOCTLCMD)
- err = -ENOTTY;
+ err = -EINVAL;
if (has_array_args) {
*kernel_ptr = user_ptr;
@@ -2467,7 +2315,7 @@
goto out;
out_array_args:
- /* Copy results into user buffer */
+
switch (_IOC_DIR(cmd)) {
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index 6fe88e9..2d1560a 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -20,11 +20,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/videodev2.h>
-#include <linux/export.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@@ -35,7 +35,7 @@
static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
{
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
- /* Allocate try format and crop in the same memory block */
+
fh->try_fmt = kzalloc((sizeof(*fh->try_fmt) + sizeof(*fh->try_crop))
* sd->entity.num_pads, GFP_KERNEL);
if (fh->try_fmt == NULL)
@@ -76,7 +76,20 @@
return ret;
}
- v4l2_fh_init(&subdev_fh->vfh, vdev);
+ ret = v4l2_fh_init(&subdev_fh->vfh, vdev);
+ if (ret)
+ goto err;
+
+ if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
+ ret = v4l2_event_init(&subdev_fh->vfh);
+ if (ret)
+ goto err;
+
+ ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
+ if (ret)
+ goto err;
+ }
+
v4l2_fh_add(&subdev_fh->vfh);
file->private_data = &subdev_fh->vfh;
#if defined(CONFIG_MEDIA_CONTROLLER)
@@ -143,25 +156,25 @@
switch (cmd) {
case VIDIOC_QUERYCTRL:
- return v4l2_queryctrl(vfh->ctrl_handler, arg);
+ return v4l2_queryctrl(sd->ctrl_handler, arg);
case VIDIOC_QUERYMENU:
- return v4l2_querymenu(vfh->ctrl_handler, arg);
+ return v4l2_querymenu(sd->ctrl_handler, arg);
case VIDIOC_G_CTRL:
- return v4l2_g_ctrl(vfh->ctrl_handler, arg);
+ return v4l2_g_ctrl(sd->ctrl_handler, arg);
case VIDIOC_S_CTRL:
- return v4l2_s_ctrl(vfh, vfh->ctrl_handler, arg);
+ return v4l2_s_ctrl(sd->ctrl_handler, arg);
case VIDIOC_G_EXT_CTRLS:
- return v4l2_g_ext_ctrls(vfh->ctrl_handler, arg);
+ return v4l2_g_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_S_EXT_CTRLS:
- return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, arg);
+ return v4l2_s_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_TRY_EXT_CTRLS:
- return v4l2_try_ext_ctrls(vfh->ctrl_handler, arg);
+ return v4l2_try_ext_ctrls(sd->ctrl_handler, arg);
case VIDIOC_DQEVENT:
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
@@ -174,37 +187,6 @@
case VIDIOC_UNSUBSCRIBE_EVENT:
return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
- case VIDIOC_DBG_G_REGISTER:
- {
- struct v4l2_dbg_register *p = arg;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- return v4l2_subdev_call(sd, core, g_register, p);
- }
- case VIDIOC_DBG_S_REGISTER:
- {
- struct v4l2_dbg_register *p = arg;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- return v4l2_subdev_call(sd, core, s_register, p);
- }
-#endif
-
- case VIDIOC_LOG_STATUS: {
- int ret;
-
- pr_info("%s: ================= START STATUS =================\n",
- sd->name);
- ret = v4l2_subdev_call(sd, core, log_status);
- pr_info("%s: ================== END STATUS ==================\n",
- sd->name);
- return ret;
- }
-
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
case VIDIOC_SUBDEV_G_FMT: {
struct v4l2_subdev_format *format = arg;
@@ -316,7 +298,7 @@
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
return POLLERR;
- poll_wait(file, &fh->wait, wait);
+ poll_wait(file, &fh->events->wait, wait);
if (v4l2_event_pending(fh))
return POLLPRI;
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 7395c81..51a1c2d 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -24,27 +24,23 @@
#ifndef V4L2_CHIP_IDENT_H_
#define V4L2_CHIP_IDENT_H_
-/* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */
-/* KEEP THIS LIST ORDERED BY ID!
- Otherwise it will be hard to see which ranges are already in use when
- adding support to a new chip family. */
enum {
- /* general idents: reserved range 0-49 */
- V4L2_IDENT_NONE = 0, /* No chip matched */
- V4L2_IDENT_AMBIGUOUS = 1, /* Match too general, multiple chips matched */
- V4L2_IDENT_UNKNOWN = 2, /* Chip found, but cannot identify */
+
+ V4L2_IDENT_NONE = 0,
+ V4L2_IDENT_AMBIGUOUS = 1,
+ V4L2_IDENT_UNKNOWN = 2,
- /* module tvaudio: reserved range 50-99 */
- V4L2_IDENT_TVAUDIO = 50, /* A tvaudio chip, unknown which it is exactly */
+
+ V4L2_IDENT_TVAUDIO = 50,
- /* Sony IMX074 */
+
V4L2_IDENT_IMX074 = 74,
- /* module saa7110: just ident 100 */
+
V4L2_IDENT_SAA7110 = 100,
- /* module saa7115: reserved range 101-149 */
+
V4L2_IDENT_SAA7111 = 101,
V4L2_IDENT_SAA7111A = 102,
V4L2_IDENT_SAA7113 = 103,
@@ -52,11 +48,11 @@
V4L2_IDENT_SAA7115 = 105,
V4L2_IDENT_SAA7118 = 108,
- /* module saa7127: reserved range 150-199 */
+
V4L2_IDENT_SAA7127 = 157,
V4L2_IDENT_SAA7129 = 159,
- /* module cx25840: reserved range 200-249 */
+
V4L2_IDENT_CX25836 = 236,
V4L2_IDENT_CX25837 = 237,
V4L2_IDENT_CX25840 = 240,
@@ -64,7 +60,7 @@
V4L2_IDENT_CX25842 = 242,
V4L2_IDENT_CX25843 = 243,
- /* OmniVision sensors: reserved range 250-299 */
+
V4L2_IDENT_OV7670 = 250,
V4L2_IDENT_OV7720 = 251,
V4L2_IDENT_OV7725 = 252,
@@ -76,157 +72,151 @@
V4L2_IDENT_OV6650 = 258,
V4L2_IDENT_OV2640 = 259,
V4L2_IDENT_OV9740 = 260,
- V4L2_IDENT_OV5642 = 261,
- /* module saa7146: reserved range 300-309 */
+
V4L2_IDENT_SAA7146 = 300,
- /* Conexant MPEG encoder/decoders: reserved range 400-420 */
- V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */
+
+ V4L2_IDENT_CX23418_843 = 403,
V4L2_IDENT_CX23415 = 415,
V4L2_IDENT_CX23416 = 416,
V4L2_IDENT_CX23417 = 417,
V4L2_IDENT_CX23418 = 418,
- /* module bt819: reserved range 810-819 */
+
V4L2_IDENT_BT815A = 815,
V4L2_IDENT_BT817A = 817,
V4L2_IDENT_BT819A = 819,
- /* module au0828 */
+
V4L2_IDENT_AU0828 = 828,
- /* module bt856: just ident 856 */
+
V4L2_IDENT_BT856 = 856,
- /* module bt866: just ident 866 */
+
V4L2_IDENT_BT866 = 866,
- /* module ks0127: reserved range 1120-1129 */
+
V4L2_IDENT_KS0122S = 1122,
V4L2_IDENT_KS0127 = 1127,
V4L2_IDENT_KS0127B = 1128,
- /* module indycam: just ident 2000 */
+
V4L2_IDENT_INDYCAM = 2000,
- /* module vp27smpx: just ident 2700 */
+
V4L2_IDENT_VP27SMPX = 2700,
- /* module vpx3220: reserved range: 3210-3229 */
+
V4L2_IDENT_VPX3214C = 3214,
V4L2_IDENT_VPX3216B = 3216,
V4L2_IDENT_VPX3220A = 3220,
- /* VX855 just ident 3409 */
- /* Other via devs could use 3314, 3324, 3327, 3336, 3364, 3353 */
+
+
V4L2_IDENT_VIA_VX855 = 3409,
- /* module tvp5150 */
+
V4L2_IDENT_TVP5150 = 5150,
- /* module saa5246a: just ident 5246 */
+
V4L2_IDENT_SAA5246A = 5246,
- /* module saa5249: just ident 5249 */
+
V4L2_IDENT_SAA5249 = 5249,
- /* module cs5345: just ident 5345 */
+
V4L2_IDENT_CS5345 = 5345,
- /* module tea6415c: just ident 6415 */
+
V4L2_IDENT_TEA6415C = 6415,
- /* module tea6420: just ident 6420 */
+
V4L2_IDENT_TEA6420 = 6420,
- /* module saa6588: just ident 6588 */
+
V4L2_IDENT_SAA6588 = 6588,
- /* module vs6624: just ident 6624 */
- V4L2_IDENT_VS6624 = 6624,
-
- /* module saa6752hs: reserved range 6750-6759 */
+
V4L2_IDENT_SAA6752HS = 6752,
V4L2_IDENT_SAA6752HS_AC3 = 6753,
- /* modules tef6862: just ident 6862 */
+
V4L2_IDENT_TEF6862 = 6862,
- /* module tvp7002: just ident 7002 */
+
V4L2_IDENT_TVP7002 = 7002,
- /* module adv7170: just ident 7170 */
+
V4L2_IDENT_ADV7170 = 7170,
- /* module adv7175: just ident 7175 */
+
V4L2_IDENT_ADV7175 = 7175,
- /* module adv7180: just ident 7180 */
+
V4L2_IDENT_ADV7180 = 7180,
- /* module adv7183: just ident 7183 */
- V4L2_IDENT_ADV7183 = 7183,
-
- /* module saa7185: just ident 7185 */
+
V4L2_IDENT_SAA7185 = 7185,
- /* module saa7191: just ident 7191 */
+
V4L2_IDENT_SAA7191 = 7191,
- /* module ths7303: just ident 7303 */
+
V4L2_IDENT_THS7303 = 7303,
- /* module adv7343: just ident 7343 */
+
V4L2_IDENT_ADV7343 = 7343,
- /* module saa7706h: just ident 7706 */
+
V4L2_IDENT_SAA7706H = 7706,
- /* module mt9v011, just ident 8243 */
+
V4L2_IDENT_MT9V011 = 8243,
- /* module wm8739: just ident 8739 */
+
V4L2_IDENT_WM8739 = 8739,
- /* module wm8775: just ident 8775 */
+
V4L2_IDENT_WM8775 = 8775,
- /* Marvell controllers starting at 8801 */
+
V4L2_IDENT_CAFE = 8801,
- V4L2_IDENT_ARMADA610 = 8802,
- /* AKM AK8813/AK8814 */
+
V4L2_IDENT_AK8813 = 8813,
V4L2_IDENT_AK8814 = 8814,
- /* module cx23885 and cx25840 */
+
V4L2_IDENT_CX23885 = 8850,
- V4L2_IDENT_CX23885_AV = 8851, /* Integrated A/V decoder */
+ V4L2_IDENT_CX23885_AV = 8851,
V4L2_IDENT_CX23887 = 8870,
- V4L2_IDENT_CX23887_AV = 8871, /* Integrated A/V decoder */
+ V4L2_IDENT_CX23887_AV = 8871,
V4L2_IDENT_CX23888 = 8880,
- V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */
- V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */
+ V4L2_IDENT_CX23888_AV = 8881,
+ V4L2_IDENT_CX23888_IR = 8882,
- /* module tda9840: just ident 9840 */
+
V4L2_IDENT_TDA9840 = 9840,
- /* module tw9910: just ident 9910 */
+
V4L2_IDENT_TW9910 = 9910,
- /* module sn9c20x: just ident 10000 */
+
V4L2_IDENT_SN9C20X = 10000,
- /* module cx231xx and cx25840 */
- V4L2_IDENT_CX2310X_AV = 23099, /* Integrated A/V decoder; not in '100 */
+
+ V4L2_IDENT_NOON010PC30 = 10100,
+
+
+ V4L2_IDENT_CX2310X_AV = 23099,
V4L2_IDENT_CX23100 = 23100,
V4L2_IDENT_CX23101 = 23101,
V4L2_IDENT_CX23102 = 23102,
- /* module msp3400: reserved range 34000-34999 for msp34xx */
- V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only
- use internally (tveeprom.c). */
+
+ V4L2_IDENT_MSPX4XX = 34000,
V4L2_IDENT_MSP3400B = 34002,
V4L2_IDENT_MSP3400C = 34003,
@@ -278,7 +268,7 @@
V4L2_IDENT_MSP3465G = 34657,
V4L2_IDENT_MSP3467G = 34677,
- /* module msp3400: reserved range 44000-44999 for msp44xx */
+
V4L2_IDENT_MSP4400G = 44007,
V4L2_IDENT_MSP4408G = 44087,
V4L2_IDENT_MSP4410G = 44107,
@@ -290,43 +280,43 @@
V4L2_IDENT_MSP4450G = 44507,
V4L2_IDENT_MSP4458G = 44587,
- /* Micron CMOS sensor chips: 45000-45099 */
+
V4L2_IDENT_MT9M001C12ST = 45000,
V4L2_IDENT_MT9M001C12STM = 45005,
V4L2_IDENT_MT9M111 = 45007,
V4L2_IDENT_MT9M112 = 45008,
- V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */
- V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */
+ V4L2_IDENT_MT9V022IX7ATC = 45010,
+ V4L2_IDENT_MT9V022IX7ATM = 45015,
V4L2_IDENT_MT9T031 = 45020,
V4L2_IDENT_MT9T111 = 45021,
V4L2_IDENT_MT9T112 = 45022,
V4L2_IDENT_MT9V111 = 45031,
V4L2_IDENT_MT9V112 = 45032,
- /* HV7131R CMOS sensor: just ident 46000 */
+
V4L2_IDENT_HV7131R = 46000,
- /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */
+
V4L2_IDENT_RJ54N1CB0C = 51980,
- /* module m52790: just ident 52790 */
+
V4L2_IDENT_M52790 = 52790,
- /* module cs53132a: just ident 53132 */
+
V4L2_IDENT_CS53l32A = 53132,
- /* modules upd61151 MPEG2 encoder: just ident 54000 */
+
V4L2_IDENT_UPD61161 = 54000,
- /* modules upd61152 MPEG2 encoder with AC3: just ident 54001 */
+
V4L2_IDENT_UPD61162 = 54001,
- /* module upd64031a: just ident 64031 */
+
V4L2_IDENT_UPD64031A = 64031,
- /* module upd64083: just ident 64083 */
+
V4L2_IDENT_UPD64083 = 64083,
- /* Don't just add new IDs at the end: KEEP THIS LIST ORDERED BY ID! */
+
};
#endif
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index a298ec4..24bca98 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -28,9 +28,6 @@
#include <media/v4l2-dev.h>
-/* Common printk constucts for v4l-i2c drivers. These macros create a unique
- prefix consisting of the driver name, the adapter number and the i2c
- address. */
#define v4l_printk(level, name, adapter, addr, fmt, arg...) \
printk(level "%s %d-%04x: " fmt, name, i2c_adapter_id(adapter), addr , ## arg)
@@ -47,17 +44,13 @@
#define v4l_info(client, fmt, arg...) \
v4l_client_printk(KERN_INFO, client, fmt , ## arg)
-/* These three macros assume that the debug level is set with a module
- parameter called 'debug'. */
#define v4l_dbg(level, debug, client, fmt, arg...) \
do { \
if (debug >= (level)) \
v4l_client_printk(KERN_DEBUG, client, fmt , ## arg); \
} while (0)
-/* ------------------------------------------------------------------------- */
-/* These printk constructs can be used with v4l2_device and v4l2_subdev */
#define v4l2_printk(level, dev, fmt, arg...) \
printk(level "%s: " fmt, (dev)->name , ## arg)
@@ -70,17 +63,13 @@
#define v4l2_info(dev, fmt, arg...) \
v4l2_printk(KERN_INFO, dev, fmt , ## arg)
-/* These three macros assume that the debug level is set with a module
- parameter called 'debug'. */
#define v4l2_dbg(level, debug, dev, fmt, arg...) \
do { \
if (debug >= (level)) \
v4l2_printk(KERN_DEBUG, dev, fmt , ## arg); \
} while (0)
-/* ------------------------------------------------------------------------- */
-/* Control helper functions */
int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
const char * const *menu_items);
@@ -92,25 +81,17 @@
#define V4L2_CTRL_MENU_IDS_END (0xffffffff)
int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids);
-/* Note: ctrl_classes points to an array of u32 pointers. Each u32 array is a
- 0-terminated array of control IDs. Each array must be sorted low to high
- and belong to the same control class. The array of u32 pointers must also
- be sorted, from low class IDs to high class IDs. */
u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
-/* ------------------------------------------------------------------------- */
-/* Register/chip ident helper function */
-struct i2c_client; /* forward reference */
+struct i2c_client;
int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match);
int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip,
u32 ident, u32 revision);
int v4l2_chip_match_host(const struct v4l2_dbg_match *match);
-/* ------------------------------------------------------------------------- */
-/* I2C Helper functions */
struct i2c_driver;
struct i2c_adapter;
@@ -121,8 +102,6 @@
struct v4l2_subdev_ops;
-/* Load an i2c module and return an initialized v4l2_subdev struct.
- The client_type argument is the name of the chip that's on the adapter. */
struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
struct i2c_adapter *adapter, const char *client_type,
u8 addr, const unsigned short *probe_addrs);
@@ -133,52 +112,34 @@
struct i2c_adapter *adapter, struct i2c_board_info *info,
const unsigned short *probe_addrs);
-/* Initialize an v4l2_subdev with data from an i2c_client struct */
void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
const struct v4l2_subdev_ops *ops);
-/* Return i2c client address of v4l2_subdev. */
unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd);
enum v4l2_i2c_tuner_type {
- ADDRS_RADIO, /* Radio tuner addresses */
- ADDRS_DEMOD, /* Demod tuner addresses */
- ADDRS_TV, /* TV tuner addresses */
- /* TV tuner addresses if demod is present, this excludes
- addresses used by the demodulator from the list of
- candidates. */
+ ADDRS_RADIO,
+ ADDRS_DEMOD,
+ ADDRS_TV,
ADDRS_TV_WITH_DEMOD,
};
-/* Return a list of I2C tuner addresses to probe. Use only if the tuner
- addresses are unknown. */
const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type);
-/* ------------------------------------------------------------------------- */
-/* SPI Helper functions */
#if defined(CONFIG_SPI)
#include <linux/spi/spi.h>
struct spi_device;
-/* Load an spi module and return an initialized v4l2_subdev struct.
- The client_type argument is the name of the chip that's on the adapter. */
struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
struct spi_master *master, struct spi_board_info *info);
-/* Initialize an v4l2_subdev with data from an spi_device struct */
void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
const struct v4l2_subdev_ops *ops);
#endif
-/* ------------------------------------------------------------------------- */
-/* Note: these remaining ioctls/structs should be removed as well, but they are
- still used in tuner-simple.c (TUNER_SET_CONFIG), cx18/ivtv (RESET) and
- v4l2-int-device.h (v4l2_routing). To remove these ioctls some more cleanup
- is needed in those modules. */
-/* s_config */
struct v4l2_priv_tun_config {
int tuner;
void *priv;
@@ -192,9 +153,7 @@
u32 output;
};
-/* ------------------------------------------------------------------------- */
-/* Miscellaneous helper functions */
void v4l_bound_align_image(unsigned int *w, unsigned int wmin,
unsigned int wmax, unsigned int walign,
@@ -212,4 +171,4 @@
const struct v4l2_discrete_probe *probe,
s32 width, s32 height);
-#endif /* V4L2_COMMON_H_ */
+#endif
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 3a44b62..166f624 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -22,94 +22,23 @@
#define _V4L2_CTRLS_H
#include <linux/list.h>
+#include <linux/device.h>
#include <linux/videodev2.h>
-/* forward references */
struct v4l2_ctrl_handler;
-struct v4l2_ctrl_helper;
struct v4l2_ctrl;
struct video_device;
struct v4l2_subdev;
-struct v4l2_subscribed_event;
-struct v4l2_fh;
-struct poll_table_struct;
-struct file;
-/** struct v4l2_ctrl_ops - The control operations that the driver has to provide.
- * @g_volatile_ctrl: Get a new value for this control. Generally only relevant
- * for volatile (and usually read-only) controls such as a control
- * that returns the current signal strength which changes
- * continuously.
- * If not set, then the currently cached value will be returned.
- * @try_ctrl: Test whether the control's value is valid. Only relevant when
- * the usual min/max/step checks are not sufficient.
- * @s_ctrl: Actually set the new control value. s_ctrl is compulsory. The
- * ctrl->handler->lock is held when these ops are called, so no
- * one else can access controls owned by that handler.
- */
struct v4l2_ctrl_ops {
int (*g_volatile_ctrl)(struct v4l2_ctrl *ctrl);
int (*try_ctrl)(struct v4l2_ctrl *ctrl);
int (*s_ctrl)(struct v4l2_ctrl *ctrl);
};
-/** struct v4l2_ctrl - The control structure.
- * @node: The list node.
- * @ev_subs: The list of control event subscriptions.
- * @handler: The handler that owns the control.
- * @cluster: Point to start of cluster array.
- * @ncontrols: Number of controls in cluster array.
- * @done: Internal flag: set for each processed control.
- * @is_new: Set when the user specified a new value for this control. It
- * is also set when called from v4l2_ctrl_handler_setup. Drivers
- * should never set this flag.
- * @is_private: If set, then this control is private to its handler and it
- * will not be added to any other handlers. Drivers can set
- * this flag.
- * @is_auto: If set, then this control selects whether the other cluster
- * members are in 'automatic' mode or 'manual' mode. This is
- * used for autogain/gain type clusters. Drivers should never
- * set this flag directly.
- * @has_volatiles: If set, then one or more members of the cluster are volatile.
- * Drivers should never touch this flag.
- * @manual_mode_value: If the is_auto flag is set, then this is the value
- * of the auto control that determines if that control is in
- * manual mode. So if the value of the auto control equals this
- * value, then the whole cluster is in manual mode. Drivers should
- * never set this flag directly.
- * @ops: The control ops.
- * @id: The control ID.
- * @name: The control name.
- * @type: The control type.
- * @minimum: The control's minimum value.
- * @maximum: The control's maximum value.
- * @default_value: The control's default value.
- * @step: The control's step value for non-menu controls.
- * @menu_skip_mask: The control's skip mask for menu controls. This makes it
- * easy to skip menu items that are not valid. If bit X is set,
- * then menu item X is skipped. Of course, this only works for
- * menus with <= 32 menu items. There are no menus that come
- * close to that number, so this is OK. Should we ever need more,
- * then this will have to be extended to a u64 or a bit array.
- * @qmenu: A const char * array for all menu items. Array entries that are
- * empty strings ("") correspond to non-existing menu items (this
- * is in addition to the menu_skip_mask above). The last entry
- * must be NULL.
- * @flags: The control's flags.
- * @cur: The control's current value.
- * @val: The control's new s32 value.
- * @val64: The control's new s64 value.
- * @string: The control's new string value.
- * @priv: The control's private pointer. For use by the driver. It is
- * untouched by the control framework. Note that this pointer is
- * not freed when the control is deleted. Should this be needed
- * then a new internal bitfield can be added to tell the framework
- * to free this pointer.
- */
struct v4l2_ctrl {
- /* Administrative fields */
+
struct list_head node;
- struct list_head ev_subs;
struct v4l2_ctrl_handler *handler;
struct v4l2_ctrl **cluster;
unsigned ncontrols;
@@ -117,9 +46,7 @@
unsigned int is_new:1;
unsigned int is_private:1;
- unsigned int is_auto:1;
- unsigned int has_volatiles:1;
- unsigned int manual_mode_value:8;
+ unsigned int is_volatile:1;
const struct v4l2_ctrl_ops *ops;
u32 id;
@@ -145,36 +72,12 @@
void *priv;
};
-/** struct v4l2_ctrl_ref - The control reference.
- * @node: List node for the sorted list.
- * @next: Single-link list node for the hash.
- * @ctrl: The actual control information.
- * @helper: Pointer to helper struct. Used internally in prepare_ext_ctrls().
- *
- * Each control handler has a list of these refs. The list_head is used to
- * keep a sorted-by-control-ID list of all controls, while the next pointer
- * is used to link the control in the hash's bucket.
- */
struct v4l2_ctrl_ref {
struct list_head node;
struct v4l2_ctrl_ref *next;
struct v4l2_ctrl *ctrl;
- struct v4l2_ctrl_helper *helper;
};
-/** struct v4l2_ctrl_handler - The control handler keeps track of all the
- * controls: both the controls owned by the handler and those inherited
- * from other handlers.
- * @lock: Lock to control access to this handler and its controls.
- * @ctrls: The list of controls owned by this handler.
- * @ctrl_refs: The list of control references.
- * @cached: The last found control reference. It is common that the same
- * control is needed multiple times, so this is a simple
- * optimization.
- * @buckets: Buckets for the hashing. Allows for quick control lookup.
- * @nr_of_buckets: Total number of buckets in the array.
- * @error: The error code of the first failed control addition.
- */
struct v4l2_ctrl_handler {
struct mutex lock;
struct list_head ctrls;
@@ -185,29 +88,6 @@
int error;
};
-/** struct v4l2_ctrl_config - Control configuration structure.
- * @ops: The control ops.
- * @id: The control ID.
- * @name: The control name.
- * @type: The control type.
- * @min: The control's minimum value.
- * @max: The control's maximum value.
- * @step: The control's step value for non-menu controls.
- * @def: The control's default value.
- * @flags: The control's flags.
- * @menu_skip_mask: The control's skip mask for menu controls. This makes it
- * easy to skip menu items that are not valid. If bit X is set,
- * then menu item X is skipped. Of course, this only works for
- * menus with <= 32 menu items. There are no menus that come
- * close to that number, so this is OK. Should we ever need more,
- * then this will have to be extended to a u64 or a bit array.
- * @qmenu: A const char * array for all menu items. Array entries that are
- * empty strings ("") correspond to non-existing menu items (this
- * is in addition to the menu_skip_mask above). The last entry
- * must be NULL.
- * @is_private: If set, then this control is private to its handler and it
- * will not be added to any other handlers.
- */
struct v4l2_ctrl_config {
const struct v4l2_ctrl_ops *ops;
u32 id;
@@ -221,303 +101,73 @@
u32 menu_skip_mask;
const char * const *qmenu;
unsigned int is_private:1;
+ unsigned int is_volatile:1;
};
-/** v4l2_ctrl_fill() - Fill in the control fields based on the control ID.
- *
- * This works for all standard V4L2 controls.
- * For non-standard controls it will only fill in the given arguments
- * and @name will be NULL.
- *
- * This function will overwrite the contents of @name, @type and @flags.
- * The contents of @min, @max, @step and @def may be modified depending on
- * the type.
- *
- * Do not use in drivers! It is used internally for backwards compatibility
- * control handling only. Once all drivers are converted to use the new
- * control framework this function will no longer be exported.
- */
void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags);
-/** v4l2_ctrl_handler_init() - Initialize the control handler.
- * @hdl: The control handler.
- * @nr_of_controls_hint: A hint of how many controls this handler is
- * expected to refer to. This is the total number, so including
- * any inherited controls. It doesn't have to be precise, but if
- * it is way off, then you either waste memory (too many buckets
- * are allocated) or the control lookup becomes slower (not enough
- * buckets are allocated, so there are more slow list lookups).
- * It will always work, though.
- *
- * Returns an error if the buckets could not be allocated. This error will
- * also be stored in @hdl->error.
- */
int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl,
unsigned nr_of_controls_hint);
-/** v4l2_ctrl_handler_free() - Free all controls owned by the handler and free
- * the control list.
- * @hdl: The control handler.
- *
- * Does nothing if @hdl == NULL.
- */
void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl);
-/** v4l2_ctrl_handler_setup() - Call the s_ctrl op for all controls belonging
- * to the handler to initialize the hardware to the current control values.
- * @hdl: The control handler.
- *
- * Button controls will be skipped, as are read-only controls.
- *
- * If @hdl == NULL, then this just returns 0.
- */
int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl);
-/** v4l2_ctrl_handler_log_status() - Log all controls owned by the handler.
- * @hdl: The control handler.
- * @prefix: The prefix to use when logging the control values. If the
- * prefix does not end with a space, then ": " will be added
- * after the prefix. If @prefix == NULL, then no prefix will be
- * used.
- *
- * For use with VIDIOC_LOG_STATUS.
- *
- * Does nothing if @hdl == NULL.
- */
void v4l2_ctrl_handler_log_status(struct v4l2_ctrl_handler *hdl,
const char *prefix);
-/** v4l2_ctrl_new_custom() - Allocate and initialize a new custom V4L2
- * control.
- * @hdl: The control handler.
- * @cfg: The control's configuration data.
- * @priv: The control's driver-specific private data.
- *
- * If the &v4l2_ctrl struct could not be allocated then NULL is returned
- * and @hdl->error is set to the error code (if it wasn't set already).
- */
struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_config *cfg, void *priv);
-/** v4l2_ctrl_new_std() - Allocate and initialize a new standard V4L2 non-menu control.
- * @hdl: The control handler.
- * @ops: The control ops.
- * @id: The control ID.
- * @min: The control's minimum value.
- * @max: The control's maximum value.
- * @step: The control's step value
- * @def: The control's default value.
- *
- * If the &v4l2_ctrl struct could not be allocated, or the control
- * ID is not known, then NULL is returned and @hdl->error is set to the
- * appropriate error code (if it wasn't set already).
- *
- * If @id refers to a menu control, then this function will return NULL.
- *
- * Use v4l2_ctrl_new_std_menu() when adding menu controls.
- */
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 min, s32 max, u32 step, s32 def);
-/** v4l2_ctrl_new_std_menu() - Allocate and initialize a new standard V4L2 menu control.
- * @hdl: The control handler.
- * @ops: The control ops.
- * @id: The control ID.
- * @max: The control's maximum value.
- * @mask: The control's skip mask for menu controls. This makes it
- * easy to skip menu items that are not valid. If bit X is set,
- * then menu item X is skipped. Of course, this only works for
- * menus with <= 32 menu items. There are no menus that come
- * close to that number, so this is OK. Should we ever need more,
- * then this will have to be extended to a u64 or a bit array.
- * @def: The control's default value.
- *
- * Same as v4l2_ctrl_new_std(), but @min is set to 0 and the @mask value
- * determines which menu items are to be skipped.
- *
- * If @id refers to a non-menu control, then this function will return NULL.
- */
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
u32 id, s32 max, s32 mask, s32 def);
-/** v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler.
- * @hdl: The control handler.
- * @ctrl: The control to add.
- *
- * It will return NULL if it was unable to add the control reference.
- * If the control already belonged to the handler, then it will do
- * nothing and just return @ctrl.
- */
struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl,
struct v4l2_ctrl *ctrl);
-/** v4l2_ctrl_add_handler() - Add all controls from handler @add to
- * handler @hdl.
- * @hdl: The control handler.
- * @add: The control handler whose controls you want to add to
- * the @hdl control handler.
- *
- * Does nothing if either of the two is a NULL pointer.
- * In case of an error @hdl->error will be set to the error code (if it
- * wasn't set already).
- */
int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
struct v4l2_ctrl_handler *add);
-/** v4l2_ctrl_cluster() - Mark all controls in the cluster as belonging to that cluster.
- * @ncontrols: The number of controls in this cluster.
- * @controls: The cluster control array of size @ncontrols.
- */
void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls);
-/** v4l2_ctrl_auto_cluster() - Mark all controls in the cluster as belonging to
- * that cluster and set it up for autofoo/foo-type handling.
- * @ncontrols: The number of controls in this cluster.
- * @controls: The cluster control array of size @ncontrols. The first control
- * must be the 'auto' control (e.g. autogain, autoexposure, etc.)
- * @manual_val: The value for the first control in the cluster that equals the
- * manual setting.
- * @set_volatile: If true, then all controls except the first auto control will
- * be volatile.
- *
- * Use for control groups where one control selects some automatic feature and
- * the other controls are only active whenever the automatic feature is turned
- * off (manual mode). Typical examples: autogain vs gain, auto-whitebalance vs
- * red and blue balance, etc.
- *
- * The behavior of such controls is as follows:
- *
- * When the autofoo control is set to automatic, then any manual controls
- * are set to inactive and any reads will call g_volatile_ctrl (if the control
- * was marked volatile).
- *
- * When the autofoo control is set to manual, then any manual controls will
- * be marked active, and any reads will just return the current value without
- * going through g_volatile_ctrl.
- *
- * In addition, this function will set the V4L2_CTRL_FLAG_UPDATE flag
- * on the autofoo control and V4L2_CTRL_FLAG_INACTIVE on the foo control(s)
- * if autofoo is in auto mode.
- */
-void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
- u8 manual_val, bool set_volatile);
-
-
-/** v4l2_ctrl_find() - Find a control with the given ID.
- * @hdl: The control handler.
- * @id: The control ID to find.
- *
- * If @hdl == NULL this will return NULL as well. Will lock the handler so
- * do not use from inside &v4l2_ctrl_ops.
- */
struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id);
-/** v4l2_ctrl_activate() - Make the control active or inactive.
- * @ctrl: The control to (de)activate.
- * @active: True if the control should become active.
- *
- * This sets or clears the V4L2_CTRL_FLAG_INACTIVE flag atomically.
- * Does nothing if @ctrl == NULL.
- * This will usually be called from within the s_ctrl op.
- * The V4L2_EVENT_CTRL event will be generated afterwards.
- *
- * This function assumes that the control handler is locked.
- */
void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
-/** v4l2_ctrl_grab() - Mark the control as grabbed or not grabbed.
- * @ctrl: The control to (de)activate.
- * @grabbed: True if the control should become grabbed.
- *
- * This sets or clears the V4L2_CTRL_FLAG_GRABBED flag atomically.
- * Does nothing if @ctrl == NULL.
- * The V4L2_EVENT_CTRL event will be generated afterwards.
- * This will usually be called when starting or stopping streaming in the
- * driver.
- *
- * This function assumes that the control handler is not locked and will
- * take the lock itself.
- */
void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
-/** v4l2_ctrl_lock() - Helper function to lock the handler
- * associated with the control.
- * @ctrl: The control to lock.
- */
static inline void v4l2_ctrl_lock(struct v4l2_ctrl *ctrl)
{
mutex_lock(&ctrl->handler->lock);
}
-/** v4l2_ctrl_lock() - Helper function to unlock the handler
- * associated with the control.
- * @ctrl: The control to unlock.
- */
static inline void v4l2_ctrl_unlock(struct v4l2_ctrl *ctrl)
{
mutex_unlock(&ctrl->handler->lock);
}
-/** v4l2_ctrl_g_ctrl() - Helper function to get the control's value from within a driver.
- * @ctrl: The control.
- *
- * This returns the control's value safely by going through the control
- * framework. This function will lock the control's handler, so it cannot be
- * used from within the &v4l2_ctrl_ops functions.
- *
- * This function is for integer type controls only.
- */
s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
-/** v4l2_ctrl_s_ctrl() - Helper function to set the control's value from within a driver.
- * @ctrl: The control.
- * @val: The new value.
- *
- * This set the control's new value safely by going through the control
- * framework. This function will lock the control's handler, so it cannot be
- * used from within the &v4l2_ctrl_ops functions.
- *
- * This function is for integer type controls only.
- */
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
-/* Internal helper functions that deal with control events. */
-void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev);
-void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
- struct v4l2_subscribed_event *sev);
-/* Can be used as a vidioc_log_status function that just dumps all controls
- associated with the filehandle. */
-int v4l2_ctrl_log_status(struct file *file, void *fh);
-
-/* Can be used as a vidioc_subscribe_event function that just subscribes
- control events. */
-int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub);
-
-/* Can be used as a poll function that just polls for control events. */
-unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait);
-
-/* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */
int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc);
int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm);
int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
-int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
- struct v4l2_control *ctrl);
+int v4l2_s_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
int v4l2_try_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
-int v4l2_s_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
- struct v4l2_ext_controls *c);
+int v4l2_s_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *c);
-/* Helpers for subdevices. If the associated ctrl_handler == NULL then they
- will all return -EINVAL. */
int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc);
int v4l2_subdev_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm);
int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs);
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 96d2221..b7bee3f 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -1,11 +1,3 @@
-/*
- *
- * V 4 L 2 D R I V E R H E L P E R A P I
- *
- * Moved from videodev2.h
- *
- * Some commonly needed functions for drivers (v4l2-common.o module)
- */
#ifndef _V4L2_DEV_H
#define _V4L2_DEV_H
@@ -31,16 +23,10 @@
struct v4l2_device;
struct v4l2_ctrl_handler;
-/* Flag to mark the video_device struct as registered.
- Drivers can clear this flag if they want to block all future
- device access. It is cleared by video_unregister_device. */
#define V4L2_FL_REGISTERED (0)
-/* file->private_data points to struct v4l2_fh */
#define V4L2_FL_USES_V4L2_FH (1)
-/* Use the prio field of v4l2_fh for core priority checking */
#define V4L2_FL_USE_FH_PRIO (2)
-/* Priority helper functions */
struct v4l2_prio_state {
atomic_t prios[4];
@@ -62,9 +48,6 @@
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*ioctl) (struct file *, unsigned int, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
-#ifdef CONFIG_COMPAT
- long (*compat_ioctl32) (struct file *, unsigned int, unsigned long);
-#endif
unsigned long (*get_unmapped_area) (struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
@@ -72,108 +55,87 @@
int (*release) (struct file *);
};
-/*
- * Newer version of video_device, handled by videodev2.c
- * This version moves redundant code from video device code to
- * the common handler
- */
struct video_device
{
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
#endif
- /* device ops */
+
const struct v4l2_file_operations *fops;
- /* sysfs */
- struct device dev; /* v4l device */
- struct cdev *cdev; /* character device */
+
+ struct device dev;
+ struct cdev *cdev;
- /* Set either parent or v4l2_dev if your driver uses v4l2_device */
- struct device *parent; /* device parent */
- struct v4l2_device *v4l2_dev; /* v4l2_device parent */
+
+ struct device *parent;
+ struct v4l2_device *v4l2_dev;
- /* Control handler associated with this device node. May be NULL. */
+
struct v4l2_ctrl_handler *ctrl_handler;
- /* Priority state. If NULL, then v4l2_dev->prio will be used. */
+
struct v4l2_prio_state *prio;
- /* device info */
+
char name[32];
int vfl_type;
- /* 'minor' is set to -1 if the registration failed */
+
int minor;
u16 num;
- /* use bitops to set/clear/test flags */
+
unsigned long flags;
- /* attribute to differentiate multiple indices on one physical device */
+
int index;
- /* V4L2 file handles */
- spinlock_t fh_lock; /* Lock for all v4l2_fhs */
- struct list_head fh_list; /* List of struct v4l2_fh */
+
+ spinlock_t fh_lock;
+ struct list_head fh_list;
- int debug; /* Activates debug level*/
+ int debug;
- /* Video standard vars */
- v4l2_std_id tvnorms; /* Supported tv norms */
- v4l2_std_id current_norm; /* Current tvnorm */
+
+ v4l2_std_id tvnorms;
+ v4l2_std_id current_norm;
- /* callbacks */
+
void (*release)(struct video_device *vdev);
- /* ioctl callbacks */
+
const struct v4l2_ioctl_ops *ioctl_ops;
- /* serialization lock */
+
struct mutex *lock;
};
#define media_entity_to_video_device(__e) \
container_of(__e, struct video_device, entity)
-/* dev to video-device */
#define to_video_device(cd) container_of(cd, struct video_device, dev)
int __must_check __video_register_device(struct video_device *vdev, int type,
int nr, int warn_if_nr_in_use, struct module *owner);
-/* Register video devices. Note that if video_register_device fails,
- the release() callback of the video_device structure is *not* called, so
- the caller is responsible for freeing any data. Usually that means that
- you call video_device_release() on failure. */
static inline int __must_check video_register_device(struct video_device *vdev,
int type, int nr)
{
return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
}
-/* Same as video_register_device, but no warning is issued if the desired
- device node number was already in use. */
static inline int __must_check video_register_device_no_warn(
struct video_device *vdev, int type, int nr)
{
return __video_register_device(vdev, type, nr, 0, vdev->fops->owner);
}
-/* Unregister video devices. Will do nothing if vdev == NULL or
- video_is_registered() returns false. */
void video_unregister_device(struct video_device *vdev);
-/* helper functions to alloc/release struct video_device, the
- latter can also be used for video_device->release(). */
struct video_device * __must_check video_device_alloc(void);
-/* this release function frees the vdev pointer */
void video_device_release(struct video_device *vdev);
-/* this release function does nothing, use when the video_device is a
- static global struct. Note that having a static video_device is
- a dubious construction at best. */
void video_device_release_empty(struct video_device *vdev);
-/* helper functions to access driver private data. */
static inline void *video_get_drvdata(struct video_device *vdev)
{
return dev_get_drvdata(&vdev->dev);
@@ -186,8 +148,6 @@
struct video_device *video_devdata(struct file *file);
-/* Combine video_get_drvdata and video_devdata as this is
- used very often. */
static inline void *video_drvdata(struct file *file)
{
return video_get_drvdata(video_devdata(file));
@@ -203,4 +163,4 @@
return test_bit(V4L2_FL_REGISTERED, &vdev->flags);
}
-#endif /* _V4L2_DEV_H */
+#endif
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index d61febf..a69738e 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -25,44 +25,33 @@
#include <media/v4l2-subdev.h>
#include <media/v4l2-dev.h>
-/* Each instance of a V4L2 device should create the v4l2_device struct,
- either stand-alone or embedded in a larger struct.
-
- It allows easy access to sub-devices (see v4l2-subdev.h) and provides
- basic V4L2 device-level support.
- */
#define V4L2_DEVICE_NAME_SIZE (20 + 16)
struct v4l2_ctrl_handler;
struct v4l2_device {
- /* dev->driver_data points to this struct.
- Note: dev might be NULL if there is no parent device
- as is the case with e.g. ISA devices. */
struct device *dev;
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_device *mdev;
#endif
- /* used to keep track of the registered subdevs */
+
struct list_head subdevs;
- /* lock this struct; can be used by the driver as well if this
- struct is embedded into a larger struct. */
spinlock_t lock;
- /* unique device name, by default the driver name + bus ID */
+
char name[V4L2_DEVICE_NAME_SIZE];
- /* notify callback called by some sub-devices. */
+
void (*notify)(struct v4l2_subdev *sd,
unsigned int notification, void *arg);
- /* The control handler. May be NULL. */
+
struct v4l2_ctrl_handler *ctrl_handler;
- /* Device's priority state */
+
struct v4l2_prio_state prio;
- /* BKL replacement mutex. Temporary solution only. */
+
struct mutex ioctl_lock;
- /* Keep track of the references to this struct. */
+
struct kref ref;
- /* Release function that is called when the ref count goes to 0. */
+
void (*release)(struct v4l2_device *v4l2_dev);
};
@@ -73,60 +62,25 @@
int v4l2_device_put(struct v4l2_device *v4l2_dev);
-/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
- dev may be NULL in rare cases (ISA devices). In that case you
- must fill in the v4l2_dev->name field before calling this function. */
int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
-/* Optional function to initialize the name field of struct v4l2_device using
- the driver name and a driver-global atomic_t instance.
- This function will increment the instance counter and returns the instance
- value used in the name.
-
- Example:
-
- static atomic_t drv_instance = ATOMIC_INIT(0);
-
- ...
-
- instance = v4l2_device_set_name(&v4l2_dev, "foo", &drv_instance);
-
- The first time this is called the name field will be set to foo0 and
- this function returns 0. If the name ends with a digit (e.g. cx18),
- then the name will be set to cx18-0 since cx180 looks really odd. */
int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
atomic_t *instance);
-/* Set v4l2_dev->dev to NULL. Call when the USB parent disconnects.
- Since the parent disappears this ensures that v4l2_dev doesn't have an
- invalid parent pointer. */
void v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
-/* Unregister all sub-devices and any other resources related to v4l2_dev. */
void v4l2_device_unregister(struct v4l2_device *v4l2_dev);
-/* Register a subdev with a v4l2 device. While registered the subdev module
- is marked as in-use. An error is returned if the module is no longer
- loaded when you attempt to register it. */
int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
struct v4l2_subdev *sd);
-/* Unregister a subdev with a v4l2 device. Can also be called if the subdev
- wasn't registered. In that case it will do nothing. */
void v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
-/* Register device nodes for all subdev of the v4l2 device that are marked with
- * the V4L2_SUBDEV_FL_HAS_DEVNODE flag.
- */
int __must_check
v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
-/* Iterate over all subdevs. */
#define v4l2_device_for_each_subdev(sd, v4l2_dev) \
list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)
-/* Call the specified callback for all subdevs matching the condition.
- Ignore any errors. Note that you cannot add or delete a subdev
- while walking the subdevs list. */
#define __v4l2_device_call_subdevs_p(v4l2_dev, sd, cond, o, f, args...) \
do { \
list_for_each_entry((sd), &(v4l2_dev)->subdevs, list) \
@@ -142,10 +96,6 @@
f , ##args); \
} while (0)
-/* Call the specified callback for all subdevs matching the condition.
- If the callback returns an error other than 0 or -ENOIOCTLCMD, then
- return with that error code. Note that you cannot add or delete a
- subdev while walking the subdevs list. */
#define __v4l2_device_call_subdevs_until_err_p(v4l2_dev, sd, cond, o, f, args...) \
({ \
long __err = 0; \
@@ -166,9 +116,6 @@
f , ##args); \
})
-/* Call the specified callback for all subdevs matching grp_id (if 0, then
- match them all). Ignore any errors. Note that you cannot add or delete
- a subdev while walking the subdevs list. */
#define v4l2_device_call_all(v4l2_dev, grpid, o, f, args...) \
do { \
struct v4l2_subdev *__sd; \
@@ -178,10 +125,6 @@
##args); \
} while (0)
-/* Call the specified callback for all subdevs matching grp_id (if 0, then
- match them all). If the callback returns an error other than 0 or
- -ENOIOCTLCMD, then return with that error code. Note that you cannot
- add or delete a subdev while walking the subdevs list. */
#define v4l2_device_call_until_err(v4l2_dev, grpid, o, f, args...) \
({ \
struct v4l2_subdev *__sd; \
diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h
index 5f14e88..fb1841e 100644
--- a/include/media/v4l2-event.h
+++ b/include/media/v4l2-event.h
@@ -29,95 +29,39 @@
#include <linux/videodev2.h>
#include <linux/wait.h>
-/*
- * Overview:
- *
- * Events are subscribed per-filehandle. An event specification consists of a
- * type and is optionally associated with an object identified through the
- * 'id' field. So an event is uniquely identified by the (type, id) tuple.
- *
- * The v4l2-fh struct has a list of subscribed events. The v4l2_subscribed_event
- * struct is added to that list, one for every subscribed event.
- *
- * Each v4l2_subscribed_event struct ends with an array of v4l2_kevent structs.
- * This array (ringbuffer, really) is used to store any events raised by the
- * driver. The v4l2_kevent struct links into the 'available' list of the
- * v4l2_fh struct so VIDIOC_DQEVENT will know which event to dequeue first.
- *
- * Finally, if the event subscription is associated with a particular object
- * such as a V4L2 control, then that object needs to know about that as well
- * so that an event can be raised by that object. So the 'node' field can
- * be used to link the v4l2_subscribed_event struct into a list of that
- * object.
- *
- * So to summarize:
- *
- * struct v4l2_fh has two lists: one of the subscribed events, and one of the
- * pending events.
- *
- * struct v4l2_subscribed_event has a ringbuffer of raised (pending) events of
- * that particular type.
- *
- * If struct v4l2_subscribed_event is associated with a specific object, then
- * that object will have an internal list of struct v4l2_subscribed_event so
- * it knows who subscribed an event to that object.
- */
-
struct v4l2_fh;
-struct v4l2_subscribed_event;
struct video_device;
-/** struct v4l2_kevent - Internal kernel event struct.
- * @list: List node for the v4l2_fh->available list.
- * @sev: Pointer to parent v4l2_subscribed_event.
- * @event: The event itself.
- */
struct v4l2_kevent {
struct list_head list;
- struct v4l2_subscribed_event *sev;
struct v4l2_event event;
};
-/** struct v4l2_subscribed_event - Internal struct representing a subscribed event.
- * @list: List node for the v4l2_fh->subscribed list.
- * @type: Event type.
- * @id: Associated object ID (e.g. control ID). 0 if there isn't any.
- * @flags: Copy of v4l2_event_subscription->flags.
- * @fh: Filehandle that subscribed to this event.
- * @node: List node that hooks into the object's event list (if there is one).
- * @replace: Optional callback that can replace event 'old' with event 'new'.
- * @merge: Optional callback that can merge event 'old' into event 'new'.
- * @elems: The number of elements in the events array.
- * @first: The index of the events containing the oldest available event.
- * @in_use: The number of queued events.
- * @events: An array of @elems events.
- */
struct v4l2_subscribed_event {
struct list_head list;
u32 type;
- u32 id;
- u32 flags;
- struct v4l2_fh *fh;
- struct list_head node;
- void (*replace)(struct v4l2_event *old,
- const struct v4l2_event *new);
- void (*merge)(const struct v4l2_event *old,
- struct v4l2_event *new);
- unsigned elems;
- unsigned first;
- unsigned in_use;
- struct v4l2_kevent events[];
};
+struct v4l2_events {
+ wait_queue_head_t wait;
+ struct list_head subscribed;
+ struct list_head free;
+ struct list_head available;
+ unsigned int navailable;
+ unsigned int nallocated;
+ u32 sequence;
+};
+
+int v4l2_event_init(struct v4l2_fh *fh);
+int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n);
+void v4l2_event_free(struct v4l2_fh *fh);
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
int nonblocking);
void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev);
-void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev);
int v4l2_event_pending(struct v4l2_fh *fh);
int v4l2_event_subscribe(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub, unsigned elems);
+ struct v4l2_event_subscription *sub);
int v4l2_event_unsubscribe(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
-void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
-#endif /* V4L2_EVENT_H */
+#endif
diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h
index 52513c2..9509e9d 100644
--- a/include/media/v4l2-fh.h
+++ b/include/media/v4l2-fh.h
@@ -29,73 +29,25 @@
#include <linux/list.h>
struct video_device;
-struct v4l2_ctrl_handler;
+struct v4l2_events;
struct v4l2_fh {
struct list_head list;
struct video_device *vdev;
- struct v4l2_ctrl_handler *ctrl_handler;
+ struct v4l2_events *events;
enum v4l2_priority prio;
-
- /* Events */
- wait_queue_head_t wait;
- struct list_head subscribed; /* Subscribed events */
- struct list_head available; /* Dequeueable event */
- unsigned int navailable;
- u32 sequence;
};
-/*
- * Initialise the file handle. Parts of the V4L2 framework using the
- * file handles should be initialised in this function. Must be called
- * from driver's v4l2_file_operations->open() handler if the driver
- * uses v4l2_fh.
- */
-void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
-/*
- * Add the fh to the list of file handles on a video_device. The file
- * handle must be initialised first.
- */
+int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
void v4l2_fh_add(struct v4l2_fh *fh);
-/*
- * Can be used as the open() op of v4l2_file_operations.
- * It allocates a v4l2_fh and inits and adds it to the video_device associated
- * with the file pointer.
- */
int v4l2_fh_open(struct file *filp);
-/*
- * Remove file handle from the list of file handles. Must be called in
- * v4l2_file_operations->release() handler if the driver uses v4l2_fh.
- * On error filp->private_data will be NULL, otherwise it will point to
- * the v4l2_fh struct.
- */
void v4l2_fh_del(struct v4l2_fh *fh);
-/*
- * Release resources related to a file handle. Parts of the V4L2
- * framework using the v4l2_fh must release their resources here, too.
- * Must be called in v4l2_file_operations->release() handler if the
- * driver uses v4l2_fh.
- */
void v4l2_fh_exit(struct v4l2_fh *fh);
-/*
- * Can be used as the release() op of v4l2_file_operations.
- * It deletes and exits the v4l2_fh associated with the file pointer and
- * frees it. It will do nothing if filp->private_data (the pointer to the
- * v4l2_fh struct) is NULL. This function always returns 0.
- */
int v4l2_fh_release(struct file *filp);
-/*
- * Returns 1 if this filehandle is the only filehandle opened for the
- * associated video_device. If fh is NULL, then it returns 0.
- */
int v4l2_fh_is_singular(struct v4l2_fh *fh);
-/*
- * Helper function with struct file as argument. If filp->private_data is
- * NULL, then it will return 0.
- */
static inline int v4l2_fh_is_singular_file(struct file *filp)
{
return v4l2_fh_is_singular(filp->private_data);
}
-#endif /* V4L2_EVENT_H */
+#endif
diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h
index e6aa231..e52ddc9 100644
--- a/include/media/v4l2-int-device.h
+++ b/include/media/v4l2-int-device.h
@@ -25,23 +25,17 @@
#ifndef V4L2_INT_DEVICE_H
#define V4L2_INT_DEVICE_H
+#include <linux/module.h>
#include <media/v4l2-common.h>
#define V4L2NAMESIZE 32
-/*
- *
- * The internal V4L2 device interface core.
- *
- */
enum v4l2_int_type {
v4l2_int_type_master = 1,
v4l2_int_type_slave
};
-struct module;
-
struct v4l2_int_device;
struct v4l2_int_master {
@@ -59,7 +53,7 @@
};
struct v4l2_int_slave {
- /* Don't touch master. */
+
struct v4l2_int_device *master;
char attach_to[V4L2NAMESIZE];
@@ -69,7 +63,7 @@
};
struct v4l2_int_device {
- /* Don't touch head. */
+
struct list_head head;
struct module *module;
@@ -93,11 +87,6 @@
int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd);
int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg);
-/*
- *
- * Types and definitions for IOCTL commands.
- *
- */
enum v4l2_power {
V4L2_POWER_OFF = 0,
@@ -105,56 +94,35 @@
V4L2_POWER_STANDBY,
};
-/* Slave interface type. */
enum v4l2_if_type {
- /*
- * Parallel 8-, 10- or 12-bit interface, used by for example
- * on certain image sensors.
- */
V4L2_IF_TYPE_BT656,
};
enum v4l2_if_type_bt656_mode {
- /*
- * Modes without Bt synchronisation codes. Separate
- * synchronisation signal lines are used.
- */
V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT,
V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT,
V4L2_IF_TYPE_BT656_MODE_NOBT_12BIT,
- /*
- * Use Bt synchronisation codes. The vertical and horizontal
- * synchronisation is done based on synchronisation codes.
- */
V4L2_IF_TYPE_BT656_MODE_BT_8BIT,
V4L2_IF_TYPE_BT656_MODE_BT_10BIT,
};
struct v4l2_if_type_bt656 {
- /*
- * 0: Frame begins when vsync is high.
- * 1: Frame begins when vsync changes from low to high.
- */
unsigned frame_start_on_rising_vs:1;
- /* Use Bt synchronisation codes for sync correction. */
+
unsigned bt_sync_correct:1;
- /* Swap every two adjacent image data elements. */
+
unsigned swap:1;
- /* Inverted latch clock polarity from slave. */
+
unsigned latch_clk_inv:1;
- /* Hs polarity. 0 is active high, 1 active low. */
+
unsigned nobt_hs_inv:1;
- /* Vs polarity. 0 is active high, 1 active low. */
+
unsigned nobt_vs_inv:1;
enum v4l2_if_type_bt656_mode mode;
- /* Minimum accepted bus clock for slave (in Hz). */
+
u32 clock_min;
- /* Maximum accepted bus clock for slave. */
+
u32 clock_max;
- /*
- * Current wish of the slave. May only change in response to
- * ioctls that affect image capture.
- */
u32 clock_curr;
};
@@ -165,13 +133,7 @@
} u;
};
-/* IOCTL command numbers. */
enum v4l2_int_ioctl_num {
- /*
- *
- * "Proper" V4L ioctls, as in struct video_device.
- *
- */
vidioc_int_enum_fmt_cap_num = 1,
vidioc_int_g_fmt_cap_num,
vidioc_int_s_fmt_cap_num,
@@ -188,54 +150,30 @@
vidioc_int_s_std_num,
vidioc_int_s_video_routing_num,
- /*
- *
- * Strictly internal ioctls.
- *
- */
- /* Initialise the device when slave attaches to the master. */
+
vidioc_int_dev_init_num = 1000,
- /* Delinitialise the device at slave detach. */
+
vidioc_int_dev_exit_num,
- /* Set device power state. */
+
vidioc_int_s_power_num,
- /*
- * Get slave private data, e.g. platform-specific slave
- * configuration used by the master.
- */
vidioc_int_g_priv_num,
- /* Get slave interface parameters. */
+
vidioc_int_g_ifparm_num,
- /* Does the slave need to be reset after VIDIOC_DQBUF? */
+
vidioc_int_g_needs_reset_num,
vidioc_int_enum_framesizes_num,
vidioc_int_enum_frameintervals_num,
- /*
- *
- * VIDIOC_INT_* ioctls.
- *
- */
- /* VIDIOC_INT_RESET */
+
vidioc_int_reset_num,
- /* VIDIOC_INT_INIT */
+
vidioc_int_init_num,
- /* VIDIOC_DBG_G_CHIP_IDENT */
+
vidioc_int_g_chip_ident_num,
- /*
- *
- * Start of private ioctls.
- *
- */
vidioc_int_priv_start_num = 2000,
};
-/*
- *
- * IOCTL wrapper functions for better type checking.
- *
- */
#define V4L2_INT_WRAPPER_0(name) \
static inline int vidioc_int_##name(struct v4l2_int_device *d) \
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 3cb939c..7209cda 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -1,35 +1,28 @@
-/*
- *
- * V 4 L 2 D R I V E R H E L P E R A P I
- *
- * Moved from videodev2.h
- *
- * Some commonly needed functions for drivers (v4l2-common.o module)
- */
#ifndef _V4L2_IOCTL_H
#define _V4L2_IOCTL_H
#include <linux/poll.h>
#include <linux/fs.h>
+#include <linux/device.h>
#include <linux/mutex.h>
-#include <linux/compiler.h> /* need __user */
+#include <linux/compiler.h>
#include <linux/videodev2.h>
struct v4l2_fh;
struct v4l2_ioctl_ops {
- /* ioctl callbacks */
+
- /* VIDIOC_QUERYCAP handler */
+
int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);
- /* Priority handling */
+
int (*vidioc_g_priority) (struct file *file, void *fh,
enum v4l2_priority *p);
int (*vidioc_s_priority) (struct file *file, void *fh,
enum v4l2_priority p);
- /* VIDIOC_ENUM_FMT handlers */
+
int (*vidioc_enum_fmt_vid_cap) (struct file *file, void *fh,
struct v4l2_fmtdesc *f);
int (*vidioc_enum_fmt_vid_overlay) (struct file *file, void *fh,
@@ -43,7 +36,7 @@
int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
struct v4l2_fmtdesc *f);
- /* VIDIOC_G_FMT handlers */
+
int (*vidioc_g_fmt_vid_cap) (struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,
@@ -67,7 +60,7 @@
int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
struct v4l2_format *f);
- /* VIDIOC_S_FMT handlers */
+
int (*vidioc_s_fmt_vid_cap) (struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,
@@ -91,7 +84,7 @@
int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
struct v4l2_format *f);
- /* VIDIOC_TRY_FMT handlers */
+
int (*vidioc_try_fmt_vid_cap) (struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh,
@@ -115,14 +108,12 @@
int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
struct v4l2_format *f);
- /* Buffer handlers */
+
int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
int (*vidioc_qbuf) (struct file *file, void *fh, struct v4l2_buffer *b);
int (*vidioc_dqbuf) (struct file *file, void *fh, struct v4l2_buffer *b);
- int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
- int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b);
int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
int (*vidioc_g_fbuf) (struct file *file, void *fh,
@@ -130,30 +121,27 @@
int (*vidioc_s_fbuf) (struct file *file, void *fh,
struct v4l2_framebuffer *a);
- /* Stream on/off */
+
int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
- /* Standard handling
- ENUMSTD is handled by videodev.c
- */
int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);
int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
- /* Input handling */
+
int (*vidioc_enum_input)(struct file *file, void *fh,
struct v4l2_input *inp);
int (*vidioc_g_input) (struct file *file, void *fh, unsigned int *i);
int (*vidioc_s_input) (struct file *file, void *fh, unsigned int i);
- /* Output handling */
+
int (*vidioc_enum_output) (struct file *file, void *fh,
struct v4l2_output *a);
int (*vidioc_g_output) (struct file *file, void *fh, unsigned int *i);
int (*vidioc_s_output) (struct file *file, void *fh, unsigned int i);
- /* Control handling */
+
int (*vidioc_queryctrl) (struct file *file, void *fh,
struct v4l2_queryctrl *a);
int (*vidioc_g_ctrl) (struct file *file, void *fh,
@@ -169,7 +157,7 @@
int (*vidioc_querymenu) (struct file *file, void *fh,
struct v4l2_querymenu *a);
- /* Audio ioctls */
+
int (*vidioc_enumaudio) (struct file *file, void *fh,
struct v4l2_audio *a);
int (*vidioc_g_audio) (struct file *file, void *fh,
@@ -177,7 +165,7 @@
int (*vidioc_s_audio) (struct file *file, void *fh,
struct v4l2_audio *a);
- /* Audio out ioctls */
+
int (*vidioc_enumaudout) (struct file *file, void *fh,
struct v4l2_audioout *a);
int (*vidioc_g_audout) (struct file *file, void *fh,
@@ -188,18 +176,14 @@
struct v4l2_modulator *a);
int (*vidioc_s_modulator) (struct file *file, void *fh,
struct v4l2_modulator *a);
- /* Crop ioctls */
+
int (*vidioc_cropcap) (struct file *file, void *fh,
struct v4l2_cropcap *a);
int (*vidioc_g_crop) (struct file *file, void *fh,
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);
int (*vidioc_s_jpegcomp) (struct file *file, void *fh,
@@ -210,18 +194,14 @@
struct v4l2_encoder_cmd *a);
int (*vidioc_try_encoder_cmd) (struct file *file, void *fh,
struct v4l2_encoder_cmd *a);
- int (*vidioc_decoder_cmd) (struct file *file, void *fh,
- struct v4l2_decoder_cmd *a);
- int (*vidioc_try_decoder_cmd) (struct file *file, void *fh,
- struct v4l2_decoder_cmd *a);
- /* Stream type-dependent parameter ioctls */
+
int (*vidioc_g_parm) (struct file *file, void *fh,
struct v4l2_streamparm *a);
int (*vidioc_s_parm) (struct file *file, void *fh,
struct v4l2_streamparm *a);
- /* Tuner ioctls */
+
int (*vidioc_g_tuner) (struct file *file, void *fh,
struct v4l2_tuner *a);
int (*vidioc_s_tuner) (struct file *file, void *fh,
@@ -231,17 +211,17 @@
int (*vidioc_s_frequency) (struct file *file, void *fh,
struct v4l2_frequency *a);
- /* Sliced VBI cap */
+
int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,
struct v4l2_sliced_vbi_cap *a);
- /* Log status ioctl */
+
int (*vidioc_log_status) (struct file *file, void *fh);
int (*vidioc_s_hw_freq_seek) (struct file *file, void *fh,
struct v4l2_hw_freq_seek *a);
- /* Debugging ioctls */
+
#ifdef CONFIG_VIDEO_ADV_DEBUG
int (*vidioc_g_register) (struct file *file, void *fh,
struct v4l2_dbg_register *reg);
@@ -257,7 +237,7 @@
int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
struct v4l2_frmivalenum *fival);
- /* DV Timings IOCTLs */
+
int (*vidioc_enum_dv_presets) (struct file *file, void *fh,
struct v4l2_dv_enum_preset *preset);
@@ -277,47 +257,38 @@
int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
- /* For other private ioctls */
+
long (*vidioc_default) (struct file *file, void *fh,
bool valid_prio, int cmd, void *arg);
};
-/* v4l debugging and diagnostics */
-/* Debug bitmask flags to be used on V4L2 */
#define V4L2_DEBUG_IOCTL 0x01
#define V4L2_DEBUG_IOCTL_ARG 0x02
-/* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */
#define v4l_print_ioctl(name, cmd) \
do { \
printk(KERN_DEBUG "%s: ", name); \
v4l_printk_ioctl(cmd); \
} while (0)
-/* Use this macro in I2C drivers where 'client' is the struct i2c_client
- pointer */
#define v4l_i2c_print_ioctl(client, cmd) \
do { \
v4l_client_printk(KERN_DEBUG, client, ""); \
v4l_printk_ioctl(cmd); \
} while (0)
-/* Video standard functions */
extern const char *v4l2_norm_to_name(v4l2_std_id id);
extern void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod);
extern int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, const char *name);
-/* Prints the ioctl in a human-readable format */
extern void v4l_printk_ioctl(unsigned int cmd);
-/* names for fancy debug output */
extern const char *v4l2_field_names[];
extern const char *v4l2_type_names[];
#ifdef CONFIG_COMPAT
-/* 32 Bits compatibility layer for 64 bits processors */
extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd,
unsigned long arg);
#endif
@@ -325,12 +296,10 @@
typedef long (*v4l2_kioctl)(struct file *file,
unsigned int cmd, void *arg);
-/* Include support for obsoleted stuff */
extern long video_usercopy(struct file *file, unsigned int cmd,
unsigned long arg, v4l2_kioctl func);
-/* Standard handlers for V4L ioctl's */
extern long video_ioctl2(struct file *file,
unsigned int cmd, unsigned long arg);
-#endif /* _V4L2_IOCTL_H */
+#endif
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
index 83ae07e..971c7fa 100644
--- a/include/media/v4l2-mediabus.h
+++ b/include/media/v4l2-mediabus.h
@@ -13,77 +13,6 @@
#include <linux/v4l2-mediabus.h>
-/* Parallel flags */
-/*
- * Can the client run in master or in slave mode. By "Master mode" an operation
- * mode is meant, when the client (e.g., a camera sensor) is producing
- * horizontal and vertical synchronisation. In "Slave mode" the host is
- * providing these signals to the slave.
- */
-#define V4L2_MBUS_MASTER (1 << 0)
-#define V4L2_MBUS_SLAVE (1 << 1)
-/*
- * Signal polarity flags
- * Note: in BT.656 mode HSYNC, FIELD, and VSYNC are unused
- * V4L2_MBUS_[HV]SYNC* flags should be also used for specifying
- * configuration of hardware that uses [HV]REF signals
- */
-#define V4L2_MBUS_HSYNC_ACTIVE_HIGH (1 << 2)
-#define V4L2_MBUS_HSYNC_ACTIVE_LOW (1 << 3)
-#define V4L2_MBUS_VSYNC_ACTIVE_HIGH (1 << 4)
-#define V4L2_MBUS_VSYNC_ACTIVE_LOW (1 << 5)
-#define V4L2_MBUS_PCLK_SAMPLE_RISING (1 << 6)
-#define V4L2_MBUS_PCLK_SAMPLE_FALLING (1 << 7)
-#define V4L2_MBUS_DATA_ACTIVE_HIGH (1 << 8)
-#define V4L2_MBUS_DATA_ACTIVE_LOW (1 << 9)
-/* FIELD = 0/1 - Field1 (odd)/Field2 (even) */
-#define V4L2_MBUS_FIELD_EVEN_HIGH (1 << 10)
-/* FIELD = 1/0 - Field1 (odd)/Field2 (even) */
-#define V4L2_MBUS_FIELD_EVEN_LOW (1 << 11)
-
-/* Serial flags */
-/* How many lanes the client can use */
-#define V4L2_MBUS_CSI2_1_LANE (1 << 0)
-#define V4L2_MBUS_CSI2_2_LANE (1 << 1)
-#define V4L2_MBUS_CSI2_3_LANE (1 << 2)
-#define V4L2_MBUS_CSI2_4_LANE (1 << 3)
-/* On which channels it can send video data */
-#define V4L2_MBUS_CSI2_CHANNEL_0 (1 << 4)
-#define V4L2_MBUS_CSI2_CHANNEL_1 (1 << 5)
-#define V4L2_MBUS_CSI2_CHANNEL_2 (1 << 6)
-#define V4L2_MBUS_CSI2_CHANNEL_3 (1 << 7)
-/* Does it support only continuous or also non-continuous clock mode */
-#define V4L2_MBUS_CSI2_CONTINUOUS_CLOCK (1 << 8)
-#define V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK (1 << 9)
-
-#define V4L2_MBUS_CSI2_LANES (V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_2_LANE | \
- V4L2_MBUS_CSI2_3_LANE | V4L2_MBUS_CSI2_4_LANE)
-#define V4L2_MBUS_CSI2_CHANNELS (V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CHANNEL_1 | \
- V4L2_MBUS_CSI2_CHANNEL_2 | V4L2_MBUS_CSI2_CHANNEL_3)
-
-/**
- * v4l2_mbus_type - media bus type
- * @V4L2_MBUS_PARALLEL: parallel interface with hsync and vsync
- * @V4L2_MBUS_BT656: parallel interface with embedded synchronisation, can
- * also be used for BT.1120
- * @V4L2_MBUS_CSI2: MIPI CSI-2 serial interface
- */
-enum v4l2_mbus_type {
- V4L2_MBUS_PARALLEL,
- V4L2_MBUS_BT656,
- V4L2_MBUS_CSI2,
-};
-
-/**
- * v4l2_mbus_config - media bus configuration
- * @type: in: interface type
- * @flags: in / out: configuration flags, depending on @type
- */
-struct v4l2_mbus_config {
- enum v4l2_mbus_type type;
- unsigned int flags;
-};
-
static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt,
const struct v4l2_mbus_framefmt *mbus_fmt)
{
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index f0f3358..defd4bc 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -28,7 +28,6 @@
#include <media/v4l2-fh.h>
#include <media/v4l2-mediabus.h>
-/* generic v4l2_device notify callback notification values */
#define V4L2_SUBDEV_IR_RX_NOTIFY _IOW('v', 0, u32)
#define V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ 0x00000001
#define V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED 0x00000002
@@ -46,102 +45,29 @@
struct v4l2_subdev_fh;
struct tuner_setup;
-/* decode_vbi_line */
struct v4l2_decode_vbi_line {
- u32 is_second_field; /* Set to 0 for the first (odd) field,
- set to 1 for the second (even) field. */
- u8 *p; /* Pointer to the sliced VBI data from the decoder.
- On exit points to the start of the payload. */
- u32 line; /* Line number of the sliced VBI data (1-23) */
- u32 type; /* VBI service type (V4L2_SLICED_*). 0 if no service found */
+ u32 is_second_field;
+ u8 *p;
+ u32 line;
+ u32 type;
};
-/* Sub-devices are devices that are connected somehow to the main bridge
- device. These devices are usually audio/video muxers/encoders/decoders or
- sensors and webcam controllers.
- Usually these devices are controlled through an i2c bus, but other busses
- may also be used.
- The v4l2_subdev struct provides a way of accessing these devices in a
- generic manner. Most operations that these sub-devices support fall in
- a few categories: core ops, audio ops, video ops and tuner ops.
-
- More categories can be added if needed, although this should remain a
- limited set (no more than approx. 8 categories).
-
- Each category has its own set of ops that subdev drivers can implement.
-
- A subdev driver can leave the pointer to the category ops NULL if
- it does not implement them (e.g. an audio subdev will generally not
- implement the video category ops). The exception is the core category:
- this must always be present.
-
- These ops are all used internally so it is no problem to change, remove
- or add ops or move ops from one to another category. Currently these
- ops are based on the original ioctls, but since ops are not limited to
- one argument there is room for improvement here once all i2c subdev
- drivers are converted to use these ops.
- */
-
-/* Core ops: it is highly recommended to implement at least these ops:
-
- g_chip_ident
- log_status
- g_register
- s_register
-
- This provides basic debugging support.
-
- The ioctl ops is meant for generic ioctl-like commands. Depending on
- the use-case it might be better to use subdev-specific ops (currently
- not yet implemented) since ops provide proper type-checking.
- */
-
-/* Subdevice external IO pin configuration */
-#define V4L2_SUBDEV_IO_PIN_DISABLE (1 << 0) /* ENABLE assumed */
+#define V4L2_SUBDEV_IO_PIN_DISABLE (1 << 0)
#define V4L2_SUBDEV_IO_PIN_OUTPUT (1 << 1)
#define V4L2_SUBDEV_IO_PIN_INPUT (1 << 2)
-#define V4L2_SUBDEV_IO_PIN_SET_VALUE (1 << 3) /* Set output value */
-#define V4L2_SUBDEV_IO_PIN_ACTIVE_LOW (1 << 4) /* ACTIVE HIGH assumed */
+#define V4L2_SUBDEV_IO_PIN_SET_VALUE (1 << 3)
+#define V4L2_SUBDEV_IO_PIN_ACTIVE_LOW (1 << 4)
struct v4l2_subdev_io_pin_config {
- u32 flags; /* V4L2_SUBDEV_IO_PIN_* flags for this pin's config */
- u8 pin; /* Chip external IO pin to configure */
- u8 function; /* Internal signal pad/function to route to IO pin */
- u8 value; /* Initial value for pin - e.g. GPIO output value */
- u8 strength; /* Pin drive strength */
+ u32 flags;
+ u8 pin;
+ u8 function;
+ u8 value;
+ u8 strength;
};
-/*
- s_io_pin_config: configure one or more chip I/O pins for chips that
- multiplex different internal signal pads out to IO pins. This function
- takes a pointer to an array of 'n' pin configuration entries, one for
- each pin being configured. This function could be called at times
- other than just subdevice initialization.
-
- init: initialize the sensor registors to some sort of reasonable default
- values. Do not use for new drivers and should be removed in existing
- drivers.
-
- load_fw: load firmware.
-
- reset: generic reset command. The argument selects which subsystems to
- reset. Passing 0 will always reset the whole chip. Do not use for new
- drivers without discussing this first on the linux-media mailinglist.
- There should be no reason normally to reset a device.
-
- s_gpio: set GPIO pins. Very simple right now, might need to be extended with
- a direction argument if needed.
-
- s_power: puts subdevice in power saving mode (on == 0) or normal operation
- mode (on == 1).
-
- interrupt_service_routine: Called by the bridge chip's interrupt service
- handler, when an interrupt status has be raised due to this subdev,
- so that this subdev can handle the details. It may schedule work to be
- performed later. It must not sleep. *Called from an IRQ context*.
- */
struct v4l2_subdev_core_ops {
int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
int (*log_status)(struct v4l2_subdev *sd);
@@ -158,7 +84,6 @@
int (*s_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
int (*try_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm);
- int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -174,19 +99,6 @@
struct v4l2_event_subscription *sub);
};
-/* s_radio: v4l device was opened in radio mode.
-
- g_frequency: freq->type must be filled in. Normally done by video_ioctl2
- or the bridge driver.
-
- g_tuner:
- s_tuner: vt->type must be filled in. Normally done by video_ioctl2 or the
- bridge driver.
-
- s_type_addr: sets tuner type and its I2C addr.
-
- s_config: sets tda9887 specific stuff, like port1, port2 and qss
- */
struct v4l2_subdev_tuner_ops {
int (*s_radio)(struct v4l2_subdev *sd);
int (*s_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
@@ -199,26 +111,6 @@
int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config);
};
-/* s_clock_freq: set the frequency (in Hz) of the audio clock output.
- Used to slave an audio processor to the video decoder, ensuring that
- audio and video remain synchronized. Usual values for the frequency
- are 48000, 44100 or 32000 Hz. If the frequency is not supported, then
- -EINVAL is returned.
-
- s_i2s_clock_freq: sets I2S speed in bps. This is used to provide a standard
- way to select I2S clock used by driving digital audio streams at some
- board designs. Usual values for the frequency are 1024000 and 2048000.
- If the frequency is not supported, then -EINVAL is returned.
-
- s_routing: used to define the input and/or output pins of an audio chip,
- and any additional configuration data.
- Never attempt to use user-level input IDs (e.g. Composite, S-Video,
- Tuner) at this level. An i2c device shouldn't know about whether an
- input pin is connected to a Composite connector, become on another
- board or platform it might be connected to something else entirely.
- The calling driver is responsible for mapping a user-level input to
- the right pins on the i2c device.
- */
struct v4l2_subdev_audio_ops {
int (*s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_i2s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
@@ -226,62 +118,11 @@
int (*s_stream)(struct v4l2_subdev *sd, int enable);
};
-/*
- s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
- video input devices.
-
- g_std_output: get current standard for video OUTPUT devices. This is ignored
- by video input devices.
-
- g_tvnorms_output: get v4l2_std_id with all standards supported by video
- OUTPUT device. This is ignored by video input devices.
-
- s_crystal_freq: sets the frequency of the crystal used to generate the
- clocks in Hz. An extra flags field allows device specific configuration
- regarding clock frequency dividers, etc. If not used, then set flags
- to 0. If the frequency is not supported, then -EINVAL is returned.
-
- g_input_status: get input status. Same as the status field in the v4l2_input
- struct.
-
- s_routing: see s_routing in audio_ops, except this version is for video
- devices.
-
- s_dv_preset: set dv (Digital Video) preset in the sub device. Similar to
- s_std()
-
- g_dv_preset: get current dv (Digital Video) preset in the sub device.
-
- query_dv_preset: query dv preset in the sub device. This is similar to
- querystd()
-
- s_dv_timings(): Set custom dv timings in the sub device. This is used
- when sub device is capable of setting detailed timing information
- in the hardware to generate/detect the video signal.
-
- g_dv_timings(): Get custom dv timings in the sub device.
-
- enum_mbus_fmt: enumerate pixel formats, provided by a video data source
-
- g_mbus_fmt: get the current pixel format, provided by a video data source
-
- try_mbus_fmt: try to set a pixel format on a video data source
-
- s_mbus_fmt: set a pixel format on a video data source
-
- g_mbus_config: get supported mediabus configurations
-
- s_mbus_config: set a certain mediabus configuration. This operation is added
- for compatibility with soc-camera drivers and should not be used by new
- software.
- */
struct v4l2_subdev_video_ops {
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags);
int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
- int (*g_std_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
- int (*g_tvnorms_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
int (*cropcap)(struct v4l2_subdev *sd, struct v4l2_cropcap *cc);
@@ -299,8 +140,6 @@
struct v4l2_dv_enum_preset *preset);
int (*s_dv_preset)(struct v4l2_subdev *sd,
struct v4l2_dv_preset *preset);
- int (*g_dv_preset)(struct v4l2_subdev *sd,
- struct v4l2_dv_preset *preset);
int (*query_dv_preset)(struct v4l2_subdev *sd,
struct v4l2_dv_preset *preset);
int (*s_dv_timings)(struct v4l2_subdev *sd,
@@ -317,41 +156,8 @@
struct v4l2_mbus_framefmt *fmt);
int (*s_mbus_fmt)(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt);
- int (*g_mbus_config)(struct v4l2_subdev *sd,
- struct v4l2_mbus_config *cfg);
- int (*s_mbus_config)(struct v4l2_subdev *sd,
- const struct v4l2_mbus_config *cfg);
};
-/*
- decode_vbi_line: video decoders that support sliced VBI need to implement
- this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the
- start of the VBI data that was generated by the decoder. The driver
- then parses the sliced VBI data and sets the other fields in the
- struct accordingly. The pointer p is updated to point to the start of
- the payload which can be copied verbatim into the data field of the
- v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the
- type field is set to 0 on return.
-
- s_vbi_data: used to generate VBI signals on a video signal.
- v4l2_sliced_vbi_data is filled with the data packets that should be
- output. Note that if you set the line field to 0, then that VBI signal
- is disabled. If no valid VBI data was found, then the type field is
- set to 0 on return.
-
- g_vbi_data: used to obtain the sliced VBI packet from a readback register.
- Not all video decoders support this. If no data is available because
- the readback register contains invalid or erroneous data -EIO is
- returned. Note that you must fill in the 'id' member and the 'field'
- member (to determine whether CC data from the first or second field
- should be obtained).
-
- s_raw_fmt: setup the video encoder/decoder for raw VBI.
-
- g_sliced_fmt: retrieve the current sliced VBI settings.
-
- s_sliced_fmt: setup the sliced VBI settings.
- */
struct v4l2_subdev_vbi_ops {
int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);
int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);
@@ -362,75 +168,43 @@
int (*s_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
};
-/**
- * struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations
- * @g_skip_top_lines: number of lines at the top of the image to be skipped.
- * This is needed for some sensors, which always corrupt
- * several top lines of the output image, or which send their
- * metadata in them.
- * @g_skip_frames: number of frames to skip at stream start. This is needed for
- * buggy sensors that generate faulty frames when they are
- * turned on.
- */
struct v4l2_subdev_sensor_ops {
int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames);
};
-/*
- [rt]x_g_parameters: Get the current operating parameters and state of the
- the IR receiver or transmitter.
-
- [rt]x_s_parameters: Set the current operating parameters and state of the
- the IR receiver or transmitter. It is recommended to call
- [rt]x_g_parameters first to fill out the current state, and only change
- the fields that need to be changed. Upon return, the actual device
- operating parameters and state will be returned. Note that hardware
- limitations may prevent the actual settings from matching the requested
- settings - e.g. an actual carrier setting of 35,904 Hz when 36,000 Hz
- was requested. An exception is when the shutdown parameter is true.
- The last used operational parameters will be returned, but the actual
- state of the hardware be different to minimize power consumption and
- processing when shutdown is true.
-
- rx_read: Reads received codes or pulse width data.
- The semantics are similar to a non-blocking read() call.
-
- tx_write: Writes codes or pulse width data for transmission.
- The semantics are similar to a non-blocking write() call.
- */
enum v4l2_subdev_ir_mode {
- V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, /* uses struct ir_raw_event records */
+ V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
};
struct v4l2_subdev_ir_parameters {
- /* Either Rx or Tx */
- unsigned int bytes_per_data_element; /* of data in read or write call */
+
+ unsigned int bytes_per_data_element;
enum v4l2_subdev_ir_mode mode;
bool enable;
bool interrupt_enable;
- bool shutdown; /* true: set hardware to low/no power, false: normal */
+ bool shutdown;
- bool modulation; /* true: uses carrier, false: baseband */
- u32 max_pulse_width; /* ns, valid only for baseband signal */
- unsigned int carrier_freq; /* Hz, valid only for modulated signal*/
- unsigned int duty_cycle; /* percent, valid only for modulated signal*/
- bool invert_level; /* invert signal level */
+ bool modulation;
+ u32 max_pulse_width;
+ unsigned int carrier_freq;
+ unsigned int duty_cycle;
+ bool invert_level;
- /* Tx only */
- bool invert_carrier_sense; /* Send 0/space as a carrier burst */
+
+ bool invert_carrier_sense;
- /* Rx only */
- u32 noise_filter_min_width; /* ns, min time of a valid pulse */
- unsigned int carrier_range_lower; /* Hz, valid only for modulated sig */
- unsigned int carrier_range_upper; /* Hz, valid only for modulated sig */
- u32 resolution; /* ns */
+
+ u32 noise_filter_min_width;
+ unsigned int carrier_range_lower;
+ unsigned int carrier_range_upper;
+ u32 resolution;
};
struct v4l2_subdev_ir_ops {
- /* Receiver */
+
int (*rx_read)(struct v4l2_subdev *sd, u8 *buf, size_t count,
ssize_t *num);
@@ -439,7 +213,7 @@
int (*rx_s_parameters)(struct v4l2_subdev *sd,
struct v4l2_subdev_ir_parameters *params);
- /* Transmitter */
+
int (*tx_write)(struct v4l2_subdev *sd, u8 *buf, size_t count,
ssize_t *num);
@@ -479,20 +253,6 @@
const struct v4l2_subdev_pad_ops *pad;
};
-/*
- * Internal ops. Never call this from drivers, only the v4l2 framework can call
- * these ops.
- *
- * registered: called when this subdev is registered. When called the v4l2_dev
- * field is set to the correct v4l2_device.
- *
- * unregistered: called when this subdev is unregistered. When called the
- * v4l2_dev field is still set to the correct v4l2_device.
- *
- * open: called when the subdev device node is opened by an application.
- *
- * close: called when the subdev device node is closed.
- */
struct v4l2_subdev_internal_ops {
int (*registered)(struct v4l2_subdev *sd);
void (*unregistered)(struct v4l2_subdev *sd);
@@ -502,18 +262,11 @@
#define V4L2_SUBDEV_NAME_SIZE 32
-/* Set this flag if this subdev is a i2c device. */
#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
-/* Set this flag if this subdev is a spi device. */
#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
-/* Set this flag if this subdev needs a device node. */
#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2)
-/* Set this flag if this subdev generates events. */
#define V4L2_SUBDEV_FL_HAS_EVENTS (1U << 3)
-/* Each instance of a subdev driver should create this struct, either
- stand-alone or embedded in a larger struct.
- */
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
@@ -523,29 +276,28 @@
u32 flags;
struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops;
- /* Never call these internal ops from within a driver! */
+
const struct v4l2_subdev_internal_ops *internal_ops;
- /* The control handler of this subdev. May be NULL. */
+
struct v4l2_ctrl_handler *ctrl_handler;
- /* name must be unique */
+
char name[V4L2_SUBDEV_NAME_SIZE];
- /* can be used to group similar subdevs, value is driver-specific */
+
u32 grp_id;
- /* pointer to private data */
+
void *dev_priv;
void *host_priv;
- /* subdev device node */
- struct video_device *devnode;
+
+ struct video_device devnode;
+
+ unsigned int nevents;
};
#define media_entity_to_v4l2_subdev(ent) \
container_of(ent, struct v4l2_subdev, entity)
#define vdev_to_v4l2_subdev(vdev) \
- video_get_drvdata(vdev)
+ container_of(vdev, struct v4l2_subdev, devnode)
-/*
- * Used for storing subdev information per file handle
- */
struct v4l2_subdev_fh {
struct v4l2_fh vfh;
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
@@ -596,16 +348,10 @@
void v4l2_subdev_init(struct v4l2_subdev *sd,
const struct v4l2_subdev_ops *ops);
-/* Call an ops of a v4l2_subdev, doing the right checks against
- NULL pointers.
-
- Example: err = v4l2_subdev_call(sd, core, g_chip_ident, &chip);
- */
#define v4l2_subdev_call(sd, o, f, args...) \
- (!(sd) ? -ENODEV : (((sd)->ops->o && (sd)->ops->o->f) ? \
+ (!(sd) ? -ENODEV : (((sd)->ops && (sd)->ops->o && (sd)->ops->o->f) ? \
(sd)->ops->o->f((sd) , ##args) : -ENOIOCTLCMD))
-/* Send a notification to v4l2_device. */
#define v4l2_subdev_notify(sd, notification, arg) \
((!(sd) || !(sd)->v4l2_dev || !(sd)->v4l2_dev->notify) ? -ENODEV : \
(sd)->v4l2_dev->notify((sd), (notification), (arg)))