From dc0867ff7ec693953afb62f9512ad7dd3339a2b2 Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Wed, 1 May 2013 22:12:26 +0100 Subject: [PATCH] pv::DeviceManager now manages opening/closing devices It also notifies pv::SigSession objects when their devices are going to be cleared. --- pv/devicemanager.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++-- pv/devicemanager.h | 12 +++++++++- pv/mainwindow.cpp | 11 +++++---- pv/sigsession.cpp | 21 ++++++++++++++--- pv/sigsession.h | 9 +++++++- 5 files changed, 97 insertions(+), 11 deletions(-) diff --git a/pv/devicemanager.cpp b/pv/devicemanager.cpp index 5a72b31b..0765cac6 100644 --- a/pv/devicemanager.cpp +++ b/pv/devicemanager.cpp @@ -19,6 +19,7 @@ */ #include "devicemanager.h" +#include "sigsession.h" #include #include @@ -48,6 +49,27 @@ const std::list& DeviceManager::devices() const return _devices; } +void DeviceManager::use_device(sr_dev_inst *sdi, SigSession *owner) +{ + assert(sdi); + assert(owner); + + _used_devices[sdi] = owner; + + sr_dev_open(sdi); +} + +void DeviceManager::release_device(sr_dev_inst *sdi) +{ + assert(sdi); + + // Notify the owner, and removed the device from the used device list + _used_devices[sdi]->release_device(sdi); + _used_devices.erase(sdi); + + sr_dev_close(sdi); +} + list DeviceManager::driver_scan( struct sr_dev_driver *const driver, GSList *const drvopts) { @@ -65,8 +87,8 @@ list DeviceManager::driver_scan( i++; } - // Clear all the old device instances from this driver - sr_dev_clear(driver); + // Release this driver and all it's attached devices + release_driver(driver); // Do the scan GSList *const devices = sr_driver_scan(driver, drvopts); @@ -123,6 +145,14 @@ void DeviceManager::init_drivers() void DeviceManager::release_devices() { + // Release all the used devices + for (map::iterator i = _used_devices.begin(); + i != _used_devices.end(); i++) + release_device((*i).first); + + _used_devices.clear(); + + // Clear all the drivers sr_dev_driver **const drivers = sr_driver_list(); for (sr_dev_driver **driver = drivers; *driver; driver++) sr_dev_clear(*driver); @@ -136,6 +166,27 @@ void DeviceManager::scan_all_drivers() driver_scan(*driver); } +void DeviceManager::release_driver(struct sr_dev_driver *const driver) +{ + assert(driver); + for (map::iterator i = _used_devices.begin(); + i != _used_devices.end(); i++) + if((*i).first->driver == driver) + { + // Notify the current owner of the device + (*i).second->release_device((*i).first); + + // Remove it from the used device list + _used_devices.erase(i); + + // Close the device instance + sr_dev_close((*i).first); + } + + // Clear all the old device instances from this driver + sr_dev_clear(driver); +} + bool DeviceManager::compare_devices(const sr_dev_inst *const a, const sr_dev_inst *const b) { diff --git a/pv/devicemanager.h b/pv/devicemanager.h index f4be73b9..b7f2d49a 100644 --- a/pv/devicemanager.h +++ b/pv/devicemanager.h @@ -24,6 +24,7 @@ #include #include +#include #include struct sr_context; @@ -32,6 +33,8 @@ struct sr_dev_inst; namespace pv { +class SigSession; + class DeviceManager { public: @@ -41,6 +44,10 @@ public: const std::list& devices() const; + void use_device(sr_dev_inst *sdi, SigSession *owner); + + void release_device(sr_dev_inst *sdi); + std::list driver_scan( struct sr_dev_driver *const driver, GSList *const drvopts = NULL); @@ -50,16 +57,19 @@ public: private: void init_drivers(); - static void release_devices(); + void release_devices(); void scan_all_drivers(); + void release_driver(struct sr_dev_driver *const driver); + static bool compare_devices(const sr_dev_inst *const a, const sr_dev_inst *const b); private: struct sr_context *const _sr_ctx; std::list _devices; + std::map _used_devices; }; } // namespace pv diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index ca514bf9..dcbaf181 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -60,7 +60,8 @@ MainWindow::MainWindow(DeviceManager &device_manager, const char *open_file_name, QWidget *parent) : QMainWindow(parent), - _device_manager(device_manager) + _device_manager(device_manager), + _session(device_manager) { setup_ui(); if (open_file_name) { @@ -278,10 +279,12 @@ void MainWindow::on_actionOpen_triggered() void MainWindow::on_actionConnect_triggered() { dialogs::Connect dlg(this, _device_manager); - if (!dlg.exec()) - return; - struct sr_dev_inst *const sdi = dlg.get_selected_device(); + // If the user selected a device, select it in the device list. Select the + // current device otherwise. + struct sr_dev_inst *const sdi = dlg.exec() ? + dlg.get_selected_device() : _session.get_device(); + update_device_list(sdi); } diff --git a/pv/sigsession.cpp b/pv/sigsession.cpp index 4fe51dd5..5ab30ab1 100644 --- a/pv/sigsession.cpp +++ b/pv/sigsession.cpp @@ -20,6 +20,7 @@ #include "sigsession.h" +#include "devicemanager.h" #include "data/analog.h" #include "data/analogsnapshot.h" #include "data/logic.h" @@ -39,7 +40,8 @@ namespace pv { // TODO: This should not be necessary SigSession* SigSession::_session = NULL; -SigSession::SigSession() : +SigSession::SigSession(DeviceManager &device_manager) : + _device_manager(device_manager), _sdi(NULL), _capture_state(Stopped) { @@ -59,15 +61,28 @@ SigSession::~SigSession() _session = NULL; } +struct sr_dev_inst* SigSession::get_device() const +{ + return _sdi; +} + void SigSession::set_device(struct sr_dev_inst *sdi) { if (_sdi) - sr_dev_close(_sdi); + _device_manager.release_device(_sdi); if (sdi) - sr_dev_open(sdi); + _device_manager.use_device(sdi, this); _sdi = sdi; } +void SigSession::release_device(struct sr_dev_inst *sdi) +{ + (void)sdi; + + assert(_capture_state == Stopped); + _sdi = NULL; +} + void SigSession::load_file(const string &name, function error_handler) { diff --git a/pv/sigsession.h b/pv/sigsession.h index 19782934..ae33c3a8 100644 --- a/pv/sigsession.h +++ b/pv/sigsession.h @@ -36,6 +36,8 @@ namespace pv { +class DeviceManager; + namespace data { class Analog; class AnalogSnapshot; @@ -58,15 +60,19 @@ public: }; public: - SigSession(); + SigSession(DeviceManager &device_manager); ~SigSession(); + struct sr_dev_inst* get_device() const; + /** * Sets device instance that will be used in the next capture session. */ void set_device(struct sr_dev_inst *sdi); + void release_device(struct sr_dev_inst *sdi); + void load_file(const std::string &name, boost::function error_handler); @@ -109,6 +115,7 @@ private: const struct sr_datafeed_packet *packet, void *cb_data); private: + DeviceManager &_device_manager; /** * The device instance that will be used in the next capture session. -- 2.30.2