From patchwork Tue Apr 13 07:50:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hirokazu Honda X-Patchwork-Id: 11901 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 39E44BD224 for ; Tue, 13 Apr 2021 07:50:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E5D2C687F4; Tue, 13 Apr 2021 09:50:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="cqXgrn7R"; dkim-atps=neutral Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E55B687F3 for ; Tue, 13 Apr 2021 09:50:28 +0200 (CEST) Received: by mail-pl1-x62a.google.com with SMTP id u7so5954292plr.6 for ; Tue, 13 Apr 2021 00:50:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MAtwUFk5YBMKGPW17l5Cri2kGo7Z4b7JfXgabycfy1c=; b=cqXgrn7RMo1C+moOSwJSu2xxQwlYOjcm6xBRKiDDsb8WplO7WGhSnxDfUJ5irOi4Kv 7AclWc/iITMjYWItKP/IH+YtpZf5U3oVcp/tmjHDYTaRRpVVfiM9vNFmJdWAGof275fy CjkZVHwGOYmG2T9VUTNUcoH6yoOE5ekTic/o8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MAtwUFk5YBMKGPW17l5Cri2kGo7Z4b7JfXgabycfy1c=; b=js2+i+veNTJJO/PZEL8CPnaz6xcUFU1NYCrOTNtDfyTvrANH9vx5FW2Tg/1V5qmUgD hsuEcDxASB2yGOjbu77qm7450mjajPERZyGwPsvb9i8hGCLgtql9CRD7q/w99PI7GafR 9pozDJXvWrT3YqW6Dce0Ovoa6hQOA2aNXpzzfWZxVrqGt38yecIyrd2/ql4L6bwImXQl HX9T7F0q/SB5iylQWyd9Fyf+nxNyxvwcwyUbHn7o1Lc5jwh8AmqQmUUwr8bNJ47cHIiI rTCiAVARacenHof6IXRJ/6nt2WxH/gpNx50CwIg5J2lfJL1sACfhb2CMq4FNuW3Fabzi uR6w== X-Gm-Message-State: AOAM531AHu/K9iKUzukp7/nHeW9XucWzJgJ8UCr0adGloCSqig4ezwcd ADDsc9K/T1ncbdHyRa82sshk8IPvii8stg== X-Google-Smtp-Source: ABdhPJwPvkewKroQmBBlT2acqbck/uV1EHpkepfWORUyUi7Q/VTX9JJWO8GtnGnq8fzG1wFiZLkIBg== X-Received: by 2002:a17:90a:9512:: with SMTP id t18mr3402540pjo.44.1618300226779; Tue, 13 Apr 2021 00:50:26 -0700 (PDT) Received: from hiroh2.tok.corp.google.com ([2401:fa00:8f:2:84f5:7981:dfbe:8f02]) by smtp.gmail.com with ESMTPSA id n25sm11525125pff.154.2021.04.13.00.50.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Apr 2021 00:50:26 -0700 (PDT) From: Hirokazu Honda To: libcamera-devel@lists.libcamera.org Date: Tue, 13 Apr 2021 16:50:10 +0900 Message-Id: <20210413075013.3069213-3-hiroh@chromium.org> X-Mailer: git-send-email 2.31.1.295.g9ea45b61b8-goog In-Reply-To: <20210413075013.3069213-1-hiroh@chromium.org> References: <20210413075013.3069213-1-hiroh@chromium.org> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH v2 2/5] libcamera: V4L2Device: Support v4l2 menu control X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jmondi@jacopo.org Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This adds a support of v4l2 menu. Signed-off-by: Hirokazu Honda --- include/libcamera/internal/v4l2_controls.h | 1 + include/libcamera/internal/v4l2_device.h | 3 + src/libcamera/v4l2_controls.cpp | 10 +- src/libcamera/v4l2_device.cpp | 104 ++++++++++++++++++++- 4 files changed, 112 insertions(+), 6 deletions(-) diff --git a/include/libcamera/internal/v4l2_controls.h b/include/libcamera/internal/v4l2_controls.h index 0851b8dd..c42f2529 100644 --- a/include/libcamera/internal/v4l2_controls.h +++ b/include/libcamera/internal/v4l2_controls.h @@ -24,6 +24,7 @@ class V4L2ControlInfo : public ControlInfo { public: V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl); + V4L2ControlInfo(const ControlInfo &ctrl); }; } /* namespace libcamera */ diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h index 4cce3840..2436a83c 100644 --- a/include/libcamera/internal/v4l2_device.h +++ b/include/libcamera/internal/v4l2_device.h @@ -53,6 +53,9 @@ protected: int fd() const { return fd_; } private: + bool createV4L2ControlInfoForMenu(const v4l2_query_ext_ctrl &ctrl, + V4L2ControlInfo &v4l2CtrlInfo); + void listControls(); void updateControls(ControlList *ctrls, const std::vector &v4l2Ctrls); diff --git a/src/libcamera/v4l2_controls.cpp b/src/libcamera/v4l2_controls.cpp index 3f8ec6ca..2c965cfa 100644 --- a/src/libcamera/v4l2_controls.cpp +++ b/src/libcamera/v4l2_controls.cpp @@ -73,9 +73,12 @@ ControlType v4l2_ctrl_type(const struct v4l2_query_ext_ctrl &ctrl) return ControlTypeInteger64; case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER_MENU: + return ControlTypeMenu; + case V4L2_CTRL_TYPE_BUTTON: case V4L2_CTRL_TYPE_BITMASK: - case V4L2_CTRL_TYPE_INTEGER_MENU: + /* * More precise types may be needed, for now use a 32-bit * integer type. @@ -148,4 +151,9 @@ V4L2ControlInfo::V4L2ControlInfo(const struct v4l2_query_ext_ctrl &ctrl) } } +V4L2ControlInfo::V4L2ControlInfo(const ControlInfo &ctrl) + : ControlInfo(ctrl) +{ +} + } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 8f29cd7f..7fbca8b1 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -459,6 +460,60 @@ int V4L2Device::ioctl(unsigned long request, void *argp) * \return The device node path */ +bool V4L2Device::createV4L2ControlInfoForMenu(const v4l2_query_ext_ctrl &ctrl, + V4L2ControlInfo &v4l2CtrlInfo) +{ + ASSERT(ctrl.type == V4L2_CTRL_TYPE_MENU || + ctrl.type == V4L2_CTRL_TYPE_INTEGER_MENU); + bool isName = false; + switch (ctrl.id) { + case V4L2_CID_TEST_PATTERN: + case V4L2_CID_INTEL_IPU3_MODE: + isName = true; + break; + case V4L2_CID_LINK_FREQ: + isName = false; + break; + default: + LOG(V4L2, Error) << "Unsupported menu: " << ctrl.name + << " (" << utils::hex(ctrl.id) << ")"; + return false; + } + + std::vector values; + v4l2_querymenu menu; + memset(&menu, 0, sizeof(menu)); + menu.id = ctrl.id; + for (menu.index = ctrl.minimum; + static_cast(menu.index) <= ctrl.maximum; menu.index++) { + if (ioctl(VIDIOC_QUERYMENU, &menu) != 0) + continue; + ControlMenu ctrlMenu; + ctrlMenu.index = static_cast(menu.index); + ctrlMenu.isName = isName; + if (isName) { + strcpy(ctrlMenu.name, + reinterpret_cast(menu.name)); + } else { + ctrlMenu.value = menu.value; + } + + values.push_back(ControlValue(ctrlMenu)); + } + + if (values.empty()) { + LOG(V4L2, Error) + << "No applicable value: " << utils::hex(ctrl.id); + return false; + } + + v4l2CtrlInfo = V4L2ControlInfo( + ControlInfo(libcamera::Span( + values.data(), values.size()))); + + return true; +} + /** * \fn V4L2Device::fd() * \brief Retrieve the V4L2 device file descriptor @@ -474,7 +529,6 @@ void V4L2Device::listControls() ControlInfoMap::Map ctrls; struct v4l2_query_ext_ctrl ctrl = {}; - /* \todo Add support for menu controls. */ while (1) { ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; @@ -485,15 +539,20 @@ void V4L2Device::listControls() ctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue; + V4L2ControlInfo v4l2CtrlInfo(ControlInfo(0)); switch (ctrl.type) { case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_BUTTON: case V4L2_CTRL_TYPE_INTEGER64: case V4L2_CTRL_TYPE_BITMASK: - case V4L2_CTRL_TYPE_INTEGER_MENU: case V4L2_CTRL_TYPE_U8: + v4l2CtrlInfo = V4L2ControlInfo(ctrl); + break; + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER_MENU: + if (!createV4L2ControlInfoForMenu(ctrl, v4l2CtrlInfo)) + continue; break; /* \todo Support other control types. */ default: @@ -503,10 +562,13 @@ void V4L2Device::listControls() continue; } + LOG(V4L2, Debug) << "Control: " << ctrl.name + << " (" << utils::hex(ctrl.id) << ")"; + controlIds_.emplace_back(std::make_unique(ctrl)); controlInfo_.emplace(ctrl.id, ctrl); - ctrls.emplace(controlIds_.back().get(), V4L2ControlInfo(ctrl)); + ctrls.emplace(controlIds_.back().get(), std::move(v4l2CtrlInfo)); } controls_ = std::move(ctrls); @@ -539,7 +601,39 @@ void V4L2Device::updateControls(ControlList *ctrls, case ControlTypeInteger64: newValue.set(v4l2Ctrl.value64); break; - + case ControlTypeMenu: + switch (v4l2Ctrl.id) { + case V4L2_CID_TEST_PATTERN: { + ControlMenu menu; + menu.index = v4l2Ctrl.value; + menu.isName = true; + + bool found = false; + for (const ControlValue &validValue : it->second.values()) { + const auto &ctrlMenu = validValue.get(); + if (!ctrlMenu.isName) + continue; + if (menu.index == ctrlMenu.index) { + strcpy(menu.name, ctrlMenu.name); + found = true; + break; + } + } + + if (!found) { + LOG(V4L2, Error) + << "Matched value is not found" + << ", index=" << menu.index; + continue; + } + + newValue.set(menu); + break; + } + default: + LOG(V4L2, Error) << "Unknown id: " << v4l2Ctrl.id; + break; + } case ControlTypeByte: /* * No action required, the VIDIOC_[GS]_EXT_CTRLS ioctl