From nobody Tue Jun 16 11:23:04 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gfl3D4drSz6hSsM for ; Tue, 16 Jun 2026 11:23:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gfl3D2gxwz3MJb for ; Tue, 16 Jun 2026 11:23:04 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781608984; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=daRk4e6YK/9oDX95ULpU0dOAQAr7lpxzOg7oXB3nFfs=; b=haoV5+nCm+lWjOqtliPjE7qUwlPthrt73t0Q5TI+E9dB6zLvcpzPldvsCxOsu8zDpnp1+r bg5chPoUvdzyQOXBBthzktqMrh9fHrp267Urva5kUtobNaZgONHaUyiMz79rtbVg3RphXI YUt85UZrOv/9z02t+Yt6mn70sh5yIn1TDNXztKAN31BvCd1sW3bgyD/0QXh0XupxH55Ysr j3FQWe6F7KcbU/nK39/Qf+EaiqBebfuFfiO9KQn9wUCq7bC0MJ55X7FUYh5S+r+nPN4r9a p45AjjQAsT2MR7Je0CfXtmVaFBAiVEq8fP0FODiJxyBscAAF4Xxz+WfUPmebJg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1781608984; a=rsa-sha256; cv=none; b=O8AjApO0I3UzA6TX/OcOxLIZPMNgSs9uik8sdTf2d5vgjfShedKx26Xc++d0mwGtO6pB+i NV6VOCc/H0mXWXzgQJB3VadN5w3OXTZXSZB7eNtAeQ/co5YZ0iXLS/G64rNB4nfIe6goUN 29bz2cwyAXLZgUbK+S3bmqHVWUZHvLuvULZX1YPKYK7FXEzXF3RVzXuFhdPNveQXaRcJK6 Ig/8wwtcmoXP44GTnN+BR8dMEQKPY4/YQ96BhBuIfH91mTq4Ej6GRnmyjf6bs2Kywqdqhu OmBdw85aRPvLNdM1Ovi1pkYAqOiErgNqB9BdJ5rtRFtrgIQeQPpmi2KZtxX+oQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1781608984; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=daRk4e6YK/9oDX95ULpU0dOAQAr7lpxzOg7oXB3nFfs=; b=gjCFMLLAF3g3hNQFRpP+V67VI5sf8GoqWG0xpBIcAJGrPXvEyLz9tcV/j+QyU7EGzdiwbr qhmrsjbRtOyTrBNtkL2/ojfyc5dAimjZpSlXiWkTJSFdzPYsL0hGOKKaQM73uqPqL3jzNn pi6ZnEy4LEGWSFWCdsZbvl0omwmHs5KpcwrFGD/zx57Miq/4zZoMDBQ6hOnAuilZYlRO+h Vre/DJWbDReXhrUrPuz4JAqkK0djcP5+29256Zu5HGoYXOMegnEKuwKZwCdtoX7QJHX8LD WHbUUlNPEDLBKPcuMBQd+LmBnW0QX/PX3bXkiAQdLMzKosRDeAi1up/K1HfwLg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gfl3D2DVzz821 for ; Tue, 16 Jun 2026 11:23:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1e0cd by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 16 Jun 2026 11:23:04 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Baptiste Daroussin Subject: git: d0450cbec7e6 - main - uvideo: add Camera Terminal controls List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bapt X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d0450cbec7e66ee56fd48c6482fd3bd9fb6549dc Auto-Submitted: auto-generated Date: Tue, 16 Jun 2026 11:23:04 +0000 Message-Id: <6a313218.1e0cd.1a843b45@gitrepo.freebsd.org> The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=d0450cbec7e66ee56fd48c6482fd3bd9fb6549dc commit d0450cbec7e66ee56fd48c6482fd3bd9fb6549dc Author: Baptiste Daroussin AuthorDate: 2026-05-06 16:28:27 +0000 Commit: Baptiste Daroussin CommitDate: 2026-06-16 11:21:01 +0000 uvideo: add Camera Terminal controls Implement UVC Camera Terminal (CT) controls per UVC 1.5 specification Table A-12. This adds support for camera-specific controls that are separate from the Processing Unit controls already supported. Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D56962 --- sys/dev/usb/video/uvideo.c | 210 +++++++++++++++++++++++++++++++++++++--- sys/dev/usb/video/uvideo.h | 2 +- sys/dev/usb/video/uvideo_v4l2.h | 13 +++ 3 files changed, 211 insertions(+), 14 deletions(-) diff --git a/sys/dev/usb/video/uvideo.c b/sys/dev/usb/video/uvideo.c index a33b3ac31ea6..52998fbc9b40 100644 --- a/sys/dev/usb/video/uvideo.c +++ b/sys/dev/usb/video/uvideo.c @@ -95,6 +95,10 @@ static usb_error_t uvideo_vc_parse_desc_header(struct uvideo_softc *, const struct usb_descriptor *); static usb_error_t uvideo_vc_parse_desc_pu(struct uvideo_softc *, const struct usb_descriptor *); +static usb_error_t uvideo_vc_parse_desc_ct(struct uvideo_softc *, + const struct usb_descriptor *); +static int uvideo_has_ct_ctrl( + struct usb_video_camera_terminal_desc *, int); static usb_error_t uvideo_vc_get_ctrl(struct uvideo_softc *, uint8_t *, uint8_t, uint8_t, uint16_t, uint16_t); static usb_error_t uvideo_vc_set_ctrl(struct uvideo_softc *, uint8_t *, @@ -245,6 +249,11 @@ struct uvideo_softc { struct usb_video_vc_processing_desc *sc_desc_vc_pu_cur; struct usb_video_vc_processing_desc *sc_desc_vc_pu[UVIDEO_MAX_PU]; +#define UVIDEO_MAX_CT 8 + int sc_desc_vc_ct_num; + struct usb_video_camera_terminal_desc *sc_desc_vc_ct_cur; + struct usb_video_camera_terminal_desc *sc_desc_vc_ct[UVIDEO_MAX_CT]; + #define UVIDEO_MAX_FORMAT 8 int sc_fmtgrp_idx; int sc_fmtgrp_num; @@ -391,6 +400,88 @@ static struct uvideo_controls uvideo_ctrls[] = { 1, 0 }, + /* Camera Terminal Controls (UVC 1.5 spec Table A-12) */ + { + V4L2_CID_EXPOSURE_AUTO, + V4L2_CTRL_TYPE_MENU, + "Exposure, Auto", + 1, + CT_AE_MODE_CONTROL, + 1, + 0 + }, + { + V4L2_CID_EXPOSURE_AUTO_PRIORITY, + V4L2_CTRL_TYPE_BOOLEAN, + "Exposure, Auto Priority", + 2, + CT_AE_PRIORITY_CONTROL, + 1, + 0 + }, + { + V4L2_CID_EXPOSURE_ABSOLUTE, + V4L2_CTRL_TYPE_INTEGER, + "Exposure (Absolute)", + 3, + CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, + 4, + 0 + }, + { + V4L2_CID_FOCUS_ABSOLUTE, + V4L2_CTRL_TYPE_INTEGER, + "Focus (Absolute)", + 5, + CT_FOCUS_ABSOLUTE_CONTROL, + 2, + 0 + }, + { + V4L2_CID_FOCUS_AUTO, + V4L2_CTRL_TYPE_BOOLEAN, + "Focus, Auto", + 17, + CT_FOCUS_AUTO_CONTROL, + 1, + 0 + }, + { + V4L2_CID_ZOOM_ABSOLUTE, + V4L2_CTRL_TYPE_INTEGER, + "Zoom (Absolute)", + 9, + CT_ZOOM_ABSOLUTE_CONTROL, + 2, + 0 + }, + { + V4L2_CID_PAN_ABSOLUTE, + V4L2_CTRL_TYPE_INTEGER, + "Pan (Absolute)", + 11, + CT_PANTILT_ABSOLUTE_CONTROL, + 4, + 1 + }, + { + V4L2_CID_TILT_ABSOLUTE, + V4L2_CTRL_TYPE_INTEGER, + "Tilt (Absolute)", + 11, + CT_PANTILT_ABSOLUTE_CONTROL, + 4, + 1 + }, + { + V4L2_CID_PRIVACY, + V4L2_CTRL_TYPE_BOOLEAN, + "Privacy", + 18, + CT_PRIVACY_CONTROL, + 1, + 0 + }, { 0, 0, "", 0, 0, 0, 0 } }; @@ -824,6 +915,14 @@ uvideo_vc_parse_desc(struct uvideo_softc *sc) return (error); vc_header_found = 1; break; + case UDESCSUB_VC_INPUT_TERMINAL: + { + struct usb_video_input_terminal_desc *itd; + itd = (struct usb_video_input_terminal_desc *)desc; + if (UGETW(itd->wTerminalType) == ITT_CAMERA) + (void)uvideo_vc_parse_desc_ct(sc, desc); + break; + } case UDESCSUB_VC_PROCESSING_UNIT: (void)uvideo_vc_parse_desc_pu(sc, desc); break; @@ -883,6 +982,25 @@ uvideo_vc_parse_desc_pu(struct uvideo_softc *sc, return (USB_ERR_NORMAL_COMPLETION); } +static usb_error_t +uvideo_vc_parse_desc_ct(struct uvideo_softc *sc, + const struct usb_descriptor *desc) +{ + struct usb_video_camera_terminal_desc *d; + + d = __DECONST(struct usb_video_camera_terminal_desc *, desc); + + if (sc->sc_desc_vc_ct_num == UVIDEO_MAX_CT) { + device_printf(sc->sc_dev, "too many CT descriptors\n"); + return (USB_ERR_INVAL); + } + + sc->sc_desc_vc_ct[sc->sc_desc_vc_ct_num] = d; + sc->sc_desc_vc_ct_num++; + + return (USB_ERR_NORMAL_COMPLETION); +} + static usb_error_t uvideo_vc_get_ctrl(struct uvideo_softc *sc, uint8_t *ctrl_data, uint8_t request, uint8_t unitid, uint16_t ctrl_selector, uint16_t ctrl_len) @@ -934,8 +1052,8 @@ uvideo_find_ctrl(struct uvideo_softc *sc, int id) { int i, j, found; - if (sc->sc_desc_vc_pu_num == 0) { - DPRINTFN(1, "no processing unit descriptors found!\n"); + if (sc->sc_desc_vc_pu_num == 0 && sc->sc_desc_vc_ct_num == 0) { + DPRINTFN(1, "no PU or CT descriptors found!\n"); return (EINVAL); } @@ -951,19 +1069,34 @@ uvideo_find_ctrl(struct uvideo_softc *sc, int id) return (EINVAL); } - /* does the device support this control? */ + /* does a PU support this control? */ + sc->sc_desc_vc_pu_cur = NULL; + sc->sc_desc_vc_ct_cur = NULL; for (found = 0, j = 0; j < sc->sc_desc_vc_pu_num; j++) { if (uvideo_has_ctrl(sc->sc_desc_vc_pu[j], uvideo_ctrls[i].ctrl_bit) != 0) { found = 1; + sc->sc_desc_vc_pu_cur = sc->sc_desc_vc_pu[j]; break; } } + + /* does a CT support this control? */ + if (found == 0) { + for (j = 0; j < sc->sc_desc_vc_ct_num; j++) { + if (uvideo_has_ct_ctrl(sc->sc_desc_vc_ct[j], + uvideo_ctrls[i].ctrl_bit) != 0) { + found = 1; + sc->sc_desc_vc_ct_cur = sc->sc_desc_vc_ct[j]; + break; + } + } + } + if (found == 0) { DPRINTFN(1, "control not supported by device!\n"); return (EINVAL); } - sc->sc_desc_vc_pu_cur = sc->sc_desc_vc_pu[j]; return (i); } @@ -978,6 +1111,16 @@ uvideo_has_ctrl(struct usb_video_vc_processing_desc *desc, int ctrl_bit) return (desc->bmControls[byteof(ctrl_bit)] & bitof(ctrl_bit)); } +static int +uvideo_has_ct_ctrl(struct usb_video_camera_terminal_desc *desc, int ctrl_bit) +{ + + if (desc->bControlSize * 8 <= ctrl_bit) + return (0); + + return (desc->bmControls[byteof(ctrl_bit)] & bitof(ctrl_bit)); +} + static usb_error_t uvideo_vs_parse_desc(struct uvideo_softc *sc, struct usb_config_descriptor *cdesc) @@ -3353,13 +3496,19 @@ uvideo_queryctrl(struct uvideo_softc *sc, struct v4l2_queryctrl *qctrl) usb_error_t error; uint8_t *ctrl_data; uint16_t ctrl_len; + uint8_t unit_id; i = uvideo_find_ctrl(sc, qctrl->id); if (i == EINVAL) return (i); + if (sc->sc_desc_vc_ct_cur != NULL) + unit_id = sc->sc_desc_vc_ct_cur->bTerminalID; + else + unit_id = sc->sc_desc_vc_pu_cur->bUnitID; + ctrl_len = uvideo_ctrls[i].ctrl_len; - if (ctrl_len < 1 || ctrl_len > 2) { + if (ctrl_len < 1 || ctrl_len > 4) { device_printf(sc->sc_dev, "invalid control length: %d\n", ctrl_len); return (EINVAL); @@ -3374,7 +3523,7 @@ uvideo_queryctrl(struct uvideo_softc *sc, struct v4l2_queryctrl *qctrl) /* get minimum */ error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MIN, - sc->sc_desc_vc_pu_cur->bUnitID, + unit_id, uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len); if (error != USB_ERR_NORMAL_COMPLETION) { ret = EINVAL; @@ -3389,11 +3538,15 @@ uvideo_queryctrl(struct uvideo_softc *sc, struct v4l2_queryctrl *qctrl) qctrl->minimum = uvideo_ctrls[i].sig ? (int16_t)UGETW(ctrl_data) : UGETW(ctrl_data); break; + case 4: + qctrl->minimum = uvideo_ctrls[i].sig ? + (int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data); + break; } /* get maximum */ error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MAX, - sc->sc_desc_vc_pu_cur->bUnitID, + unit_id, uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len); if (error != USB_ERR_NORMAL_COMPLETION) { ret = EINVAL; @@ -3408,11 +3561,15 @@ uvideo_queryctrl(struct uvideo_softc *sc, struct v4l2_queryctrl *qctrl) qctrl->maximum = uvideo_ctrls[i].sig ? (int16_t)UGETW(ctrl_data) : UGETW(ctrl_data); break; + case 4: + qctrl->maximum = uvideo_ctrls[i].sig ? + (int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data); + break; } /* get resolution/step */ error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_RES, - sc->sc_desc_vc_pu_cur->bUnitID, + unit_id, uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len); if (error != USB_ERR_NORMAL_COMPLETION) { ret = EINVAL; @@ -3427,11 +3584,15 @@ uvideo_queryctrl(struct uvideo_softc *sc, struct v4l2_queryctrl *qctrl) qctrl->step = uvideo_ctrls[i].sig ? (int16_t)UGETW(ctrl_data) : UGETW(ctrl_data); break; + case 4: + qctrl->step = uvideo_ctrls[i].sig ? + (int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data); + break; } /* get default */ error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_DEF, - sc->sc_desc_vc_pu_cur->bUnitID, + unit_id, uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len); if (error != USB_ERR_NORMAL_COMPLETION) { ret = EINVAL; @@ -3446,6 +3607,10 @@ uvideo_queryctrl(struct uvideo_softc *sc, struct v4l2_queryctrl *qctrl) qctrl->default_value = uvideo_ctrls[i].sig ? (int16_t)UGETW(ctrl_data) : UGETW(ctrl_data); break; + case 4: + qctrl->default_value = uvideo_ctrls[i].sig ? + (int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data); + break; } qctrl->flags = 0; @@ -3462,13 +3627,19 @@ uvideo_g_ctrl(struct uvideo_softc *sc, struct v4l2_control *gctrl) usb_error_t error; uint8_t *ctrl_data; uint16_t ctrl_len; + uint8_t unit_id; i = uvideo_find_ctrl(sc, gctrl->id); if (i == EINVAL) return (i); + if (sc->sc_desc_vc_ct_cur != NULL) + unit_id = sc->sc_desc_vc_ct_cur->bTerminalID; + else + unit_id = sc->sc_desc_vc_pu_cur->bUnitID; + ctrl_len = uvideo_ctrls[i].ctrl_len; - if (ctrl_len < 1 || ctrl_len > 2) + if (ctrl_len < 1 || ctrl_len > 4) return (EINVAL); ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_ZERO); @@ -3476,7 +3647,7 @@ uvideo_g_ctrl(struct uvideo_softc *sc, struct v4l2_control *gctrl) return (ENOMEM); error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_CUR, - sc->sc_desc_vc_pu_cur->bUnitID, + unit_id, uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len); if (error != USB_ERR_NORMAL_COMPLETION) { ret = EINVAL; @@ -3491,6 +3662,10 @@ uvideo_g_ctrl(struct uvideo_softc *sc, struct v4l2_control *gctrl) gctrl->value = uvideo_ctrls[i].sig ? (int16_t)UGETW(ctrl_data) : UGETW(ctrl_data); break; + case 4: + gctrl->value = uvideo_ctrls[i].sig ? + (int32_t)UGETDW(ctrl_data) : UGETDW(ctrl_data); + break; } out: @@ -3505,13 +3680,19 @@ uvideo_s_ctrl(struct uvideo_softc *sc, struct v4l2_control *sctrl) usb_error_t error; uint8_t *ctrl_data; uint16_t ctrl_len; + uint8_t unit_id; i = uvideo_find_ctrl(sc, sctrl->id); if (i == EINVAL) return (i); + if (sc->sc_desc_vc_ct_cur != NULL) + unit_id = sc->sc_desc_vc_ct_cur->bTerminalID; + else + unit_id = sc->sc_desc_vc_pu_cur->bUnitID; + ctrl_len = uvideo_ctrls[i].ctrl_len; - if (ctrl_len < 1 || ctrl_len > 2) + if (ctrl_len < 1 || ctrl_len > 4) return (EINVAL); ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK | M_ZERO); @@ -3528,10 +3709,13 @@ uvideo_s_ctrl(struct uvideo_softc *sc, struct v4l2_control *sctrl) case 2: USETW(ctrl_data, sctrl->value); break; + case 4: + USETDW(ctrl_data, sctrl->value); + break; } error = uvideo_vc_set_ctrl(sc, ctrl_data, SET_CUR, - sc->sc_desc_vc_pu_cur->bUnitID, + unit_id, uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len); if (error != USB_ERR_NORMAL_COMPLETION) ret = EINVAL; diff --git a/sys/dev/usb/video/uvideo.h b/sys/dev/usb/video/uvideo.h index bccaf4cf0216..00e5118a65ae 100644 --- a/sys/dev/usb/video/uvideo.h +++ b/sys/dev/usb/video/uvideo.h @@ -211,7 +211,7 @@ struct usb_video_camera_terminal_desc { uWord wObjectiveFocalLengthMax; uWord wOcularFocalLength; uByte bControlSize; - uByte *bmControls; + uByte bmControls[255]; /* [bControlSize] */ } __packed; /* Table 3-8: VC Processing Unit Descriptor */ diff --git a/sys/dev/usb/video/uvideo_v4l2.h b/sys/dev/usb/video/uvideo_v4l2.h index 05736bff3e9c..6192ada9fbb6 100644 --- a/sys/dev/usb/video/uvideo_v4l2.h +++ b/sys/dev/usb/video/uvideo_v4l2.h @@ -453,6 +453,19 @@ struct v4l2_frmivalenum { #define V4L2_CID_SHARPNESS (V4L2_CID_BASE + 27) #define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE + 28) +#define V4L2_CID_CAMERA_CLASS_BASE 0x009a0000 +#define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE + 1) +#define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE + 2) +#define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE + 3) +#define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE + 4) +#define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE + 5) +#define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE + 8) +#define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE + 9) +#define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE + 12) +#define V4L2_CID_ZOOM_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE + 13) +#define V4L2_CID_ZOOM_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE + 15) +#define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE + 16) + /* * V4L2 ioctl definitions */