Add macOS USB UART support
Ubuntu build / build-and-test (ubuntu-22.04) (push) Has been cancelled
Ubuntu build / build-and-test (ubuntu-24.04) (push) Has been cancelled

This commit is contained in:
2026-07-18 12:03:38 +03:00
parent 851642296a
commit 049f6301e8
8 changed files with 279 additions and 48 deletions
+79 -13
View File
@@ -212,6 +212,45 @@ QString optionalDopText(const std::optional<double> &value)
return QString::number(*value, 'f', 3);
}
QStringList detectedSerialPorts()
{
const QDir deviceDirectory(QStringLiteral("/dev"));
QStringList patterns;
#ifdef Q_OS_MACOS
// macOS exposes USB UARTs as paired callout (cu.*) and terminal (tty.*)
// devices. Prefer cu.* because it does not wait for carrier detect.
patterns = {
QStringLiteral("cu.usb*"), QStringLiteral("cu.wchusbserial*"),
QStringLiteral("cu.SLAB_USBtoUART*"), QStringLiteral("cu.*USB*"),
QStringLiteral("tty.usb*"), QStringLiteral("tty.wchusbserial*"),
QStringLiteral("tty.SLAB_USBtoUART*"), QStringLiteral("tty.*USB*")};
#else
patterns = {QStringLiteral("ttyUSB*"), QStringLiteral("ttyACM*")};
#endif
QStringList ports;
for (const QString &pattern : patterns) {
const QStringList names = deviceDirectory.entryList(
{pattern}, QDir::System | QDir::Files, QDir::Name);
for (const QString &name : names) {
const QString path = QStringLiteral("/dev/") + name;
if (!ports.contains(path)) {
ports.push_back(path);
}
}
}
return ports;
}
QString fallbackSerialPort()
{
#ifdef Q_OS_MACOS
return QStringLiteral("/dev/cu.usbserial");
#else
return QStringLiteral("/dev/ttyUSB2");
#endif
}
void mergeDopValues(DopValues &target, const DopValues &source)
{
if (source.gdop.has_value()) {
@@ -425,6 +464,34 @@ void MainWindow::openTelemetryLog()
}
}
void MainWindow::refreshSerialPorts()
{
const QString previousPort = m_portCombo->currentText().trimmed();
const QString configuredPort = qEnvironmentVariable("LOCATION_PLOTTER_PORT").trimmed();
const QStringList detectedPorts = detectedSerialPorts();
m_portCombo->clear();
for (const QString &port : detectedPorts) {
m_portCombo->addItem(port);
}
QString selectedPort;
if (!configuredPort.isEmpty()) {
selectedPort = configuredPort;
} else if (!previousPort.isEmpty() && detectedPorts.contains(previousPort)) {
selectedPort = previousPort;
} else if (!detectedPorts.isEmpty()) {
selectedPort = detectedPorts.first();
} else {
selectedPort = previousPort.isEmpty() ? fallbackSerialPort() : previousPort;
}
if (m_portCombo->findText(selectedPort) < 0) {
m_portCombo->addItem(selectedPort);
}
m_portCombo->setCurrentText(selectedPort);
}
void MainWindow::handleSerialLine(const QString &line)
{
static const QRegularExpression solveStartRegex(
@@ -727,19 +794,16 @@ void MainWindow::buildUi()
m_portCombo = new QComboBox(this);
m_portCombo->setObjectName(QStringLiteral("portSelector"));
m_portCombo->setMinimumWidth(165);
m_portCombo->setEditable(false);
QDir deviceDirectory(QStringLiteral("/dev"));
const QStringList deviceNames = deviceDirectory.entryList(
{QStringLiteral("ttyUSB*")},
QDir::System | QDir::Files | QDir::Readable, QDir::Name);
for (const QString &deviceName : deviceNames) {
m_portCombo->addItem(QStringLiteral("/dev/") + deviceName);
}
if (m_portCombo->findText(QStringLiteral("/dev/ttyUSB2")) < 0) {
m_portCombo->addItem(QStringLiteral("/dev/ttyUSB2"));
}
m_portCombo->setCurrentText(QStringLiteral("/dev/ttyUSB2"));
m_portCombo->setMinimumWidth(220);
m_portCombo->setEditable(true);
m_portCombo->setToolTip(QStringLiteral(
"USB UART portu. macOS'ta /dev/cu.usb... tercih edilir; /dev/tty.usb... da desteklenir."));
refreshSerialPorts();
auto *refreshPortsButton = new QToolButton(this);
refreshPortsButton->setObjectName(QStringLiteral("refreshPortsButton"));
refreshPortsButton->setText(QStringLiteral("Yenile"));
refreshPortsButton->setToolTip(QStringLiteral("Seri port listesini yenile"));
m_baudCombo = new QComboBox(this);
for (const int baud : {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600}) {
@@ -773,6 +837,7 @@ void MainWindow::buildUi()
toolbarLayout->addWidget(new QLabel(QStringLiteral("Port"), this));
toolbarLayout->addWidget(m_portCombo);
toolbarLayout->addWidget(refreshPortsButton);
toolbarLayout->addWidget(new QLabel(QStringLiteral("Baud"), this));
toolbarLayout->addWidget(m_baudCombo);
toolbarLayout->addWidget(new QLabel(QStringLiteral("Max"), this));
@@ -996,6 +1061,7 @@ void MainWindow::buildUi()
connect(m_connectButton, &QPushButton::clicked, this, &MainWindow::toggleSerial);
connect(m_clearButton, &QPushButton::clicked, this, &MainWindow::clearPoints);
connect(m_openLogButton, &QPushButton::clicked, this, &MainWindow::openTelemetryLog);
connect(refreshPortsButton, &QToolButton::clicked, this, &MainWindow::refreshSerialPorts);
connect(m_maxPointsSpin, qOverload<int>(&QSpinBox::valueChanged), this,
&MainWindow::trimToMaxPoints);
connect(m_autoFollowCheck, &QCheckBox::toggled, m_map, &MapWidget::setAutoFollow);