Skip to content

Commit

Permalink
V4L/DVB (9903): uvcvideo: V4L2 zoom controls support
Browse files Browse the repository at this point in the history
Add support for absolute and continuous zoom controls (mapped to absolute
and relative UVC zoom controls).

Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Laurent Pinchart authored and Mauro Carvalho Chehab committed Dec 30, 2008
1 parent 6df126f commit 9768352
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 14 deletions.
76 changes: 64 additions & 12 deletions drivers/media/video/uvc/uvc_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,31 @@ static struct uvc_menu_info exposure_auto_controls[] = {
{ 8, "Aperture Priority Mode" },
};

static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
__u8 query, const __u8 *data)
{
__s8 zoom = (__s8)data[0];

switch (query) {
case GET_CUR:
return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);

case GET_MIN:
case GET_MAX:
case GET_RES:
case GET_DEF:
default:
return data[2];
}
}

static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
__s32 value, __u8 *data)
{
data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
data[2] = min(abs(value), 0xff);
}

static struct uvc_control_mapping uvc_ctrl_mappings[] = {
{
.id = V4L2_CID_BRIGHTNESS,
Expand Down Expand Up @@ -532,6 +557,28 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = {
.v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
.data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
},
{
.id = V4L2_CID_ZOOM_ABSOLUTE,
.name = "Zoom, Absolute",
.entity = UVC_GUID_UVC_CAMERA,
.selector = CT_ZOOM_ABSOLUTE_CONTROL,
.size = 16,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
},
{
.id = V4L2_CID_ZOOM_CONTINUOUS,
.name = "Zoom, Continuous",
.entity = UVC_GUID_UVC_CAMERA,
.selector = CT_ZOOM_RELATIVE_CONTROL,
.size = 0,
.offset = 0,
.v4l2_type = V4L2_CTRL_TYPE_INTEGER,
.data_type = UVC_CTRL_DATA_TYPE_SIGNED,
.get = uvc_ctrl_get_zoom,
.set = uvc_ctrl_set_zoom,
},
{
.id = V4L2_CID_PRIVACY,
.name = "Privacy",
Expand Down Expand Up @@ -568,8 +615,8 @@ static inline void uvc_clear_bit(__u8 *data, int bit)
* a signed 32bit integer. Sign extension will be performed if the mapping
* references a signed data type.
*/
static __s32 uvc_get_le_value(const __u8 *data,
struct uvc_control_mapping *mapping)
static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
__u8 query, const __u8 *data)
{
int bits = mapping->size;
int offset = mapping->offset;
Expand Down Expand Up @@ -598,8 +645,8 @@ static __s32 uvc_get_le_value(const __u8 *data,
/* Set the bit string specified by mapping->offset and mapping->size
* in the little-endian data stored at 'data' to the value 'value'.
*/
static void uvc_set_le_value(__s32 value, __u8 *data,
struct uvc_control_mapping *mapping)
static void uvc_set_le_value(struct uvc_control_mapping *mapping,
__s32 value, __u8 *data)
{
int bits = mapping->size;
int offset = mapping->offset;
Expand Down Expand Up @@ -751,7 +798,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
video->dev->intfnum, ctrl->info->selector,
data, ctrl->info->size)) < 0)
goto out;
v4l2_ctrl->default_value = uvc_get_le_value(data, mapping);
v4l2_ctrl->default_value = mapping->get(mapping, GET_DEF, data);
}

switch (mapping->v4l2_type) {
Expand Down Expand Up @@ -787,21 +834,21 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
video->dev->intfnum, ctrl->info->selector,
data, ctrl->info->size)) < 0)
goto out;
v4l2_ctrl->minimum = uvc_get_le_value(data, mapping);
v4l2_ctrl->minimum = mapping->get(mapping, GET_MIN, data);
}
if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id,
video->dev->intfnum, ctrl->info->selector,
data, ctrl->info->size)) < 0)
goto out;
v4l2_ctrl->maximum = uvc_get_le_value(data, mapping);
v4l2_ctrl->maximum = mapping->get(mapping, GET_MAX, data);
}
if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id,
video->dev->intfnum, ctrl->info->selector,
data, ctrl->info->size)) < 0)
goto out;
v4l2_ctrl->step = uvc_get_le_value(data, mapping);
v4l2_ctrl->step = mapping->get(mapping, GET_RES, data);
}

ret = 0;
Expand Down Expand Up @@ -938,8 +985,8 @@ int uvc_ctrl_get(struct uvc_video_device *video,
ctrl->loaded = 1;
}

xctrl->value = uvc_get_le_value(
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
xctrl->value = mapping->get(mapping, GET_CUR,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));

if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
menu = mapping->menu_info;
Expand Down Expand Up @@ -995,8 +1042,8 @@ int uvc_ctrl_set(struct uvc_video_device *video,
ctrl->info->size);
}

uvc_set_le_value(value,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
mapping->set(mapping, value,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));

ctrl->dirty = 1;
ctrl->modified = 1;
Expand Down Expand Up @@ -1272,6 +1319,11 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping)
struct uvc_control_mapping *map;
int ret = -EINVAL;

if (mapping->get == NULL)
mapping->get = uvc_get_le_value;
if (mapping->set == NULL)
mapping->set = uvc_set_le_value;

if (mapping->id & ~V4L2_CTRL_ID_MASK) {
uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with "
"invalid control id 0x%08x\n", mapping->name,
Expand Down
4 changes: 2 additions & 2 deletions drivers/media/video/uvc/uvc_v4l2.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;

info = kmalloc(sizeof *info, GFP_KERNEL);
info = kzalloc(sizeof *info, GFP_KERNEL);
if (info == NULL)
return -ENOMEM;

Expand All @@ -941,7 +941,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;

map = kmalloc(sizeof *map, GFP_KERNEL);
map = kzalloc(sizeof *map, GFP_KERNEL);
if (map == NULL)
return -ENOMEM;

Expand Down
5 changes: 5 additions & 0 deletions drivers/media/video/uvc/uvcvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,11 @@ struct uvc_control_mapping {

struct uvc_menu_info *menu_info;
__u32 menu_count;

__s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,
const __u8 *data);
void (*set) (struct uvc_control_mapping *mapping, __s32 value,
__u8 *data);
};

struct uvc_control {
Expand Down

0 comments on commit 9768352

Please sign in to comment.