The kde@ team presents KDE SC 4.14.3, the last planed release of the KDE SC 4 series. In addition to the updates provided by the KDE SC developers, this update also addresses numerous FreeBSD and PORTS specific issues, found and solved by the kde@ team and area51 testers, most notorously Tobias C. Berner <tcberner@gmail.com> PR: 197751 PR: 197871 PR: 184996 Reviewed by: rakuco (mentor) Differential: https://reviews.freebsd.org/D1950
493 lines
14 KiB
Text
493 lines
14 KiB
Text
Use libusb-1 to query info about usb devices on all platforms, leave old
|
|
method as a fallback for Linux only.
|
|
Remove *BSD specific code, it doesn't work on FreeBSD 8.x and greater.
|
|
Old code probably works on NetBSD, but let it use libusb-1 as well.
|
|
Use DeviceNotifier instead of polling.
|
|
|
|
--- /dev/null
|
|
+++ cmake/modules/FindLibUSB1.cmake
|
|
@@ -0,0 +1,21 @@
|
|
+# - Try to find libusb v1.0 library
|
|
+# Once done this defines
|
|
+#
|
|
+# LIBUSB1_FOUND - system has libusb
|
|
+# LIBUSB1_INCLUDE_DIR - libusb include directory
|
|
+# LIBUSB1_LIBRARY - libusb library
|
|
+
|
|
+find_package(PkgConfig)
|
|
+pkg_check_modules(PC_LIBUSB1 QUIET libusb-1.0)
|
|
+
|
|
+find_path(LIBUSB1_INCLUDE_DIR libusb.h
|
|
+ HINTS ${PC_LIBUSB1_INCLUDEDIR} ${PC_LIBUSB1_INCLUDE_DIRS})
|
|
+
|
|
+# On FreeBSD libusb provides both v0.1 and v1.0 API
|
|
+find_library(LIBUSB1_LIBRARY NAMES usb-1.0 usb
|
|
+ HINTS ${PC_LIBUSB1_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS})
|
|
+
|
|
+include(FindPackageHandleStandardArgs)
|
|
+find_package_handle_standard_args(LIBUSB1 DEFAULT_MSG LIBUSB1_LIBRARY LIBUSB1_INCLUDE_DIR)
|
|
+
|
|
+mark_as_advanced(LIBUSB1_INCLUDE_DIR LIBUSB1_LIBRARY)
|
|
--- kinfocenter/Modules/usbview/CMakeLists.txt
|
|
+++ kinfocenter/Modules/usbview/CMakeLists.txt
|
|
@@ -1,15 +1,25 @@
|
|
+macro_optional_find_package(LibUSB1)
|
|
+macro_bool_to_01(LIBUSB1_FOUND HAVE_LIBUSB1)
|
|
+macro_log_feature(LIBUSB1_FOUND "libusb-1" "User level access to USB devices" "http://libusb.sourceforge.net/" FALSE "" "Provides usb info support in KControl.")
|
|
|
|
-
|
|
+configure_file (config-kcmusb.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kcmusb.h )
|
|
|
|
########### next target ###############
|
|
|
|
+if (LIBUSB1_FOUND)
|
|
+ include_directories( ${LIBUSB1_INCLUDE_DIR} )
|
|
+endif (LIBUSB1_FOUND)
|
|
+
|
|
set(kcm_usb_PART_SRCS kcmusb.cpp usbdevices.cpp usbdb.cpp )
|
|
|
|
|
|
kde4_add_plugin(kcm_usb ${kcm_usb_PART_SRCS})
|
|
|
|
|
|
-target_link_libraries(kcm_usb ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY})
|
|
+target_link_libraries(kcm_usb ${KDE4_KDEUI_LIBS} ${KDE4_SOLID_LIBS} ${QT_QTGUI_LIBRARY})
|
|
+if (LIBUSB1_FOUND)
|
|
+ target_link_libraries(kcm_usb ${LIBUSB1_LIBRARY})
|
|
+endif (LIBUSB1_FOUND)
|
|
|
|
install(TARGETS kcm_usb DESTINATION ${PLUGIN_INSTALL_DIR} )
|
|
|
|
--- /dev/null
|
|
+++ kinfocenter/Modules/usbview/config-kcmusb.h.cmake
|
|
@@ -0,0 +1,2 @@
|
|
+/* Defined if you have libusb */
|
|
+#cmakedefine HAVE_LIBUSB1 1
|
|
--- kinfocenter/Modules/usbview/kcmusb.cpp
|
|
+++ kinfocenter/Modules/usbview/kcmusb.cpp
|
|
@@ -12,7 +12,6 @@
|
|
#include <QLayout>
|
|
#include <QSplitter>
|
|
#include <QtGui/QTextEdit>
|
|
-#include <QTimer>
|
|
#include <QHBoxLayout>
|
|
#include <QList>
|
|
#include <QTreeWidget>
|
|
@@ -20,6 +19,7 @@
|
|
|
|
#include <kaboutdata.h>
|
|
#include <kdialog.h>
|
|
+#include <solid/devicenotifier.h>
|
|
|
|
#include <KPluginFactory>
|
|
#include <KPluginLoader>
|
|
@@ -63,11 +63,8 @@ USBViewer::USBViewer(QWidget *parent, const QVariantList &) :
|
|
_details = new QTextEdit(splitter);
|
|
_details->setReadOnly(true);
|
|
|
|
- QTimer *refreshTimer = new QTimer(this);
|
|
- // 1 sec seems to be a good compromise between latency and polling load.
|
|
- refreshTimer->start(1000);
|
|
-
|
|
- connect(refreshTimer, SIGNAL(timeout()), SLOT(refresh()));
|
|
+ connect(Solid::DeviceNotifier::instance(),SIGNAL(deviceAdded(QString)), SLOT(refresh()));
|
|
+ connect(Solid::DeviceNotifier::instance(),SIGNAL(deviceRemoved(const QString)), SLOT(refresh()));
|
|
connect(_devices, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(selectionChanged(QTreeWidgetItem*)));
|
|
|
|
KAboutData *about = new KAboutData(I18N_NOOP("kcmusb"), 0, ki18n("KDE USB Viewer"),
|
|
@@ -113,8 +110,12 @@ static void delete_recursive(QTreeWidgetItem *item, const QMap<int, QTreeWidgetI
|
|
void USBViewer::refresh() {
|
|
QMap<int, QTreeWidgetItem*> new_items;
|
|
|
|
+#if defined(HAVE_LIBUSB1)
|
|
+ USBDevice::parse();
|
|
+#else
|
|
if (!USBDevice::parse("/proc/bus/usb/devices"))
|
|
USBDevice::parseSys("/sys/bus/usb/devices");
|
|
+#endif
|
|
|
|
int level = 0;
|
|
bool found = true;
|
|
--- kinfocenter/Modules/usbview/usbdevices.cpp
|
|
+++ kinfocenter/Modules/usbview/usbdevices.cpp
|
|
@@ -27,9 +27,9 @@
|
|
|
|
#include <math.h>
|
|
|
|
-#if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
|
|
-#include <sys/ioctl.h>
|
|
-#include <sys/param.h>
|
|
+#include <config-kcmusb.h>
|
|
+#if defined(HAVE_LIBUSB1)
|
|
+#include <libusb.h>
|
|
#endif
|
|
|
|
QList<USBDevice*> USBDevice::_devices;
|
|
@@ -48,6 +48,7 @@ USBDevice::~USBDevice() {
|
|
|
|
}
|
|
|
|
+#if !defined(HAVE_LIBUSB1)
|
|
static QString catFile(QString fname) {
|
|
char buffer[256];
|
|
QString result;
|
|
@@ -129,6 +130,7 @@ void USBDevice::parseLine(const QString& line) {
|
|
} else if (line.startsWith("P:"))
|
|
sscanf(line.toLocal8Bit().data(), "P: Vendor=%x ProdID=%x Rev=%x.%x", &_vendorID, &_prodID, &_revMajor, &_revMinor);
|
|
}
|
|
+#endif // !defined(HAVE_LIBUSB1)
|
|
|
|
USBDevice* USBDevice::find(int bus, int device) {
|
|
foreach(USBDevice* usbDevice, _devices) {
|
|
@@ -160,6 +162,10 @@ QString USBDevice::dump() {
|
|
|
|
r += "<br/><table>";
|
|
|
|
+ r += i18n("<tr><td><i>Bus number</i></td><td>%1</td></tr>", _bus);
|
|
+ r += i18n("<tr><td><i>Device address</i></td><td>%1</td></tr>", _device);
|
|
+ r += "<tr><td></td></tr>";
|
|
+
|
|
QString c = QString("<td>%1</td>").arg(_class);
|
|
QString cname = _db->cls(_class);
|
|
if (!cname.isEmpty())
|
|
@@ -175,11 +181,9 @@ QString USBDevice::dump() {
|
|
if (!prname.isEmpty())
|
|
pr += "<td>(" + prname +")</td>";
|
|
r += i18n("<tr><td><i>Protocol</i></td>%1</tr>", pr);
|
|
-#if !(defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD))
|
|
r += ki18n("<tr><td><i>USB Version</i></td><td>%1.%2</td></tr>")
|
|
.subs(_verMajor,0,16).subs(_verMinor,2,16,QChar::fromLatin1('0'))
|
|
.toString();
|
|
-#endif
|
|
r += "<tr><td></td></tr>";
|
|
|
|
QString v = QString::number(_vendorID, 16);
|
|
@@ -198,22 +202,15 @@ QString USBDevice::dump() {
|
|
r += "<tr><td></td></tr>";
|
|
|
|
r += i18n("<tr><td><i>Speed</i></td><td>%1 Mbit/s</td></tr>", _speed);
|
|
- r += i18n("<tr><td><i>Channels</i></td><td>%1</td></tr>", _channels);
|
|
-#if (defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)) && !defined(DISABLE_USBDEVICES_FREEBSD)
|
|
- if ( _power )
|
|
+#if defined(HAVE_LIBUSB1)
|
|
+ if ( _power != -1 )
|
|
r += i18n("<tr><td><i>Power Consumption</i></td><td>%1 mA</td></tr>", _power);
|
|
else
|
|
- r += i18n("<tr><td><i>Power Consumption</i></td><td>self powered</td></tr>");
|
|
- r += i18n("<tr><td><i>Attached Devicenodes</i></td><td>%1</td></tr>", _devnodes.at(0));
|
|
- if ( _devnodes.count() > 1 ) {
|
|
- QStringList::const_iterator it = _devnodes.constBegin();
|
|
- ++it;
|
|
- for (; it != _devnodes.constEnd(); ++it )
|
|
- r += "<tr><td></td><td>" + *it + "</td></tr>";
|
|
- }
|
|
-#else
|
|
+ r += i18n("<tr><td><i>Power Consumption</i></td><td>unknown</td></tr>");
|
|
+#else // defined(HAVE_LIBUSB1)
|
|
+ r += i18n("<tr><td><i>Channels</i></td><td>%1</td></tr>", _channels);
|
|
+#endif // defined(HAVE_LIBUSB1)
|
|
r += i18n("<tr><td><i>Max. Packet Size</i></td><td>%1</td></tr>", _maxPacketSize);
|
|
-#endif
|
|
r += "<tr><td></td></tr>";
|
|
|
|
if (_hasBW) {
|
|
@@ -228,7 +225,82 @@ QString USBDevice::dump() {
|
|
return r;
|
|
}
|
|
|
|
-#if !(defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD))
|
|
+#if defined(HAVE_LIBUSB1)
|
|
+
|
|
+void USBDevice::dump_usbdev_info(libusb_device *dev) {
|
|
+
|
|
+ _bus = libusb_get_bus_number(dev);
|
|
+ _device = libusb_get_device_address(dev);
|
|
+
|
|
+ switch (libusb_get_device_speed(dev)) {
|
|
+ case LIBUSB_SPEED_LOW: _speed = 1.5; break;
|
|
+ case LIBUSB_SPEED_FULL: _speed = 12; break;
|
|
+ case LIBUSB_SPEED_HIGH: _speed = 480; break;
|
|
+ case LIBUSB_SPEED_SUPER: _speed = 5000; break;
|
|
+ }
|
|
+
|
|
+ struct libusb_config_descriptor *conf;
|
|
+ if (libusb_get_active_config_descriptor(dev, &conf) == 0) {
|
|
+ _power = conf->MaxPower;
|
|
+ libusb_free_config_descriptor(conf);
|
|
+ } else {
|
|
+ _power = -1;
|
|
+ }
|
|
+
|
|
+ struct libusb_device_descriptor desc;
|
|
+ if (libusb_get_device_descriptor(dev, &desc) == 0) {
|
|
+ _verMajor = desc.bcdUSB >> 8;
|
|
+ _verMinor = desc.bcdUSB & 0x00FF;
|
|
+ _class = desc.bDeviceClass;
|
|
+ _sub = desc.bDeviceSubClass;
|
|
+ _prot = desc.bDeviceProtocol;
|
|
+ _maxPacketSize = desc.bMaxPacketSize0;
|
|
+ _configs = desc.bNumConfigurations;
|
|
+ _vendorID = desc.idVendor;
|
|
+ _prodID = desc.idProduct;
|
|
+ _revMajor = desc.bcdDevice >> 8;
|
|
+ _revMinor = desc.bcdDevice & 0x00FF;
|
|
+ }
|
|
+
|
|
+ libusb_device_handle *hdev;
|
|
+ uchar buf[256];
|
|
+ if (libusb_open(dev, &hdev) == 0) {
|
|
+ if (libusb_get_string_descriptor_ascii(hdev, desc.iManufacturer, buf, sizeof(buf)) > 0)
|
|
+ _manufacturer = (char*) buf;
|
|
+ if (libusb_get_string_descriptor_ascii(hdev, desc.iProduct, buf, sizeof(buf)) > 0)
|
|
+ _product = (char*) buf;
|
|
+ if (libusb_get_string_descriptor_ascii(hdev, desc.iSerialNumber, buf, sizeof(buf)) > 0)
|
|
+ _serial = (char*) buf;
|
|
+ libusb_close(hdev);
|
|
+ }
|
|
+}
|
|
+
|
|
+bool USBDevice::parse() {
|
|
+ _devices.clear();
|
|
+
|
|
+ int r = libusb_init(NULL);
|
|
+ if (r != 0)
|
|
+ return false;
|
|
+
|
|
+ libusb_device **devs;
|
|
+ ssize_t cnt = libusb_get_device_list(NULL, &devs);
|
|
+ if (cnt < 0)
|
|
+ return false;
|
|
+
|
|
+ libusb_device *dev;
|
|
+ int i = 0;
|
|
+ while ((dev = devs[i++]) != NULL) {
|
|
+ USBDevice* device = new USBDevice();
|
|
+ device->dump_usbdev_info(dev);
|
|
+ }
|
|
+ libusb_free_device_list(devs, 1);
|
|
+
|
|
+ libusb_exit(NULL);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+#else // defined(HAVE_LIBUSB1)
|
|
+#if defined(Q_OS_LINUX)
|
|
bool USBDevice::parse(const QString &fname) {
|
|
_devices.clear();
|
|
|
|
@@ -290,146 +362,19 @@ bool USBDevice::parseSys(const QString &dname) {
|
|
return d.count();
|
|
}
|
|
|
|
-#else
|
|
-
|
|
-// Unused by *BSD
|
|
-bool USBDevice::parseSys(const QString &fname)
|
|
-{
|
|
- Q_UNUSED(fname)
|
|
-
|
|
- return true;
|
|
-}
|
|
-
|
|
-# if defined(DISABLE_USBDEVICES_FREEBSD)
|
|
-
|
|
-/*
|
|
- * FIXME: The USB subsystem has changed a lot in FreeBSD 8.0
|
|
- * Support for it must be written.
|
|
- */
|
|
+#else // defined(Q_OS_LINUX)
|
|
|
|
-bool USBDevice::parse(const QString &fname)
|
|
-{
|
|
+bool USBDevice::parse(const QString &fname) {
|
|
Q_UNUSED(fname)
|
|
|
|
return true;
|
|
}
|
|
|
|
-# else
|
|
-
|
|
-/*
|
|
- * FreeBSD support by Markus Brueffer <markus@brueffer.de>
|
|
- *
|
|
- * Basic idea and some code fragments were taken from FreeBSD's usbdevs(8),
|
|
- * originally developed for NetBSD, so this code should work with no or
|
|
- * only little modification on NetBSD.
|
|
- */
|
|
-
|
|
-void USBDevice::collectData( int fd, int level, usb_device_info &di, int parent)
|
|
-{
|
|
- // determine data for this device
|
|
- _level = level;
|
|
- _parent = parent;
|
|
-
|
|
- _bus = di.udi_bus;
|
|
- _device = di.udi_addr;
|
|
- _product = QLatin1String(di.udi_product);
|
|
- if ( _device == 1 )
|
|
- _product += ' ' + QString::number( _bus );
|
|
- _manufacturer = QLatin1String(di.udi_vendor);
|
|
- _prodID = di.udi_productNo;
|
|
- _vendorID = di.udi_vendorNo;
|
|
- _class = di.udi_class;
|
|
- _sub = di.udi_subclass;
|
|
- _prot = di.udi_protocol;
|
|
- _power = di.udi_power;
|
|
- _channels = di.udi_nports;
|
|
-
|
|
- // determine the speed
|
|
-#if defined(__DragonFly__) || (defined(Q_OS_FREEBSD) && __FreeBSD_version > 490102) || defined(Q_OS_NETBSD)
|
|
- switch (di.udi_speed) {
|
|
- case USB_SPEED_LOW: _speed = 1.5; break;
|
|
- case USB_SPEED_FULL: _speed = 12.0; break;
|
|
- case USB_SPEED_HIGH: _speed = 480.0; break;
|
|
- }
|
|
-#else
|
|
- _speed = di.udi_lowspeed ? 1.5 : 12.0;
|
|
-#endif
|
|
-
|
|
- // Get all attached devicenodes
|
|
- for ( int i = 0; i < USB_MAX_DEVNAMES; ++i )
|
|
- if ( di.udi_devnames[i][0] )
|
|
- _devnodes << di.udi_devnames[i];
|
|
-
|
|
- // For compatibility, split the revision number
|
|
- sscanf( di.udi_release, "%x.%x", &_revMajor, &_revMinor );
|
|
-
|
|
- // Cycle through the attached devices if there are any
|
|
- for ( int p = 0; p < di.udi_nports; ++p ) {
|
|
- // Get data for device
|
|
- struct usb_device_info di2;
|
|
-
|
|
- di2.udi_addr = di.udi_ports[p];
|
|
-
|
|
- if ( di2.udi_addr >= USB_MAX_DEVICES )
|
|
- continue;
|
|
-
|
|
- if ( ioctl(fd, USB_DEVICEINFO, &di2) == -1 )
|
|
- continue;
|
|
-
|
|
- // Only add the device if we didn't detect it, yet
|
|
- if (!find( di2.udi_bus, di2.udi_addr ) )
|
|
- {
|
|
- USBDevice *device = new USBDevice();
|
|
- device->collectData( fd, level + 1, di2, di.udi_addr );
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-bool USBDevice::parse(const QString &fname)
|
|
-{
|
|
- Q_UNUSED(fname)
|
|
-
|
|
- static bool showErrorMessage = true;
|
|
- bool error = false;
|
|
- _devices.clear();
|
|
-
|
|
- QFile controller("/dev/usb0");
|
|
- int i = 1;
|
|
- while ( controller.exists() )
|
|
- {
|
|
- // If the devicenode exists, continue with further inspection
|
|
- if ( controller.open(QIODevice::ReadOnly) )
|
|
- {
|
|
- for ( int addr = 1; addr < USB_MAX_DEVICES; ++addr )
|
|
- {
|
|
- struct usb_device_info di;
|
|
-
|
|
- di.udi_addr = addr;
|
|
- if ( ioctl(controller.handle(), USB_DEVICEINFO, &di) != -1 )
|
|
- {
|
|
- if (!find( di.udi_bus, di.udi_addr ) )
|
|
- {
|
|
- USBDevice *device = new USBDevice();
|
|
- device->collectData( controller.handle(), 0, di, 0);
|
|
- }
|
|
- }
|
|
- }
|
|
- controller.close();
|
|
-#ifndef Q_OS_NETBSD
|
|
- } else {
|
|
- error = true;
|
|
-#endif
|
|
- }
|
|
- controller.setFileName( QString::fromLocal8Bit("/dev/usb%1").arg(i++) );
|
|
- }
|
|
-
|
|
- if ( showErrorMessage && error ) {
|
|
- showErrorMessage = false;
|
|
- KMessageBox::error( 0, i18n("Could not open one or more USB controller. Make sure, you have read access to all USB controllers that should be listed here."));
|
|
- }
|
|
+bool USBDevice::parseSys(const QString &dname) {
|
|
+ Q_UNUSED(dname)
|
|
|
|
return true;
|
|
}
|
|
|
|
-# endif // defined(DISABLE_USBDEVICES_FREEBSD)
|
|
-#endif // !(defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD))
|
|
+#endif // defined(Q_OS_LINUX)
|
|
+#endif // defined(HAVE_LIBUSB1)
|
|
--- kinfocenter/Modules/usbview/usbdevices.h
|
|
+++ kinfocenter/Modules/usbview/usbdevices.h
|
|
@@ -14,18 +14,9 @@
|
|
#include <QList>
|
|
#include <QString>
|
|
|
|
-#if defined(__DragonFly__)
|
|
-#include <bus/usb/usb.h>
|
|
-#include <QStringList>
|
|
-#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
|
|
-#include <sys/param.h>
|
|
-# if defined(__FreeBSD_version) && __FreeBSD_version >= 800100
|
|
-# define DISABLE_USBDEVICES_FREEBSD
|
|
-# warning "The USB subsystem has changed in 8.0. Disabling."
|
|
-# else
|
|
-# include <dev/usb/usb.h>
|
|
-# include <QStringList>
|
|
-# endif
|
|
+#include <config-kcmusb.h>
|
|
+#if defined(HAVE_LIBUSB1)
|
|
+#include <libusb.h>
|
|
#endif
|
|
|
|
class USBDB;
|
|
@@ -36,10 +27,12 @@ public:
|
|
USBDevice();
|
|
|
|
~USBDevice();
|
|
-
|
|
+#if defined(HAVE_LIBUSB1)
|
|
+ void dump_usbdev_info(libusb_device *dev);
|
|
+#else
|
|
void parseLine(const QString &line);
|
|
void parseSysDir(int bus, int parent, int level, const QString &line);
|
|
-
|
|
+#endif
|
|
int level() const {
|
|
return _level;
|
|
}
|
|
@@ -60,8 +53,12 @@ public:
|
|
return _devices;
|
|
}
|
|
static USBDevice *find(int bus, int device);
|
|
+#if defined(HAVE_LIBUSB1)
|
|
+ static bool parse();
|
|
+#else
|
|
static bool parse(const QString& fname);
|
|
static bool parseSys(const QString& fname);
|
|
+#endif
|
|
|
|
private:
|
|
|
|
@@ -82,10 +79,6 @@ private:
|
|
|
|
unsigned int _vendorID, _prodID, _revMajor, _revMinor;
|
|
|
|
-#if (defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)) && !defined(DISABLE_USBDEVICES_FREEBSD)
|
|
- void collectData( int fd, int level, usb_device_info &di, int parent );
|
|
- QStringList _devnodes;
|
|
-#endif
|
|
};
|
|
|
|
#endif
|