Divecomputer download: try to offer only those devices that make sense

If the user selects a Uemis divecomputer, don't show serial devices.
If the user selects a serial divecomputer, don't show the Uemis
filesystem.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2014-05-18 13:29:40 +09:00
parent 6d42a99e7f
commit 047032ee46
7 changed files with 178 additions and 111 deletions

View file

@ -29,7 +29,7 @@ const char *system_default_filename(void)
return strdup(system_default_filename.toUtf8().data()); return strdup(system_default_filename.toUtf8().data());
} }
int enumerate_devices (device_callback_t callback, void *userdata) int enumerate_devices (device_callback_t callback, void *userdata, int dc_type)
{ {
/* FIXME: we need to enumerate in some other way on android */ /* FIXME: we need to enumerate in some other way on android */
/* qtserialport maybee? */ /* qtserialport maybee? */

View file

@ -55,7 +55,12 @@ extern int is_default_dive_computer_device(const char *);
extern int is_default_dive_computer(const char *, const char *); extern int is_default_dive_computer(const char *, const char *);
typedef void (*device_callback_t)(const char *name, void *userdata); typedef void (*device_callback_t)(const char *name, void *userdata);
int enumerate_devices(device_callback_t callback, void *userdata);
#define DC_TYPE_SERIAL 1
#define DC_TYPE_UEMIS 2
#define DC_TYPE_OTHER 3
int enumerate_devices(device_callback_t callback, void *userdata, int dc_type);
extern const char *default_dive_computer_vendor; extern const char *default_dive_computer_vendor;
extern const char *default_dive_computer_product; extern const char *default_dive_computer_product;

104
linux.c
View file

@ -49,78 +49,80 @@ const char *system_default_filename(void)
return buffer; return buffer;
} }
int enumerate_devices(device_callback_t callback, void *userdata) int enumerate_devices(device_callback_t callback, void *userdata, int dc_type)
{ {
int index = -1; int index = -1;
DIR *dp = NULL; DIR *dp = NULL;
struct dirent *ep = NULL; struct dirent *ep = NULL;
size_t i; size_t i;
const char *dirname = "/dev";
const char *patterns[] = {
"ttyUSB*",
"ttyS*",
"ttyACM*",
"rfcomm*",
NULL
};
FILE *file; FILE *file;
char *line = NULL; char *line = NULL;
char *fname; char *fname;
size_t len; size_t len;
if (dc_type != DC_TYPE_UEMIS) {
const char *dirname = "/dev";
const char *patterns[] = {
"ttyUSB*",
"ttyS*",
"ttyACM*",
"rfcomm*",
NULL
};
dp = opendir(dirname); dp = opendir(dirname);
if (dp == NULL) { if (dp == NULL) {
return -1; return -1;
} }
while ((ep = readdir(dp)) != NULL) { while ((ep = readdir(dp)) != NULL) {
for (i = 0; patterns[i] != NULL; ++i) { for (i = 0; patterns[i] != NULL; ++i) {
if (fnmatch(patterns[i], ep->d_name, 0) == 0) { if (fnmatch(patterns[i], ep->d_name, 0) == 0) {
char filename[1024]; char filename[1024];
int n = snprintf(filename, sizeof(filename), "%s/%s", dirname, ep->d_name); int n = snprintf(filename, sizeof(filename), "%s/%s", dirname, ep->d_name);
if (n >= sizeof(filename)) { if (n >= sizeof(filename)) {
closedir(dp); closedir(dp);
return -1; return -1;
}
callback(filename, userdata);
if (is_default_dive_computer_device(filename))
index = i;
break;
} }
callback(filename, userdata);
if (is_default_dive_computer_device(filename))
index = i;
break;
} }
} }
closedir(dp);
} }
closedir(dp); if (dc_type != DC_TYPE_SERIAL) {
file = fopen("/proc/mounts", "r");
if (file == NULL)
return index;
file = fopen("/proc/mounts", "r"); while ((getline(&line, &len, file)) != -1) {
if (file == NULL) char *ptr = strstr(line, "UEMISSDA");
return index; if (ptr) {
char *end = ptr, *start = ptr;
while (start > line && *start != ' ')
start--;
if (*start == ' ')
start++;
while (*end != ' ' && *end != '\0')
end++;
while ((getline(&line, &len, file)) != -1) { *end = '\0';
char *ptr = strstr(line, "UEMISSDA"); fname = strdup(start);
if (ptr) {
char *end = ptr, *start = ptr;
while (start > line && *start != ' ')
start--;
if (*start == ' ')
start++;
while (*end != ' ' && *end != '\0')
end++;
*end = '\0'; callback(fname, userdata);
fname = strdup(start);
callback(fname, userdata); if (is_default_dive_computer_device(fname))
index = i;
if (is_default_dive_computer_device(fname)) i++;
index = i; free((void *)fname);
i++; }
free((void *)fname);
} }
free(line);
fclose(file);
} }
free(line);
fclose(file);
return index; return index;
} }

55
macos.c
View file

@ -45,27 +45,52 @@ const char *system_default_filename(void)
return buffer; return buffer;
} }
int enumerate_devices(device_callback_t callback, void *userdata) int enumerate_devices(device_callback_t callback, void *userdata, int dc_type)
{ {
int index = -1; int index = -1;
DIR *dp = NULL; DIR *dp = NULL;
struct dirent *ep = NULL; struct dirent *ep = NULL;
size_t i; size_t i;
const char *dirname = "/dev"; if (dc_type != DC_TYPE_UEMIS) {
const char *patterns[] = { const char *dirname = "/dev";
"tty.*", const char *patterns[] = {
"usbserial", "tty.*",
NULL "usbserial",
}; NULL
};
dp = opendir(dirname); dp = opendir(dirname);
if (dp == NULL) { if (dp == NULL) {
return -1; 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;
}
}
}
closedir(dp);
} }
if (dc_type != DC_TYPE_SERIAL) {
const char *dirname = "/Volumes";
dp = opendir(dirname);
if (dp == NULL) {
return -1;
}
while ((ep = readdir(dp)) != NULL) { while ((ep = readdir(dp)) != NULL) {
for (i = 0; patterns[i] != NULL; ++i) { if (fnmatch("UEMISSDA", ep->d_name, 0) == 0) {
if (fnmatch(patterns[i], ep->d_name, 0) == 0) {
char filename[1024]; char filename[1024];
int n = snprintf(filename, sizeof(filename), "%s/%s", dirname, ep->d_name); int n = snprintf(filename, sizeof(filename), "%s/%s", dirname, ep->d_name);
if (n >= sizeof(filename)) { if (n >= sizeof(filename)) {
@ -78,10 +103,8 @@ int enumerate_devices(device_callback_t callback, void *userdata)
break; break;
} }
} }
closedir(dp);
} }
// TODO: list UEMIS mount point from /proc/mounts
closedir(dp);
return index; return index;
} }

View file

@ -56,7 +56,7 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) :
progress_bar_text = ""; progress_bar_text = "";
fill_device_list(); fill_device_list(DC_TYPE_OTHER);
fill_computer_list(); fill_computer_list();
ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked()); ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked());
@ -104,7 +104,7 @@ void DownloadFromDCWidget::updateState(states state)
return; return;
if (state == INITIAL) { if (state == INITIAL) {
fill_device_list(); fill_device_list(DC_TYPE_OTHER);
ui.progressBar->hide(); ui.progressBar->hide();
markChildrenAsEnabled(); markChildrenAsEnabled();
timer->stop(); timer->stop();
@ -176,6 +176,7 @@ void DownloadFromDCWidget::updateState(states state)
void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor) void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor)
{ {
int dcType = DC_TYPE_SERIAL;
QAbstractItemModel *currentModel = ui.product->model(); QAbstractItemModel *currentModel = ui.product->model();
if (!currentModel) if (!currentModel)
return; return;
@ -183,6 +184,10 @@ void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor)
productModel = new QStringListModel(productList[vendor]); productModel = new QStringListModel(productList[vendor]);
ui.product->setModel(productModel); ui.product->setModel(productModel);
if (vendor == QString("Uemis"))
dcType = DC_TYPE_UEMIS;
fill_device_list(dcType);
// Memleak - but deleting gives me a crash. // Memleak - but deleting gives me a crash.
//currentModel->deleteLater(); //currentModel->deleteLater();
} }
@ -429,11 +434,11 @@ static void fillDeviceList(const char *name, void *data)
comboBox->addItem(name); comboBox->addItem(name);
} }
void DownloadFromDCWidget::fill_device_list() void DownloadFromDCWidget::fill_device_list(int dc_type)
{ {
int deviceIndex; int deviceIndex;
ui.device->clear(); ui.device->clear();
deviceIndex = enumerate_devices(fillDeviceList, ui.device); deviceIndex = enumerate_devices(fillDeviceList, ui.device, dc_type);
if (deviceIndex >= 0) if (deviceIndex >= 0)
ui.device->setCurrentIndex(deviceIndex); ui.device->setCurrentIndex(deviceIndex);
} }

View file

@ -68,7 +68,7 @@ private:
QStringListModel *vendorModel; QStringListModel *vendorModel;
QStringListModel *productModel; QStringListModel *productModel;
void fill_computer_list(); void fill_computer_list();
void fill_device_list(); void fill_device_list(int dc_type);
QString logFile; QString logFile;
QString dumpFile; QString dumpFile;
QTimer *timer; QTimer *timer;

106
windows.c
View file

@ -36,56 +36,88 @@ const char *system_default_filename(void)
return buffer; return buffer;
} }
int enumerate_devices(device_callback_t callback, void *userdata) int enumerate_devices(device_callback_t callback, void *userdata, int dc_type)
{ {
// Open the registry key.
HKEY hKey;
int index = -1; 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;
}
DWORD i; DWORD i;
for (i = 0; i < count; ++i) { if (dc_type != DC_TYPE_UEMIS) {
// Get the value name, data and type. // Open the registry key.
char name[512], data[512]; HKEY hKey;
DWORD name_len = sizeof(name); LONG rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
DWORD data_len = sizeof(data); if (rc != ERROR_SUCCESS) {
DWORD type = 0; return -1;
rc = RegEnumValue(hKey, i, name, &name_len, NULL, &type, (LPBYTE)data, &data_len); }
// 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) { if (rc != ERROR_SUCCESS) {
RegCloseKey(hKey); RegCloseKey(hKey);
return -1; return -1;
} }
for (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. // Ignore non-string values.
if (type != REG_SZ) if (type != REG_SZ)
continue; continue;
// Prevent a possible buffer overflow. // Prevent a possible buffer overflow.
if (data_len >= sizeof(data)) { if (data_len >= sizeof(data)) {
RegCloseKey(hKey); RegCloseKey(hKey);
return -1; return -1;
}
// Null terminate the string.
data[data_len] = 0;
callback(data, userdata);
index++;
if (is_default_dive_computer_device(name))
index = i;
} }
// Null terminate the string. RegCloseKey(hKey);
data[data_len] = 0;
callback(data, userdata);
index++;
if (is_default_dive_computer_device(name))
index = i;
} }
if (dc_type != DC_TYPE_SERIAL) {
int i;
const int bufdef = 512;
const char *dlabels[] = {"UEMISSDA", NULL};
char bufname[bufdef], bufval[bufdef], *p;
DWORD bufname_len;
RegCloseKey(hKey); /* add drive letters that match labels */
memset(bufname, 0, bufdef);
bufname_len = bufdef;
if (GetLogicalDriveStringsA(bufname_len, bufname)) {
p = bufname;
while (*p) {
memset(bufval, 0, bufdef);
if (GetVolumeInformationA(p, bufval, bufdef, NULL, NULL, NULL, NULL, 0)) {
for (i = 0; dlabels[i] != NULL; i++)
if (!strcmp(bufval, dlabels[i])) {
char data[512];
snprintf(data, sizeof(data), "%s (%s)", p, dlabels[i]);
callback(data, userdata);
if (is_default_dive_computer_device(p))
index = i;
i++;
}
}
p = &p[strlen(p) + 1];
}
}
}
return index; return index;
} }