DiskDeviceWatcher.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "DiskDeviceWatcher.h"
  2. #include <QDebug>
  3. #include <QSocketNotifier>
  4. #include <QByteArray>
  5. #include <QRegExp>
  6. #include <QBuffer>
  7. #include <QCoreApplication>
  8. #include <sys/un.h>
  9. #include <sys/ioctl.h>
  10. #include <sys/socket.h>
  11. #include <linux/types.h>
  12. #include <linux/netlink.h>
  13. #include <errno.h>
  14. #include <unistd.h>
  15. #define UEVENT_BUFFER_SIZE 2048
  16. #define UDEV_MONITOR_KERNEL 1
  17. //#define USE_REGEXP 1
  18. class DiskDeviceWatcherPrivate
  19. {
  20. Q_DISABLE_COPY(DiskDeviceWatcherPrivate)
  21. public:
  22. explicit DiskDeviceWatcherPrivate(DiskDeviceWatcher* parent);
  23. ~DiskDeviceWatcherPrivate();
  24. void initialize();
  25. void parseLine(const QByteArray& line);
  26. QSocketNotifier* m_SocketNotifier;
  27. QBuffer m_Buffer;
  28. int m_NetLinkSocket;
  29. private:
  30. DiskDeviceWatcher* m_Parent;
  31. };
  32. DiskDeviceWatcher::DiskDeviceWatcher(QObject *parent)
  33. : QObject(parent)
  34. , m_Private(new DiskDeviceWatcherPrivate(this))
  35. {
  36. }
  37. DiskDeviceWatcher::~DiskDeviceWatcher()
  38. {
  39. }
  40. void DiskDeviceWatcher::onSocketNotifier()
  41. {
  42. QByteArray data;
  43. data.resize(UEVENT_BUFFER_SIZE * 2);
  44. data.fill(0);
  45. size_t len = read(m_Private->m_SocketNotifier->socket(), data.data(), UEVENT_BUFFER_SIZE * 2);
  46. data.resize(len);
  47. data = data.replace(0, '\n').trimmed();
  48. if (m_Private->m_Buffer.isOpen()) {
  49. m_Private->m_Buffer.close();
  50. }
  51. m_Private->m_Buffer.setBuffer(&data);
  52. if (m_Private->m_Buffer.open(QIODevice::ReadOnly)) {
  53. while(m_Private->m_Buffer.canReadLine()) {
  54. m_Private->parseLine(m_Private->m_Buffer.readLine().trimmed());
  55. }
  56. m_Private->m_Buffer.close();
  57. }
  58. }
  59. DiskDeviceWatcherPrivate::DiskDeviceWatcherPrivate(DiskDeviceWatcher *parent)
  60. : m_Parent(parent)
  61. {
  62. m_SocketNotifier = NULL;
  63. m_NetLinkSocket = -1;
  64. initialize();
  65. }
  66. DiskDeviceWatcherPrivate::~DiskDeviceWatcherPrivate()
  67. {
  68. }
  69. void DiskDeviceWatcherPrivate::initialize()
  70. {
  71. struct sockaddr_nl snl;
  72. const int buffersize = 16 * 1024 * 1024;
  73. int retval;
  74. memset(&snl, 0x00, sizeof(struct sockaddr_nl));
  75. snl.nl_family = AF_NETLINK;
  76. snl.nl_pid = getpid();
  77. snl.nl_groups = UDEV_MONITOR_KERNEL;
  78. m_NetLinkSocket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
  79. if (-1 == m_NetLinkSocket) {
  80. exit(EXIT_FAILURE);
  81. }
  82. /* set receive buffersize */
  83. setsockopt(m_NetLinkSocket, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));
  84. retval = bind(m_NetLinkSocket, (struct sockaddr*) &snl, sizeof(struct sockaddr_nl));
  85. if (retval < 0) {
  86. close(m_NetLinkSocket);
  87. m_NetLinkSocket = -1;
  88. exit(EXIT_FAILURE);
  89. } else if (retval == 0) {
  90. struct sockaddr_nl _snl;
  91. socklen_t _addrlen;
  92. _addrlen = sizeof(struct sockaddr_nl);
  93. retval = getsockname(m_NetLinkSocket, (struct sockaddr *)&_snl, &_addrlen);
  94. if (0 == retval) {
  95. snl.nl_pid = _snl.nl_pid;
  96. }
  97. }
  98. m_SocketNotifier = new QSocketNotifier(m_NetLinkSocket, QSocketNotifier::Read, m_Parent);
  99. Qt::ConnectionType type = static_cast<Qt::ConnectionType>(Qt::UniqueConnection | Qt::AutoConnection);
  100. QObject::connect(m_SocketNotifier, SIGNAL(activated(int)),
  101. m_Parent, SLOT(onSocketNotifier()),
  102. type); //will always active
  103. m_SocketNotifier->setEnabled(true);
  104. }
  105. void DiskDeviceWatcherPrivate::parseLine(const QByteArray &line)
  106. {
  107. //qDebug() << line;
  108. if (line.contains("/block/")) { //hotplug
  109. QString action_str = line.left(line.indexOf('@')).toLower();
  110. QString dev = "/dev/" + line.right(line.length() - line.lastIndexOf('/') - 1);
  111. DiskDeviceWatcher::Action action;
  112. // if (QString(qgetenv("PROTOCOL_ID")).contains(QString("yaoxi"))) {
  113. // if (line.contains("musb-ark1680")) {
  114. // if (!line.contains("musb-ark1680.0")) {
  115. // return ;
  116. // }
  117. // }
  118. // }
  119. if (QString("add") == action_str) {
  120. action = DiskDeviceWatcher::A_Add;
  121. emit m_Parent->diskDeviceChange(dev, action);
  122. } else if (QString("remove") == action_str) {
  123. action = DiskDeviceWatcher::A_Remove;
  124. emit m_Parent->diskDeviceChange(dev, action);
  125. }
  126. }
  127. }