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
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 if (!buffer.open(QIODevice::ReadOnly))
94 while(!buffer.atEnd()) {
95 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 if (buffer.open(QIODevice::ReadOnly))
120 QByteArray line = buffer.readLine();
121 while(!line.isNull()) {
122 parseLine(line.trimmed());
123 line = buffer.readLine();
128 #endif //CONFIG_THREAD
149 struct sockaddr_nl snl;
150 const int buffersize = 16 * 1024 * 1024;
153 memset(&snl, 0x00,
sizeof(
struct sockaddr_nl));
154 snl.nl_family = AF_NETLINK;
155 snl.nl_groups = UDEV_MONITOR_KERNEL;
157 netlink_socket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
159 if (netlink_socket == -1) {
160 qWarning(
"error getting socket: %s", strerror(errno));
165 setsockopt(netlink_socket, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize,
sizeof(buffersize));
166 retval = bind(netlink_socket, (
struct sockaddr*) &snl,
sizeof(
struct sockaddr_nl));
168 qWarning(
"bind failed: %s", strerror(errno));
169 close(netlink_socket);
172 }
else if (retval == 0) {
174 struct sockaddr_nl _snl;
181 _addrlen =
sizeof(
struct sockaddr_nl);
182 retval = getsockname(netlink_socket, (
struct sockaddr *)&_snl, &_addrlen);
184 snl.nl_pid = _snl.nl_pid;
187 #if CONFIG_SOCKETNOTIFIER
188 socket_notifier =
new QSocketNotifier(netlink_socket, QSocketNotifier::Read,
this);
189 connect(socket_notifier, SIGNAL(activated(
int)), SLOT(
parseDeviceInfo()));
190 socket_notifier->setEnabled(
false);
191 #elif CONFIG_TCPSOCKET
193 tcp_socket =
new QTcpSocket(
this);
194 if (!tcp_socket->setSocketDescriptor(netlink_socket, QAbstractSocket::ConnectedState)) {
195 qWarning(
"Failed to assign native socket to QAbstractSocket: %s",
qPrintable(tcp_socket->errorString()));
203 void QDeviceWatcherPrivate::parseLine(
const QByteArray &line)
205 qDebug(
"%s", line.constData());
208 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