V4L2 Camera Driver Development Custom Controls

Hello. I am new to Jetson Nano and V4L2 Driver Development in general. I have written a working V4L2 camera driver for another Linux platform. While porting to Jetson Nano I came up with 2 questions I have not found an answer for in the examples. If I was missing something, please let me know :)
While porting I was using your guide on how to implement the driver with tegracam. So I am using 2.0. Since I am using monochrome sensor I am not using your ISP with gstreamer, instead I use v4l2 C-API in my own C++ application I am writing. I mostly used the v4l2-cuda example for that.

I can set exposure time correctly using v4l2-ctl -c exposure=90 from the command line. But when I try to set it in my C Application it gives “Invalid Argument”.

bool v4l2_ctrl_set(int fd, uint32_t id, int val)
    struct v4l2_control ctrl;

    ctrl.id = id;
    ctrl.value = val;
    if (xioctl(fd, VIDIOC_S_CTRL, &ctrl) == -1) {
        std::cout << "Failed to set ctrl with id " 
                  << id << " to value " << val
                  << "\nerror (" << errno << "): " << strerror(errno) << std::endl;

       	return false;
    return true;
  1. How do I set V4l2-ctrls with C-API using the tegracam implementation in my driver?

  2. How should I implement custom V4L2 controls using tegracam. For example I want to set top/left readout offset values for my camera. Should I change the tegracam files, or should I add another custom control handler from my driver? How to make it compatible with tegracam 2.0 driver development?

Sorry for my basic questions.

Best regards,

hello busch.johannes,

assume you have check Sensor Software Driver Programming Guide for sensor driver implementation.

you may check below kernel sources for available TEGRA_CAMERA_CID_* controls,
let’s taking preferred stride controls as an example,


you should also refer to VI driver, which define the CID control property and also parse the control settings,

static const struct v4l2_ctrl_config common_custom_ctrls[] = {
                .ops = &channel_ctrl_ops,

int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)

        switch (ctrl->id) {
                chan->preferred_stride = ctrl->val;

you may enable v4l2-ctl to display all available information, to check whether you’d implement that correctly,

$ v4l2-ctl --all
               preferred_stride 0x009a206e (int)    : min=0 max=65535 step=1 default=0 value=0

then, you’ll able to enable --set-ctrl flags to assign your property settings into VI drivers.
for example, $ v4l2-ctl -d /dev/video0 ... --set-ctrl preferred_stride=256 ...

if you would like to extend your customize CID controls,
please adding specific CID flags to tegra-v4l2-camera.h,
you should also have implementation in the VI drivers, channel.c.

Thanks for your fast response. I’ll try that next week.
Can you also help me with my 1st question? For Exposure setting the v4l2-ctl command does work but calling from my userspace application the above code for exposure gives me invalid argument. Which header files do I have to include to set exposure from c++ user space application?

Am I doing sth wrong?

Best regards,

hello busch.johannes,

please also refer to Property-Value Pairs supported for version 2.0 sensor drivers.
you should enable TEGRA_CAMERA_CID_EXPOSURE controls to set your sensor exposure times.

I could figure out how to achieve what I wanted by myself, so here is what I needed to do to set Sensor Ctrl Settings from my C++ userspace application:

struct v4l2_ext_controls ctrls;
struct v4l2_ext_control ctrl;
ctrls.controls = &ctrl;
ctrls.count = 1;
ctrls.which = V4L2_CTRL_WHICH_CUR_VAL;

ctrl.value = ;
if (xioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) == -1) {
     fprintf(stderr, "Error VIDIOC_S_EXT_CTRLS %s\n",strerror(errno));

Thank you anyway for your help!