Skip to content

Commit 1ad8fc7

Browse files
committed
Count power state requests in device, not sensor
1 parent cf7ed8c commit 1ad8fc7

File tree

8 files changed

+157
-73
lines changed

8 files changed

+157
-73
lines changed

src/linux/backend-v4l2.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,8 @@ namespace librealsense
12051205
}
12061206

12071207
v4l_uvc_device::v4l_uvc_device(const uvc_device_info& info, bool use_memory_map)
1208-
: _name(info.id),
1208+
: _power_counter( 0 ),
1209+
_name(info.id),
12091210
_device_path(info.device_path),
12101211
_device_usb_spec(info.conn_spec),
12111212
_info(info),
@@ -1814,15 +1815,44 @@ namespace librealsense
18141815

18151816
void v4l_uvc_device::set_power_state(power_state state)
18161817
{
1817-
if (state == D0 && _state == D3)
1818+
std::lock_guard< std::recursive_mutex > lock( _power_lock );
1819+
switch (state)
18181820
{
1819-
map_device_descriptor();
1821+
case D0:
1822+
{
1823+
if( _power_counter.fetch_add( 1 ) == 0 )
1824+
{
1825+
try
1826+
{
1827+
map_device_descriptor();
1828+
}
1829+
//In case of failure need to decrease use counter
1830+
catch( std::exception const & e )
1831+
{
1832+
_power_counter.fetch_add( -1 );
1833+
throw e;
1834+
}
1835+
catch( ... )
1836+
{
1837+
_power_counter.fetch_add( -1 );
1838+
throw;
1839+
}
1840+
}
1841+
break;
18201842
}
1821-
if (state == D3 && _state == D0)
1843+
case D3:
18221844
{
1823-
close(_profile);
1824-
unmap_device_descriptor();
1845+
if( _power_counter.fetch_add( -1 ) == 1 )
1846+
{
1847+
close(_profile);
1848+
unmap_device_descriptor();
1849+
}
1850+
break;
1851+
}
1852+
default:
1853+
throw std::runtime_error("illegal power state request");
18251854
}
1855+
18261856
_state = state;
18271857
}
18281858

src/linux/backend-v4l2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ namespace librealsense
407407

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

410+
std::recursive_mutex _power_lock;
411+
std::atomic< int > _power_counter;
410412
power_state _state = D3;
411413
std::string _name = "";
412414
std::string _device_path = "";

src/mf/mf-uvc.cpp

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -773,23 +773,55 @@ namespace librealsense
773773
774774
void wmf_uvc_device::set_power_state(power_state state)
775775
{
776-
if (state == _power_state)
777-
return;
776+
std::lock_guard< std::recursive_mutex > lock( _source_lock );
778777
779778
switch (state)
780779
{
781-
case D0: set_d0(); break;
782-
case D3: set_d3(); break;
780+
case D0:
781+
{
782+
if( _power_counter.fetch_add( 1 ) == 0 )
783+
{
784+
try
785+
{
786+
set_d0();
787+
}
788+
//In case of failure need to decrease use counter
789+
catch( std::exception const & e )
790+
{
791+
_power_counter.fetch_add( -1 );
792+
throw e;
793+
}
794+
catch( ... )
795+
{
796+
_power_counter.fetch_add( -1 );
797+
throw;
798+
}
799+
}
800+
break;
801+
}
802+
case D3:
803+
{
804+
if( _power_counter.fetch_add( -1 ) == 1 )
805+
{
806+
set_d3();
807+
}
808+
break;
809+
}
783810
default:
784811
throw std::runtime_error("illegal power state request");
785812
}
786813
}
787814
788-
wmf_uvc_device::wmf_uvc_device(const uvc_device_info& info,
789-
std::shared_ptr<const wmf_backend> backend)
790-
: _streamIndex(MAX_PINS), _info(info), _is_flushed(), _has_started(), _backend(std::move(backend)),
791-
_systemwide_lock(info.unique_id.c_str(), WAIT_FOR_MUTEX_TIME_OUT),
792-
_location(""), _device_usb_spec(usb3_type)
815+
wmf_uvc_device::wmf_uvc_device( const uvc_device_info & info, std::shared_ptr< const wmf_backend > backend )
816+
: _streamIndex( MAX_PINS )
817+
, _info( info )
818+
, _is_flushed()
819+
, _has_started()
820+
, _backend( std::move( backend ) )
821+
, _systemwide_lock( info.unique_id.c_str(), WAIT_FOR_MUTEX_TIME_OUT )
822+
, _location( "" )
823+
, _device_usb_spec( usb3_type )
824+
, _power_counter( 0 )
793825
{
794826
if (!is_connected(info))
795827
{
@@ -884,7 +916,6 @@ namespace librealsense
884916
//enable reader
885917
CHECK_HR(MFCreateSourceReaderFromMediaSource(_source, _reader_attrs, &_reader));
886918
CHECK_HR(_reader->SetStreamSelection(static_cast<DWORD>(MF_SOURCE_READER_ALL_STREAMS), TRUE));
887-
_power_state = D0;
888919
889920
for( auto && xu : _xus )
890921
init_xu( xu );
@@ -899,7 +930,6 @@ namespace librealsense
899930
safe_release(_source);
900931
for (auto& elem : _streams)
901932
elem.callback = nullptr;
902-
_power_state = D3;
903933
}
904934
905935
void wmf_uvc_device::foreach_profile(std::function<void(const mf_profile& profile, CComPtr<IMFMediaType> media_type, bool& quit)> action) const
@@ -1210,5 +1240,14 @@ namespace librealsense
12101240
_profiles.clear();
12111241
_frame_callbacks.clear();
12121242
}
1213-
}
1214-
}
1243+
1244+
power_state wmf_uvc_device::get_power_state() const
1245+
{
1246+
LOG_ERROR( "wmf_uvc_device::get_power_state start. this = " << this );
1247+
std::lock_guard< std::recursive_mutex > lock( _source_lock );
1248+
std::string tmp = _source ? "D0" : "D3";
1249+
LOG_ERROR( "wmf_uvc_device::get_power_state got lock. power state is " << tmp );
1250+
return _source ? D0 : D3;
1251+
}
1252+
} //namespace platform
1253+
} //namespace librealsense

src/mf/mf-uvc.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ namespace librealsense
7373
void stop_callbacks() override;
7474
void close(stream_profile profile) override;
7575
void set_power_state(power_state state) override;
76-
power_state get_power_state() const override { return _power_state; }
76+
power_state get_power_state() const override;
7777
std::vector<stream_profile> get_profiles() const override;
7878

7979
static bool is_connected(const uvc_device_info& info);
@@ -119,7 +119,6 @@ namespace librealsense
119119
std::shared_ptr<const wmf_backend> _backend;
120120

121121
const uvc_device_info _info;
122-
power_state _power_state = D3;
123122

124123
CComPtr<IMFSourceReader> _reader = nullptr;
125124
CComPtr<IMFMediaSource> _source = nullptr;
@@ -138,6 +137,7 @@ namespace librealsense
138137
std::vector<profile_and_callback> _streams;
139138
std::mutex _streams_mutex;
140139

140+
mutable std::recursive_mutex _source_lock; // Guarding access to _source
141141
named_mutex _systemwide_lock;
142142
std::string _location;
143143
usb_spec _device_usb_spec;
@@ -147,6 +147,7 @@ namespace librealsense
147147
bool _streaming = false;
148148
std::atomic<bool> _is_started = false;
149149
std::wstring _device_id;
150+
std::atomic< int > _power_counter;
150151
std::vector< platform::extension_unit > _xus;
151152
};
152153

src/uvc-sensor.cpp

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ uvc_sensor::uvc_sensor( std::string const & name,
3131
device * dev )
3232
: super( name, dev )
3333
, _device( std::move( uvc_device ) )
34-
, _user_count( 0 )
3534
, _timestamp_reader( std::move( timestamp_reader ) )
3635
, _gyro_counter(0)
3736
, _accel_counter(0)
@@ -413,47 +412,35 @@ void uvc_sensor::reset_streaming()
413412

414413
void uvc_sensor::acquire_power()
415414
{
416-
std::lock_guard< std::mutex > lock( _power_lock );
417-
if( _user_count.fetch_add( 1 ) == 0 )
415+
try
418416
{
419-
try
420-
{
421-
_device->set_power_state( platform::D0 );
422-
}
423-
catch( std::exception const & e )
424-
{
425-
_user_count.fetch_add( -1 );
426-
LOG_ERROR( "acquire_power failed: " << e.what() );
427-
throw;
428-
}
429-
catch( ... )
430-
{
431-
_user_count.fetch_add( -1 );
432-
LOG_ERROR( "acquire_power failed" );
433-
throw;
434-
}
417+
_device->set_power_state( platform::D0 );
418+
}
419+
catch( std::exception const & e )
420+
{
421+
LOG_ERROR( "acquire_power failed: " << e.what() );
422+
throw;
423+
}
424+
catch( ... )
425+
{
426+
LOG_ERROR( "acquire_power failed" );
427+
throw;
435428
}
436429
}
437430

438431
void uvc_sensor::release_power()
439432
{
440-
std::lock_guard< std::mutex > lock( _power_lock );
441-
if( _user_count.fetch_add( -1 ) == 1 )
433+
try
442434
{
443-
try
444-
{
445-
_device->set_power_state( platform::D3 );
446-
}
447-
catch( std::exception const & e )
448-
{
449-
// TODO may need to change the user-count?
450-
LOG_ERROR( "release_power failed: " << e.what() );
451-
}
452-
catch( ... )
453-
{
454-
// TODO may need to change the user-count?
455-
LOG_ERROR( "release_power failed" );
456-
}
435+
_device->set_power_state( platform::D3 );
436+
}
437+
catch( std::exception const & e )
438+
{
439+
LOG_ERROR( "release_power failed: " << e.what() );
440+
}
441+
catch( ... )
442+
{
443+
LOG_ERROR( "release_power failed" );
457444
}
458445
}
459446

src/uvc-sensor.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ class uvc_sensor : public raw_sensor_base
101101

102102
std::shared_ptr< platform::uvc_device > _device;
103103
std::vector< platform::stream_profile > _internal_config;
104-
std::atomic< int > _user_count;
105-
std::mutex _power_lock;
106104
std::mutex _configure_lock;
107105
std::unique_ptr< power > _power;
108106
std::unique_ptr< frame_timestamp_reader > _timestamp_reader;

src/uvc/uvc-device.cpp

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ namespace librealsense
8080
}
8181

8282
rs_uvc_device::rs_uvc_device(const rs_usb_device& usb_device, const uvc_device_info &info, uint8_t usb_request_count) :
83-
_usb_device(usb_device),
8483
_info(info),
85-
_action_dispatcher(10),
84+
_power_counter( 0 ),
85+
_usb_device(usb_device),
8686
_usb_request_count(usb_request_count)
87+
_action_dispatcher(10),
8788
{
8889
_parser = std::make_shared<uvc_parser>(usb_device, info);
8990
_action_dispatcher.start();
@@ -174,28 +175,53 @@ namespace librealsense
174175
{
175176
if(state != _power_state)
176177
{
178+
std::lock_guard< std::recursive_mutex > lock( _power_lock );
177179
switch(state)
178180
{
179181
case D0:
180-
_messenger = _usb_device->open(static_cast<uint8_t>(_info.mi));
181-
if (_messenger)
182+
if( _power_counter.fetch_add( 1 ) == 0 )
182183
{
183-
try{
184-
listen_to_interrupts();
185-
} catch(const std::exception& exception) {
186-
// this exception catching avoids crash when disconnecting 2 devices at once - bug seen in android os
187-
LOG_WARNING("rs_uvc_device exception in listen_to_interrupts method: " << exception.what());
184+
try
185+
{
186+
_messenger = _usb_device->open(static_cast<uint8_t>(_info.mi));
187+
if (_messenger)
188+
{
189+
try
190+
{
191+
listen_to_interrupts();
192+
}
193+
catch(const std::exception& exception)
194+
{
195+
// this exception catching avoids crash when disconnecting 2 devices at once - bug seen in android os
196+
LOG_WARNING("rs_uvc_device exception in listen_to_interrupts method: " << exception.what());
197+
}
198+
_power_state = D0;
199+
}
200+
}
201+
//In case of failure need to decrease use counter
202+
catch( std::exception const & e )
203+
{
204+
_power_counter.fetch_add( -1 );
205+
throw e;
206+
}
207+
catch( ... )
208+
{
209+
_power_counter.fetch_add( -1 );
210+
throw;
188211
}
189-
_power_state = D0;
190212
}
213+
191214
break;
192215
case D3:
193-
if(_messenger)
216+
if( _power_counter.fetch_add( -1 ) == 1 )
194217
{
195-
close_uvc_device();
196-
_messenger.reset();
218+
if( _messenger )
219+
{
220+
close_uvc_device();
221+
_messenger.reset();
222+
}
223+
_power_state = D3;
197224
}
198-
_power_state = D3;
199225
break;
200226
}
201227
}

src/uvc/uvc-device.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ namespace librealsense
9696

9797
const uvc_device_info _info;
9898
power_state _power_state = D3; // power state change is unsupported
99-
99+
std::recursive_mutex _power_lock;
100+
std::atomic< int > _power_counter;
100101
std::vector<profile_and_callback> _streams;
101102

102103
std::string _location;

0 commit comments

Comments
 (0)