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

Power uvc_device for 1 second after creation #13618

Draft
wants to merge 3 commits into
base: development
Choose a base branch
from
Draft
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
3 changes: 3 additions & 0 deletions src/ds/d400/d400-color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ namespace librealsense
std::unique_ptr<frame_timestamp_reader>(new global_timestamp_reader(std::move(ds_timestamp_reader_metadata), _tf_keeper, enable_global_time_option)),
this);

// Many commands need power during initialization phase, no point turning it on and off again for each.
raw_color_ep->power_for_duration( std::chrono::milliseconds( 1000 ) );

auto color_ep = std::make_shared<d400_color_sensor>(this,
raw_color_ep,
d400_color_fourcc_to_rs2_format,
Expand Down
3 changes: 3 additions & 0 deletions src/ds/d400/d400-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,9 @@ namespace librealsense

raw_depth_ep->register_xu(depth_xu); // make sure the XU is initialized every time we power the camera

// Many commands need power during initialization phase, no point turning it on and off again for each.
raw_depth_ep->power_for_duration( std::chrono::milliseconds( 1000 ) );
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved

auto depth_ep = std::make_shared<d400_depth_sensor>(this, raw_depth_ep);

depth_ep->register_info(RS2_CAMERA_INFO_PHYSICAL_PORT, filter_by_mi(all_device_infos, 0).front().device_path);
Expand Down
3 changes: 3 additions & 0 deletions src/ds/d500/d500-color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ namespace librealsense
enable_global_time_option ) ),
this );

// Many commands need power during initialization phase, no point turning it on and off again for each.
raw_color_ep->power_for_duration( std::chrono::milliseconds( 1000 ) );

auto color_ep = std::make_shared<d500_color_sensor>(this,
raw_color_ep,
d500_color_fourcc_to_rs2_format,
Expand Down
3 changes: 3 additions & 0 deletions src/ds/d500/d500-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,9 @@ namespace librealsense

raw_depth_ep->register_xu(depth_xu); // make sure the XU is initialized every time we power the camera

// Many commands need power during initialization phase, no point turning it on and off again for each.
raw_depth_ep->power_for_duration( std::chrono::milliseconds( 1000 ) );

auto depth_ep = std::make_shared<d500_depth_sensor>(this, raw_depth_ep);

depth_ep->register_info(RS2_CAMERA_INFO_PHYSICAL_PORT, filter_by_mi(all_device_infos, 0).front().device_path);
Expand Down
42 changes: 36 additions & 6 deletions src/linux/backend-v4l2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,8 @@ namespace librealsense
}

v4l_uvc_device::v4l_uvc_device(const uvc_device_info& info, bool use_memory_map)
: _name(info.id),
: _power_counter( 0 ),
_name(info.id),
_device_path(info.device_path),
_device_usb_spec(info.conn_spec),
_info(info),
Expand Down Expand Up @@ -1814,15 +1815,44 @@ namespace librealsense

void v4l_uvc_device::set_power_state(power_state state)
{
if (state == D0 && _state == D3)
std::lock_guard< std::recursive_mutex > lock( _power_lock );
switch (state)
{
map_device_descriptor();
case D0:
{
if( _power_counter.fetch_add( 1 ) == 0 )
{
try
{
map_device_descriptor();
}
//In case of failure need to decrease use counter
catch( std::exception const & e )
{
_power_counter.fetch_add( -1 );
throw e;
}
catch( ... )
{
_power_counter.fetch_add( -1 );
throw;
}
}
break;
}
if (state == D3 && _state == D0)
case D3:
{
close(_profile);
unmap_device_descriptor();
if( _power_counter.fetch_add( -1 ) == 1 )
{
close(_profile);
unmap_device_descriptor();
}
break;
}
default:
throw std::runtime_error("illegal power state request");
}

_state = state;
}

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,7 @@ 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 {}
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 Down Expand Up @@ -407,6 +407,8 @@ namespace librealsense

static bool get_devname_from_video_path(const std::string& real_path, std::string& devname);

std::recursive_mutex _power_lock;
std::atomic< int > _power_counter;
power_state _state = D3;
std::string _name = "";
std::string _device_path = "";
Expand Down
68 changes: 55 additions & 13 deletions src/mf/mf-uvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -773,23 +773,55 @@ namespace librealsense

void wmf_uvc_device::set_power_state(power_state state)
{
if (state == _power_state)
return;
std::lock_guard< std::recursive_mutex > lock( _source_lock );

switch (state)
{
case D0: set_d0(); break;
case D3: set_d3(); break;
case D0:
{
if( _power_counter.fetch_add( 1 ) == 0 )
{
try
{
set_d0();
}
//In case of failure need to decrease use counter
catch( std::exception const & e )
{
_power_counter.fetch_add( -1 );
throw e;
}
catch( ... )
{
_power_counter.fetch_add( -1 );
throw;
}
}
break;
}
case D3:
{
if( _power_counter.fetch_add( -1 ) == 1 )
{
set_d3();
}
break;
}
default:
throw std::runtime_error("illegal power state request");
}
}

wmf_uvc_device::wmf_uvc_device(const uvc_device_info& info,
std::shared_ptr<const wmf_backend> backend)
: _streamIndex(MAX_PINS), _info(info), _is_flushed(), _has_started(), _backend(std::move(backend)),
_systemwide_lock(info.unique_id.c_str(), WAIT_FOR_MUTEX_TIME_OUT),
_location(""), _device_usb_spec(usb3_type)
wmf_uvc_device::wmf_uvc_device( const uvc_device_info & info, std::shared_ptr< const wmf_backend > backend )
: _streamIndex( MAX_PINS )
, _info( info )
, _is_flushed()
, _has_started()
, _backend( std::move( backend ) )
, _systemwide_lock( info.unique_id.c_str(), WAIT_FOR_MUTEX_TIME_OUT )
, _location( "" )
, _device_usb_spec( usb3_type )
, _power_counter( 0 )
{
if (!is_connected(info))
{
Expand Down Expand Up @@ -884,7 +916,9 @@ namespace librealsense
//enable reader
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 );
}

void wmf_uvc_device::set_d3()
Expand All @@ -896,7 +930,6 @@ namespace librealsense
safe_release(_source);
for (auto& elem : _streams)
elem.callback = nullptr;
_power_state = D3;
}

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 @@ -1207,5 +1240,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. 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,13 @@ 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 ) ); }
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 @@ -101,6 +101,7 @@ namespace librealsense
private:
friend class source_reader_callback;

void init_xu(const extension_unit& xu);
void play_profile(stream_profile profile, frame_callback callback);
void stop_stream_cleanup(const stream_profile& profile, std::vector<profile_and_callback>::iterator& elem);
void flush(int sIndex);
Expand All @@ -118,7 +119,6 @@ namespace librealsense
std::shared_ptr<const wmf_backend> _backend;

const uvc_device_info _info;
power_state _power_state = D3;

CComPtr<IMFSourceReader> _reader = nullptr;
CComPtr<IMFMediaSource> _source = nullptr;
Expand All @@ -137,6 +137,7 @@ namespace librealsense
std::vector<profile_and_callback> _streams;
std::mutex _streams_mutex;

mutable std::recursive_mutex _source_lock; // Guarding access to _source
named_mutex _systemwide_lock;
std::string _location;
usb_spec _device_usb_spec;
Expand All @@ -146,6 +147,8 @@ namespace librealsense
bool _streaming = false;
std::atomic<bool> _is_started = false;
std::wstring _device_id;
std::atomic< int > _power_counter;
std::vector< platform::extension_unit > _xus;
};

class source_reader_callback : public IMFSourceReaderCallback
Expand Down
6 changes: 3 additions & 3 deletions src/platform/uvc-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class uvc_device
virtual void set_power_state( power_state state ) = 0;
virtual power_state get_power_state() const = 0;

virtual void init_xu( const extension_unit & xu ) = 0;
virtual void register_xu( platform::extension_unit && xu ) = 0;
virtual bool set_xu( const extension_unit & xu, uint8_t ctrl, const uint8_t * data, int len ) = 0;
virtual bool get_xu( const extension_unit & xu, uint8_t ctrl, uint8_t * data, int len ) const = 0;
virtual control_range get_xu_range( const extension_unit & xu, uint8_t ctrl, int len ) const = 0;
Expand Down Expand Up @@ -183,7 +183,7 @@ class retry_controls_work_around : public uvc_device

power_state get_power_state() const override { return _dev->get_power_state(); }

void init_xu( const extension_unit & xu ) override { _dev->init_xu( xu ); }
void register_xu( platform::extension_unit && xu ) override { _dev->register_xu( std::move( xu ) ); }

bool set_xu( const extension_unit & xu, uint8_t ctrl, const uint8_t * data, int len ) override
{
Expand Down Expand Up @@ -313,7 +313,7 @@ class multi_pins_uvc_device : public uvc_device

power_state get_power_state() const override { return _dev.front()->get_power_state(); }

void init_xu( const extension_unit & xu ) override { _dev.front()->init_xu( xu ); }
void register_xu( platform::extension_unit && xu ) override { _dev.front()->register_xu( std::move( xu ) ); }

bool set_xu( const extension_unit & xu, uint8_t ctrl, const uint8_t * data, int len ) override
{
Expand Down
61 changes: 23 additions & 38 deletions src/uvc-sensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ uvc_sensor::uvc_sensor( std::string const & name,
device * dev )
: super( name, dev )
, _device( std::move( uvc_device ) )
, _user_count( 0 )
, _timestamp_reader( std::move( timestamp_reader ) )
, _gyro_counter(0)
, _accel_counter(0)
Expand Down Expand Up @@ -372,7 +371,7 @@ void uvc_sensor::finished_bulk_operation()

void uvc_sensor::register_xu( platform::extension_unit xu )
{
_xus.push_back( std::move( xu ) );
_device->register_xu( std::move( xu ) );
}


Expand Down Expand Up @@ -413,49 +412,35 @@ void uvc_sensor::reset_streaming()

void uvc_sensor::acquire_power()
{
std::lock_guard< std::mutex > lock( _power_lock );
if( _user_count.fetch_add( 1 ) == 0 )
try
{
try
{
_device->set_power_state( platform::D0 );
for( auto && xu : _xus )
_device->init_xu( xu );
}
catch( std::exception const & e )
{
_user_count.fetch_add( -1 );
LOG_ERROR( "acquire_power failed: " << e.what() );
throw;
}
catch( ... )
{
_user_count.fetch_add( -1 );
LOG_ERROR( "acquire_power failed" );
throw;
}
_device->set_power_state( platform::D0 );
}
catch( std::exception const & e )
{
LOG_ERROR( "acquire_power failed: " << e.what() );
throw;
}
catch( ... )
{
LOG_ERROR( "acquire_power failed" );
throw;
}
}

void uvc_sensor::release_power()
{
std::lock_guard< std::mutex > lock( _power_lock );
if( _user_count.fetch_add( -1 ) == 1 )
try
{
try
{
_device->set_power_state( platform::D3 );
}
catch( std::exception const & e )
{
// TODO may need to change the user-count?
LOG_ERROR( "release_power failed: " << e.what() );
}
catch( ... )
{
// TODO may need to change the user-count?
LOG_ERROR( "release_power failed" );
}
_device->set_power_state( platform::D3 );
}
catch( std::exception const & e )
{
LOG_ERROR( "release_power failed: " << e.what() );
}
catch( ... )
{
LOG_ERROR( "release_power failed" );
}
}

Expand Down
3 changes: 0 additions & 3 deletions src/uvc-sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,7 @@ class uvc_sensor : public raw_sensor_base

std::shared_ptr< platform::uvc_device > _device;
std::vector< platform::stream_profile > _internal_config;
std::atomic< int > _user_count;
std::mutex _power_lock;
std::mutex _configure_lock;
std::vector< platform::extension_unit > _xus;
std::unique_ptr< power > _power;
std::unique_ptr< frame_timestamp_reader > _timestamp_reader;
};
Expand Down
Loading
Loading