From f5656a3935364a222b9bec22dcf7eb92685def09 Mon Sep 17 00:00:00 2001 From: Tobias Blomberg Date: Sun, 1 Feb 2026 12:28:08 +0100 Subject: [PATCH 1/5] Move COMMAND_PTY to correct section in svxlink.conf.5 --- src/doc/man/svxlink.conf.5 | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/doc/man/svxlink.conf.5 b/src/doc/man/svxlink.conf.5 index 2f79cb885..444724780 100644 --- a/src/doc/man/svxlink.conf.5 +++ b/src/doc/man/svxlink.conf.5 @@ -1,4 +1,4 @@ -.TH SVXLINK.CONF 5 "OCTOBER 2025" Linux "File Formats" +.TH SVXLINK.CONF 5 "FEBRUARY 2026" Linux "File Formats" . .SH NAME . @@ -437,6 +437,34 @@ If the squelch close before the delay time has expired, no talkgroup will be reported. Default: 0. Example: CTCSS_TO_TG_DELAY=1000 +.TP +.B COMMAND_PTY +Using this configuration variable it is possible to specify a path to a UNIX 98 +PTY that can be used to send commands to a SvxLink logic core. SvxLink will +create a softlink to the actual slave PTY. For that reason, SvxLink must have +write permissions in the directory where the softlink should be created. +Sending commands to the PTY is as simple as doing a +.B "echo 'THE COMMAND TO EXECUTE' > /path/to/pty" +after starting SvxLink. + +Valid commands: +.RS +.IP \(bu 4 +.BR "CFG
" " --" +Set a configuration variable. Only a few configuration variables support being +set at runtime. Example: CFG RepeaterLogic ONLINE 0. +.IP \(bu 4 +.BR "EVENT [ ...]" " --" +Call an event handler (TCL function). It is important to specify the correct +TCL namespace for the function to be found. If no namespace is given, the +namespace of the current logic core will be added, e.g. "manual_identification" +is the same as "RepeaterLogic::manual_identification" if the logic core +namnespace is "RepeaterLogic". To call a function in the root namespace, the +function name must be prepended with "::". +Example: EVENT ::playNumber -42.5. +.RE + +Example: COMMAND_PTY=/dev/shm/repeater_logic_ctrl . .SS Simplex Logic Section . @@ -470,34 +498,6 @@ is open. .B RGR_SOUND_ALWAYS Set to 1 to always send roger sound after squelch close, even when no module is active. -.TP -.B COMMAND_PTY -Using this configuration variable it is possible to specify a path to a UNIX 98 -PTY that can be used to send commands to a SvxLink logic core. SvxLink will -create a softlink to the actual slave PTY. For that reason, SvxLink must have -write permissions in the directory where the softlink should be created. -Sending commands to the PTY is as simple as doing a -.B "echo 'THE COMMAND TO EXECUTE' > /path/to/pty" -after starting SvxLink. - -Valid commands: -.RS -.IP \(bu 4 -.BR "CFG
" " --" -Set a configuration variable. Only a few configuration variables support being -set at runtime. Example: CFG RepeaterLogic ONLINE 0. -.IP \(bu 4 -.BR "EVENT [ ...]" " --" -Call an event handler (TCL function). It is important to specify the correct -TCL namespace for the function to be found. If no namespace is given, the -namespace of the current logic core will be added, e.g. "manual_identification" -is the same as "RepeaterLogic::manual_identification" if the logic core -namnespace is "RepeaterLogic". To call a function in the root namespace, the -function name must be prepended with "::". -Example: EVENT ::playNumber -42.5. -.RE - -Example: COMMAND_PTY=/dev/shm/repeater_logic_ctrl . .SS Repeater Logic Section . From 45d020b8bdea9a568188db4ecb6e5267b4b76b98 Mon Sep 17 00:00:00 2001 From: Tobias Blomberg Date: Sun, 12 Apr 2026 19:43:11 +0200 Subject: [PATCH 2/5] Reopen squelch HIDRAW device on failure --- src/svxlink/trx/SquelchHidraw.cpp | 130 ++++++++++++++++++------------ src/svxlink/trx/SquelchHidraw.h | 23 +++--- 2 files changed, 92 insertions(+), 61 deletions(-) diff --git a/src/svxlink/trx/SquelchHidraw.cpp b/src/svxlink/trx/SquelchHidraw.cpp index 3601e864b..c654d6538 100644 --- a/src/svxlink/trx/SquelchHidraw.cpp +++ b/src/svxlink/trx/SquelchHidraw.cpp @@ -7,7 +7,7 @@ \verbatim SvxLink - A Multi Purpose Voice Services System for Ham Radio Use -Copyright (C) 2003-2014 Tobias Blomberg / SM0SVX +Copyright (C) 2003-2026 Tobias Blomberg / SM0SVX This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,13 +33,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ****************************************************************************/ -#include -#include #include #include #include #include +#include +#include + /**************************************************************************** * @@ -48,6 +49,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ****************************************************************************/ #include +#include /**************************************************************************** @@ -119,18 +121,24 @@ using namespace Async; ****************************************************************************/ SquelchHidraw::SquelchHidraw(void) - : fd(-1), watch(0), active_low(false), pin(0) { + m_reopen_timer.expired.connect(sigc::hide_return(sigc::hide( + sigc::mem_fun(*this, &SquelchHidraw::openDevice) + ))); } /* SquelchHidraw::SquelchHidraw */ SquelchHidraw::~SquelchHidraw(void) { - delete watch; - if (fd >= 0) + m_reopen_timer.setEnable(false); + + delete m_watch; + m_watch = nullptr; + + if (m_fd >= 0) { - close(fd); - fd = -1; + close(m_fd); + m_fd = -1; } } /* SquelchHidraw::~SquelchHidraw */ @@ -145,30 +153,55 @@ For further information: */ bool SquelchHidraw::initialize(Async::Config& cfg, const std::string& rx_name) { - if (!Squelch::initialize(cfg, rx_name)) + m_cfg = &cfg; + m_rx_name = rx_name; + + if (!Squelch::initialize(cfg, m_rx_name)) { return false; } + return openDevice(); +} /* SquelchHidraw::initialize */ + + +/**************************************************************************** + * + * Protected member functions + * + ****************************************************************************/ + + + +/**************************************************************************** + * + * Private member functions + * + ****************************************************************************/ + +bool SquelchHidraw::openDevice(void) +{ string devicename; - if (!cfg.getValue(rx_name, "HID_DEVICE", devicename)) + if (!m_cfg->getValue(m_rx_name, "HID_DEVICE", devicename)) { - cerr << "*** ERROR: Config variable " << devicename << - "/HID_DEVICE not set" << endl; + std::cerr << "*** ERROR: Config variable " << m_rx_name + << "/HID_DEVICE not set" + << std::endl; return false; } string sql_pin; - if (!cfg.getValue(rx_name, "HID_SQL_PIN", sql_pin) || sql_pin.empty()) + if (!m_cfg->getValue(m_rx_name, "HID_SQL_PIN", sql_pin) || sql_pin.empty()) { - cerr << "*** ERROR: Config variable " << rx_name - << "/HID_SQL_PIN not set or invalid\n"; + std::cerr << "*** ERROR: Config variable " << m_rx_name + << "/HID_SQL_PIN not set or invalid" + << std::endl; return false; } if ((sql_pin.size() > 1) && (sql_pin[0] == '!')) { - active_low = true; + m_active_low = true; sql_pin.erase(0, 1); } @@ -181,22 +214,26 @@ bool SquelchHidraw::initialize(Async::Config& cfg, const std::string& rx_name) map::iterator it = pin_mask.find(sql_pin); if (it == pin_mask.end()) { - cerr << "*** ERROR: Invalid value for " << rx_name << "/HID_SQL_PIN=" + cerr << "*** ERROR: Invalid value for " << m_rx_name << "/HID_SQL_PIN=" << sql_pin << ", must be VOL_UP, VOL_DN, MUTE_PLAY, MUTE_REC" << endl; return false; } - pin = (*it).second; + m_pin = (*it).second; - if ((fd = open(devicename.c_str(), O_RDWR, 0)) < 0) + if (m_fd >= 0) + { + close(m_fd); + } + if ((m_fd = ::open(devicename.c_str(), O_RDWR, 0)) < 0) { - cout << "*** ERROR: Could not open event device " << devicename - << " specified in " << rx_name << "/HID_DEVICE: " - << strerror(errno) << endl; + std::cout << "*** ERROR: Could not open event device " << devicename + << " specified in " << m_rx_name << "/HID_DEVICE: " + << SvxLink::strError(errno) << std::endl; return false; } struct hidraw_devinfo hiddevinfo; - if ((ioctl(fd, HIDIOCGRAWINFO, &hiddevinfo) != -1) && + if ((ioctl(m_fd, HIDIOCGRAWINFO, &hiddevinfo) != -1) && (hiddevinfo.vendor == 0x0d8c)) { cout << "--- Hidraw sound chip is "; @@ -232,53 +269,46 @@ bool SquelchHidraw::initialize(Async::Config& cfg, const std::string& rx_name) } else { - cout << "*** ERROR: unknown/unsupported sound chip detected...\n"; + std::cerr << "*** ERROR: Unknown/unsupported sound chip detected..." + << std::endl; return false; } - watch = new Async::FdWatch(fd, Async::FdWatch::FD_WATCH_RD); - assert(watch != 0); - watch->activity.connect(mem_fun(*this, &SquelchHidraw::hidrawActivity)); - - return true; -} - - - -/**************************************************************************** - * - * Protected member functions - * - ****************************************************************************/ + delete m_watch; + m_watch = new Async::FdWatch(m_fd, Async::FdWatch::FD_WATCH_RD); + assert(m_watch != 0); + m_watch->activity.connect(sigc::hide( + sigc::mem_fun(*this, &SquelchHidraw::hidrawActivity) + )); + m_reopen_timer.setEnable(false); + return true; +} /* SquelchHidraw::openDevice */ -/**************************************************************************** - * - * Private member functions - * - ****************************************************************************/ /** * @brief Called when state of Hidraw port has been changed - * */ -void SquelchHidraw::hidrawActivity(FdWatch *watch) +void SquelchHidraw::hidrawActivity(void) { char buf[5]; - int rd = read(fd, buf, sizeof(buf)); + int rd = read(m_fd, buf, sizeof(buf)); if (rd < 0) { - cerr << "*** ERROR: reading HID_DEVICE\n"; + std::cerr << "*** ERROR: Failed to read HID_DEVICE: " + << SvxLink::strError(errno) + << std::endl; + setSignalDetected(false); + m_reopen_timer.setEnable(true); return; } - bool pin_high = buf[0] & pin; - setSignalDetected(pin_high != active_low); + bool pin_high = buf[0] & m_pin; + setSignalDetected(pin_high != m_active_low); } /* SquelchHidraw::hidrawActivity */ - /* * This file has not been truncated */ diff --git a/src/svxlink/trx/SquelchHidraw.h b/src/svxlink/trx/SquelchHidraw.h index fffcfaba9..fbec08ad9 100644 --- a/src/svxlink/trx/SquelchHidraw.h +++ b/src/svxlink/trx/SquelchHidraw.h @@ -6,7 +6,7 @@ \verbatim SvxLink - A Multi Purpose Voice Services System for Ham Radio Use -Copyright (C) 2003-2014 Tobias Blomberg / SM0SVX +Copyright (C) 2003-2026 Tobias Blomberg / SM0SVX This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,6 +44,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ****************************************************************************/ +#include /**************************************************************************** @@ -61,10 +62,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ****************************************************************************/ -namespace Async -{ - class Timer; -}; /**************************************************************************** @@ -143,16 +140,20 @@ class SquelchHidraw : public Squelch protected: private: - int fd; - Async::FdWatch *watch; - bool active_low; - char pin; + int m_fd {-1}; + Async::FdWatch* m_watch {nullptr}; + bool m_active_low {false}; + char m_pin {0}; + Async::Config* m_cfg {nullptr}; + std::string m_rx_name; + Async::Timer m_reopen_timer {5000, Async::Timer::TYPE_PERIODIC, false}; SquelchHidraw(const SquelchHidraw&); SquelchHidraw& operator=(const SquelchHidraw&); - void hidrawActivity(Async::FdWatch *watch); + bool openDevice(void); + void hidrawActivity(void); -}; /* class SquelchGpio */ +}; /* class SquelchHidraw */ //} /* namespace */ From c913fc41935f49141de64fd46a68307fb478e2f2 Mon Sep 17 00:00:00 2001 From: Tobias Blomberg Date: Sun, 12 Apr 2026 23:44:22 +0200 Subject: [PATCH 3/5] Stop fd watch on error --- src/svxlink/trx/SquelchHidraw.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/svxlink/trx/SquelchHidraw.cpp b/src/svxlink/trx/SquelchHidraw.cpp index c654d6538..ddb7b1974 100644 --- a/src/svxlink/trx/SquelchHidraw.cpp +++ b/src/svxlink/trx/SquelchHidraw.cpp @@ -300,6 +300,7 @@ void SquelchHidraw::hidrawActivity(void) << SvxLink::strError(errno) << std::endl; setSignalDetected(false); + m_watch->setEnabled(false); m_reopen_timer.setEnable(true); return; } From 9c1bf0e823ca3d3d7efe9e31fac9f1178d591428 Mon Sep 17 00:00:00 2001 From: Tobias Blomberg Date: Mon, 13 Apr 2026 22:00:50 +0200 Subject: [PATCH 4/5] Reopen PTT Hidraw device on failure --- src/svxlink/trx/PttHidraw.cpp | 146 ++++++++++++++++++++++------------ src/svxlink/trx/PttHidraw.h | 20 +++-- 2 files changed, 105 insertions(+), 61 deletions(-) diff --git a/src/svxlink/trx/PttHidraw.cpp b/src/svxlink/trx/PttHidraw.cpp index ada121806..327b588ca 100644 --- a/src/svxlink/trx/PttHidraw.cpp +++ b/src/svxlink/trx/PttHidraw.cpp @@ -6,7 +6,7 @@ \verbatim SvxLink - A Multi Purpose Voice Services System for Ham Radio Use -Copyright (C) 2003-2014 Tobias Blomberg / SM0SVX +Copyright (C) 2003-2026 Tobias Blomberg / SM0SVX This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,6 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ****************************************************************************/ +#include /**************************************************************************** @@ -64,7 +65,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ****************************************************************************/ using namespace std; -using namespace Async; @@ -115,52 +115,90 @@ using namespace Async; ****************************************************************************/ PttHidraw::PttHidraw(void) - : active_low(false), fd(-1), pin(0) { } /* PttHidraw::PttHidraw */ PttHidraw::~PttHidraw(void) { - if (fd >= 0) - { - close(fd); - fd = -1; - } + closeDevice(); } /* PttHidraw::~PttHidraw */ -bool PttHidraw::initialize(Async::Config &cfg, const std::string name) +bool PttHidraw::initialize(Async::Config& cfg, const std::string name) { + m_cfg = &cfg; + m_tx_name = name; + + return openDevice(); +} /* PttHidraw::initialize */ + + + +/**************************************************************************** + * + * Protected member functions + * + ****************************************************************************/ + + - map pin_mask; - pin_mask["GPIO1"] = 0x01; - pin_mask["GPIO2"] = 0x02; - pin_mask["GPIO3"] = 0x04; - pin_mask["GPIO4"] = 0x08; +/**************************************************************************** + * + * Private member functions + * + ****************************************************************************/ + +bool PttHidraw::openDevice(void) +{ + static const std::map pin_mask{ + {"GPIO1", 0x01}, + {"GPIO2", 0x02}, + {"GPIO3", 0x04}, + {"GPIO4", 0x08} + }; + + std::string hidraw_dev; + if (!m_cfg->getValue(m_tx_name, "HID_DEVICE", hidraw_dev) || + hidraw_dev.empty()) + { + std::cerr << "*** ERROR: Config variable " << m_tx_name + << "/HID_DEVICE not set" + << std::endl; + return false; + } - string hidraw_pin; - if (!cfg.getValue(name, "HID_PTT_PIN", hidraw_pin) || hidraw_pin.empty()) + std::string hidraw_pin; + if (!m_cfg->getValue(m_tx_name, "HID_PTT_PIN", hidraw_pin) || + hidraw_pin.empty()) { - cerr << "*** ERROR: Config variable " << name << "/HID_PTT_PIN not set\n"; + std::cerr << "*** ERROR: Config variable " << m_tx_name + << "/HID_PTT_PIN not set" + << std::endl; return false; } - string hidraw_dev; - if (!cfg.getValue(name, "HID_DEVICE", hidraw_dev) || hidraw_dev.empty()) + auto it = pin_mask.find(hidraw_pin); + if (it == pin_mask.end()) { - cerr << "*** ERROR: Config variable " << name << "/HID_DEVICE not set\n"; + std::cerr << "*** ERROR: Wrong value for " << m_tx_name << "/HID_PTT_PIN=" + << hidraw_pin << ", valid values are GPIO1, GPIO2, GPIO3, GPIO4" + << std::endl; return false; } + m_pin = (*it).second; - if ((fd = open(hidraw_dev.c_str(), O_WRONLY, 0)) < 0) + if ((m_fd = ::open(hidraw_dev.c_str(), O_WRONLY, 0)) < 0) { - cerr << "*** ERROR: Can't open port " << hidraw_dev << endl; + std::cerr << "*** ERROR: Can't open HIDRAW device '" << hidraw_dev + << "': " << SvxLink::strError(errno) + << std::endl; + closeDevice(); return false; } struct hidraw_devinfo hiddevinfo; - if ((ioctl(fd, HIDIOCGRAWINFO, &hiddevinfo) != -1) && + if ((::ioctl(m_fd, HIDIOCGRAWINFO, &hiddevinfo) != -1) && (hiddevinfo.vendor == 0x0d8c)) { cout << "--- Hidraw sound chip is "; @@ -197,61 +235,63 @@ bool PttHidraw::initialize(Async::Config &cfg, const std::string name) else { cerr << "*** ERROR: unknown/unsupported sound chip detected...\n"; + closeDevice(); return false; } if (hidraw_pin[0] == '!') { - active_low = true; + m_active_low = true; hidraw_pin.erase(0, 1); } - map::iterator it = pin_mask.find(hidraw_pin); - if (it == pin_mask.end()) + return true; +} /* PttHidraw::openDevice */ + + +void PttHidraw::closeDevice(void) +{ + m_active_low = false; + m_pin = 0; + + if (m_fd >= 0) { - cerr << "*** ERROR: Wrong value for " << name << "/HID_PIN=" << hidraw_pin - << ", valid are GPIO1, GPIO2, GPIO3, GPIO4" << endl; - return false; + ::close(m_fd); + m_fd = -1; } - pin = (*it).second; - - return true; -} /* PttHidraw::initialize */ +} /* PttHidraw::closeDevice */ bool PttHidraw::setTxOn(bool tx_on) { //cerr << "### PttHidraw::setTxOn(" << (tx_on ? "true" : "false") << ")\n"; - char a[5] = {'\000', '\000', - (tx_on ^ active_low ? pin : '\000'), pin, '\000'}; + const char a[5] = { + '\000', + '\000', + (tx_on ^ m_active_low ? m_pin : '\000'), + m_pin, + '\000' + }; - if (write(fd, a, sizeof(a)) == -1) + if ((m_fd < 0) && !openDevice()) { return false; } + if (::write(m_fd, a, sizeof(a)) == -1) + { + std::cerr << "*** ERROR: Failed to write to HIDRAW device: " + << SvxLink::strError(errno) + << std::endl; + closeDevice(); + return false; + } + return true; } /* PttHidraw::setTxOn */ - -/**************************************************************************** - * - * Protected member functions - * - ****************************************************************************/ - - - -/**************************************************************************** - * - * Private member functions - * - ****************************************************************************/ - - - /* * This file has not been truncated */ diff --git a/src/svxlink/trx/PttHidraw.h b/src/svxlink/trx/PttHidraw.h index 219a3ce70..3b2353ad8 100644 --- a/src/svxlink/trx/PttHidraw.h +++ b/src/svxlink/trx/PttHidraw.h @@ -6,7 +6,7 @@ \verbatim SvxLink - A Multi Purpose Voice Services System for Ham Radio Use -Copyright (C) 2003-2014 Tobias Blomberg / SM0SVX +Copyright (C) 2003-2026 Tobias Blomberg / SM0SVX This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -121,7 +121,7 @@ class PttHidraw : public Ptt /** * @brief Destructor */ - ~PttHidraw(void); + virtual ~PttHidraw(void); /** * @brief Initialize the PTT hardware @@ -129,25 +129,29 @@ class PttHidraw : public Ptt * @param name The name of the config section to read config from * @returns Returns \em true on success or else \em false */ - virtual bool initialize(Async::Config &cfg, const std::string name); + virtual bool initialize(Async::Config& cfg, + const std::string name) override; /** * @brief Set the state of the PTT, TX on or off * @param tx_on Set to \em true to turn the transmitter on * @returns Returns \em true on success or else \em false */ - virtual bool setTxOn(bool tx_on); + virtual bool setTxOn(bool tx_on) override; protected: private: - bool active_low; - - int fd; - char pin; + bool m_active_low {false}; + int m_fd {-1}; + char m_pin {0}; + Async::Config* m_cfg {nullptr}; + std::string m_tx_name; PttHidraw(const PttHidraw&); PttHidraw& operator=(const PttHidraw&); + bool openDevice(void); + void closeDevice(void); }; /* class PttHidraw */ From 5cdd009fb69b25eaae6498616c94fb09ddfd2bef Mon Sep 17 00:00:00 2001 From: Tobias Blomberg Date: Mon, 13 Apr 2026 23:30:32 +0200 Subject: [PATCH 5/5] SquelchHidraw code cleanup --- src/svxlink/trx/SquelchHidraw.cpp | 66 +++++++++++++++++-------------- src/svxlink/trx/SquelchHidraw.h | 4 +- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/svxlink/trx/SquelchHidraw.cpp b/src/svxlink/trx/SquelchHidraw.cpp index ddb7b1974..ecf7933d1 100644 --- a/src/svxlink/trx/SquelchHidraw.cpp +++ b/src/svxlink/trx/SquelchHidraw.cpp @@ -125,21 +125,15 @@ SquelchHidraw::SquelchHidraw(void) m_reopen_timer.expired.connect(sigc::hide_return(sigc::hide( sigc::mem_fun(*this, &SquelchHidraw::openDevice) ))); + m_watch.activity.connect(sigc::hide( + sigc::mem_fun(*this, &SquelchHidraw::hidrawActivity) + )); } /* SquelchHidraw::SquelchHidraw */ SquelchHidraw::~SquelchHidraw(void) { - m_reopen_timer.setEnable(false); - - delete m_watch; - m_watch = nullptr; - - if (m_fd >= 0) - { - close(m_fd); - m_fd = -1; - } + closeDevice(); } /* SquelchHidraw::~SquelchHidraw */ @@ -181,6 +175,8 @@ bool SquelchHidraw::initialize(Async::Config& cfg, const std::string& rx_name) bool SquelchHidraw::openDevice(void) { + closeDevice(); + string devicename; if (!m_cfg->getValue(m_rx_name, "HID_DEVICE", devicename)) { @@ -205,13 +201,14 @@ bool SquelchHidraw::openDevice(void) sql_pin.erase(0, 1); } - map pin_mask; - pin_mask["VOL_UP"] = 0x01; - pin_mask["VOL_DN"] = 0x02; - pin_mask["MUTE_PLAY"] = 0x04; - pin_mask["MUTE_REC"] = 0x08; + static const std::map pin_mask{ + {"VOL_UP", 0x01}, + {"VOL_DN", 0x02}, + {"MUTE_PLAY", 0x04}, + {"MUTE_REC", 0x08} + }; - map::iterator it = pin_mask.find(sql_pin); + auto it = pin_mask.find(sql_pin); if (it == pin_mask.end()) { cerr << "*** ERROR: Invalid value for " << m_rx_name << "/HID_SQL_PIN=" @@ -220,20 +217,17 @@ bool SquelchHidraw::openDevice(void) } m_pin = (*it).second; - if (m_fd >= 0) - { - close(m_fd); - } if ((m_fd = ::open(devicename.c_str(), O_RDWR, 0)) < 0) { std::cout << "*** ERROR: Could not open event device " << devicename << " specified in " << m_rx_name << "/HID_DEVICE: " << SvxLink::strError(errno) << std::endl; + closeDevice(); return false; } struct hidraw_devinfo hiddevinfo; - if ((ioctl(m_fd, HIDIOCGRAWINFO, &hiddevinfo) != -1) && + if ((::ioctl(m_fd, HIDIOCGRAWINFO, &hiddevinfo) != -1) && (hiddevinfo.vendor == 0x0d8c)) { cout << "--- Hidraw sound chip is "; @@ -271,36 +265,48 @@ bool SquelchHidraw::openDevice(void) { std::cerr << "*** ERROR: Unknown/unsupported sound chip detected..." << std::endl; + closeDevice(); return false; } - delete m_watch; - m_watch = new Async::FdWatch(m_fd, Async::FdWatch::FD_WATCH_RD); - assert(m_watch != 0); - m_watch->activity.connect(sigc::hide( - sigc::mem_fun(*this, &SquelchHidraw::hidrawActivity) - )); - + m_watch.setFd(m_fd, Async::FdWatch::FD_WATCH_RD); + m_watch.setEnabled(true); m_reopen_timer.setEnable(false); return true; } /* SquelchHidraw::openDevice */ +void SquelchHidraw::closeDevice(void) +{ + m_reopen_timer.setEnable(false); + m_watch.setEnabled(false); + + m_active_low = false; + m_pin = 0; + + if (m_fd >= 0) + { + ::close(m_fd); + m_fd = -1; + } +} /* SquelchHidraw::closeDevice */ + + /** * @brief Called when state of Hidraw port has been changed */ void SquelchHidraw::hidrawActivity(void) { char buf[5]; - int rd = read(m_fd, buf, sizeof(buf)); + int rd = ::read(m_fd, buf, sizeof(buf)); if (rd < 0) { std::cerr << "*** ERROR: Failed to read HID_DEVICE: " << SvxLink::strError(errno) << std::endl; + closeDevice(); setSignalDetected(false); - m_watch->setEnabled(false); m_reopen_timer.setEnable(true); return; } diff --git a/src/svxlink/trx/SquelchHidraw.h b/src/svxlink/trx/SquelchHidraw.h index fbec08ad9..081ff1f77 100644 --- a/src/svxlink/trx/SquelchHidraw.h +++ b/src/svxlink/trx/SquelchHidraw.h @@ -45,6 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ****************************************************************************/ #include +#include /**************************************************************************** @@ -141,7 +142,7 @@ class SquelchHidraw : public Squelch private: int m_fd {-1}; - Async::FdWatch* m_watch {nullptr}; + Async::FdWatch m_watch; bool m_active_low {false}; char m_pin {0}; Async::Config* m_cfg {nullptr}; @@ -151,6 +152,7 @@ class SquelchHidraw : public Squelch SquelchHidraw(const SquelchHidraw&); SquelchHidraw& operator=(const SquelchHidraw&); bool openDevice(void); + void closeDevice(void); void hidrawActivity(void); }; /* class SquelchHidraw */