diff --git a/src/device/device.cc b/src/device/device.cc index 000e7c7..28afe38 100644 --- a/src/device/device.cc +++ b/src/device/device.cc @@ -6,6 +6,7 @@ #include #include "device/device_s.h" +#include "internal/channels.h" #include "internal/config.h" #include "internal/streams.h" #include "internal/strings.h" @@ -19,7 +20,8 @@ Device::Device(const Model &model, std::shared_ptr device) motion_tracking_(false), model_(model), device_(device), - streams_(nullptr) { + streams_(nullptr), + channels_(std::make_shared(device)) { VLOG(2) << __func__; ReadDeviceInfo(); } diff --git a/src/device/device.h b/src/device/device.h index 8d03c73..f2e3a03 100644 --- a/src/device/device.h +++ b/src/device/device.h @@ -23,6 +23,7 @@ struct device; struct DeviceInfo; +class Channels; class Streams; class Device { @@ -115,6 +116,8 @@ class Device { std::mutex mtx_streams_; + std::shared_ptr channels_; + void ReadDeviceInfo(); void WriteImgIntrinsics(const ImgIntrinsics &intrinsics); diff --git a/src/internal/channels.cc b/src/internal/channels.cc index b386a48..5b99b43 100644 --- a/src/internal/channels.cc +++ b/src/internal/channels.cc @@ -2,8 +2,6 @@ #include -#include "uvc/uvc.h" - MYNTEYE_BEGIN_NAMESPACE Channels::Channels(std::shared_ptr device) : device_(device) { @@ -14,31 +12,16 @@ Channels::~Channels() { VLOG(2) << __func__; } -bool Channels::ControlQuery( - const uvc::xu &xu, uint8_t selector, const query_t &query, uint16_t size, +bool Channels::XuControlQuery( + uint8_t selector, uvc::xu_query query, uint16_t size, uint8_t *data) { + return XuControlQuery({3}, selector, query, size, data); +} + +bool Channels::XuControlQuery( + const uvc::xu &xu, uint8_t selector, uvc::xu_query query, uint16_t size, uint8_t *data) { CHECK_NOTNULL(device_); - uvc::xu_query code; - switch (query) { - case SET_CUR: - code = uvc::XU_SET_CUR; - break; - case GET_CUR: - code = uvc::XU_GET_CUR; - break; - case GET_MIN: - code = uvc::XU_GET_MIN; - break; - case GET_MAX: - code = uvc::XU_GET_MAX; - break; - case GET_DEF: - code = uvc::XU_GET_DEF; - break; - default: - LOG(FATAL) << "ControlQuery query code is unaccepted"; - } - return uvc::xu_control_query(*device_, xu, selector, code, size, data); + return uvc::xu_control_query(*device_, xu, selector, query, size, data); } MYNTEYE_END_NAMESPACE diff --git a/src/internal/channels.h b/src/internal/channels.h index 37c7833..467029d 100644 --- a/src/internal/channels.h +++ b/src/internal/channels.h @@ -2,9 +2,11 @@ #define MYNTEYE_INTERNAL_CHANNELS_H_ #pragma once +#include #include #include "mynteye/mynteye.h" +#include "uvc/uvc.h" MYNTEYE_BEGIN_NAMESPACE @@ -17,24 +19,34 @@ struct xu; class Channels { public: - typedef enum Query { - SET_CUR, - GET_CUR, - GET_MIN, - GET_MAX, - GET_DEF, - LAST - } query_t; + typedef enum Channel { + CHANNEL_CAM_CTRL = 0x0100, + CHANNEL_HALF_DUPLEX = 0x0200, + CHANNEL_IMU_WRITE = 0x0300, + CHANNEL_IMU_READ = 0x0400, + CHANNEL_FILE = 0x0500, + CHANNEL_LAST + } channel_t; + + typedef struct ControlInfo { + std::int32_t min; + std::int32_t max; + std::int32_t def; + } control_info_t; explicit Channels(std::shared_ptr device); ~Channels(); private: - bool ControlQuery( - const uvc::xu &xu, uint8_t selector, const query_t &query, uint16_t size, + bool XuControlQuery( + uint8_t selector, uvc::xu_query query, uint16_t size, uint8_t *data); + bool XuControlQuery( + const uvc::xu &xu, uint8_t selector, uvc::xu_query query, uint16_t size, uint8_t *data); std::shared_ptr device_; + + std::map control_infos_; }; MYNTEYE_END_NAMESPACE diff --git a/src/uvc/uvc-libuvc.cc b/src/uvc/uvc-libuvc.cc index 0e2caef..78fcca8 100644 --- a/src/uvc/uvc-libuvc.cc +++ b/src/uvc/uvc-libuvc.cc @@ -109,6 +109,28 @@ std::string get_video_name(const device &device) { return ""; } +bool pu_control_range( + const device &device, Option option, int32_t *min, int32_t *max, + int32_t *def) { + // TODO(JohnZhao) + UNUSED(device) + UNUSED(option) + UNUSED(min) + UNUSED(max) + UNUSED(def) + return false; +} + +bool pu_control_query( + const device &device, Option option, pu_query query, int32_t *value) { + // TODO(JohnZhao) + UNUSED(device) + UNUSED(option) + UNUSED(query) + UNUSED(value) + return false; +} + bool xu_control_query( const device &device, const xu &xu, uint8_t selector, xu_query query, uint16_t size, uint8_t *data) { diff --git a/src/uvc/uvc-v4l2.cc b/src/uvc/uvc-v4l2.cc index 6bf07b7..7ba88f5 100644 --- a/src/uvc/uvc-v4l2.cc +++ b/src/uvc/uvc-v4l2.cc @@ -192,12 +192,41 @@ struct device { } } + bool pu_control_range( + uint32_t id, int32_t *min, int32_t *max, int32_t *def) const { + struct v4l2_queryctrl query = {}; + query.id = id; + if (xioctl(fd, VIDIOC_QUERYCTRL, &query) < 0) { + LOG_ERROR(WARNING, "pu_control_range failed"); + return false; + } + if (min) + *min = query.minimum; + if (max) + *max = query.maximum; + if (def) + *def = query.default_value; + return true; + } + + bool pu_control_query(uint32_t id, int query, int32_t *value) const { + CHECK_NOTNULL(value); + struct v4l2_control control = {id, *value}; + if (xioctl(fd, query, &control) < 0) { + LOG_ERROR(WARNING, "pu_control_query failed"); + return false; + } + *value = control.value; + return true; + } + bool xu_control_query( const xu &xu, uint8_t selector, uint8_t query, uint16_t size, uint8_t *data) const { + CHECK_NOTNULL(data); uvc_xu_control_query q = {xu.unit, selector, query, size, data}; if (xioctl(fd, UVCIOC_CTRL_QUERY, &q) < 0) { - LOG_ERROR(WARNING, "UVCIOC_CTRL_QUERY failed"); + LOG_ERROR(WARNING, "xu_control_query failed"); return false; } return true; @@ -433,24 +462,60 @@ std::string get_video_name(const device &device) { return device.dev_name; } +static uint32_t get_cid(Option option) { + switch (option) { + case Option::GAIN: + return V4L2_CID_GAIN; + case Option::BRIGHTNESS: + return V4L2_CID_BRIGHTNESS; + case Option::CONTRAST: + return V4L2_CID_CONTRAST; + default: + LOG(FATAL) << "No v4l2 cid for " << option; + } +} + +bool pu_control_range( + const device &device, Option option, int32_t *min, int32_t *max, + int32_t *def) { + return device.pu_control_range(get_cid(option), min, max, def); +} + +bool pu_control_query( + const device &device, Option option, pu_query query, int32_t *value) { + int code; + switch (query) { + case PU_QUERY_SET: + code = VIDIOC_S_CTRL; + break; + case PU_QUERY_GET: + code = VIDIOC_G_CTRL; + break; + default: + LOG(ERROR) << "pu_control_query request code is unaccepted"; + return false; + } + return device.pu_control_query(get_cid(option), code, value); +} + bool xu_control_query( const device &device, const xu &xu, uint8_t selector, xu_query query, uint16_t size, uint8_t *data) { uint8_t code; switch (query) { - case XU_SET_CUR: + case XU_QUERY_SET: code = UVC_SET_CUR; break; - case XU_GET_CUR: + case XU_QUERY_GET: code = UVC_GET_CUR; break; - case XU_GET_MIN: + case XU_QUERY_MIN: code = UVC_GET_MIN; break; - case XU_GET_MAX: + case XU_QUERY_MAX: code = UVC_GET_MAX; break; - case XU_GET_DEF: + case XU_QUERY_DEF: code = UVC_GET_DEF; break; default: diff --git a/src/uvc/uvc.h b/src/uvc/uvc.h index 68c6942..62666c7 100644 --- a/src/uvc/uvc.h +++ b/src/uvc/uvc.h @@ -8,6 +8,7 @@ #include #include "mynteye/mynteye.h" +#include "mynteye/types.h" #define MYNTEYE_VID 0x04B4 #define MYNTEYE_PID 0x00F9 @@ -16,28 +17,24 @@ MYNTEYE_BEGIN_NAMESPACE namespace uvc { -/* -struct uvc_xu_control_query +typedef enum pu_query { + PU_QUERY_SET, // Set the value of a control + PU_QUERY_GET, // Get the value of a control + PU_QUERY_LAST +} pu_query; -__u8 unit Extension unit ID -__u8 selector Control selector -__u8 query Request code to send to the device -__u16 size Control data size (in bytes) -__u8 *data Control value -*/ - -// extension unit +// Extension Unit struct xu { - uint8_t unit = 3; + uint8_t unit; }; typedef enum xu_query { - XU_SET_CUR, // Set current value of the control - XU_GET_CUR, // Get current value of the control - XU_GET_MIN, // Get min value of the control - XU_GET_MAX, // Get max value of the control - XU_GET_DEF, // Get default value of the control - XU_LAST + XU_QUERY_SET, // Set current value of the control + XU_QUERY_GET, // Get current value of the control + XU_QUERY_MIN, // Get min value of the control + XU_QUERY_MAX, // Get max value of the control + XU_QUERY_DEF, // Get default value of the control + XU_QUERY_LAST } xu_query; struct context; // Opaque type representing access to the underlying UVC @@ -56,7 +53,17 @@ int get_product_id(const device &device); std::string get_video_name(const device &device); -// Access XU controls +// Access PU (Processing Unit) controls +inline bool is_pu_control(Option option) { + return option >= Option::GAIN && option <= Option::CONTRAST; +} +bool pu_control_range( + const device &device, Option option, int32_t *min, int32_t *max, + int32_t *def); +bool pu_control_query( + const device &device, Option option, pu_query query, int32_t *value); + +// Access XU (Extension Unit) controls bool xu_control_query( const device &device, const xu &xu, uint8_t selector, xu_query query, uint16_t size, uint8_t *data);