Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UVC device power #13082

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/ds/d400/d400-color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ namespace librealsense
info = color_devs_info[1];
else
info = color_devs_info.front();
auto uvcd = get_backend()->create_uvc_device( info );
auto & uvcd = environment::get_instance().get_uvc_device( info.unique_id );
if( ! uvcd )
{
uvcd = get_backend()->create_uvc_device( info );
environment::get_instance().set_uvc_device( info.unique_id, uvcd );
}
//auto ftr = std::unique_ptr<frame_timestamp_reader>(new global_timestamp_reader(std::move(d400_timestamp_reader_metadata), _tf_keeper, enable_global_time_option));
auto raw_color_ep = std::make_shared<uvc_sensor>("Raw RGB Camera",
uvcd,
Expand Down
12 changes: 10 additions & 2 deletions src/ds/d400/d400-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,8 +473,16 @@ namespace librealsense
using namespace ds;

std::vector<std::shared_ptr<platform::uvc_device>> depth_devices;
for (auto&& info : filter_by_mi(all_device_infos, 0)) // Filter just mi=0, DEPTH
depth_devices.push_back( get_backend()->create_uvc_device( info ) );
for( auto && info : filter_by_mi( all_device_infos, 0 ) ) // Filter just mi=0, DEPTH
{
auto & dev = environment::get_instance().get_uvc_device( info.unique_id );
if( !dev )
{
dev = get_backend()->create_uvc_device( info );
environment::get_instance().set_uvc_device( info.unique_id, dev );
}
depth_devices.push_back( dev );
}

std::unique_ptr< frame_timestamp_reader > timestamp_reader_backup( new ds_timestamp_reader() );
frame_timestamp_reader* timestamp_reader_from_metadata;
Expand Down
12 changes: 10 additions & 2 deletions src/ds/d400/d400-motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,16 @@ namespace librealsense
}

std::vector<std::shared_ptr<platform::uvc_device>> imu_devices;
for (auto&& info : filter_by_mi(all_uvc_infos, 4)) // Filter just mi=4, IMU
imu_devices.push_back( get_backend()->create_uvc_device( info ) );
for( auto && info : filter_by_mi( all_uvc_infos, 4 ) ) // Filter just mi=4, IMU
{
auto & dev = environment::get_instance().get_uvc_device( info.unique_id );
if( ! dev )
{
dev = get_backend()->create_uvc_device( info );
environment::get_instance().set_uvc_device( info.unique_id, dev );
}
imu_devices.push_back( dev );
}

std::unique_ptr< frame_timestamp_reader > timestamp_reader_backup( new ds_timestamp_reader() );
std::unique_ptr<frame_timestamp_reader> timestamp_reader_metadata(new ds_timestamp_reader_from_metadata_mipi_motion(std::move(timestamp_reader_backup)));
Expand Down
8 changes: 7 additions & 1 deletion src/ds/d500/d500-color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,15 @@ namespace librealsense
std::unique_ptr<frame_timestamp_reader> ds_timestamp_reader_metadata(new ds_timestamp_reader_from_metadata(std::move(ds_timestamp_reader_backup)));

auto enable_global_time_option = std::shared_ptr<global_time_option>(new global_time_option());
auto & dev = environment::get_instance().get_uvc_device( color_devs_info.front().unique_id );
if( ! dev )
{
dev = get_backend()->create_uvc_device( color_devs_info.front() );
environment::get_instance().set_uvc_device( color_devs_info.front().unique_id, dev );
}
auto raw_color_ep = std::make_shared< uvc_sensor >(
"Raw RGB Camera",
get_backend()->create_uvc_device( color_devs_info.front() ),
dev,
std::unique_ptr< frame_timestamp_reader >(
new global_timestamp_reader( std::move( ds_timestamp_reader_metadata ),
_tf_keeper,
Expand Down
10 changes: 9 additions & 1 deletion src/ds/d500/d500-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,15 @@ namespace librealsense

std::vector<std::shared_ptr<platform::uvc_device>> depth_devices;
for( auto & info : filter_by_mi( all_device_infos, 0 ) ) // Filter just mi=0, DEPTH
depth_devices.push_back( get_backend()->create_uvc_device( info ) );
{
auto & dev = environment::get_instance().get_uvc_device( info.unique_id );
if( ! dev )
{
dev = get_backend()->create_uvc_device( info );
environment::get_instance().set_uvc_device( info.unique_id, dev );
}
depth_devices.push_back( dev );
}

std::unique_ptr< frame_timestamp_reader > timestamp_reader_backup( new ds_timestamp_reader() );
std::unique_ptr<frame_timestamp_reader> timestamp_reader_metadata(new ds_timestamp_reader_from_metadata(std::move(timestamp_reader_backup)));
Expand Down
21 changes: 21 additions & 0 deletions src/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ namespace librealsense

};

namespace platform
{
class uvc_device;
}

class environment
{
Expand All @@ -108,6 +112,21 @@ namespace librealsense

int generate_stream_id() { return _stream_id.fetch_add(1); }

std::atomic< int > & get_device_power_counter( const std::string & uid )
{
return _uvc_device_to_power_counter[uid];
}

std::shared_ptr< platform::uvc_device > & get_uvc_device( const std::string & uvc_device_info_uid )
{
return _device_info_uid_to_uvc_device[uvc_device_info_uid];
}

void set_uvc_device( const std::string & uvc_device_info_uid, std::shared_ptr< platform::uvc_device > & device )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks OK but the device is NEVER removed! I don't think that's what we want.
We want it to be removed when the last reference to it is gone.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that not only is it never removed but if we have new info with the same ID then we'll use the old one. I don't know if this will ever happen - but it'd be worth checking.

{
_device_info_uid_to_uvc_device[uvc_device_info_uid] = device;
}

environment(const environment&) = delete;
environment(const environment&&) = delete;
environment operator=(const environment&) = delete;
Expand All @@ -116,6 +135,8 @@ namespace librealsense
private:
extrinsics_graph _extrinsics;
std::atomic<int> _stream_id;
std::map< std::string /*uid*/, std::atomic< int > /*counter*/ > _uvc_device_to_power_counter;
std::map< std::string /*uid*/, std::shared_ptr< platform::uvc_device > > _device_info_uid_to_uvc_device;

environment();
};
Expand Down
5 changes: 5 additions & 0 deletions src/linux/backend-v4l2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2167,6 +2167,11 @@ namespace librealsense
_named_mtx->unlock();
}

std::string v4l_uvc_device::get_device_unique_id() const
{
return std::to_string( _info.mi ) + _info.unique_id;
}

uint32_t v4l_uvc_device::get_cid(rs2_option option) const
{
switch(option)
Expand Down
4 changes: 3 additions & 1 deletion src/linux/backend-v4l2.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ namespace librealsense
void set_power_state(power_state state) override;
power_state get_power_state() const override { return _state; }

void init_xu(const extension_unit&) override {}
void register_xu( platform::extension_unit && xu ) override {}
void init_xu( const extension_unit & ) override {}
bool set_xu(const extension_unit& xu, uint8_t control, const uint8_t* data, int size) override;
bool get_xu(const extension_unit& xu, uint8_t control, uint8_t* data, int size) const override;
control_range get_xu_range(const extension_unit& xu, uint8_t control, int len) const override;
Expand All @@ -372,6 +373,7 @@ namespace librealsense
void unlock() const override;

std::string get_device_location() const override { return _device_path; }
virtual std::string get_device_unique_id() const override;
usb_spec get_usb_specification() const override { return _device_usb_spec; }

bool is_platform_jetson() const override {return false;}
Expand Down
72 changes: 63 additions & 9 deletions src/mf/mf-uvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ namespace librealsense

void wmf_uvc_device::init_xu(const extension_unit& xu)
{
LOG_ERROR( "wmf_uvc_device::init_xu start. UID = " << get_device_unique_id() << " this = " << this );
std::lock_guard< std::recursive_mutex > lock( _source_lock );
LOG_ERROR( "wmf_uvc_device::init_xu got lock" );
if (!_source)
throw std::runtime_error("Could not initialize extensions controls!");

Expand All @@ -280,11 +283,15 @@ namespace librealsense
CHECK_HR(unknown->QueryInterface(__uuidof(IKsControl),
reinterpret_cast<void **>(&ks_control)));
_ks_controls[xu.node] = ks_control;

LOG_ERROR( "wmf_uvc_device::init_xu finished. _ks_controls[" << xu.node << "] = " << ks_control );
}

bool wmf_uvc_device::set_xu(const extension_unit& xu, uint8_t ctrl, const uint8_t* data, int len)
{
auto ks_control = get_ks_control(xu);
LOG_ERROR( "wmf_uvc_device::set_xu start. UID = " << get_device_unique_id() << " this = " << this );
auto ks_control = get_ks_control( xu );
LOG_ERROR( "wmf_uvc_device::set_xu got ks_control " << ks_control << " for xu.node " << xu.node );

KSP_NODE node;
memset(&node, 0, sizeof(KSP_NODE));
Expand All @@ -306,7 +313,9 @@ namespace librealsense

bool wmf_uvc_device::get_xu(const extension_unit& xu, uint8_t ctrl, uint8_t* data, int len) const
{
auto ks_control = get_ks_control(xu);
LOG_ERROR( "wmf_uvc_device::get_xu start. UID = " << get_device_unique_id() << " this = " << this );
auto ks_control = get_ks_control( xu );
LOG_ERROR( "wmf_uvc_device::get_xu got ks_control " << ks_control << " for xu.node " << xu.node );

KSP_NODE node;
memset(&node, 0, sizeof(KSP_NODE));
Expand Down Expand Up @@ -397,7 +406,9 @@ namespace librealsense

control_range wmf_uvc_device::get_xu_range(const extension_unit& xu, uint8_t ctrl, int len) const
{
auto ks_control = get_ks_control(xu);
LOG_ERROR( "wmf_uvc_device::get_xu_range start. UID = " << get_device_unique_id() << " this = " << this );
auto ks_control = get_ks_control( xu );
LOG_ERROR( "wmf_uvc_device::get_xu_range got ks_control " << ks_control << " for xu.node " << xu.node );

/* get step, min and max values*/
KSP_NODE node;
Expand Down Expand Up @@ -502,11 +513,15 @@ namespace librealsense

bool wmf_uvc_device::get_pu(rs2_option opt, int32_t& value) const
{
LOG_ERROR( "wmf_uvc_device::get_pu for option " << opt << ". UID = " << get_device_unique_id() << " this = " << this );
long val = 0, flags = 0;
if ((opt == RS2_OPTION_EXPOSURE) || (opt == RS2_OPTION_ENABLE_AUTO_EXPOSURE))
{
auto hr = get_camera_control()->Get(CameraControl_Exposure, &val, &flags);
if (hr == DEVICE_NOT_READY_ERROR)
auto cam = get_camera_control();
LOG_ERROR( "wmf_uvc_device::get_pu get_camera_control returned " << cam );
auto hr = cam->Get(CameraControl_Exposure, &val, &flags);
LOG_ERROR( "wmf_uvc_device::get_pu Get result = " << std::hex << hr );
if( hr == DEVICE_NOT_READY_ERROR )
return false;

value = (opt == RS2_OPTION_EXPOSURE) ? to_100micros(val) : (flags == CameraControl_Flags_Auto);
Expand Down Expand Up @@ -549,6 +564,7 @@ namespace librealsense

bool wmf_uvc_device::set_pu(rs2_option opt, int value)
{
LOG_ERROR( "wmf_uvc_device::set_pu for option " << opt << ". UID = " << get_device_unique_id() << " this = " << this );
if (opt == RS2_OPTION_EXPOSURE)
{
auto hr = get_camera_control()->Set(CameraControl_Exposure, from_100micros(value), CameraControl_Flags_Manual);
Expand Down Expand Up @@ -684,6 +700,7 @@ namespace librealsense

control_range wmf_uvc_device::get_pu_range(rs2_option opt) const
{
LOG_ERROR( "wmf_uvc_device::get_pu_range for option " << opt << ". UID = " << get_device_unique_id() << " this = " << this );
if (opt == RS2_OPTION_ENABLE_AUTO_EXPOSURE ||
opt == RS2_OPTION_ENABLE_AUTO_WHITE_BALANCE)
{
Expand Down Expand Up @@ -789,7 +806,8 @@ namespace librealsense
_systemwide_lock(info.unique_id.c_str(), WAIT_FOR_MUTEX_TIME_OUT),
_location(""), _device_usb_spec(usb3_type)
{
if (!is_connected(info))
LOG_ERROR( "wmf_uvc_device::wmf_uvc_device. this = " << this );
if( ! is_connected( info ) )
{
throw std::runtime_error("Camera not connected!");
}
Expand Down Expand Up @@ -818,7 +836,9 @@ namespace librealsense

wmf_uvc_device::~wmf_uvc_device()
{
try {
LOG_ERROR( "wmf_uvc_device::~wmf_uvc_device. this = " << this );
try
{
if (_streaming)
{
flush(MF_SOURCE_READER_ALL_STREAMS);
Expand Down Expand Up @@ -862,6 +882,10 @@ namespace librealsense

void wmf_uvc_device::set_d0()
{
LOG_ERROR( "wmf_uvc_device::set_d0 start. UID = " << get_device_unique_id() << " this = " << this );
std::lock_guard< std::recursive_mutex > lock( _source_lock );
LOG_ERROR( "wmf_uvc_device::set_d0 got lock" );

if (!_device_attrs)
_device_attrs = create_device_attrs();

Expand All @@ -872,9 +896,11 @@ namespace librealsense
//enable source
CHECK_HR(MFCreateDeviceSource(_device_attrs, &_source));
LOG_HR(_source->QueryInterface(__uuidof(IAMCameraControl), reinterpret_cast<void **>(&_camera_control)));
LOG_ERROR( "wmf_uvc_device::set_d0 _camera_control = " << _camera_control << " _camera_control.p = " << _camera_control.p);
// The IAMVideoProcAmp interface adjusts the qualities of an incoming video signal, such as brightness,
// contrast, hue, saturation, gamma, and sharpness.
auto hr = _source->QueryInterface( __uuidof( IAMVideoProcAmp ), reinterpret_cast< void ** >( &_video_proc ) );
LOG_ERROR( "wmf_uvc_device::set_d0 _video_proc = " << _video_proc << " _video_proc.p = " << _video_proc.p);
// E_NOINTERFACE is expected... especially when no video camera
if( hr != E_NOINTERFACE )
LOG_HR_STR( "QueryInterface(IAMVideoProcAmp)", hr );
Expand All @@ -883,10 +909,19 @@ namespace librealsense
CHECK_HR(MFCreateSourceReaderFromMediaSource(_source, _reader_attrs, &_reader));
CHECK_HR(_reader->SetStreamSelection(static_cast<DWORD>(MF_SOURCE_READER_ALL_STREAMS), TRUE));
_power_state = D0;

for( auto && xu : _xus )
init_xu( xu );

LOG_ERROR( "wmf_uvc_device::set_d0 finished" );
}

void wmf_uvc_device::set_d3()
{
LOG_ERROR( "wmf_uvc_device::set_d3 start. UID = " << get_device_unique_id() << " this = " << this );
std::lock_guard< std::recursive_mutex > lock( _source_lock );
LOG_ERROR( "wmf_uvc_device::set_d3 got lock" );

safe_release(_camera_control);
safe_release(_video_proc);
safe_release(_reader);
Expand All @@ -895,6 +930,8 @@ namespace librealsense
for (auto& elem : _streams)
elem.callback = nullptr;
_power_state = D3;

LOG_ERROR( "wmf_uvc_device::set_d3 finished" );
}

void wmf_uvc_device::foreach_profile(std::function<void(const mf_profile& profile, CComPtr<IMFMediaType> media_type, bool& quit)> action) const
Expand Down Expand Up @@ -1053,8 +1090,14 @@ namespace librealsense
_frame_callbacks.push_back(callback);
}

std::string wmf_uvc_device::get_device_unique_id() const
{
return std::to_string( _info.mi ) + _info.unique_id;
}

IAMVideoProcAmp* wmf_uvc_device::get_video_proc() const
{
LOG_ERROR( "wmf_uvc_device::get_video_proc _video_proc = " << _video_proc << " _video_proc.p = " << _video_proc.p);
if (get_power_state() != D0)
throw std::runtime_error("Device must be powered to query video_proc!");
if (!_video_proc.p)
Expand All @@ -1064,6 +1107,8 @@ namespace librealsense

IAMCameraControl* wmf_uvc_device::get_camera_control() const
{
LOG_ERROR( "wmf_uvc_device::get_camera_control _camera_control = " << _camera_control << " _camera_control.p = " << _camera_control.p);

if (get_power_state() != D0)
throw std::runtime_error("Device must be powered to query camera_control!");
if (!_camera_control.p)
Expand Down Expand Up @@ -1202,5 +1247,14 @@ namespace librealsense
_profiles.clear();
_frame_callbacks.clear();
}
}
}

power_state wmf_uvc_device::get_power_state() const
{
LOG_ERROR( "wmf_uvc_device::get_power_state start. UID = " << get_device_unique_id() << " this = " << this );
std::lock_guard< std::recursive_mutex > lock( _source_lock );
std::string tmp = _source ? "D0" : "D3";
LOG_ERROR( "wmf_uvc_device::get_power_state got lock. power state is " << tmp );
return _source ? D0 : D3;
}
} //namespace platform
} //namespace librealsense
9 changes: 6 additions & 3 deletions src/mf/mf-uvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,14 @@ namespace librealsense
void stop_callbacks() override;
void close(stream_profile profile) override;
void set_power_state(power_state state) override;
power_state get_power_state() const override { return _power_state; }
power_state get_power_state() const override;
std::vector<stream_profile> get_profiles() const override;

static bool is_connected(const uvc_device_info& info);
static void foreach_uvc_device(enumeration_callback action);

void init_xu(const extension_unit& xu) override;
void register_xu( platform::extension_unit && xu ) override { _xus.push_back( std::move( xu ) ); }
void init_xu( const extension_unit & xu ) override;
bool set_xu(const extension_unit& xu, uint8_t ctrl, const uint8_t* data, int len) override;
bool get_xu(const extension_unit& xu, uint8_t ctrl, uint8_t* data, int len) const override;
control_range get_xu_range(const extension_unit& xu, uint8_t ctrl, int len) const override;
Expand All @@ -94,6 +95,7 @@ namespace librealsense
bool is_platform_jetson() const override { return false;}

std::string get_device_location() const override { return _location; }
std::string get_device_unique_id() const override;
usb_spec get_usb_specification() const override { return _device_usb_spec; }
IAMVideoProcAmp* get_video_proc() const;
IAMCameraControl* get_camera_control() const;
Expand Down Expand Up @@ -136,7 +138,7 @@ namespace librealsense
uint16_t _streamIndex;
std::vector<profile_and_callback> _streams;
std::mutex _streams_mutex;

mutable std::recursive_mutex _source_lock;
named_mutex _systemwide_lock;
std::string _location;
usb_spec _device_usb_spec;
Expand All @@ -146,6 +148,7 @@ namespace librealsense
bool _streaming = false;
std::atomic<bool> _is_started = false;
std::wstring _device_id;
std::vector< platform::extension_unit > _xus;
};

class source_reader_callback : public IMFSourceReaderCallback
Expand Down
Loading
Loading