11 #include <sys/ioctl.h>
12 #include <sys/socket.h>
13 #include <linux/types.h>
14 #include <linux/netlink.h>
21 #include <QCoreApplication>
22 #if CONFIG_SOCKETNOTIFIER
23 # include <QSocketNotifier>
24 #elif CONFIG_TCPSOCKET
25 # include <QtNetwork/QTcpSocket>
29 #define UEVENT_BUFFER_SIZE 2048
31 enum udev_monitor_netlink_group {
40 close(netlink_socket);
48 #if CONFIG_SOCKETNOTIFIER
49 socket_notifier->setEnabled(
true);
50 #elif CONFIG_TCPSOCKET
60 if (netlink_socket!=-1) {
61 #if CONFIG_SOCKETNOTIFIER
62 socket_notifier->setEnabled(
false);
63 #elif CONFIG_TCPSOCKET
69 close(netlink_socket);
79 #if CONFIG_SOCKETNOTIFIER
81 data.resize(UEVENT_BUFFER_SIZE * 2);
83 size_t len = read(socket_notifier->socket(), data.data(), UEVENT_BUFFER_SIZE * 2);
84 qDebug(
"read fro socket %ld bytes", len);
87 #elif CONFIG_TCPSOCKET
88 data = tcp_socket->readAll();
90 data = data.replace(0,
'\n').trimmed();
93 buffer.setBuffer(&data);
94 if (!buffer.open(QIODevice::ReadOnly))
96 while(!buffer.atEnd()) {
97 parseLine(buffer.readLine().trimmed());
104 void QDeviceWatcherPrivate::run()
111 data.resize(UEVENT_BUFFER_SIZE * 2);
113 size_t len = recv(netlink_socket, data.data(), data.length(), 0);
114 qDebug(
"read fro socket %ld bytes", len);
116 data = data.replace(0,
'\n').trimmed();
119 buffer.setBuffer(&data);
120 if (!buffer.open(QIODevice::ReadOnly))
122 QByteArray line = buffer.readLine();
123 while(!line.isNull()) {
124 parseLine(line.trimmed());
125 line = buffer.readLine();
130 #endif //CONFIG_THREAD
151 struct sockaddr_nl snl;
152 const int buffersize = 16 * 1024 * 1024;
155 memset(&snl, 0x00,
sizeof(
struct sockaddr_nl));
156 snl.nl_family = AF_NETLINK;
157 snl.nl_groups = UDEV_MONITOR_KERNEL;
159 netlink_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
161 if (netlink_socket == -1) {
162 qWarning(
"error getting socket: %s", strerror(errno));
167 setsockopt(netlink_socket, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize,
sizeof(buffersize));
168 retval = bind(netlink_socket, (
struct sockaddr*) &snl,
sizeof(
struct sockaddr_nl));
170 qWarning(
"bind failed: %s", strerror(errno));
171 close(netlink_socket);
174 }
else if (retval == 0) {
176 struct sockaddr_nl _snl;
183 _addrlen =
sizeof(
struct sockaddr_nl);
184 retval = getsockname(netlink_socket, (
struct sockaddr *)&_snl, &_addrlen);
186 snl.nl_pid = _snl.nl_pid;
189 #if CONFIG_SOCKETNOTIFIER
190 socket_notifier =
new QSocketNotifier(netlink_socket, QSocketNotifier::Read,
this);
191 connect(socket_notifier, SIGNAL(activated(
int)), SLOT(
parseDeviceInfo()));
192 socket_notifier->setEnabled(
false);
193 #elif CONFIG_TCPSOCKET
195 tcp_socket =
new QTcpSocket(
this);
196 if (!tcp_socket->setSocketDescriptor(netlink_socket, QAbstractSocket::ConnectedState)) {
197 qWarning(
"Failed to assign native socket to QAbstractSocket: %s",
qPrintable(tcp_socket->errorString()));
205 void QDeviceWatcherPrivate::parseLine(
const QByteArray &line)
207 qDebug(
"%s", line.constData());
209 const QRegExp rx(
"(\\w+)(?:@/.*/block/.*/)(\\w+)\\W*");
210 if (rx.indexIn(line) == -1)
212 QString action_str = rx.cap(1).toLower();
213 QString dev =
"/dev/" + rx.cap(2);
215 if (!line.contains(
"/block/"))
217 QString action_str = line.left(line.indexOf(
'@')).toLower();
218 QString dev =
"/dev/" + line.right(line.length() - line.lastIndexOf(
'/') - 1);
222 if (action_str==QLatin1String(
"add")) {
225 }
else if (action_str==QLatin1String(
"remove")) {
228 }
else if (action_str==QLatin1String(
"change")) {
237 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