Instrument Neutral Distributed Interface INDI  1.9.2
connectionserial.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2017 Jasem Mutlaq. All rights reserved.
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 *******************************************************************************/
18 
19 #include "connectionserial.h"
20 #include "indistandardproperty.h"
21 #include "indicom.h"
22 #include "indilogger.h"
23 
24 #include <dirent.h>
25 #include <cerrno>
26 #include <cstring>
27 #include <algorithm>
28 #include <thread>
29 #include <chrono>
30 #include <regex>
31 
32 namespace Connection
33 {
34 extern const char *CONNECTION_TAB;
35 
36 Serial::Serial(INDI::DefaultDevice *dev) : Interface(dev, CONNECTION_SERIAL)
37 {
38  char configPort[256] = {0};
39  // Try to load the port from the config file. If that fails, use default port.
40  if (IUGetConfigText(dev->getDeviceName(), INDI::SP::DEVICE_PORT, "PORT", configPort, 256) < 0)
41  {
42 #ifdef __APPLE__
43  strncpy(configPort, "/dev/cu.usbserial", MAXINDINAME);
44 #else
45  strncpy(configPort, "/dev/ttyUSB0", MAXINDINAME);
46 #endif
47  }
48  IUFillText(&PortT[0], "PORT", "Port", configPort);
50  IPS_IDLE);
51 
52  m_ConfigPort = configPort;
53 
54  int autoSearchIndex = 0;
55  // Try to load the port from the config file. If that fails, use default port.
57  IUFillSwitch(&AutoSearchS[INDI::DefaultDevice::INDI_ENABLED], "INDI_ENABLED", "Enabled",
58  autoSearchIndex == 0 ? ISS_ON : ISS_OFF);
59  IUFillSwitch(&AutoSearchS[INDI::DefaultDevice::INDI_DISABLED], "INDI_DISABLED", "Disabled",
60  autoSearchIndex == 0 ? ISS_OFF : ISS_ON);
61  IUFillSwitchVector(&AutoSearchSP, AutoSearchS, 2, dev->getDeviceName(), INDI::SP::DEVICE_AUTO_SEARCH, "Auto Search",
63 
64  IUFillSwitch(&RefreshS[0], "Scan Ports", "Scan Ports", ISS_OFF);
65  IUFillSwitchVector(&RefreshSP, RefreshS, 1, dev->getDeviceName(), "DEVICE_PORT_SCAN", "Refresh", CONNECTION_TAB,
66  IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
67 
68  IUFillSwitch(&BaudRateS[0], "9600", "", ISS_ON);
69  IUFillSwitch(&BaudRateS[1], "19200", "", ISS_OFF);
70  IUFillSwitch(&BaudRateS[2], "38400", "", ISS_OFF);
71  IUFillSwitch(&BaudRateS[3], "57600", "", ISS_OFF);
72  IUFillSwitch(&BaudRateS[4], "115200", "", ISS_OFF);
73  IUFillSwitch(&BaudRateS[5], "230400", "", ISS_OFF);
74  IUFillSwitchVector(&BaudRateSP, BaudRateS, 6, dev->getDeviceName(), INDI::SP::DEVICE_BAUD_RATE, "Baud Rate", CONNECTION_TAB,
75  IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
76 
77  // Try to load the port from the config file. If that fails, use default port.
79  // If we have a valid config entry, se it.
80  if (m_ConfigBaudRate >= 0)
81  {
82  IUResetSwitch(&BaudRateSP);
83  BaudRateS[m_ConfigBaudRate].s = ISS_ON;
84  }
85 }
86 
88 {
89  delete[] SystemPortS;
90 }
91 
92 bool Serial::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
93 {
94  if (!strcmp(dev, m_Device->getDeviceName()))
95  {
96  // Serial Port
97  if (!strcmp(name, PortTP.name))
98  {
99  IUUpdateText(&PortTP, texts, names, n);
100  PortTP.s = IPS_OK;
101  IDSetText(&PortTP, nullptr);
102 
103  auto pos = std::find_if(m_SystemPorts.begin(), m_SystemPorts.end(), [&](const std::string onePort)
104  {
105  return !strcmp(PortT[0].text, onePort.c_str());
106  });
107  if (pos != m_SystemPorts.end())
108  {
109  LOGF_DEBUG("Auto search is disabled because %s is not a system port.", PortT[0].text);
110  AutoSearchS[0].s = ISS_OFF;
111  AutoSearchS[1].s = ISS_ON;
112  IDSetSwitch(&AutoSearchSP, nullptr);
113  }
114  }
115  return true;
116  }
117 
118  return false;
119 }
120 
121 bool Serial::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
122 {
123  if (!strcmp(dev, m_Device->getDeviceName()))
124  {
125  // Change Baud Rate
126  if (!strcmp(name, BaudRateSP.name))
127  {
128  IUUpdateSwitch(&BaudRateSP, states, names, n);
129  BaudRateSP.s = IPS_OK;
130  IDSetSwitch(&BaudRateSP, nullptr);
131  return true;
132  }
133 
134  // Auto Search Devices on connection failure
135  if (!strcmp(name, AutoSearchSP.name))
136  {
137  bool wasEnabled = (AutoSearchS[0].s == ISS_ON);
138 
139  IUUpdateSwitch(&AutoSearchSP, states, names, n);
141 
142  // Only display message if there is an actual change
143  if (wasEnabled == false && AutoSearchS[0].s == ISS_ON)
144  LOG_INFO("Auto search is enabled. When connecting, the driver shall attempt to "
145  "communicate with all available system ports until a connection is "
146  "established.");
147  else if (wasEnabled && AutoSearchS[1].s == ISS_ON)
148  LOG_INFO("Auto search is disabled.");
149  IDSetSwitch(&AutoSearchSP, nullptr);
150 
151  return true;
152  }
153 
154  // Refresh Serial Devices
155  if (!strcmp(name, RefreshSP.name))
156  {
158  IDSetSwitch(&RefreshSP, nullptr);
159  return true;
160  }
161 
162  // Check if a system port is selected.
163  if (!strcmp(name, SystemPortSP.name))
164  {
165  IUUpdateSwitch(&SystemPortSP, states, names, n);
166 
167  int index = IUFindOnSwitchIndex(&SystemPortSP);
168  if (index >= 0)
169  {
170  IUSaveText(&PortT[0], m_SystemPorts[index].c_str());
171  IDSetText(&PortTP, nullptr);
172  }
173 
175  IDSetSwitch(&SystemPortSP, nullptr);
176  return true;
177  }
178  }
179 
180  return false;
181 }
182 
183 bool Serial::Connect()
184 {
185  uint32_t baud = atoi(IUFindOnSwitch(&BaudRateSP)->name);
186  if (Connect(PortT[0].text, baud) && processHandshake())
187  return true;
188 
189  // Important, disconnect from port immediately
190  // to release the lock, otherwise another driver will find it busy.
192 
193  // Start auto-search if option was selected and IF we have system ports to try connecting to
194  if (AutoSearchS[0].s == ISS_ON && SystemPortS != nullptr && SystemPortSP.nsp > 1)
195  {
196  LOGF_WARN("Communication with %s @ %d failed. Starting Auto Search...", PortT[0].text,
197  baud);
198 
199  std::this_thread::sleep_for(std::chrono::milliseconds(500 + (rand() % 1000)));
200 
201  // Try to connect "randomly" so that competing devices don't all try to connect to the same
202  // ports at the same time.
203  std::vector<std::string> systemPorts;
204  for (int i = 0; i < SystemPortSP.nsp; i++)
205  {
206  // Only try the same port last again.
207  if (!strcmp(m_SystemPorts[i].c_str(), PortT[0].text))
208  continue;
209 
210  systemPorts.push_back(m_SystemPorts[i].c_str());
211  }
212  std::random_shuffle (systemPorts.begin(), systemPorts.end());
213 
214  std::vector<std::string> doubleSearch = systemPorts;
215 
216  // Try the current port as LAST port again
217  systemPorts.push_back(PortT[0].text);
218 
219  // Double search just in case some items were BUSY in the first pass
220  systemPorts.insert(systemPorts.end(), doubleSearch.begin(), doubleSearch.end());
221 
222  for (const auto &port : systemPorts)
223  {
224  LOGF_INFO("Trying connecting to %s @ %d ...", port.c_str(), baud);
225  if (Connect(port.c_str(), baud) && processHandshake())
226  {
227  IUSaveText(&PortT[0], port.c_str());
228  IDSetText(&PortTP, nullptr);
229 
230 #ifdef __linux__
231  bool saveConfig = false;
232  // Disable auto-search on Linux if not disabled already
234  {
235  saveConfig = true;
238  IDSetSwitch(&AutoSearchSP, nullptr);
239  }
240  // Only save config if different from default port
241  if (m_ConfigPort != std::string(PortT[0].text))
242  {
243  saveConfig = true;
244  }
245 
246  if (saveConfig)
247  m_Device->saveConfig(true);
248 #else
249  // Do not overwrite custom ports because it can be actually cause
250  // temporary failure. For users who use mapped named ports (e.g. /dev/mount), it's not good to override their choice.
251  // So only write to config if the port was a system port.
252  if (std::find(m_SystemPorts.begin(), m_SystemPorts.end(), PortT[0].text) != m_SystemPorts.end())
253  m_Device->saveConfig(true, PortTP.name);
254 #endif
255  return true;
256  }
257 
259  // sleep randomly anytime between 0.5s and ~1.5s
260  // This enables different competing devices to connect
261  std::this_thread::sleep_for(std::chrono::milliseconds(500 + (rand() % 1000)));
262  }
263  }
264 
265  return false;
266 }
267 
269 {
270  LOG_DEBUG("Connection successful, attempting handshake...");
271  bool rc = Handshake();
272  if (rc)
273  {
274  LOGF_INFO("%s is online.", getDeviceName());
275  if (std::string(PortT[0].text) != m_ConfigPort || IUFindOnSwitchIndex(&BaudRateSP) != m_ConfigBaudRate)
276  {
279  }
280  }
281  else
282  LOG_DEBUG("Handshake failed.");
283 
284  return rc;
285 }
286 
287 bool Serial::Connect(const char *port, uint32_t baud)
288 {
289  if (m_Device->isSimulation())
290  return true;
291 
292  int connectrc = 0;
293  char errorMsg[MAXRBUF];
294 
295  LOGF_DEBUG("Connecting to %s @ %d", port, baud);
296 
297  if ((connectrc = tty_connect(port, baud, wordSize, parity, stopBits, &PortFD)) != TTY_OK)
298  {
299  if (connectrc == TTY_PORT_BUSY)
300  {
301  LOGF_WARN("Port %s is already used by another driver or process.", port);
302  return false;
303  }
304 
305  tty_error_msg(connectrc, errorMsg, MAXRBUF);
306  LOGF_ERROR("Failed to connect to port (%s). Error: %s", port, errorMsg);
307  return false;
308  }
309 
310  LOGF_DEBUG("Port FD %d", PortFD);
311 
312  return true;
313 }
314 
315 bool Serial::Disconnect()
316 {
317  if (PortFD > 0)
318  {
320  PortFD = -1;
321  }
322  return true;
323 }
324 
325 void Serial::Activated()
326 {
327  Refresh(true);
332 }
333 
334 void Serial::Deactivated()
335 {
341  delete[] SystemPortS;
342  SystemPortS = nullptr;
343 }
344 
345 bool Serial::saveConfigItems(FILE *fp)
346 {
347  IUSaveConfigText(fp, &PortTP);
350 
351  return true;
352 }
353 
354 void Serial::setDefaultPort(const char *port)
355 {
356  IUSaveText(&PortT[0], port);
357 }
358 
359 void Serial::setDefaultBaudRate(BaudRate newRate)
360 {
362  BaudRateS[newRate].s = ISS_ON;
363 }
364 
365 uint32_t Serial::baud()
366 {
367  return atoi(IUFindOnSwitch(&BaudRateSP)->name);
368 }
369 
370 int serial_dev_file_select(const dirent *entry)
371 {
372 #if defined(__APPLE__)
373  static const char *filter_names[] = { "cu.", nullptr };
374 #else
375  static const char *filter_names[] = { "ttyUSB", "ttyACM", nullptr };
376 #endif
377  const char **filter;
378 
379  for (filter = filter_names; *filter; ++filter)
380  {
381  if (strstr(entry->d_name, *filter) != nullptr)
382  {
383  return (true);
384  }
385  }
386  return (false);
387 }
388 
389 int usb_dev_file_select(const dirent *entry)
390 {
391  static const char *filter_names[] = { "usb-", nullptr };
392  const char **filter;
393 
394  for (filter = filter_names; *filter; ++filter)
395  {
396  if (strstr(entry->d_name, *filter) != nullptr)
397  {
398  return (true);
399  }
400  }
401  return (false);
402 }
403 
404 int bluetooth_dev_file_select(const dirent *entry)
405 {
406  static const char *filter_names[] = {"rfcomm", nullptr };
407  const char **filter;
408 
409  for (filter = filter_names; *filter; ++filter)
410  {
411  if (strstr(entry->d_name, *filter) != nullptr)
412  {
413  return (true);
414  }
415  }
416  return (false);
417 }
418 
419 bool Serial::Refresh(bool silent)
420 {
421  std::vector<std::string> m_Ports;
422 
423  // 0 Serial Only, 1 By USB-ID, 2 Bluetooth
424  auto searchPath = [&](std::string prefix, uint8_t searchType)
425  {
426  struct dirent **namelist;
427  std::vector<std::string> detectedDevices;
428  int devCount = 0;
429  if (searchType == SERIAL_DEV)
430  devCount = scandir(prefix.c_str(), &namelist, serial_dev_file_select, alphasort);
431  else if (searchType == USB_ID_DEV)
432  devCount = scandir(prefix.c_str(), &namelist, usb_dev_file_select, alphasort);
433  else
434  devCount = scandir(prefix.c_str(), &namelist, bluetooth_dev_file_select, alphasort);
435  if (devCount > 0)
436  {
437  while (devCount--)
438  {
439  if (detectedDevices.size() < 10)
440  {
441  std::string s(namelist[devCount]->d_name);
442  s.erase(s.find_last_not_of(" \n\r\t") + 1);
443  detectedDevices.push_back(prefix + s);
444  }
445  else
446  {
447  LOGF_DEBUG("Ignoring devices over %d : %s", detectedDevices.size(),
448  namelist[devCount]->d_name);
449  }
450  free(namelist[devCount]);
451  }
452  free(namelist);
453  }
454 
455  return detectedDevices;
456  };
457 
458 #ifdef __linux__
459  // Search for serial, usb, and bluetooth devices.
460  const std::vector<std::string> serialDevices = searchPath("/dev/", SERIAL_DEV);
461  const std::vector<std::string> usbIDDevices = searchPath("/dev/serial/by-id/", USB_ID_DEV);
462  const std::vector<std::string> btDevices = searchPath("/dev/", BLUETOOTH_DEV);
463  m_Ports.insert(m_Ports.end(), btDevices.begin(), btDevices.end());
464  // Linux Kernel does not add identical VID:PID adapter to serial/by-id
465  // Therefore, we check if there is a 1:1 correspondence between serial/by-id and /dev/ttyUSBX nodes
466  // In case we have more by-id devices then /dev/ttyUSBX, we use them since these symlinks are more reusable in subsequence
467  // sessions
468  if (usbIDDevices.size() >= serialDevices.size())
469  m_Ports.insert(m_Ports.end(), usbIDDevices.begin(), usbIDDevices.end());
470  else
471  m_Ports.insert(m_Ports.end(), serialDevices.begin(), serialDevices.end());
472 #else
473  const std::vector<std::string> serialDevices = searchPath("/dev/", SERIAL_DEV);
474  m_Ports.insert(m_Ports.end(), serialDevices.begin(), serialDevices.end());
475 #endif
476 
477  const int pCount = m_Ports.size();
478 
479  if (pCount == 0)
480  {
481  if (!silent)
482  LOG_WARN("No candidate ports found on the system.");
483  return false;
484  }
485  else
486  {
487  if (!silent)
488  LOGF_INFO("Scan complete. Found %d port(s).", pCount);
489  }
490 
491  // Check if anything changed. If not we return.
492  if (m_Ports == m_SystemPorts)
493  return true;
494 
495  m_SystemPorts = m_Ports;
496 
497  if (SystemPortS)
499 
500  delete[] SystemPortS;
501 
502  SystemPortS = new ISwitch[pCount];
503  ISwitch *sp = SystemPortS;
504 
505  for (const auto &onePort : m_Ports)
506  {
507  // Simplify label by removing directory prefix
508  std::string name = onePort.substr(onePort.find_last_of("/\\") + 1);
509  std::string label = name;
510 
511  // Remove Linux extra stuff to simplify string
512 #ifdef __linux__
513  std::regex re("usb-(.[^-]+)");
514  std::smatch match;
515  if (std::regex_search(onePort, match, re))
516  {
517  name = label = match.str(1);
518  // Simplify further by removing non-unique strings
519  std::regex target("FTDI_|UART_|USB_|Bridge_Controller_|to_");
520  label = std::regex_replace(label, target, "");
521  }
522 #endif
523  IUFillSwitch(sp++, name.c_str(), label.c_str(), ISS_OFF);
524  }
525 
526  IUFillSwitchVector(&SystemPortSP, SystemPortS, pCount, m_Device->getDeviceName(), "SYSTEM_PORTS", "System Ports",
528 
530 
531  // If we have one physical port only, set it to the device port if the current port
532  // is the default port.
533  if (pCount == 1 && std::string(PortT[0].text) == m_ConfigPort)
534  IUSaveText(&PortT[0], m_Ports[0].c_str());
535  return true;
536 }
537 }
Connection::Serial::port
virtual const char * port()
Definition: connectionserial.h:108
Connection::Serial::parity
uint8_t parity
Definition: connectionserial.h:227
Connection::Serial::m_ConfigBaudRate
int m_ConfigBaudRate
Definition: connectionserial.h:231
indistandardproperty.h
Connection::Serial::wordSize
uint8_t wordSize
Definition: connectionserial.h:226
Connection::Interface::Handshake
std::function< bool()> Handshake
Definition: connectioninterface.h:129
Connection::usb_dev_file_select
int usb_dev_file_select(const dirent *entry)
Definition: connectionserial.cpp:405
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
IPS_OK
@ IPS_OK
Definition: indiapi.h:161
Connection::Serial::Connect
virtual bool Connect() override
Connect Connect to device via the implemented communication medium. Do not perform any handshakes.
Definition: connectionserial.cpp:199
ISwitch
One switch descriptor.
ISS_OFF
@ ISS_OFF
Definition: indiapi.h:150
indicom.h
Implementations for common driver routines.
Connection::Serial::stopBits
uint8_t stopBits
Definition: connectionserial.h:228
IDSetText
void IDSetText(const ITextVectorProperty *t, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing text vector property.
tty_disconnect
int tty_disconnect(int fd)
Closes a tty connection and flushes the bus.
Definition: indicom.c:1116
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
Connection::Serial::Refresh
bool Refresh(bool silent=false)
Definition: connectionserial.cpp:435
MAXINDINAME
#define MAXINDINAME
Definition: indiapi.h:190
INDI::DefaultDevice::isSimulation
bool isSimulation() const
Definition: defaultdevice.cpp:734
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
Connection::Serial::Serial
Serial(INDI::DefaultDevice *dev)
Definition: connectionserial.cpp:52
Connection::Serial::AutoSearchSP
ISwitchVectorProperty AutoSearchSP
Definition: connectionserial.h:215
IUFillTextVector
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:477
Connection::Serial::BLUETOOTH_DEV
@ BLUETOOTH_DEV
Definition: connectionserial.h:204
Connection::Serial::PortTP
ITextVectorProperty PortTP
Definition: connectionserial.h:208
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
Connection::Serial::~Serial
virtual ~Serial()
Definition: connectionserial.cpp:103
INDI::SP::DEVICE_BAUD_RATE
const char * DEVICE_BAUD_RATE
Set device baud rate.
Definition: indistandardproperty.cpp:66
IUFillText
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition: indidriver.c:369
IUUpdateText
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
Definition: indidriver.c:259
LOG_INFO
#define LOG_INFO(txt)
Definition: indilogger.h:74
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
IUResetSwitch
void IUResetSwitch(ISwitchVectorProperty *svp)
Reset all switches in a switch vector property to OFF.
Definition: indicom.c:1421
Connection::Serial::Disconnect
virtual bool Disconnect() override
Disconnect Disconnect from device.
Definition: connectionserial.cpp:331
Connection::Interface::getDeviceName
const char * getDeviceName()
Definition: connectioninterface.cpp:53
tty_error_msg
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1135
Connection::Serial::m_ConfigPort
std::string m_ConfigPort
Definition: connectionserial.h:230
IUFindOnSwitch
ISwitch * IUFindOnSwitch(const ISwitchVectorProperty *sp)
Returns the first ON switch it finds in the vector switch property.
Definition: indicom.c:1393
indilogger.h
Connection::Serial::name
virtual std::string name() override
Definition: connectionserial.h:95
Connection::Serial::setDefaultPort
void setDefaultPort(const char *port)
setDefaultPort Set default port. Call this function in initProperties() of your driver if you want to...
Definition: connectionserial.cpp:370
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
Connection::Serial::setDefaultBaudRate
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
Definition: connectionserial.cpp:375
IUGetConfigText
int IUGetConfigText(const char *dev, const char *property, const char *member, char *value, int len)
IUGetConfigText Opens configuration file and reads single text property.
Definition: indidriver.c:1447
Connection::Serial::SystemPortSP
ISwitchVectorProperty SystemPortSP
Definition: connectionserial.h:218
Connection::Serial::label
virtual std::string label() override
Definition: connectionserial.h:100
Connection::Serial::saveConfigItems
virtual bool saveConfigItems(FILE *fp) override
Definition: connectionserial.cpp:361
IUSaveConfigText
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition: indicom.c:1439
_ISwitchVectorProperty::nsp
int nsp
Definition: indiapi.h:386
LOGF_WARN
#define LOGF_WARN(fmt,...)
Definition: indilogger.h:81
IUFillSwitchVector
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidriver.c:412
ISR_1OFMANY
@ ISR_1OFMANY
Definition: indiapi.h:172
Connection::Interface::m_Device
INDI::DefaultDevice * m_Device
Definition: connectioninterface.h:130
connectionserial.h
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
Connection::CONNECTION_TAB
const char * CONNECTION_TAB
CONNECTION_TAB Where all device connection settings (serial, usb, ethernet) are defined and controlle...
Definition: connectioninterface.cpp:41
tty_connect
int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd)
Establishes a tty connection to a terminal device.
Definition: indicom.c:916
Connection::Serial::RefreshSP
ISwitchVectorProperty RefreshSP
Definition: connectionserial.h:221
ISR_ATMOST1
@ ISR_ATMOST1
Definition: indiapi.h:173
IUUpdateSwitch
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
Definition: indidriver.c:171
_ITextVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:249
Connection::Serial::m_SystemPorts
std::vector< std::string > m_SystemPorts
Definition: connectionserial.h:232
LOG_DEBUG
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
Connection::Serial::PortFD
int PortFD
Definition: connectionserial.h:223
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
Connection::Serial::ISNewText
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Definition: connectionserial.cpp:108
INDI::BaseDevice::INDI_ENABLED
@ INDI_ENABLED
Definition: basedevice.h:64
Connection::Serial::BaudRateSP
ISwitchVectorProperty BaudRateSP
Definition: connectionserial.h:212
Connection
Combines all INDI Connection Plugins. Each INDI connection plugin is responsible of managing communic...
Definition: arduino_st4.h:33
IUSaveText
void IUSaveText(IText *tp, const char *newtext)
Function to reliably save new text in a IText.
Definition: indicom.c:1428
Connection::Serial::AutoSearchS
ISwitch AutoSearchS[2]
Definition: connectionserial.h:214
_ISwitchVectorProperty::s
IPState s
Definition: indiapi.h:382
Connection::Serial::baud
virtual uint32_t baud()
Definition: connectionserial.cpp:381
Connection::Serial::ISNewSwitch
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Definition: connectionserial.cpp:137
_ITextVectorProperty::s
IPState s
Definition: indiapi.h:259
Connection::Serial::processHandshake
virtual bool processHandshake()
Definition: connectionserial.cpp:284
INDI::DefaultDevice::saveConfig
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
Definition: defaultdevice.cpp:221
IP_RW
@ IP_RW
Definition: indiapi.h:185
LOG_WARN
#define LOG_WARN(txt)
Definition: indilogger.h:73
INDI::SP::DEVICE_PORT
const char * DEVICE_PORT
Device serial (or bluetooth) connection port. The default value on Linux is /dev/ttyUSB0 while on Mac...
Definition: indistandardproperty.cpp:64
TTY_PORT_BUSY
@ TTY_PORT_BUSY
Definition: indicom.h:103
Connection::serial_dev_file_select
int serial_dev_file_select(const dirent *entry)
Definition: connectionserial.cpp:386
Connection::Serial::SystemPortS
ISwitch * SystemPortS
Definition: connectionserial.h:217
INDI::BaseDevice::INDI_DISABLED
@ INDI_DISABLED
Definition: basedevice.h:65
Connection::Serial::Deactivated
virtual void Deactivated() override
Deactivated Function called by the framework when the plugin is deactivated. It is usually used to de...
Definition: connectionserial.cpp:350
ISState
ISState
Switch state.
Definition: indiapi.h:148
INDI::SP::DEVICE_AUTO_SEARCH
const char * DEVICE_AUTO_SEARCH
Toggle device auto search. If enabled and on connection failure with the default port,...
Definition: indistandardproperty.cpp:65
IUGetConfigOnSwitchIndex
int IUGetConfigOnSwitchIndex(const char *dev, const char *property, int *index)
IUGetConfigOnSwitchIndex Opens configuration file and reads single switch property to find ON switch ...
Definition: indidriver.c:1270
IUFindOnSwitchIndex
int IUFindOnSwitchIndex(const ISwitchVectorProperty *sp)
Returns the index of first ON switch it finds in the vector switch property.
Definition: indicom.c:1403
Connection::Serial::PortT
IText PortT[1]
Definition: connectionserial.h:209
Connection::Serial::USB_ID_DEV
@ USB_ID_DEV
Definition: connectionserial.h:203
Connection::Serial::SERIAL_DEV
@ SERIAL_DEV
Definition: connectionserial.h:202
IUSaveConfigSwitch
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition: indicom.c:1444
INDI::DefaultDevice
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
Definition: defaultdevice.h:118
TTY_OK
@ TTY_OK
Definition: indicom.h:94
Connection::Serial::Activated
virtual void Activated() override
Activated Function called by the framework when the plugin is activated (i.e. selected by the user)....
Definition: connectionserial.cpp:341
PortTP
ITextVectorProperty PortTP
Definition: magellan1.cpp:64
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
Connection::Serial::BaudRateS
ISwitch BaudRateS[6]
Definition: connectionserial.h:211
Connection::bluetooth_dev_file_select
int bluetooth_dev_file_select(const dirent *entry)
Definition: connectionserial.cpp:420
IDSetSwitch
void void void void void IDSetSwitch(const ISwitchVectorProperty *s, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing switch vector property.
IUFillSwitch
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition: indidriver.c:320
_ISwitchVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:370
ISS_ON
@ ISS_ON
Definition: indiapi.h:151