dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
usbmonitor.cpp
Go to the documentation of this file.
1 
13 /*
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  *
27  * Additional note on redistribution: The copyright and license notices above
28  * must be maintained in each individual source file that is a derivative work
29  * of this source file; otherwise redistribution is prohibited.
30  */
31 
32 #include "usbmonitor.h"
33 #include <QDebug>
34 
35 #include "rawhid.h"
36 
37 //#define USB_MON_DEBUG
38 #ifdef USB_MON_DEBUG
39 #define USB_MON_QXTLOG_DEBUG(...) qDebug() << __VA_ARGS__
40 #else // USB_MON_DEBUG
41 #define USB_MON_QXTLOG_DEBUG(...)
42 #endif // USB_MON_DEBUG
43 
44 #define printf USB_MON_QXTLOG_DEBUG
45 
46 USBMonitor *USBMonitor::m_instance = nullptr;
47 
51 USBMonitor::USBMonitor(QObject *parent)
52  : QObject(parent)
53 {
54  m_instance = this;
55 
56  qRegisterMetaType<USBPortInfo>();
57 
58  hid_init();
59 
60  connect(&periodicTimer, &QTimer::timeout, this, &USBMonitor::periodic);
61  periodicTimer.setSingleShot(true);
62  periodicTimer.start(150);
63 
64  enumerating = false;
65  prevDevList = NULL;
66 }
67 
69 {
70  hid_free_enumeration(prevDevList);
71 }
72 
73 void USBMonitor::periodic()
74 {
75  // This is here to catch recursion, from the process_pending_events in
76  // hidapi on OS X.
77  if (enumerating) {
78  return;
79  }
80 
81  enumerating = true;
82 
83  struct hid_device_info *hidDevList = hid_enumerate(0, 0, prevDevList);
84 
85  QList<USBPortInfo> unseenDevices = knowndevices;
86  QList<USBPortInfo> newDevices;
87 
88  bool didAnything = false;
89 
90  for (struct hid_device_info *hidDev = hidDevList; hidDev != NULL; hidDev = hidDev->next) {
91  USBPortInfo info;
92 
93  info.vendorID = hidDev->vendor_id;
94  info.productID = hidDev->product_id;
95  info.bcdDevice = hidDev->release_number;
96  info.serialNumber = QString::fromWCharArray(hidDev->serial_number);
97  info.product = QString::fromWCharArray(hidDev->product_string);
98  info.manufacturer = QString::fromWCharArray(hidDev->manufacturer_string);
99  info.path = QString::fromLatin1(hidDev->path);
100 
101  if (!unseenDevices.removeOne(info)) {
102  newDevices.append(info);
103  }
104  }
105 
106  prevDevList = hidDevList;
107 
108  enumerating = false;
109 
110  foreach (USBPortInfo item, unseenDevices) {
111  didAnything = true;
112 
113  qDebug() << "Removing " << item.vendorID << item.productID << item.bcdDevice
114  << item.serialNumber << item.product << item.manufacturer;
115 
116  knowndevices.removeOne(item);
117 
118  emit deviceRemoved(item);
119  }
120 
121  foreach (USBPortInfo item, newDevices) {
122  if (!knowndevices.contains(item)) {
123  didAnything = true;
124 
125  qDebug() << "Adding " << item.vendorID << item.productID << item.bcdDevice
126  << item.serialNumber << item.product << item.manufacturer;
127 
128  knowndevices.append(item);
129 
130  emit deviceDiscovered(item);
131  }
132  }
133 
134  if (didAnything) {
135  qDebug() << "usbmonitor detection cycle complete.";
136  }
137 
138  /* Ensure our signals are spaced out. Also limit our CPU consumption */
139  periodicTimer.start(150);
140 }
141 
143 {
144  periodic();
145  return knowndevices;
146 }
147 
159 QList<USBPortInfo> USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB,
160  int bcdDeviceLSB)
161 {
162  periodic();
163 
164  QList<USBPortInfo> thePortsWeWant;
165 
166  foreach (USBPortInfo port, knowndevices) {
167  if ((port.vendorID == vid || vid == -1) && (port.productID == pid || pid == -1)
168  && ((port.bcdDevice >> 8) == bcdDeviceMSB || bcdDeviceMSB == -1)
169  && ((port.bcdDevice & 0x00ff) == bcdDeviceLSB || bcdDeviceLSB == -1))
170  thePortsWeWant.append(port);
171  }
172 
173  return thePortsWeWant;
174 }
175 
177 {
178  return m_instance;
179 }
int productID
Product ID.
Definition: usbmonitor.h:51
QString manufacturer
Definition: usbmonitor.h:45
int bcdDevice
Definition: usbmonitor.h:52
QString serialNumber
Definition: usbmonitor.h:44
QList< USBPortInfo > availableDevices()
Definition: usbmonitor.cpp:142
void deviceDiscovered(const USBPortInfo &info)
USBMonitor(QObject *parent=nullptr)
Definition: usbmonitor.cpp:51
static USBMonitor * instance()
Definition: usbmonitor.cpp:176
QString product
Definition: usbmonitor.h:46
void deviceRemoved(const USBPortInfo &info)
QString path
Opaque OS-specific path.
Definition: usbmonitor.h:48
int vendorID
Vendor ID.
Definition: usbmonitor.h:50