summaryrefslogtreecommitdiffstats
path: root/tools/runonphone
diff options
context:
space:
mode:
authorThomas Zander <t.zander@nokia.com>2010-03-18 16:40:30 +0100
committerThomas Zander <t.zander@nokia.com>2010-03-19 09:44:29 +0100
commita34c82bb5a0a0e6c2bdccfef5fb31e7a0667c906 (patch)
tree79e762de08576ecf108db1c4da3a879366ceddb1 /tools/runonphone
parentd758a688f037d8d369e4150dda322736ce6b5346 (diff)
Use libusb to auto-detect the port to use to communicate with the phone
Diffstat (limited to 'tools/runonphone')
-rw-r--r--tools/runonphone/main.cpp26
-rw-r--r--tools/runonphone/runonphone.pro3
-rw-r--r--tools/runonphone/serenum_unix.cpp71
3 files changed, 85 insertions, 15 deletions
diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp
index 65085e067e..af08777fea 100644
--- a/tools/runonphone/main.cpp
+++ b/tools/runonphone/main.cpp
@@ -136,22 +136,22 @@ int main(int argc, char *argv[])
if (serialPortName.isEmpty()) {
if (loglevel > 0)
outstream << "Detecting serial ports" << endl;
- QList <SerialPortId> ports = enumerateSerialPorts();
- foreach(SerialPortId id, ports) {
+ foreach (const SerialPortId &id, enumerateSerialPorts()) {
if (loglevel > 0)
outstream << "Port Name: " << id.portName << ", "
<< "Friendly Name:" << id.friendlyName << endl;
- if (serialPortName.isEmpty()) {
- if (!id.friendlyName.isEmpty()
- && serialPortFriendlyName.isEmpty()
- && (id.friendlyName.contains("symbian", Qt::CaseInsensitive)
- || id.friendlyName.contains("s60", Qt::CaseInsensitive)
- || id.friendlyName.contains("nokia", Qt::CaseInsensitive)))
- serialPortName = id.portName;
- else if (!id.friendlyName.isEmpty()
- && !serialPortFriendlyName.isEmpty()
- && id.friendlyName.contains(serialPortFriendlyName))
- serialPortName = id.portName;
+ if (!id.friendlyName.isEmpty()
+ && serialPortFriendlyName.isEmpty()
+ && (id.friendlyName.contains("symbian", Qt::CaseInsensitive)
+ || id.friendlyName.contains("s60", Qt::CaseInsensitive)
+ || id.friendlyName.contains("nokia", Qt::CaseInsensitive))) {
+ serialPortName = id.portName;
+ break;
+ } else if (!id.friendlyName.isEmpty()
+ && !serialPortFriendlyName.isEmpty()
+ && id.friendlyName.contains(serialPortFriendlyName)) {
+ serialPortName = id.portName;
+ break;
}
}
if (serialPortName.isEmpty()) {
diff --git a/tools/runonphone/runonphone.pro b/tools/runonphone/runonphone.pro
index 7bed3e5517..0c63723843 100644
--- a/tools/runonphone/runonphone.pro
+++ b/tools/runonphone/runonphone.pro
@@ -22,7 +22,10 @@ windows {
}
else:unix:!symbian {
SOURCES += serenum_unix.cpp
+ LIBS += -lusb
}
else {
SOURCES += serenum_stub.cpp
}
+
+
diff --git a/tools/runonphone/serenum_unix.cpp b/tools/runonphone/serenum_unix.cpp
index c8ec02103b..b6f02935e7 100644
--- a/tools/runonphone/serenum_unix.cpp
+++ b/tools/runonphone/serenum_unix.cpp
@@ -46,13 +46,80 @@
#include <QFileInfo>
#include <QDir>
+#include <usb.h>
+
QList<SerialPortId> enumerateSerialPorts()
{
+ QList<QString> eligableInterfaces;
QList<SerialPortId> list;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ for (struct usb_bus *bus = usb_get_busses(); bus; bus = bus->next) {
+ for (struct usb_device *device = bus->devices; device; device = device->next) {
+ for (int n = 0; n < device->descriptor.bNumConfigurations; ++n) {
+ struct usb_config_descriptor &usbConfig =device->config[n];
+ QList<int> usableInterfaces;
+ for (int m = 0; m < usbConfig.bNumInterfaces; ++m) {
+ for (int o = 0; o < usbConfig.interface[m].num_altsetting; ++o) {
+ struct usb_interface_descriptor &descriptor = usbConfig.interface[m].altsetting[o];
+ if (descriptor.bInterfaceClass != 2 // "Communication"
+ || descriptor.bInterfaceSubClass != 2 // Abstract (modem)
+ || descriptor.bInterfaceProtocol != 255) // Vendor Specific
+ continue;
+
+ unsigned char *buf = descriptor.extra;
+ unsigned int size = descriptor.extralen;
+ while (size >= 2 * sizeof(u_int8_t)) {
+ // for Communication devices there is a slave interface for the actual
+ // data transmission.
+ // the extra info stores that as a index for the interface
+ if (buf[0] >= 5 && buf[1] == 36 && buf[2] == 6) { // CDC Union
+ for (int i = 4; i < buf[0]; i++)
+ usableInterfaces.append((int) buf[i]);
+ }
+ size -= buf[0];
+ buf += buf[0];
+ }
+ }
+ }
+
+ // second loop to find the actual data interface.
+ foreach (int i, usableInterfaces) {
+ for (int m = 0; m < usbConfig.bNumInterfaces; ++m) {
+ for (int o = 0; o < usbConfig.interface[m].num_altsetting; ++o) {
+ struct usb_interface_descriptor &descriptor = usbConfig.interface[m].altsetting[o];
+ if (descriptor.bInterfaceNumber != i)
+ continue;
+ if (descriptor.bInterfaceClass == 10) { // "CDC Data"
+ // qDebug() << " found the data port"
+ // << "bus:" << bus->dirname
+ // << "device" << device->filename
+ // << "interface" << descriptor.bInterfaceNumber;
+ eligableInterfaces << QString("if%1").arg(QString::number(i), 2, QChar('0')); // fix!
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
QDir dir("/dev/serial/by-id/");
- QFileInfoList ports(dir.entryInfoList());
- foreach (const QFileInfo &info, ports) {
+ foreach (const QFileInfo &info, dir.entryInfoList()) {
if (!info.isDir()) {
+ bool usable = eligableInterfaces.isEmpty();
+ foreach (const QString &iface, eligableInterfaces) {
+ if (info.fileName().contains(iface)) {
+ usable = true;
+ break;
+ }
+ }
+ if (!usable)
+ continue;
+
SerialPortId id;
id.friendlyName = info.fileName();
id.portName = info.canonicalFilePath();