diff options
author | Szczepan Zalega <szczepan@nitrokey.com> | 2017-02-28 21:02:30 +0100 |
---|---|---|
committer | Szczepan Zalega <szczepan@nitrokey.com> | 2017-03-11 15:41:51 +0100 |
commit | 802dd4543b7634f498bd44909461eae6d7975abb (patch) | |
tree | 5a244bfa7677f98a82e3ee2922dcea05b1c37a61 | |
parent | f12b6a9c29f8d236ca969f45d3be1cd9ee5a749f (diff) | |
download | libnitrokey-802dd4543b7634f498bd44909461eae6d7975abb.tar.gz libnitrokey-802dd4543b7634f498bd44909461eae6d7975abb.tar.bz2 |
Make device-level reconnect on problem with sending
Make it 3 times before throwing exception
Call hid_exit on last device disconnection
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
-rw-r--r-- | device.cc | 56 | ||||
-rw-r--r-- | include/device.h | 8 |
2 files changed, 56 insertions, 8 deletions
@@ -15,6 +15,8 @@ using namespace nitrokey::device; using namespace nitrokey::log; using namespace std::chrono; +std::atomic_int Device::instances_count{0}; + Device::Device(const uint16_t vid, const uint16_t pid, const DeviceModel model, const milliseconds send_receive_delay, const int retry_receiving_count, const milliseconds retry_timeout) @@ -27,13 +29,19 @@ Device::Device(const uint16_t vid, const uint16_t pid, const DeviceModel model, last_command_status(0), m_model(model), m_send_receive_delay(send_receive_delay) -{} +{ + instances_count++; +} bool Device::disconnect() { //called in object's destructor LOG(__FUNCTION__, Loglevel::DEBUG_L2); std::lock_guard<std::mutex> lock(mex_dev_com); - LOG(std::string(__FUNCTION__) + std::string(m_model==DeviceModel::PRO?"PRO":"STORAGE"), Loglevel::DEBUG_L2); + return _disconnect(); +} + +bool Device::_disconnect() { + LOG(std::string(__FUNCTION__) + std::string(m_model == DeviceModel::PRO ? "PRO" : "STORAGE"), Loglevel::DEBUG_L2); LOG(std::string(__FUNCTION__) + std::string(" *IN* "), Loglevel::DEBUG_L2); LOG(std::string("Disconnection success: ") + std::to_string(mp_devhandle == nullptr), Loglevel::DEBUG_L2); @@ -41,14 +49,21 @@ bool Device::disconnect() { hid_close(mp_devhandle); mp_devhandle = nullptr; - //FIXME hidexit should not be called if some devices are still active - use static active devices counter - // hid_exit(); + if (instances_count == 1){ + LOG(std::string("Calling hid_exit"), Loglevel::DEBUG_L2); + hid_exit(); + } return true; } + bool Device::connect() { LOG(__FUNCTION__, Loglevel::DEBUG_L2); std::lock_guard<std::mutex> lock(mex_dev_com); - LOG(std::string(__FUNCTION__) + std::string(" *IN* "), Loglevel::DEBUG_L2); + return _connect(); +} + +bool Device::_connect() { + LOG(std::string(__FUNCTION__) + std::string(" *IN* "), Loglevel::DEBUG_L2); // hid_init(); // done automatically on hid_open mp_devhandle = hid_open(m_vid, m_pid, nullptr); @@ -67,8 +82,16 @@ int Device::send(const void *packet) { throw DeviceNotConnected("Attempted HID send on an invalid descriptor."); } - return (hid_send_feature_report( - mp_devhandle, (const unsigned char *)(packet), HID_REPORT_SIZE)); + int send_feature_report = -1; + + for (int i = 0; i < 3 && send_feature_report < 0; ++i) { + send_feature_report = hid_send_feature_report( + mp_devhandle, (const unsigned char *)(packet), HID_REPORT_SIZE); + if (send_feature_report < 0) _reconnect(); + //add thread sleep? + LOG(std::string("Sending attempt: ")+std::to_string(i) + " / 3" , Loglevel::DEBUG_L2); + } + return send_feature_report; } int Device::recv(void *packet) { @@ -138,6 +161,23 @@ void Device::show_stats() { LOG(s, Loglevel::DEBUG_L2); } +void Device::_reconnect() { + if (mex_dev_com.try_lock()){ + throw std::runtime_error("mutex should be locked before entering this function"); + } + LOG(__FUNCTION__, Loglevel::DEBUG_L2); + ++m_counters.low_level_reconnect; + _disconnect(); + _connect(); + +} + +Device::~Device() { + show_stats(); + disconnect(); + instances_count--; +} + Stick10::Stick10(): Device(0x20a0, 0x4108, DeviceModel::PRO, 100ms, 5, 100ms) {} @@ -167,7 +207,9 @@ std::string Device::ErrorCounters::get_as_string() { p(CRC_other_than_awaited); p(wrong_CRC); ss << "), "; + p(low_level_reconnect); p(sending_error); p(receiving_error); return ss.str(); } +#undef p
\ No newline at end of file diff --git a/include/device.h b/include/device.h index 5d7ee12..7b300e5 100644 --- a/include/device.h +++ b/include/device.h @@ -50,6 +50,7 @@ public: cnt busy_progressbar; cnt command_result_not_equal_0_recv; cnt communication_successful; + cnt low_level_reconnect; std::string get_as_string(); } m_counters = {}; @@ -59,7 +60,7 @@ public: const milliseconds send_receive_delay, const int retry_receiving_count, const milliseconds retry_timeout); - virtual ~Device(){show_stats(); disconnect();} + virtual ~Device(); // lack of device is not actually an error, // so it doesn't throw @@ -97,6 +98,9 @@ public: DeviceModel get_device_model() const {return m_model;} private: std::atomic<uint8_t> last_command_status; + void _reconnect(); + bool _connect(); + bool _disconnect(); protected: const uint16_t m_vid; @@ -115,6 +119,8 @@ protected: std::atomic<hid_device *>mp_devhandle; + + static std::atomic_int instances_count; }; class Stick10 : public Device { |