diff --git a/src/UsbCameraImpl.cpp b/src/UsbCameraImpl.cpp index c7ffda67fc..4dc35146f4 100644 --- a/src/UsbCameraImpl.cpp +++ b/src/UsbCameraImpl.cpp @@ -107,48 +107,6 @@ int UsbCameraImpl::PercentageToRaw(const UsbCameraProperty& rawProp, (rawProp.maximum - rawProp.minimum) * (percentValue / 100.0); } -static std::unique_ptr ExtCtrlIoctl(int fd, __u32* id) { - int rc; - std::unique_ptr prop; -#ifdef VIDIOC_QUERY_EXT_CTRL - v4l2_query_ext_ctrl qc_ext; - std::memset(&qc_ext, 0, sizeof(qc_ext)); - qc_ext.id = *id; - rc = TryIoctl(fd, VIDIOC_QUERY_EXT_CTRL, &qc_ext); - if (rc == 0) { - *id = qc_ext.id; // copy back - // We don't support array types - if (qc_ext.elems > 1 || qc_ext.nr_of_dims > 0) return nullptr; - prop = llvm::make_unique(qc_ext); - } -#endif - if (!prop) { - // Fall back to normal QUERYCTRL - struct v4l2_queryctrl qc; - std::memset(&qc, 0, sizeof(qc)); - qc.id = *id; - rc = TryIoctl(fd, VIDIOC_QUERYCTRL, &qc); - *id = qc.id; // copy back - if (rc != 0) return nullptr; - prop = llvm::make_unique(qc); - } - - // Cache enum property choices - if (prop->propKind == CS_PROP_ENUM) { - prop->enumChoices.resize(prop->maximum + 1); - v4l2_querymenu qmenu; - std::memset(&qmenu, 0, sizeof(qmenu)); - qmenu.id = *id; - for (int i = prop->minimum; i <= prop->maximum; ++i) { - qmenu.index = static_cast<__u32>(i); - if (TryIoctl(fd, VIDIOC_QUERYMENU, &qmenu) != 0) continue; - prop->enumChoices[i] = reinterpret_cast(qmenu.name); - } - } - - return prop; -} - static bool GetDescriptionSysV4L(llvm::StringRef path, std::string* desc) { llvm::SmallString<64> ifpath{"/sys/class/video4linux/"}; ifpath += path.substr(5); @@ -1012,7 +970,7 @@ void UsbCameraImpl::DeviceCacheProperties() { ; __u32 id = nextFlags; - while (auto prop = ExtCtrlIoctl(fd, &id)) { + while (auto prop = UsbCameraProperty::DeviceQuery(fd, &id)) { DeviceCacheProperty(std::move(prop)); id |= nextFlags; } @@ -1020,12 +978,13 @@ void UsbCameraImpl::DeviceCacheProperties() { if (id == nextFlags) { // try just enumerating standard... for (id = V4L2_CID_BASE; id < V4L2_CID_LASTP1; ++id) { - if (auto prop = ExtCtrlIoctl(fd, &id)) + if (auto prop = UsbCameraProperty::DeviceQuery(fd, &id)) DeviceCacheProperty(std::move(prop)); } // ... and custom controls std::unique_ptr prop; - for (id = V4L2_CID_PRIVATE_BASE; (prop = ExtCtrlIoctl(fd, &id)); ++id) + for (id = V4L2_CID_PRIVATE_BASE; + (prop = UsbCameraProperty::DeviceQuery(fd, &id)); ++id) DeviceCacheProperty(std::move(prop)); } } diff --git a/src/UsbCameraProperty.cpp b/src/UsbCameraProperty.cpp index 848d15fbe4..43456f0e10 100644 --- a/src/UsbCameraProperty.cpp +++ b/src/UsbCameraProperty.cpp @@ -8,6 +8,7 @@ #include "UsbCameraProperty.h" #include "llvm/SmallString.h" +#include "llvm/STLExtras.h" #include "UsbUtil.h" @@ -202,6 +203,49 @@ UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl) llvm::StringRef(reinterpret_cast(ctrl.name), len), name_buf); } +std::unique_ptr UsbCameraProperty::DeviceQuery(int fd, + __u32* id) { + int rc; + std::unique_ptr prop; +#ifdef VIDIOC_QUERY_EXT_CTRL + v4l2_query_ext_ctrl qc_ext; + std::memset(&qc_ext, 0, sizeof(qc_ext)); + qc_ext.id = *id; + rc = TryIoctl(fd, VIDIOC_QUERY_EXT_CTRL, &qc_ext); + if (rc == 0) { + *id = qc_ext.id; // copy back + // We don't support array types + if (qc_ext.elems > 1 || qc_ext.nr_of_dims > 0) return nullptr; + prop = llvm::make_unique(qc_ext); + } +#endif + if (!prop) { + // Fall back to normal QUERYCTRL + struct v4l2_queryctrl qc; + std::memset(&qc, 0, sizeof(qc)); + qc.id = *id; + rc = TryIoctl(fd, VIDIOC_QUERYCTRL, &qc); + *id = qc.id; // copy back + if (rc != 0) return nullptr; + prop = llvm::make_unique(qc); + } + + // Cache enum property choices + if (prop->propKind == CS_PROP_ENUM) { + prop->enumChoices.resize(prop->maximum + 1); + v4l2_querymenu qmenu; + std::memset(&qmenu, 0, sizeof(qmenu)); + qmenu.id = *id; + for (int i = prop->minimum; i <= prop->maximum; ++i) { + qmenu.index = static_cast<__u32>(i); + if (TryIoctl(fd, VIDIOC_QUERYMENU, &qmenu) != 0) continue; + prop->enumChoices[i] = reinterpret_cast(qmenu.name); + } + } + + return prop; +} + bool UsbCameraProperty::DeviceGet(std::unique_lock& lock, int fd) { if (fd < 0) return true; unsigned idCopy = id; diff --git a/src/UsbCameraProperty.h b/src/UsbCameraProperty.h index eae9480495..502f0a65b4 100644 --- a/src/UsbCameraProperty.h +++ b/src/UsbCameraProperty.h @@ -8,6 +8,7 @@ #ifndef CS_USBCAMERAPROPERTY_H_ #define CS_USBCAMERAPROPERTY_H_ +#include #include #ifdef __linux__ @@ -45,6 +46,8 @@ class UsbCameraProperty : public PropertyImpl { #endif UsbCameraProperty(const struct v4l2_queryctrl& ctrl); + static std::unique_ptr DeviceQuery(int fd, __u32* id); + bool DeviceGet(std::unique_lock& lock, int fd); bool DeviceSet(std::unique_lock& lock, int fd) const; bool DeviceSet(std::unique_lock& lock, int fd, int newValue,