11 #include <sys/ioctl.h>
12 #include <sys/socket.h>
13 #include <linux/types.h>
14 #include <linux/netlink.h>
18 #include <QtCore/QCoreApplication>
19 #include <QtCore/qregexp.h>
20 #if CONFIG_SOCKETNOTIFIER
21 # include <QtCore/QSocketNotifier>
22 #elif CONFIG_TCPSOCKET
23 # include <QtNetwork/QTcpSocket>
27 #define UEVENT_BUFFER_SIZE 2048
29 enum udev_monitor_netlink_group {
38 close(netlink_socket);
46 #if CONFIG_SOCKETNOTIFIER
47 socket_notifier->setEnabled(
true);
48 #elif CONFIG_TCPSOCKET
51 this->QThread::start();
58 if (netlink_socket!=-1) {
59 #if CONFIG_SOCKETNOTIFIER
60 socket_notifier->setEnabled(
false);
61 #elif CONFIG_TCPSOCKET
67 close(netlink_socket);
77 #if CONFIG_SOCKETNOTIFIER
79 data.resize(UEVENT_BUFFER_SIZE * 2);
81 size_t len = read(socket_notifier->socket(), data.data(), UEVENT_BUFFER_SIZE * 2);
82 qDebug(
"read fro socket %d bytes", len);
85 #elif CONFIG_TCPSOCKET
86 data = tcp_socket->readAll();
88 data = data.replace(0,
'\n').trimmed();
91 buffer.setBuffer(&data);
92 buffer.open(QIODevice::ReadOnly);
93 while(!buffer.atEnd()) {
94 parseLine(buffer.readLine().trimmed());
102 void QDeviceWatcherPrivate::run()
109 data.resize(UEVENT_BUFFER_SIZE * 2);
111 size_t len = recv(netlink_socket, data.data(), data.length(), 0);
112 qDebug(
"read fro socket %d bytes", len);
114 data = data.replace(0,
'\n').trimmed();
117 buffer.setBuffer(&data);
118 buffer.open(QIODevice::ReadOnly);
119 QByteArray line = buffer.readLine();
120 while(!line.isNull()) {
121 parseLine(line.trimmed());
122 line = buffer.readLine();
127 #endif //CONFIG_THREAD
148 struct sockaddr_nl snl;
149 const int buffersize = 16 * 1024 * 1024;
152 memset(&snl, 0x00,
sizeof(
struct sockaddr_nl));
153 snl.nl_family = AF_NETLINK;
154 snl.nl_groups = UDEV_MONITOR_KERNEL;
156 netlink_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
158 if (netlink_socket == -1) {
159 qWarning(
"error getting socket: %s", strerror(errno));
164 setsockopt(netlink_socket, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize,
sizeof(buffersize));
165 retval = bind(netlink_socket, (
struct sockaddr*) &snl,
sizeof(
struct sockaddr_nl));
167 qWarning(
"bind failed: %s", strerror(errno));
168 close(netlink_socket);
171 }
else if (retval == 0) {
173 struct sockaddr_nl _snl;
180 _addrlen =
sizeof(
struct sockaddr_nl);
181 retval = getsockname(netlink_socket, (
struct sockaddr *)&_snl, &_addrlen);
183 snl.nl_pid = _snl.nl_pid;
186 #if CONFIG_SOCKETNOTIFIER
187 socket_notifier =
new QSocketNotifier(netlink_socket, QSocketNotifier::Read,
this);
188 connect(socket_notifier, SIGNAL(activated(
int)), SLOT(
parseDeviceInfo()));
189 socket_notifier->setEnabled(
false);
190 #elif CONFIG_TCPSOCKET
192 tcp_socket =
new QTcpSocket(
this);
193 if (!tcp_socket->setSocketDescriptor(netlink_socket, QAbstractSocket::ConnectedState)) {
194 qWarning(
"Failed to assign native socket to QAbstractSocket: %s",
qPrintable(tcp_socket->errorString()));
202 void QDeviceWatcherPrivate::parseLine(
const QByteArray &line)
204 qDebug(
"%s", line.constData());
207 const QRegExp rx(
"(\\w+)(?:@/.*/block/.*/)(\\w+)\\W*");
209 if (rx.indexIn(line) == -1)
211 QString action_str = rx.cap(1).toLower();
212 QString dev =
"/dev/" + rx.cap(2);
214 if (!line.contains(
"/block/"))
216 QString action_str = line.left(line.indexOf(
'@')).toLower();
217 QString dev =
"/dev/" + line.right(line.length() - line.lastIndexOf(
'/') - 1);
221 if (action_str==QLatin1String(
"add")) {
224 }
else if (action_str==QLatin1String(
"remove")) {
227 }
else if (action_str==QLatin1String(
"change")) {
236 QCoreApplication::postEvent(obj, event, Qt::HighEventPriority);
void emitDeviceAdded(const QString &dev)
void emitDeviceChanged(const QString &dev)
The class of the device watcher event.
void emitDeviceRemoved(const QString &dev)
QObjectList event_receivers