Skip to content

Commit b30bc76

Browse files
authored
Merge pull request #642 from deXol/developAddLocalSocketForEmulator
Add emulator support
2 parents 8816ff2 + 3a30b09 commit b30bc76

File tree

9 files changed

+332
-10
lines changed

9 files changed

+332
-10
lines changed

daemon.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ mac {
5757

5858
SOURCES += src/main_daemon.cpp \
5959
src/MPDevice.cpp \
60+
src/MPDevice_localSocket.cpp \
6061
src/MPManager.cpp \
6162
src/Common.cpp \
6263
src/WSServer.cpp \
@@ -88,6 +89,7 @@ SOURCES += src/main_daemon.cpp \
8889
HEADERS += \
8990
src/Common.h \
9091
src/MPDevice.h \
92+
src/MPDevice_localSocket.h \
9193
src/MPManager.h \
9294
src/MooltipassCmds.h \
9395
src/QtHelper.h \

src/MPDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3528,7 +3528,7 @@ void MPDevice::processStatusChange(const QByteArray &data)
35283528
Common::MPStatus s = pMesProt->getStatus(data);
35293529
Common::MPStatus prevStatus = get_status();
35303530

3531-
if (isBLE())
3531+
if (isBLE() && Common::Unlocked == s)
35323532
{
35333533
bleImpl->readUserSettings(pMesProt->getPayloadBytes(data, 2, 4));
35343534
}

src/MPDevice_localSocket.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/******************************************************************************
2+
** Copyright (c) Andrzej Szombierski. All Rights Reserved.
3+
**
4+
** Moolticute is free software; you can redistribute it and/or modify
5+
** it under the terms of the GNU General Public License as published by
6+
** the Free Software Foundation; either version 3 of the License, or
7+
** (at your option) any later version.
8+
**
9+
** Moolticute is distributed in the hope that it will be useful,
10+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
** GNU General Public License for more details.
13+
**
14+
** You should have received a copy of the GNU General Public License
15+
** along with Moolticute; if not, write to the Free Software
16+
** Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
**
18+
******************************************************************************/
19+
#include "MPDevice_localSocket.h"
20+
#include <QDebug>
21+
22+
MPDeviceLocalMonitor::MPDeviceLocalMonitor()
23+
{
24+
const char *socketName = "moolticuted_local_dev";
25+
QLocalServer::removeServer(socketName);
26+
server.listen(socketName);
27+
connect(&server, SIGNAL(newConnection()), this, SLOT(acceptIncomingConnection()));
28+
}
29+
30+
void MPDeviceLocalMonitor::acceptIncomingConnection()
31+
{
32+
while(server.hasPendingConnections()) {
33+
auto newSocket = server.nextPendingConnection();
34+
if(!newSocket)
35+
continue;
36+
37+
QString id = QString::number(++nextId);
38+
connect(newSocket, SIGNAL(disconnected()), this, SLOT(connectionLost()));
39+
sockets[id] = newSocket;
40+
emulatorRunning = true;
41+
emit localDeviceAdded(id);
42+
}
43+
}
44+
45+
void MPDeviceLocalMonitor::connectionLost()
46+
{
47+
auto socket = static_cast<QLocalSocket*>(sender());
48+
emulatorRunning = false;
49+
50+
// this is not the greatest way to search for the socket, but realistically this map will only have one entry
51+
for(auto it = sockets.begin(); it != sockets.end(); ++it) {
52+
if(it.value() == socket) {
53+
QString id = it.key();
54+
sockets.erase(it);
55+
emit localDeviceRemoved(id);
56+
break;
57+
}
58+
}
59+
60+
socket->deleteLater();
61+
}
62+
63+
QList<MPLocalDef> MPDeviceLocalMonitor::enumerateDevices() const
64+
{
65+
QList<MPLocalDef> ret;
66+
for(auto it = sockets.begin(); it != sockets.end(); ++it)
67+
ret.append(MPLocalDef { it.key() });
68+
return ret;
69+
}
70+
71+
72+
MPDevice_localSocket::MPDevice_localSocket(QObject *parent, const MPLocalDef & def): MPDevice(parent)
73+
{
74+
socket = MonitorInstance()->sockets[def.id];
75+
deviceType = DeviceType::BLE;
76+
isBluetooth = false;
77+
78+
if(socket)
79+
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
80+
81+
setupMessageProtocol();
82+
#ifndef Q_OS_UNIX
83+
sendInitMessages();
84+
#endif
85+
}
86+
87+
MPDevice_localSocket::~MPDevice_localSocket()
88+
{
89+
}
90+
91+
void MPDevice_localSocket::readData()
92+
{
93+
// QLocalSocket is stream-based, meaning that it can arbitrarily merge/split data packets
94+
// We will split the HID packets based on the payload length field
95+
if(!socket)
96+
return;
97+
98+
for(;;) {
99+
if(incomingPacketFill >= 2) {
100+
int payloadLength = incomingPacket[0] & 63;
101+
if(payloadLength > 62) {
102+
qWarning() << "Invalid HID packet received";
103+
incomingPacketFill = 0;
104+
continue;
105+
}
106+
107+
if(incomingPacketFill >= 2 + payloadLength) {
108+
// return one packet
109+
emit platformDataRead(QByteArray((const char*)incomingPacket, 2 + payloadLength));
110+
111+
// shift bytes in buffer
112+
incomingPacketFill -= 2 + payloadLength;
113+
memmove(incomingPacket, incomingPacket + 2 + payloadLength, incomingPacketFill);
114+
continue;
115+
}
116+
}
117+
118+
int bytesRead = socket->read((char*)incomingPacket + incomingPacketFill, sizeof(incomingPacket) - incomingPacketFill);
119+
120+
if(bytesRead < 0) {
121+
incomingPacketFill = 0;
122+
return; // socket closed?
123+
}
124+
125+
if(bytesRead == 0)
126+
break;
127+
128+
incomingPacketFill += bytesRead;
129+
}
130+
}
131+
132+
void MPDevice_localSocket::platformWrite(const QByteArray &ba)
133+
{
134+
if(socket)
135+
socket->write(ba);
136+
}
137+
138+
void MPDevice_localSocket::platformRead()
139+
{
140+
// nothing to do
141+
}

src/MPDevice_localSocket.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/******************************************************************************
2+
** Copyright (c) Andrzej Szombierski. All Rights Reserved.
3+
**
4+
** Moolticute is free software; you can redistribute it and/or modify
5+
** it under the terms of the GNU General Public License as published by
6+
** the Free Software Foundation; either version 3 of the License, or
7+
** (at your option) any later version.
8+
**
9+
** Moolticute is distributed in the hope that it will be useful,
10+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
** GNU General Public License for more details.
13+
**
14+
** You should have received a copy of the GNU General Public License
15+
** along with Moolticute; if not, write to the Free Software
16+
** Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
**
18+
******************************************************************************/
19+
#ifndef MPDEVICE_LOCALSOCKET_H
20+
#define MPDEVICE_LOCALSOCKET_H
21+
22+
#include "MPDevice.h"
23+
#include <QLocalServer>
24+
#include <QLocalSocket>
25+
26+
struct MPLocalDef {
27+
QString id;
28+
};
29+
30+
class MPDeviceLocalMonitor: public QObject {
31+
Q_OBJECT
32+
friend class MPDevice_localSocket;
33+
34+
public:
35+
MPDeviceLocalMonitor();
36+
QList<MPLocalDef> enumerateDevices() const;
37+
38+
signals:
39+
void localDeviceAdded(QString id);
40+
void localDeviceRemoved(QString id);
41+
42+
private slots:
43+
void acceptIncomingConnection();
44+
void connectionLost();
45+
46+
private:
47+
QLocalServer server;
48+
QMap<QString, QLocalSocket *> sockets;
49+
50+
int nextId = 0;
51+
bool emulatorRunning = false;
52+
};
53+
54+
class MPDevice_localSocket: public MPDevice
55+
{
56+
Q_OBJECT
57+
58+
public:
59+
MPDevice_localSocket(QObject *parent, const MPLocalDef & def);
60+
virtual ~MPDevice_localSocket();
61+
62+
static MPDeviceLocalMonitor *MonitorInstance() {
63+
static MPDeviceLocalMonitor inst;
64+
return &inst;
65+
}
66+
67+
static QList<MPLocalDef> enumerateDevices() {
68+
return MonitorInstance()->enumerateDevices();
69+
}
70+
71+
bool isEmulatorRunning() const { return MonitorInstance()->emulatorRunning; }
72+
73+
private slots:
74+
void readData();
75+
76+
private:
77+
virtual void platformRead();
78+
virtual void platformWrite(const QByteArray &data);
79+
80+
QPointer<QLocalSocket> socket;
81+
82+
// incoming messages
83+
uint8_t incomingPacket[64];
84+
int incomingPacketFill = 0;
85+
};
86+
87+
#endif // MPDEVICE_LOCALSOCKET_H

src/MPManager.cpp

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#elif defined(Q_OS_MAC)
2727
#include "UsbMonitor_mac.h"
2828
#endif
29+
#include "MPDevice_localSocket.h"
2930

3031
MPManager::MPManager():
3132
QObject(nullptr)
@@ -52,6 +53,10 @@ bool MPManager::initialize()
5253
#endif
5354
}
5455

56+
// no localSocket devices will ever be connected at startup
57+
connect(MPDevice_localSocket::MonitorInstance(), SIGNAL(localDeviceAdded(QString)), this, SLOT(usbDeviceAdded()));
58+
connect(MPDevice_localSocket::MonitorInstance(), SIGNAL(localDeviceRemoved(QString)), this, SLOT(usbDeviceRemoved(QString)));
59+
5560
bool startUsbCheck = true;
5661
#if defined(Q_OS_MAC)
5762
//This is not needed on osx, the list is updated at startup by UsbMonitor
@@ -101,6 +106,9 @@ void MPManager::usbDeviceAdded(QString path)
101106
Q_UNUSED(path);
102107
return;
103108
#endif
109+
110+
disconnectLocalSocketDevice();
111+
104112
if (devices.empty())
105113
{
106114
MPDevice *device = nullptr;
@@ -136,6 +144,8 @@ void MPManager::usbDeviceAdded(QString path)
136144
#if defined(Q_OS_LINUX)
137145
void MPManager::usbDeviceAdded(QString path, bool isBLE, bool isBT)
138146
{
147+
disconnectLocalSocketDevice();
148+
139149
if (devices.empty())
140150
{
141151
if (isBLE && isBLEConnectedWithUsb())
@@ -217,16 +227,17 @@ void MPManager::checkUsbDevices()
217227

218228
if (devlist.isEmpty() && !AppDaemon::isEmulationMode())
219229
{
220-
//No USB devices found, means all MPs are gone disconnected
221-
qDebug() << "Disconnecting devices";
222-
auto it = devices.begin();
223-
while (it != devices.end())
230+
if (isLocalSocketDeviceConnected()
231+
#ifndef Q_OS_UNIX
232+
|| !devices.isEmpty()
233+
#endif
234+
)
224235
{
225-
emit mpDisconnected(it.value());
226-
delete it.value();
227-
it++;
236+
return;
228237
}
229-
devices.clear();
238+
//No USB devices found, means all MPs are gone disconnected
239+
disconnectingDevices();
240+
checkLocalSocketDevice();
230241
return;
231242
}
232243

@@ -295,9 +306,67 @@ void MPManager::checkUsbDevices()
295306
}
296307
}
297308

309+
void MPManager::checkLocalSocketDevice()
310+
{
311+
QList<MPLocalDef> local_devlist = MPDevice_localSocket::enumerateDevices();
312+
for (const MPLocalDef &def : local_devlist)
313+
{
314+
//This is a new connected mooltipass
315+
if (!devices.contains(def.id))
316+
{
317+
MPDevice *device = new MPDevice_localSocket(this, def);
318+
319+
devices[def.id] = device;
320+
emit mpConnected(device);
321+
}
322+
else
323+
{
324+
qDebug() << "Device is already connected: " << def.id;
325+
}
326+
}
327+
}
328+
329+
bool MPManager::isLocalSocketDeviceConnected()
330+
{
331+
auto it = std::find_if(devices.begin(), devices.end(),
332+
[](MPDevice *dev)
333+
{
334+
auto* localDev = dynamic_cast<MPDevice_localSocket*>(dev);
335+
if (localDev && localDev->isEmulatorRunning())
336+
{
337+
return true;
338+
}
339+
return false;
340+
});
341+
return it != devices.end();
342+
}
343+
344+
void MPManager::disconnectLocalSocketDevice()
345+
{
346+
if (isLocalSocketDeviceConnected())
347+
{
348+
qDebug() << "Device is connected, emulator disconnecting";
349+
emit sendNotification("show_emulator_disconnect");
350+
disconnectingDevices();
351+
}
352+
}
353+
298354
bool MPManager::isBLEConnectedWithUsb()
299355
{
300356
return std::find_if(devices.begin(), devices.end(),
301357
[](MPDevice * dev){ return dev->isBLE();})
302-
!= devices.end();
358+
!= devices.end();
359+
}
360+
361+
void MPManager::disconnectingDevices()
362+
{
363+
qDebug() << "Disconnecting devices";
364+
auto it = devices.begin();
365+
while (it != devices.end())
366+
{
367+
emit mpDisconnected(it.value());
368+
delete it.value();
369+
it++;
370+
}
371+
devices.clear();
303372
}

0 commit comments

Comments
 (0)