summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Danilo Cesar Lemes de Paula <danilo.eu@gmail.com>2013-09-16 18:04:42 -0300
committerGravatar Danilo Cesar Lemes de Paula <danilo.eu@gmail.com>2013-09-16 22:40:47 -0300
commita8d33f80b0e8da4acb84028be0da8f33b81de0f9 (patch)
treed3813d817fd8407e79f58d68cffb393d8741db3d
parentf5b33dede359dccc31fafa72e0e2550868d8edd2 (diff)
downloadsubsurface-a8d33f80b0e8da4acb84028be0da8f33b81de0f9.tar.gz
implement device probe in C
It's an attempt to build auto-completion for the dive-computers based on unpublished code inside libdivecomputer[1] [1] - http://git.libdivecomputer.org/?p=libdivecomputer.git;a=commitdiff;h=d44053a99435fb9fc1f408fb3f1629a54c938afc Signed-off-by: Danilo Cesar Lemes de Paula <danilo.eu@gmail.com>
-rw-r--r--display.h4
-rw-r--r--linux.c46
-rw-r--r--macos.c44
-rw-r--r--qt-ui/downloadfromdivecomputer.cpp22
-rw-r--r--qt-ui/downloadfromdivecomputer.h1
-rw-r--r--qt-ui/downloadfromdivecomputer.ui6
-rw-r--r--windows.c53
7 files changed, 171 insertions, 5 deletions
diff --git a/display.h b/display.h
index b62ae3ba3..153a9368e 100644
--- a/display.h
+++ b/display.h
@@ -74,6 +74,10 @@ extern unsigned int amount_selected;
extern int is_default_dive_computer_device(const char *);
extern int is_default_dive_computer(const char *, const char *);
+
+typedef void (*device_callback_t) (const char *name, void *userdata);
+int enumerate_devices (device_callback_t callback, void *userdata);
+
extern const char *default_dive_computer_vendor;
extern const char *default_dive_computer_product;
extern const char *default_dive_computer_device;
diff --git a/linux.c b/linux.c
index 33a846f9b..f8d645abc 100644
--- a/linux.c
+++ b/linux.c
@@ -7,6 +7,9 @@
#endif
#include <gconf/gconf-client.h>
#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fnmatch.h>
const char system_divelist_default_font[] = "Sans 8";
@@ -211,3 +214,46 @@ gboolean subsurface_launch_for_uri(const char* uri)
return TRUE;
}
#endif /* USE_GTK_UI */
+
+
+int enumerate_devices (device_callback_t callback, void *userdata)
+{
+ int index = -1;
+ DIR *dp = NULL;
+ struct dirent *ep = NULL;
+ size_t i;
+ const char *dirname = "/dev";
+ const char *patterns[] = {
+ "ttyUSB*",
+ "ttyS*",
+ "ttyACM*",
+ "rfcomm*",
+ NULL
+ };
+
+ dp = opendir (dirname);
+ if (dp == NULL) {
+ return -1;
+ }
+
+ while ((ep = readdir (dp)) != NULL) {
+ for (i = 0; patterns[i] != NULL; ++i) {
+ if (fnmatch (patterns[i], ep->d_name, 0) == 0) {
+ char filename[1024];
+ int n = snprintf (filename, sizeof (filename), "%s/%s", dirname, ep->d_name);
+ if (n >= sizeof (filename)) {
+ closedir (dp);
+ return -1;
+ }
+ callback (filename, userdata);
+ if (is_default_dive_computer_device(filename))
+ index = i;
+ break;
+ }
+ }
+ }
+ // TODO: list UEMIS mount point from /proc/mounts
+
+ closedir (dp);
+ return index;
+}
diff --git a/macos.c b/macos.c
index 75c86edf2..f5f883e5c 100644
--- a/macos.c
+++ b/macos.c
@@ -106,8 +106,8 @@ int subsurface_fill_device_list(GtkListStore *store)
dev = g_dir_open("/dev", 0, NULL);
while (dev && (name = g_dir_read_name(dev)) != NULL) {
- if (strstr(name, "usbserial") ||
- (strstr(name, "SerialPort") && strstr(name, "cu"))) {
+ if (strstr(name, "usbserial") ||
+ (strstr(name, "SerialPort") && strstr(name, "cu"))) {
int len = strlen(name) + 6;
char *devicename = malloc(len);
snprintf(devicename, len, "/dev/%s", name);
@@ -263,3 +263,43 @@ gboolean subsurface_launch_for_uri(const char* uri)
return FALSE;
return TRUE;
}
+
+int enumerate_devices (device_callback_t callback, void *userdata)
+{
+ int index = -1;
+ DIR *dp = NULL;
+ struct dirent *ep = NULL;
+ size_t i;
+ const char *dirname = "/dev";
+ const char *patterns[] = {
+ "tty.*",
+ "usbserial",
+ NULL
+ };
+
+ dp = opendir (dirname);
+ if (dp == NULL) {
+ return -1;
+ }
+
+ while ((ep = readdir (dp)) != NULL) {
+ for (i = 0; patterns[i] != NULL; ++i) {
+ if (fnmatch (patterns[i], ep->d_name, 0) == 0) {
+ char filename[1024];
+ int n = snprintf (filename, sizeof (filename), "%s/%s", d irname, ep->d_name);
+ if (n >= sizeof (filename)) {
+ closedir (dp);
+ return -1;
+ }
+ callback (filename, userdata);
+ if (is_default_dive_computer_device(filename))
+ index = i;
+ break;
+ }
+ }
+ }
+ // TODO: list UEMIS mount point from /proc/mounts
+
+ closedir (dp);
+ return index;
+}
diff --git a/qt-ui/downloadfromdivecomputer.cpp b/qt-ui/downloadfromdivecomputer.cpp
index acdca89d3..52ef77d48 100644
--- a/qt-ui/downloadfromdivecomputer.cpp
+++ b/qt-ui/downloadfromdivecomputer.cpp
@@ -51,6 +51,8 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) :
ui->progressBar->hide();
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(100);
+
+ fill_device_list();
fill_computer_list();
vendorModel = new QStringListModel(vendorList);
@@ -63,7 +65,7 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) :
ui->product->setCurrentIndex(ui->product->findText(default_dive_computer_product));
}
if (default_dive_computer_device)
- ui->device->setText(default_dive_computer_device);
+ ui->device->setEditText(default_dive_computer_device);
timer->setInterval(200);
connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
@@ -89,6 +91,7 @@ void DownloadFromDCWidget::updateState(states state)
return;
if (state == INITIAL) {
+ fill_device_list();
ui->progressBar->hide();
markChildrenAsEnabled();
timer->stop();
@@ -217,7 +220,7 @@ void DownloadFromDCWidget::on_ok_clicked()
thread->deleteLater();
}
- data.devname = strdup(ui->device->text().toUtf8().data());
+ data.devname = strdup(ui->device->currentText().toUtf8().data());
data.vendor = strdup(ui->vendor->currentText().toUtf8().data());
data.product = strdup(ui->product->currentText().toUtf8().data());
@@ -285,6 +288,21 @@ void DownloadFromDCWidget::markChildrenAsEnabled()
ui->search->setDisabled(false);
}
+static void fillDeviceList(const char *name, void *data)
+{
+ QComboBox *comboBox = (QComboBox *)data;
+ comboBox->addItem(name);
+}
+
+void DownloadFromDCWidget::fill_device_list()
+{
+ int deviceIndex;
+ ui->device->clear();
+ deviceIndex = enumerate_devices(fillDeviceList, ui->device);
+ if (deviceIndex >= 0)
+ ui->device->setCurrentIndex(deviceIndex);
+}
+
DownloadThread::DownloadThread(QObject* parent, device_data_t* data): QThread(parent),
data(data)
{
diff --git a/qt-ui/downloadfromdivecomputer.h b/qt-ui/downloadfromdivecomputer.h
index e10d61b38..bef3d541d 100644
--- a/qt-ui/downloadfromdivecomputer.h
+++ b/qt-ui/downloadfromdivecomputer.h
@@ -65,6 +65,7 @@ private:
QStringListModel *vendorModel;
QStringListModel *productModel;
void fill_computer_list();
+ void fill_device_list();
QTimer *timer;
diff --git a/qt-ui/downloadfromdivecomputer.ui b/qt-ui/downloadfromdivecomputer.ui
index 41f9a4751..72e9c5ea1 100644
--- a/qt-ui/downloadfromdivecomputer.ui
+++ b/qt-ui/downloadfromdivecomputer.ui
@@ -42,7 +42,11 @@
</widget>
</item>
<item row="3" column="0" colspan="2">
- <widget class="QLineEdit" name="device"/>
+ <widget class="QComboBox" name="device">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
</item>
<item row="3" column="2">
<widget class="QToolButton" name="search">
diff --git a/windows.c b/windows.c
index d6cb531ae..de2ef9a45 100644
--- a/windows.c
+++ b/windows.c
@@ -333,3 +333,56 @@ gboolean subsurface_os_feature_available(os_feature_t f)
return TRUE;
}
}
+
+int enumerate_devices (device_callback_t callback, void *userdata)
+{
+ // Open the registry key.
+ HKEY hKey;
+ int index = -1;
+ LONG rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
+ if (rc != ERROR_SUCCESS) {
+ return -1;
+ }
+
+ // Get the number of values.
+ DWORD count = 0;
+ rc = RegQueryInfoKey (hKey, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL);
+ if (rc != ERROR_SUCCESS) {
+ RegCloseKey(hKey);
+ return -1;
+ }
+
+ for (DWORD i = 0; i < count; ++i) {
+ // Get the value name, data and type.
+ char name[512], data[512];
+ DWORD name_len = sizeof (name);
+ DWORD data_len = sizeof (data);
+ DWORD type = 0;
+ rc = RegEnumValue (hKey, i, name, &name_len, NULL, &type, (LPBYTE) data, &data_len);
+ if (rc != ERROR_SUCCESS) {
+ RegCloseKey(hKey);
+ return -1;
+ }
+
+ // Ignore non-string values.
+ if (type != REG_SZ)
+ continue;
+
+ // Prevent a possible buffer overflow.
+ if (data_len >= sizeof (data)) {
+ RegCloseKey(hKey);
+ return -1;
+ }
+
+ // Null terminate the string.
+ data[data_len] = 0;
+
+ callback (data, userdata);
+ index++;
+ if (is_default_dive_computer_device(filename))
+ index = i;
+ }
+
+ RegCloseKey(hKey);
+ return index;
+}