[media] V4L: add two new ioctl()s for multi-size videobuffer management
A possibility to preallocate and initialise buffers of different sizes in V4L2 is required for an efficient implementation of a snapshot mode. This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and VIDIOC_PREPARE_BUF and defines respective data structures. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
ebc087d090
Коммит
2150158b31
|
@ -159,11 +159,16 @@ struct v4l2_format32 {
|
||||||
} fmt;
|
} fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
struct v4l2_create_buffers32 {
|
||||||
|
__u32 index; /* output: buffers index...index + count - 1 have been created */
|
||||||
|
__u32 count;
|
||||||
|
enum v4l2_memory memory;
|
||||||
|
struct v4l2_format32 format; /* filled in by the user, plane sizes calculated by the driver */
|
||||||
|
__u32 reserved[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
||||||
{
|
{
|
||||||
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
|
|
||||||
get_user(kp->type, &up->type))
|
|
||||||
return -EFAULT;
|
|
||||||
switch (kp->type) {
|
switch (kp->type) {
|
||||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||||
|
@ -192,11 +197,24 @@ static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
||||||
|
{
|
||||||
|
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
|
||||||
|
get_user(kp->type, &up->type))
|
||||||
|
return -EFAULT;
|
||||||
|
return __get_v4l2_format32(kp, up);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
|
||||||
|
{
|
||||||
|
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
|
||||||
|
copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt)))
|
||||||
|
return -EFAULT;
|
||||||
|
return __get_v4l2_format32(&kp->format, &up->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
||||||
{
|
{
|
||||||
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
|
|
||||||
put_user(kp->type, &up->type))
|
|
||||||
return -EFAULT;
|
|
||||||
switch (kp->type) {
|
switch (kp->type) {
|
||||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||||
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
|
||||||
|
@ -225,6 +243,22 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
||||||
|
{
|
||||||
|
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
|
||||||
|
put_user(kp->type, &up->type))
|
||||||
|
return -EFAULT;
|
||||||
|
return __put_v4l2_format32(kp, up);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
|
||||||
|
{
|
||||||
|
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
|
||||||
|
copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
|
||||||
|
return -EFAULT;
|
||||||
|
return __put_v4l2_format32(&kp->format, &up->format);
|
||||||
|
}
|
||||||
|
|
||||||
struct v4l2_standard32 {
|
struct v4l2_standard32 {
|
||||||
__u32 index;
|
__u32 index;
|
||||||
__u32 id[2]; /* __u64 would get the alignment wrong */
|
__u32 id[2]; /* __u64 would get the alignment wrong */
|
||||||
|
@ -702,6 +736,8 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
|
||||||
#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
|
#define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
|
||||||
#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
|
#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
|
||||||
#define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
|
#define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
|
||||||
|
#define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
|
||||||
|
#define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
|
||||||
|
|
||||||
#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
|
#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
|
||||||
#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
|
#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
|
||||||
|
@ -721,6 +757,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||||
struct v4l2_standard v2s;
|
struct v4l2_standard v2s;
|
||||||
struct v4l2_ext_controls v2ecs;
|
struct v4l2_ext_controls v2ecs;
|
||||||
struct v4l2_event v2ev;
|
struct v4l2_event v2ev;
|
||||||
|
struct v4l2_create_buffers v2crt;
|
||||||
unsigned long vx;
|
unsigned long vx;
|
||||||
int vi;
|
int vi;
|
||||||
} karg;
|
} karg;
|
||||||
|
@ -751,6 +788,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||||
case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
|
case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
|
||||||
case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
|
case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
|
||||||
case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
|
case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
|
||||||
|
case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
|
||||||
|
case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
@ -775,6 +814,12 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||||
compatible_arg = 0;
|
compatible_arg = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_CREATE_BUFS:
|
||||||
|
err = get_v4l2_create32(&karg.v2crt, up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_PREPARE_BUF:
|
||||||
case VIDIOC_QUERYBUF:
|
case VIDIOC_QUERYBUF:
|
||||||
case VIDIOC_QBUF:
|
case VIDIOC_QBUF:
|
||||||
case VIDIOC_DQBUF:
|
case VIDIOC_DQBUF:
|
||||||
|
@ -860,6 +905,10 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
|
||||||
err = put_v4l2_format32(&karg.v2f, up);
|
err = put_v4l2_format32(&karg.v2f, up);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_CREATE_BUFS:
|
||||||
|
err = put_v4l2_create32(&karg.v2crt, up);
|
||||||
|
break;
|
||||||
|
|
||||||
case VIDIOC_QUERYBUF:
|
case VIDIOC_QUERYBUF:
|
||||||
case VIDIOC_QBUF:
|
case VIDIOC_QBUF:
|
||||||
case VIDIOC_DQBUF:
|
case VIDIOC_DQBUF:
|
||||||
|
@ -959,6 +1008,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case VIDIOC_DQEVENT32:
|
case VIDIOC_DQEVENT32:
|
||||||
case VIDIOC_SUBSCRIBE_EVENT:
|
case VIDIOC_SUBSCRIBE_EVENT:
|
||||||
case VIDIOC_UNSUBSCRIBE_EVENT:
|
case VIDIOC_UNSUBSCRIBE_EVENT:
|
||||||
|
case VIDIOC_CREATE_BUFS32:
|
||||||
|
case VIDIOC_PREPARE_BUF32:
|
||||||
ret = do_video_ioctl(file, cmd, arg);
|
ret = do_video_ioctl(file, cmd, arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,8 @@ static const char *v4l2_ioctls[] = {
|
||||||
[_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT",
|
[_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT",
|
||||||
[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT",
|
[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT",
|
||||||
[_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_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)
|
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
|
||||||
|
|
||||||
|
@ -2104,6 +2106,40 @@ static long __video_do_ioctl(struct file *file,
|
||||||
dbgarg(cmd, "type=0x%8.8x", sub->type);
|
dbgarg(cmd, "type=0x%8.8x", sub->type);
|
||||||
break;
|
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:
|
default:
|
||||||
if (!ops->vidioc_default)
|
if (!ops->vidioc_default)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -653,6 +653,10 @@ struct v4l2_buffer {
|
||||||
#define V4L2_BUF_FLAG_ERROR 0x0040
|
#define V4L2_BUF_FLAG_ERROR 0x0040
|
||||||
#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */
|
#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */
|
||||||
#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */
|
#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */
|
||||||
|
#define V4L2_BUF_FLAG_PREPARED 0x0400 /* Buffer is prepared for queuing */
|
||||||
|
/* Cache handling flags */
|
||||||
|
#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE 0x0800
|
||||||
|
#define V4L2_BUF_FLAG_NO_CACHE_CLEAN 0x1000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* O V E R L A Y P R E V I E W
|
* O V E R L A Y P R E V I E W
|
||||||
|
@ -2138,6 +2142,15 @@ struct v4l2_dbg_chip_ident {
|
||||||
__u32 revision; /* chip revision, chip specific */
|
__u32 revision; /* chip revision, chip specific */
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* VIDIOC_CREATE_BUFS */
|
||||||
|
struct v4l2_create_buffers {
|
||||||
|
__u32 index; /* output: buffers index...index + count - 1 have been created */
|
||||||
|
__u32 count;
|
||||||
|
enum v4l2_memory memory;
|
||||||
|
struct v4l2_format format; /* "type" is used always, the rest if sizeimage == 0 */
|
||||||
|
__u32 reserved[8];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I O C T L C O D E S F O R V I D E O D E V I C E S
|
* I O C T L C O D E S F O R V I D E O D E V I C E S
|
||||||
*
|
*
|
||||||
|
@ -2228,6 +2241,11 @@ struct v4l2_dbg_chip_ident {
|
||||||
#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription)
|
#define VIDIOC_SUBSCRIBE_EVENT _IOW('V', 90, struct v4l2_event_subscription)
|
||||||
#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
|
#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
|
||||||
|
|
||||||
|
/* Experimental, the below two ioctls may change over the next couple of kernel
|
||||||
|
versions */
|
||||||
|
#define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers)
|
||||||
|
#define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer)
|
||||||
|
|
||||||
/* Reminder: when adding new ioctls please add support for them to
|
/* Reminder: when adding new ioctls please add support for them to
|
||||||
drivers/media/video/v4l2-compat-ioctl32.c as well! */
|
drivers/media/video/v4l2-compat-ioctl32.c as well! */
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,8 @@ struct v4l2_ioctl_ops {
|
||||||
int (*vidioc_qbuf) (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_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_overlay) (struct file *file, void *fh, unsigned int i);
|
||||||
int (*vidioc_g_fbuf) (struct file *file, void *fh,
|
int (*vidioc_g_fbuf) (struct file *file, void *fh,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче