24std::string trimCRLF(std::string s)
26 s.erase(std::remove(s.begin(), s.end(),
'\r'), s.end());
27 s.erase(std::remove(s.begin(), s.end(),
'\n'), s.end());
34 hub->ISGetProperties(dev);
44void ISNewText(
const char *dev,
const char *name,
char *texts[],
char *names[],
int n)
61 return "StarTech Managed USB Hub";
73 for (uint8_t i = 0; i < USB_PORTS; i++)
76 snprintf(itemName,
sizeof(itemName),
"ALIAS_P%u", i + 1);
77 PortAliasesTP[i].
fill(itemName, defaultPortLabel(i + 1).c_str(),
"");
82 syncAliasesFromProperty(
true);
83 applyPortLabelsAndRedefineUSBProperties();
85 PortAliasesTP.
apply();
93 InfoTP[INFO_IDENTITY].
fill(
"IDENTITY",
"Model",
"N/A");
94 InfoTP[INFO_MASK].
fill(
"MASK",
"Current Mask",
"N/A");
99 for (uint8_t i = 0; i < USB_PORTS; i++)
102 snprintf(propName,
sizeof(propName),
"USB_PORT_%u", i + 1);
105 USBPortSP[i][SW_ON].fill(
"ON",
"On",
ISS_OFF);
106 USBPortSP[i][SW_OFF].fill(
"OFF",
"Off",
ISS_ON);
111 USBPortSP[i].onUpdate([
this, i]()
113 const bool enable = (USBPortSP[i][SW_ON].getState() ==
ISS_ON);
114 if (setUSBPortEnabled(i + 1, enable))
115 USBPortSP[i].setState(
IPS_OK);
119 USBPortSP[i].apply();
133 if (setAllPortsEnabled(enable))
158 for (
auto &p : USBPortSP)
166 syncAliasesFromProperty(
false);
167 committedAliases = portAliases;
168 applyPortLabelsAndRedefineUSBProperties();
176 for (
auto &p : USBPortSP)
182 portAliases = committedAliases;
183 for (uint8_t i = 0; i < USB_PORTS; i++)
184 PortAliasesTP[i].setText(portAliases[i].c_str());
202 if (strcmp(name,
"CONFIG_PROCESS") == 0)
205 bool doDefault =
false;
207 for (
int i = 0; i < n; i++)
209 if (states[i] !=
ISS_ON || names[i] ==
nullptr)
212 if (strcmp(names[i],
"CONFIG_LOAD") == 0)
214 else if (strcmp(names[i],
"CONFIG_DEFAULT") == 0)
222 syncAliasesFromProperty(
true);
223 committedAliases = portAliases;
224 applyPortLabelsAndRedefineUSBProperties();
225 PortAliasesTP.
apply();
230 for (uint8_t i = 0; i < USB_PORTS; i++)
231 PortAliasesTP[i].setText(
"");
233 PortAliasesTP.
apply();
235 syncAliasesFromProperty(
false);
236 applyPortLabelsAndRedefineUSBProperties();
248 PortAliasesTP.
save(fp);
249 committedAliases = portAliases;
263 if (getPortMask(mask))
265 if (mask != currentMask)
268 updatePortsFromMask(currentMask);
275void StarTechHub::syncAliasesFromProperty(
bool rewriteTruncated)
277 bool anyRewrite =
false;
279 for (uint8_t i = 0; i < USB_PORTS; i++)
281 bool wasTruncated =
false;
282 const std::string sanitized = sanitizeAlias(PortAliasesTP[i].
getText(), wasTruncated);
283 portAliases[i] = sanitized;
285 if (rewriteTruncated && wasTruncated)
287 PortAliasesTP[i].setText(sanitized.c_str());
294 LOGF_WARN(
"StarTechHub: one or more aliases were truncated to %zu characters.", ALIAS_MAX_LEN);
298std::string StarTechHub::sanitizeAlias(
const std::string &in,
bool &wasTruncated)
const
300 wasTruncated =
false;
303 size_t start = in.find_first_not_of(
" \t");
304 if (start == std::string::npos)
307 size_t end = in.find_last_not_of(
" \t");
308 std::string s = in.substr(start, end - start + 1);
310 if (s.size() > ALIAS_MAX_LEN)
312 s.resize(ALIAS_MAX_LEN);
319std::string StarTechHub::defaultPortLabel(uint8_t port)
const
321 std::ostringstream oss;
322 oss <<
"USB Port " <<
static_cast<unsigned>(port);
326void StarTechHub::applyPortLabelsAndRedefineUSBProperties()
329 for (uint8_t i = 0; i < USB_PORTS; i++)
331 const std::string lbl = portAliases[i].empty() ? defaultPortLabel(i + 1) : portAliases[i];
332 USBPortSP[i].setLabel(lbl.c_str());
339 for (
auto &p : USBPortSP)
351bool StarTechHub::sendCommand(
const std::string &
cmd, std::string &response)
356 const std::string fullCmd =
cmd +
"\r";
358 int nbytesWritten = 0;
367 buf[std::min(nbytesRead,
static_cast<int>(
sizeof(buf) - 1))] =
'\0';
368 response = trimCRLF(buf);
372bool StarTechHub::queryIdentity(std::string &out)
375 if (!sendCommand(CMD_GET_IDENTITY, rx))
382bool StarTechHub::getPortMask(uint32_t &mask)
385 if (!sendCommand(CMD_GET_MASK, rx))
390 LOGF_ERROR(
"StarTechHub: unexpected mask length '%s'", rx.c_str());
395 const unsigned long v = strtoul(rx.c_str(), &end, 16);
396 if (end ==
nullptr || *end !=
'\0')
398 LOGF_ERROR(
"StarTechHub: failed parsing mask '%s'", rx.c_str());
402 mask =
static_cast<uint32_t
>(v);
406bool StarTechHub::setPortMask(uint32_t mask)
408 std::ostringstream oss;
409 oss << std::uppercase << std::hex << std::setw(8) << std::setfill(
'0') << mask;
410 const std::string maskStr = oss.str();
412 const std::string
cmd = std::string(CMD_SET_MASK) + DEFAULT_PASS8 + maskStr;
415 if (!sendCommand(
cmd, rx))
418 const std::string expected = std::string(
"G") + maskStr;
421 LOGF_ERROR(
"StarTechHub: unexpected ACK '%s' (expected '%s')", rx.c_str(), expected.c_str());
426 updatePortsFromMask(currentMask);
430bool StarTechHub::setUSBPortEnabled(uint8_t port,
bool enabled)
432 if (port < 1 || port > USB_PORTS)
435 const uint8_t bit = 1u << (port - 1);
436 uint8_t top =
static_cast<uint8_t
>((currentMask >> 24) & 0xFF);
441 top &=
static_cast<uint8_t
>(~bit);
443 const uint32_t newMask = (currentMask & 0x00FFFFFFu) | (
static_cast<uint32_t
>(top) << 24);
444 return setPortMask(newMask);
447bool StarTechHub::setAllPortsEnabled(
bool enabled)
449 const uint32_t newMask = enabled ? (currentMask | 0xFF000000u)
450 : (currentMask & 0x00FFFFFFu);
451 return setPortMask(newMask);
454void StarTechHub::updatePortsFromMask(uint32_t mask)
457 std::ostringstream oss;
458 oss << std::uppercase << std::hex << std::setw(8) << std::setfill(
'0') << mask;
459 InfoTP[INFO_MASK].setText(oss.str().c_str());
462 const uint8_t top =
static_cast<uint8_t
>((mask >> 24) & 0xFF);
465 const uint8_t allBits = 0x7F;
466 if ((top & allBits) == allBits)
471 else if ((top & allBits) == 0)
486 for (uint8_t i = 0; i < USB_PORTS; i++)
488 const bool enabled = (top & (1u << i)) != 0;
491 USBPortSP[i].setState(
IPS_OK);
492 USBPortSP[i].apply();
496bool StarTechHub::Handshake()
504 if (ioctl(PortFD, TIOCMGET, &status) == 0)
506 status |= (TIOCM_DTR | TIOCM_RTS);
507 ioctl(PortFD, TIOCMSET, &status);
512 if (queryIdentity(ident))
513 InfoTP[INFO_IDENTITY].setText(ident.c_str());
515 InfoTP[INFO_IDENTITY].setText(
"NA");
519 if (!getPortMask(mask))
523 updatePortsFromMask(currentMask);
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the initial connection to the devic...
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
const char * getDeviceName() const
INDI::PropertyText getText(const char *name) const
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
virtual bool ISSnoopDevice(XMLEle *root)
Process a snoop event from INDI server. This function is called when a snooped property is updated in...
void setDriverInterface(uint32_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool loadConfig(bool silent=false, const char *property=nullptr)
Load the last saved configuration file.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
uint32_t getPollingPeriod() const
getPollingPeriod Return the polling period.
void defineProperty(INumberVectorProperty *property)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
const char * getName() const
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
void onUpdate(const std::function< void()> &callback)
bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
const char * getDefaultName() override
bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Implementations for common driver routines.
#define LOGF_WARN(fmt,...)
#define LOGF_ERROR(fmt,...)
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Update the value of an existing switch vector property.
void ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Update the value of an existing text vector property.
void ISGetProperties(const char *dev)
Get Device Properties.
void ISSnoopDevice(XMLEle *root)
Function defined by Drivers that is called when another Driver it is snooping (by having previously c...