轉自http://blog.csdn.net/yanzi1225627/article/details/7889613
利用qt檢測U盤插拔,思路有用qt的qdbus,dbus接收HAL的消息,或者是接收udisks的消息,這兩種方法在x86平臺上是可行的,但到板子裏就不行。板子裏不一定有HAL的,而HAL往板子裏移植網上麼有半點資料。udisk也沒有移植的資料。更要命的是,不管hal也好udisks也好,他們得到的消息都是udev發過來的。而udev需要sysfs文件系統的支持,但現在arm板子上大多數都是yaffs或yaffs2文件系統的支持。儘管有udev移植的資料,但往yaffs、yaffs2文件系統移植,是移植不了的。最後一步配置的時候,配置不了。
linux整個處理usb的消息機制是這樣的:內核----hotplug機制----udev---------HAL/UDISKS--------dbus.儘管網上很多人說hotplug淘汰了,但貌似現在開發板上用的都是hotplug。因此如果要用qt實現檢測arm上U盤插拔的話,hotplug纔是正道,不要貪了qt封裝好的幾個QDBUS接口的函數!
這篇文章就先談一下,pc機上用qt自帶的qdbus類,得到hal或udisks消息,來實現檢測U盤插拔。咱廢話多不說,請看程序:
1,widget.h裏面添加:
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusConnection> //QDBusConnection
#define DBUS_HAL_SERVICE "org.freedesktop.Hal"
#define DBUS_HAL_PATH "/org/freedesktop/Hal/Manager"
#define DBUS_HAL_INTERFACE "org.freedesktop.Hal.Manager"
#define DBUS_HAL_DEVICE_PATH "/org/freedesktop/Hal/devices"
#define DBUS_HAL_DEVICE_INTERFACE "org.freedesktop.Hal.Device"
private slots:
void slotDeviceAdded(QString udi);
void slotDeviceRemoved(QString udi);
2,widget.cpp裏面添加
QDBusInterface *dBusInterface = new QDBusInterface(DBUS_HAL_SERVICE,
DBUS_HAL_PATH,
DBUS_HAL_INTERFACE,
QDBusConnection::systemBus(),
this);
if(!dBusInterface->isValid())
qDebug()<<tc->toUnicode("初始化錯誤,找不到QDBusInterface!")<<QDBusConnection::systemBus().lastError().message();
connect(dBusInterface, SIGNAL(DeviceAdded(QString)), this, SLOT(slotDeviceAdded(QString)));
connect(dBusInterface, SIGNAL(DeviceRemoved(QString)), this, SLOT(slotDeviceRemoved(QString)));
然後就是兩個槽函數:
void Widget::slotDeviceAdded(QString udi)
{
static int num = 0;
QDBusInterface *device = new QDBusInterface(DBUS_HAL_SERVICE, udi, DBUS_HAL_DEVICE_INTERFACE, QDBusConnection::systemBus(), this);
if(!device->isValid())
qDebug()<<tc->toUnicode("創建device失敗!");
else
num++;
QString devicePath = device->path();
qDebug()<<tc->toUnicode("正在識別usb_device")<<num<<tc->toUnicode("號----路徑:")<<devicePath;
if(devicePath.contains("volume"))
{
qDebug()<<tc->toUnicode("恭喜您,U盤找到了。name:")<<udi;
currentUDI = udi;
}
else
qDebug()<<tc->toUnicode("識別結果:不是USB存儲設備!");
}
void Widget::slotDeviceRemoved(QString udi)
{
if(udi == currentUDI || udi.contains("volume"))
{
qDebug()<<tc->toUnicode("您的U盤已彈出!")<<udi;
currentUDI = "";
}
else
qDebug()<<"usb_device="<<udi<<tc->toUnicode("已彈出---");
}
這裏的udi就是註冊usb設備的路徑!大家可以打印出來看看,註冊的時候大概註冊了七個,拔出U盤的時候也是打印了7個消息。如果沒有前面頭文件的.h裏的define,可以在widget.CPP文件裏new QDBusInterface時候直接寫上。這裏我推薦用這種先聲明一個變量,然後連接槽函數的方法。網上有人做法如下:
// // QDBusConnection::systemBus().connect(DBUS_HAL_SERVICE,
// DBUS_HAL_PATH,
// DBUS_HAL_INTERFACE,
// "DeviceAdded",
// this,
// SLOT(slotDeviceAdded(QString )));
// QDBusConnection::systemBus().connect(DBUS_HAL_SERVICE,
// DBUS_HAL_PATH,
// DBUS_HAL_INTERFACE,
// "DeviceRemoved",
// this,
// SLOT(slotDeviceRemoved(QString )));
也是可以的!
最坑爹的是有些人只說DBUS_HAL_SERVICE、DBUS_HAL_PATH不交代前面的宏定義!
另外就是,如果不想通過hal得到消息,可以通過udisks得到消息,如下:
QDBusConnection::systemBus().connect(
"org.freedesktop.UDisks",
"/org/freedesktop/UDisks",
"org.freedesktop.UDisks",
"DeviceAdded",
this, SLOT(deviceAdded(QDBusObjectPath));
void deviceAdded(QDBusObjectPath dev){
qDebug()<< "device added!"<<dev.path();
}
這樣就是通過udisks來檢測,至於原理大家看我前面博文把。
網上有個公開的用此思路寫的較爲完整的源碼:http://download.csdn.net/detail/yanzi1225627/4507716,具體能運行否我沒試。
另外,老外的http://qt-project.org/forums/viewthread/8595這個比較好。