[media] v4l2-ioctl.c: use the new table for std/tuner/modulator ioctls

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2012-06-22 06:17:48 -03:00 committed by Mauro Carvalho Chehab
parent e325b24478
commit 4b1e2e4ddf

View File

@ -364,6 +364,68 @@ static void v4l_print_buftype(const void *arg, bool write_only)
pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names));
}
static void v4l_print_modulator(const void *arg, bool write_only)
{
const struct v4l2_modulator *p = arg;
if (write_only)
pr_cont("index=%u, txsubchans=0x%x", p->index, p->txsubchans);
else
pr_cont("index=%u, name=%s, capability=0x%x, "
"rangelow=%u, rangehigh=%u, txsubchans=0x%x\n",
p->index, p->name, p->capability,
p->rangelow, p->rangehigh, p->txsubchans);
}
static void v4l_print_tuner(const void *arg, bool write_only)
{
const struct v4l2_tuner *p = arg;
if (write_only)
pr_cont("index=%u, audmode=%u\n", p->index, p->audmode);
else
pr_cont("index=%u, name=%s, type=%u, capability=0x%x, "
"rangelow=%u, rangehigh=%u, signal=%u, afc=%d, "
"rxsubchans=0x%x, audmode=%u\n",
p->index, p->name, p->type,
p->capability, p->rangelow,
p->rangehigh, p->signal, p->afc,
p->rxsubchans, p->audmode);
}
static void v4l_print_frequency(const void *arg, bool write_only)
{
const struct v4l2_frequency *p = arg;
pr_cont("tuner=%u, type=%u, frequency=%u\n",
p->tuner, p->type, p->frequency);
}
static void v4l_print_standard(const void *arg, bool write_only)
{
const struct v4l2_standard *p = arg;
pr_cont("index=%u, id=0x%Lx, name=%s, fps=%u/%u, "
"framelines=%u\n", p->index,
(unsigned long long)p->id, p->name,
p->frameperiod.numerator,
p->frameperiod.denominator,
p->framelines);
}
static void v4l_print_std(const void *arg, bool write_only)
{
pr_cont("std=0x%08Lx\n", *(const long long unsigned *)arg);
}
static void v4l_print_hw_freq_seek(const void *arg, bool write_only)
{
const struct v4l2_hw_freq_seek *p = arg;
pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n",
p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing);
}
static void v4l_print_u32(const void *arg, bool write_only)
{
pr_cont("value=%u\n", *(const u32 *)arg);
@ -861,6 +923,153 @@ static int v4l_streamoff(const struct v4l2_ioctl_ops *ops,
return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg);
}
static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
struct v4l2_tuner *p = arg;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
return ops->vidioc_g_tuner(file, fh, p);
}
static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
struct v4l2_tuner *p = arg;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
return ops->vidioc_s_tuner(file, fh, p);
}
static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
struct v4l2_frequency *p = arg;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
return ops->vidioc_g_frequency(file, fh, p);
}
static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
struct v4l2_frequency *p = arg;
enum v4l2_tuner_type type;
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
if (p->type != type)
return -EINVAL;
return ops->vidioc_s_frequency(file, fh, p);
}
static int v4l_enumstd(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
struct v4l2_standard *p = arg;
v4l2_std_id id = vfd->tvnorms, curr_id = 0;
unsigned int index = p->index, i, j = 0;
const char *descr = "";
/* 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;
descr = standards[j].descr;
j++;
if (curr_id == 0)
break;
if (curr_id != V4L2_STD_PAL &&
curr_id != V4L2_STD_SECAM &&
curr_id != V4L2_STD_NTSC)
id &= ~curr_id;
}
if (i <= index)
return -EINVAL;
v4l2_video_std_construct(p, curr_id, descr);
return 0;
}
static int v4l_g_std(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
v4l2_std_id *id = arg;
/* Calls the specific handler */
if (ops->vidioc_g_std)
return ops->vidioc_g_std(file, fh, arg);
if (vfd->current_norm) {
*id = vfd->current_norm;
return 0;
}
return -ENOTTY;
}
static int v4l_s_std(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
v4l2_std_id *id = arg, norm;
int ret;
norm = (*id) & vfd->tvnorms;
if (vfd->tvnorms && !norm) /* Check if std is supported */
return -EINVAL;
/* Calls the specific handler */
ret = ops->vidioc_s_std(file, fh, &norm);
/* Updates standard information */
if (ret >= 0)
vfd->current_norm = norm;
return ret;
}
static int v4l_querystd(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
v4l2_std_id *p = arg;
/*
* If nothing detected, it should return all supported
* standard.
* 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;
return ops->vidioc_querystd(file, fh, arg);
}
static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct video_device *vfd = video_devdata(file);
struct v4l2_hw_freq_seek *p = arg;
enum v4l2_tuner_type type;
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
if (p->type != type)
return -EINVAL;
return ops->vidioc_s_hw_freq_seek(file, fh, p);
}
struct v4l2_ioctl_info {
unsigned int ioctl;
u32 flags;
@ -927,14 +1136,14 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_PARM, INFO_FL_CLEAR(v4l2_streamparm, type)),
IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_STD, 0),
IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_ENUMSTD, INFO_FL_CLEAR(v4l2_standard, index)),
IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0),
IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)),
IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)),
IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_G_TUNER, INFO_FL_CLEAR(v4l2_tuner, index)),
IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)),
IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO),
IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0),
IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)),
@ -946,10 +1155,10 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0),
IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_MODULATOR, INFO_FL_CLEAR(v4l2_modulator, index)),
IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_FREQUENCY, INFO_FL_CLEAR(v4l2_frequency, tuner)),
IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO),
IOCTL_INFO_STD(VIDIOC_G_MODULATOR, vidioc_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)),
IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)),
IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_CROPCAP, INFO_FL_CLEAR(v4l2_cropcap, type)),
IOCTL_INFO(VIDIOC_G_CROP, INFO_FL_CLEAR(v4l2_crop, type)),
IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO),
@ -957,7 +1166,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0),
IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYSTD, 0),
IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0),
IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)),
IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)),
@ -978,7 +1187,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0),
IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0),
IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0),
IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0),
IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_DV_PRESET, 0),
@ -1160,102 +1369,6 @@ static long __video_do_ioctl(struct file *file,
dbgbuf(cmd, vfd, p);
break;
}
/* ---------- tv norms ---------- */
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *p = arg;
v4l2_std_id id = vfd->tvnorms, curr_id = 0;
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;
descr = standards[j].descr;
j++;
if (curr_id == 0)
break;
if (curr_id != V4L2_STD_PAL &&
curr_id != V4L2_STD_SECAM &&
curr_id != V4L2_STD_NTSC)
id &= ~curr_id;
}
if (i <= index)
break;
v4l2_video_std_construct(p, curr_id, descr);
dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
"framelines=%d\n", p->index,
(unsigned long long)p->id, p->name,
p->frameperiod.numerator,
p->frameperiod.denominator,
p->framelines);
ret = 0;
break;
}
case VIDIOC_G_STD:
{
v4l2_std_id *id = arg;
/* Calls the specific handler */
if (ops->vidioc_g_std)
ret = ops->vidioc_g_std(file, fh, id);
else if (vfd->current_norm) {
ret = 0;
*id = vfd->current_norm;
}
if (likely(!ret))
dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
break;
}
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg, norm;
dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
ret = -EINVAL;
norm = (*id) & vfd->tvnorms;
if (vfd->tvnorms && !norm) /* Check if std is supported */
break;
/* Calls the specific handler */
ret = ops->vidioc_s_std(file, fh, &norm);
/* Updates standard information */
if (ret >= 0)
vfd->current_norm = norm;
break;
}
case VIDIOC_QUERYSTD:
{
v4l2_std_id *p = arg;
/*
* 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;
}
/* --- controls ---------------------------------------------- */
case VIDIOC_QUERYCTRL:
@ -1426,31 +1539,6 @@ static long __video_do_ioctl(struct file *file,
p->id, p->index);
break;
}
case VIDIOC_G_MODULATOR:
{
struct v4l2_modulator *p = arg;
ret = ops->vidioc_g_modulator(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, "
"capability=%d, rangelow=%d,"
" rangehigh=%d, txsubchans=%d\n",
p->index, p->name, p->capability,
p->rangelow, p->rangehigh,
p->txsubchans);
break;
}
case VIDIOC_S_MODULATOR:
{
struct v4l2_modulator *p = arg;
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
p->index, p->name, p->capability, p->rangelow,
p->rangehigh, p->txsubchans);
ret = ops->vidioc_s_modulator(file, fh, p);
break;
}
case VIDIOC_G_CROP:
{
struct v4l2_crop *p = arg;
@ -1684,68 +1772,6 @@ static long __video_do_ioctl(struct file *file,
ret = ops->vidioc_s_parm(file, fh, p);
break;
}
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *p = arg;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_tuner(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, type=%d, "
"capability=0x%x, rangelow=%d, "
"rangehigh=%d, signal=%d, afc=%d, "
"rxsubchans=0x%x, audmode=%d\n",
p->index, p->name, p->type,
p->capability, p->rangelow,
p->rangehigh, p->signal, p->afc,
p->rxsubchans, p->audmode);
break;
}
case VIDIOC_S_TUNER:
{
struct v4l2_tuner *p = arg;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "index=%d, name=%s, type=%d, "
"capability=0x%x, rangelow=%d, "
"rangehigh=%d, signal=%d, afc=%d, "
"rxsubchans=0x%x, audmode=%d\n",
p->index, p->name, p->type,
p->capability, p->rangelow,
p->rangehigh, p->signal, p->afc,
p->rxsubchans, p->audmode);
ret = ops->vidioc_s_tuner(file, fh, p);
break;
}
case VIDIOC_G_FREQUENCY:
{
struct v4l2_frequency *p = arg;
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_frequency(file, fh, p);
if (!ret)
dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
p->tuner, p->type, p->frequency);
break;
}
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *p = arg;
enum v4l2_tuner_type type;
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);
break;
}
case VIDIOC_G_SLICED_VBI_CAP:
{
struct v4l2_sliced_vbi_cap *p = arg;
@ -1805,22 +1831,6 @@ static long __video_do_ioctl(struct file *file,
dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
break;
}
case VIDIOC_S_HW_FREQ_SEEK:
{
struct v4l2_hw_freq_seek *p = arg;
enum v4l2_tuner_type type;
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd,
"tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n",
p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing);
if (p->type != type)
ret = -EINVAL;
else
ret = ops->vidioc_s_hw_freq_seek(file, fh, p);
break;
}
case VIDIOC_ENUM_FRAMESIZES:
{
struct v4l2_frmsizeenum *p = arg;