Skip to content

Commit e4e52f1

Browse files
authored
Merge pull request #480 from deXol/developBLEIntegrateBluetooth
#414 BLE bluetooth integration
2 parents 36c0d7b + e4f5ba0 commit e4e52f1

15 files changed

+171
-39
lines changed

data/moolticute.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ ACTION!="add|change", GOTO="mooltipass_end"
5555
# console user
5656
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="09a0", MODE="0660", SYMLINK+="mooltipass_keyboard", TAG+="uaccess", TAG+="udev-acl"
5757
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="4321", MODE="0660", SYMLINK+="mooltipass_keyboard", TAG+="uaccess", TAG+="udev-acl"
58+
SUBSYSTEM=="hidraw", KERNELS=="*1209:4321*", MODE="0660", SYMLINK+="mooltipass_keyboard", TAG+="uaccess", TAG+="udev-acl"
5859
# libusb
5960
SUBSYSTEM=="usb", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="09a0", MODE="0660", SYMLINK+="mooltipass_device", TAG+="uaccess"
6061
SUBSYSTEM=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="4321", MODE="0660", SYMLINK+="mooltipass_device", TAG+="uaccess"

src/Common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#define MOOLTIPASS_BLE_PRODUCTID 0x4321
3535

3636
#define MOOLTIPASS_USBHID_DESC_SIZE 28
37+
#define MOOLTIPASS_BLEHID_DESC_SIZE 45
3738

3839
#define MOOLTIPASS_FAV_MAX 14
3940
#define MOOLTIPASS_ADDRESS_SIZE 4

src/MPDevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ class MPDevice: public QObject
196196
inline bool isBLE() const { return DeviceType::BLE == deviceType;}
197197
//true if device fw version is at least 1.2
198198
inline bool isFw12() const { return isFw12Flag; }
199+
//true if device is connected with Bluetooth
200+
inline bool isBT() const { return isBluetooth; }
199201

200202
QList<QVariantMap> getFilesCache();
201203
bool hasFilesCache();
@@ -406,6 +408,7 @@ private slots:
406408

407409
protected:
408410
IMessageProtocol *pMesProt = nullptr;
411+
bool isBluetooth = false;
409412

410413
DeviceType deviceType = DeviceType::MOOLTIPASS;
411414
static constexpr int MP_EXPORT_FIELD_NUM = 10;

src/MPDevice_linux.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ MPDevice_linux::MPDevice_linux(QObject *parent, const MPPlatformDef &platformDef
3838
if (platformDef.isBLE)
3939
{
4040
deviceType = DeviceType::BLE;
41+
isBluetooth = platformDef.isBluetooth;
4142
}
4243
setupMessageProtocol();
4344

@@ -89,7 +90,15 @@ void MPDevice_linux::readyRead(int fd)
8990
}
9091
else
9192
{
92-
emit platformDataRead(recvData);
93+
if (isBluetooth)
94+
{
95+
emit platformDataRead(recvData.remove(0,1));
96+
}
97+
else
98+
{
99+
emit platformDataRead(recvData);
100+
}
101+
93102
failToWriteLogged = false;
94103
}
95104

@@ -119,7 +128,7 @@ int MPDevice_linux::getDescriptorSize(const char *devpath)
119128
return descSize;
120129
}
121130

122-
bool MPDevice_linux::checkDevice(struct udev_device *raw_dev, bool &isBLE)
131+
bool MPDevice_linux::checkDevice(struct udev_device *raw_dev, bool &isBLE, bool &isBT)
123132
{
124133
int bus_type = 0;
125134
unsigned short dev_vid = 0;
@@ -154,12 +163,17 @@ bool MPDevice_linux::checkDevice(struct udev_device *raw_dev, bool &isBLE)
154163

155164
bool isMini = dev_vid == MOOLTIPASS_VENDORID && dev_pid == MOOLTIPASS_PRODUCTID;
156165
bool isBle = dev_vid == MOOLTIPASS_BLE_VENDORID && dev_pid == MOOLTIPASS_BLE_PRODUCTID;
157-
if (bus_type == BUS_USB &&
158-
(isMini || isBle) &&
159-
getDescriptorSize(dev_path) == MOOLTIPASS_USBHID_DESC_SIZE)
166+
if ((bus_type == BUS_USB || bus_type == BUS_BLUETOOTH) &&
167+
(isMini || isBle))
160168
{
161-
isBLE = isBle;
162-
return true;
169+
const auto descSize = getDescriptorSize(dev_path);
170+
if (MOOLTIPASS_USBHID_DESC_SIZE == descSize ||
171+
MOOLTIPASS_BLEHID_DESC_SIZE == descSize)
172+
{
173+
isBLE = isBle;
174+
isBT = bus_type == BUS_BLUETOOTH;
175+
return true;
176+
}
163177
}
164178

165179
udev_device_unref(raw_dev);
@@ -175,10 +189,11 @@ void MPDevice_linux::writeNextPacket()
175189

176190
QByteArray ba = sendBuffer.dequeue();
177191
/**
178-
* Adding a plus 0x00 byte before the message
192+
* Adding a plus 0x00 or 0x03 byte before the message
179193
* for setting the report number.
180194
*/
181-
ba.insert(0, static_cast<char>(0x0));
195+
const auto reportId = static_cast<char>(isBluetooth ? 0x03 : 0x00);
196+
ba.insert(0, static_cast<char>(reportId));
182197
ssize_t res = ::write(devfd, ba.data(), static_cast<size_t>(ba.size()));
183198

184199
if (res < 0)
@@ -217,14 +232,15 @@ QList<MPPlatformDef> MPDevice_linux::enumerateDevices()
217232
{
218233
const char *sysfs_path = udev_list_entry_get_name(dev);
219234
struct udev_device *raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
220-
bool isBLE;
221-
if (checkDevice(raw_dev, isBLE))
235+
bool isBLE, isBT;
236+
if (checkDevice(raw_dev, isBLE, isBT))
222237
{
223238
const char *dev_path = udev_device_get_devnode(raw_dev);
224239
MPPlatformDef def;
225240
def.path = QString::fromUtf8(dev_path);
226241
def.id = def.path;
227242
def.isBLE = isBLE;
243+
def.isBluetooth = isBT;
228244
devlist << def;
229245

230246
qDebug() << "Found mooltipass: " << def.path;

src/MPDevice_linux.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424

2525
#include <QThread>
2626

27-
class MPPlatformDef
27+
struct MPPlatformDef
2828
{
29-
public:
3029
QString id; //unique id for all platform
3130

3231
bool isBLE = false;
32+
bool isBluetooth = false;
3333
QString path;
3434
};
3535

@@ -51,9 +51,10 @@ class MPDevice_linux: public MPDevice
5151
* Checking if the device is a mooltipass device
5252
* @param path to the device
5353
* @param isBLE out param, true if device is a ble
54+
* @param isBT out param, true if device is connected with BT
5455
* @return true, if the device is mini/ble
5556
*/
56-
static bool checkDevice(struct udev_device *raw_dev, bool &isBLE);
57+
static bool checkDevice(struct udev_device *raw_dev, bool &isBLE, bool &isBT);
5758
static int INVALID_VALUE;
5859

5960
private slots:

src/MPDevice_mac.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ void _read_report_callback(void *context,
3535

3636
MPDevice_mac *dev = reinterpret_cast<MPDevice_mac *>(context);
3737
QByteArray data((const char *)report, report_length);
38+
if (dev->isBT())
39+
{
40+
//BT is sending an extra byte
41+
data.remove(0,1);
42+
}
3843
emit dev->platformDataRead(data);
3944
}
4045

@@ -45,6 +50,7 @@ MPDevice_mac::MPDevice_mac(QObject *parent, const MPPlatformDef &platformDef):
4550
if (platformDef.isBLE)
4651
{
4752
deviceType = DeviceType::BLE;
53+
isBluetooth = platformDef.isBluetooth;
4854
}
4955
setupMessageProtocol();
5056
/**
@@ -107,11 +113,19 @@ void MPDevice_mac::platformWrite(const QByteArray &data)
107113
{
108114
QtConcurrent::run(usbWriteThreadPool, [=]()
109115
{
116+
QByteArray dataArray;
117+
int reportId = 0;
118+
if (isBT())
119+
{
120+
dataArray.append(static_cast<char>(0x00));
121+
reportId = 3;
122+
}
123+
dataArray.append(data);
110124
IOReturn res = IOHIDDeviceSetReport(hidref,
111125
kIOHIDReportTypeOutput,
112-
0,
113-
(const uint8_t *)data.constData(),
114-
data.size());
126+
reportId,
127+
(const uint8_t *)dataArray.constData(),
128+
dataArray.size());
115129
if (res != kIOReturnSuccess)
116130
qWarning() << "Failed to write data to device";
117131
});

src/MPDevice_mac.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class MPPlatformDef
3030

3131
IOHIDDeviceRef hidref;
3232
bool isBLE = false;
33+
bool isBluetooth = false;
3334
};
3435

3536
inline bool operator==(const MPPlatformDef &lhs, const MPPlatformDef &rhs) { return lhs.id == rhs.id; }

src/MPDevice_win.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
// Windows GUID object
2323
static GUID IClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
24+
const QString MPDevice_win::BT_GATT_SERVICE_GUID = "00001812-0000-1000-8000-00805f9b34fb";
2425

2526
MPDevice_win::MPDevice_win(QObject *parent, const MPPlatformDef &p):
2627
MPDevice(parent),
@@ -36,6 +37,9 @@ MPDevice_win::MPDevice_win(QObject *parent, const MPPlatformDef &p):
3637
if (p.isBLE)
3738
{
3839
deviceType = DeviceType::BLE;
40+
#if defined(Q_OS_WIN)
41+
isBluetooth = platformDef.isBluetooth;
42+
#endif
3943
}
4044
setupMessageProtocol();
4145

@@ -166,15 +170,19 @@ void MPDevice_win::platformWrite(const QByteArray &data)
166170

167171
void MPDevice_win::platformWriteToDevice(const QByteArray &data)
168172
{
169-
const char zeroByte = static_cast<char>(0x00);
173+
char reportByte = ZERO_BYTE;
170174
QByteArray ba;
171-
ba.append(zeroByte); //add report id (even if not used). windows requires that
175+
if (isBluetooth)
176+
{
177+
reportByte = static_cast<char>(0x03);
178+
}
179+
ba.append(reportByte); //add report id (even if not used). windows requires that
172180
ba.append(data);
173181

174182
//resize array to fit windows requirements (at least outReportLen size)
175183
if (ba.size() < platformDef.outReportLen)
176184
{
177-
Common::fill(ba, platformDef.outReportLen - ba.size(), zeroByte);
185+
Common::fill(ba, platformDef.outReportLen - ba.size(), ZERO_BYTE);
178186
}
179187

180188
::ZeroMemory(&writeOverlapped, sizeof(writeOverlapped));
@@ -274,23 +282,24 @@ QList<MPPlatformDef> MPDevice_win::enumerateDevices()
274282
free(dev_detail_data);
275283

276284
bool isBLE = false;
277-
if (!checkDevice(path, isBLE))
285+
bool isBluetooth = false;
286+
if (!checkDevice(path, isBLE, isBluetooth))
278287
{
279288
continue;
280289
}
281290
qDebug() << "Found mooltipass: " << path;
282291

283292
//TODO: extract interface number from path string and check it
284293

285-
devlist << getPlatDef(path, isBLE);
294+
devlist << getPlatDef(path, isBLE, isBluetooth);
286295
}
287296

288297
SetupDiDestroyDeviceInfoList(dev_info_set);
289298

290299
return devlist;
291300
}
292301

293-
bool MPDevice_win::checkDevice(QString path, bool &isBLE /* out */)
302+
bool MPDevice_win::checkDevice(QString path, bool &isBLE /* out */, bool &isBluetooth /* out */)
294303
{
295304
HIDD_ATTRIBUTES attrib;
296305
//Get vendorid/productid
@@ -311,15 +320,21 @@ bool MPDevice_win::checkDevice(QString path, bool &isBLE /* out */)
311320
}
312321

313322
isBLE = attrib.VendorID == MOOLTIPASS_BLE_VENDORID;
323+
if (isBLE && path.contains(BT_GATT_SERVICE_GUID))
324+
{
325+
qDebug() << "BT HID connected";
326+
isBluetooth = true;
327+
}
314328
return true;
315329
}
316330

317-
MPPlatformDef MPDevice_win::getPlatDef(QString path, bool isBLE)
331+
MPPlatformDef MPDevice_win::getPlatDef(QString path, bool isBLE, bool isBluetooth)
318332
{
319333
MPPlatformDef def;
320334
def.path = path;
321335
def.id = path; //use path for ID
322336
def.isBLE = isBLE;
337+
def.isBluetooth = isBluetooth;
323338
return def;
324339
}
325340

src/MPDevice_win.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class MPPlatformDef
6363
USHORT outReportLen = 0;
6464
USHORT inReportLen = 0;
6565
bool isBLE = false;
66+
bool isBluetooth = false;
6667
};
6768

6869
inline bool operator==(const MPPlatformDef &lhs, const MPPlatformDef &rhs) { return lhs.id == rhs.id; }
@@ -84,8 +85,8 @@ class MPDevice_win: public MPDevice
8485
* @param isBLE out param, true if device is a ble
8586
* @return true, if the device is mini/ble
8687
*/
87-
static bool checkDevice(QString path, bool &isBLE);
88-
static MPPlatformDef getPlatDef(QString path, bool isBLE);
88+
static bool checkDevice(QString path, bool &isBLE, bool &isBluetooth);
89+
static MPPlatformDef getPlatDef(QString path, bool isBLE, bool isBluetooth);
8990

9091
signals:
9192
void platformWriteFinished();
@@ -112,8 +113,11 @@ private slots:
112113
OVERLAPPED writeOverlapped;
113114
OVERLAPPED readOverlapped;
114115
QWinOverlappedIoNotifier *oNotifier;
116+
117+
QQueue<QByteArray> m_writeQueue;
115118

116-
QQueue<QByteArray> m_writeQueue;
119+
const static QString BT_GATT_SERVICE_GUID;
120+
const static char ZERO_BYTE = static_cast<char>(0x00);
117121
};
118122

119123
#endif // MPDEVICE_WIN_H

0 commit comments

Comments
 (0)