How to add customized v4l2 ioctl for Read and Write

We want to implement new ioctl TEGRA_CAMERA_CID_GET_TSC for APP used. Kernel part do modified like below side.

  • add TEGRA_CAMERA_CID_GET_TSC items
  • add tegra_channel_g_ctrl for iotrl read
  • add more printk for debug purpose.

diff --git a/drivers/media/platform/tegra/camera/vi/channel.c b/drivers/media/platform/tegra/camera/vi/channel.c
index 3ea2885…1df34a4 100644
— a/drivers/media/platform/tegra/camera/vi/channel.c
+++ b/drivers/media/platform/tegra/camera/vi/channel.c

+int tegra_channel_g_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct tegra_channel *chan = container_of(ctrl->handler,
+                               struct tegra_channel, ctrl_handler);
 
+    printk("func %s ctrl-id %d(0x%x)\n ", __func__, ctrl->id, ctrl->id);
+       switch (ctrl->id) {
+    case TEGRA_CAMERA_CID_VI_BYPASS_MODE:
+       case TEGRA_CAMERA_CID_OVERRIDE_ENABLE:
+       case TEGRA_CAMERA_CID_VI_HEIGHT_ALIGN:
+       case TEGRA_CAMERA_CID_VI_SIZE_ALIGN:
+       case TEGRA_CAMERA_CID_WRITE_ISPFORMAT:
+       case TEGRA_CAMERA_CID_LOW_LATENCY:
+       case TEGRA_CAMERA_CID_GET_TSC:
+               dev_err(&chan->video.dev, "%s: ctrl-id %u\n",
+                       __func__, ctrl->id);
+               break;
+       default:
+               dev_err(&chan->video.dev, "%s: Invalid ctrl %u\n",
+                       __func__, ctrl->id);
+               return -EINVAL;
+    }
+    return 0;
+}
+       
 int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct tegra_channel *chan = container_of(ctrl->handler,
                                struct tegra_channel, ctrl_handler);
 
+    printk("func %s ctrl-id %d(0x%x)\n ", __func__, ctrl->id, ctrl->id);
        switch (ctrl->id) {
        case TEGRA_CAMERA_CID_VI_BYPASS_MODE:
                if (switch_ctrl_qmenu[ctrl->val] == SWITCH_ON)
@@ -1051,6 +1077,10 @@ int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)
        case TEGRA_CAMERA_CID_LOW_LATENCY:
                chan->low_latency = ctrl->val;
                break;
+    case TEGRA_CAMERA_CID_GET_TSC:
+        dev_err(&chan->video.dev, "%s: ctrl-id %u\n",
+                __func__, ctrl->id);
+        break;
        default:
                dev_err(&chan->video.dev, "%s: Invalid ctrl %u\n",
                        __func__, ctrl->id);
@@ -1062,6 +1092,7 @@ int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)
 
 static const struct v4l2_ctrl_ops channel_ctrl_ops = {
        .s_ctrl = tegra_channel_s_ctrl,
+    .g_volatile_ctrl = tegra_channel_g_ctrl,
 };
 
 static const struct v4l2_ctrl_config common_custom_ctrls[] = {
@@ -1185,6 +1216,17 @@ static const struct v4l2_ctrl_config common_custom_ctrls[] = {
                .max = 1,
                .step = 1,
        },
+    {
+               .ops = &channel_ctrl_ops,
+               .id = TEGRA_CAMERA_CID_GET_TSC,
+               .name = "TSC Value",
+               .type = V4L2_CTRL_TYPE_U32,
+               .def = 0,
+               .min = 0,
+               .max = 0xFFFFFFFF,
+               .step = 1,
+       },
+
 };
 
diff --git a/include/media/tegra-v4l2-camera.h b/include/media/tegra-v4l2-camera.h
index 8179b3c..407c629 100644
--- a/include/media/tegra-v4l2-camera.h
+++ b/include/media/tegra-v4l2-camera.h
@@ -49,6 +49,7 @@
 #define TEGRA_CAMERA_CID_SENSOR_DV_TIMINGS         (TEGRA_CAMERA_CID_BASE+108)
 
 #define TEGRA_CAMERA_CID_LOW_LATENCY         (TEGRA_CAMERA_CID_BASE+109)
+#define TEGRA_CAMERA_CID_GET_TSC            (TEGRA_CAMERA_CID_BASE+110)

User space do ioctrl read & write operation.

  • VIDIOC_G_CTRL/VIDIOC_S_CTRL to Read and Write
    The result is below.
  1. VIDIOC_G_CTRL doesn’t work, err message is “unable to set control: Invalid argument (22)”

  2. there is no printk message output, seems my kernel debug message doesn’t work?

  3. If we want to add our own v4l2 ioctrl how to do it ?

    struct v4l2_control ctrl;
    int ret;

    ctrl.id = TEGRA_CAMERA_CID_VI_BYPASS_MODE;
    ret = ioctl(dev->fd, VIDIOC_S_CTRL, &ctrl);
    printf(“Control 0x%08x is %u\n”, ctrl.id,
    ctrl.value);
    if (ret < 0) {
    printf(“unable to set control: %s (%d).\n”,
    strerror(errno), errno);
    return;
    }

    ctrl.id = TEGRA_CAMERA_CID_GET_TSC;
    ret = ioctl(dev->fd, VIDIOC_G_CTRL, &ctrl);
    if (ret < 0) {
    printf(“unable to set control: %s (%d).\n”,
    strerror(errno), errno);
    return;
    }

Seems the new TSC ictrl has been recognized by v4l2-ctl. Ref below info

v4l2-ctl --all
Camera Controls

                   frame_length (int)    : min=0 max=32767 step=1 default=1766 value=1766 flags=slider
                    coarse_time (int)    : min=1 max=32763 step=1 default=1762 value=1762 flags=slider
                     group_hold (intmenu): min=0 max=1 default=0 value=0
                     hdr_enable (intmenu): min=0 max=1 default=0 value=0
                        fuse_id (str)    : min=0 max=12 step=2 value='' flags=read-only, has-payload
                           gain (int)    : min=256 max=4096 step=1 default=256 value=256 flags=slider
                    bypass_mode (intmenu): min=0 max=1 default=0 value=0
                override_enable (intmenu): min=0 max=1 default=0 value=0
                   height_align (int)    : min=1 max=16 step=1 default=1 value=1
                     size_align (intmenu): min=0 max=2 default=0 value=0
               write_isp_format (int)    : min=1 max=1 step=1 default=1 value=1
       sensor_signal_properties (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
        sensor_image_properties (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
      sensor_control_properties (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
              sensor_dv_timings (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
               low_latency_mode (bool)   : default=0 value=0
                      tsc_value (u32)    : min=0 max=0 step=0 default=0 flags=has-payload
                   sensor_modes (int)    : min=0 max=30 step=1 default=30 value=3 flags=read-only

hello bdehj,

please refer to Topic 145686 to extend your customize CID controls,
thanks

JerryChang,

Yes before I open this topic, I also ref Topic 145686.

you may enable v4l2-ctl to display all available information, to check whether you’d implement that correctly,
Seems my own v4l2-ctl implementation is correct. But still cannot access with C API ioctl.

But I still figure out how to fix the issue now, can you give more clarification?

hello bdehj,

it just looks incorrect you’re have min=max, is this your expectation of tsc_value property settings?
for example,

tsc_value (u32)    : min=0 max=0 step=0 default=0 flags=has-payload

suggest you may review your custom controls settings in v4l2_ctrl_config
thanks

JerryChange,

Thanks for your correction. Suppose min/max issue fixed.

+    {
+               .ops = &channel_ctrl_ops,
+               .id = TEGRA_CAMERA_CID_GET_TSC,
+               .name = "TSC Value",
+               .type = V4L2_CTRL_TYPE_U32,
+               .def = 0,
+               .min = 0,
+               .max = 0xFFFFFFFF,
+               .step = 1,
+       },

My question is why I cannot get tsc with C API. Not set tsc command.

ctrl.id = TEGRA_CAMERA_CID_GET_TSC;
ret = ioctl(dev->fd, VIDIOC_G_CTRL, &ctrl);
if (ret < 0) {
printf(“unable to set control: %s (%d).\n”,
strerror(errno), errno);
return;
}

hello bdehj,

that should be v4l2 standard controls,
suggest you may also check imx214 kernel driver by using v4l2 get controls for reference,
for example,
$L4T_Sources/r32.4.3/Linux_for_Tegra/source/public/kernel/nvidia/drivers/media/i2c/imx214.c

static const struct v4l2_ctrl_ops imx214_ctrl_ops = {
        .g_volatile_ctrl = imx214_g_volatile_ctrl,
        .s_ctrl         = imx214_s_ctrl,
};

...

static int imx214_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
        struct imx214 *priv =
                container_of(ctrl->handler, struct imx214, ctrl_handler);
...
        switch (ctrl->id) {
        case TEGRA_CAMERA_CID_EEPROM_DATA:
                err = imx214_read_eeprom(priv, ctrl);
...

you’ll also need user-space calling such CID to parse the get controls function.
thanks

OK, I will do this test later and let you know the result.

JerryChang, Thanks for your help. It works for me!