2024-05-15 15:44:45 -04:00
|
|
|
#include "backend.h"
|
|
|
|
|
2024-05-24 03:08:17 -04:00
|
|
|
#include <QCoreApplication>
|
|
|
|
#include <QDir>
|
|
|
|
|
2024-05-23 22:47:32 -04:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
2024-05-15 15:44:45 -04:00
|
|
|
#include <vanilla.h>
|
|
|
|
|
2024-05-23 22:47:32 -04:00
|
|
|
#include "../pipe/pipe.h"
|
|
|
|
|
2024-05-15 15:44:45 -04:00
|
|
|
void vanillaEventHandler(void *context, int type, const char *data, size_t dataLength)
|
|
|
|
{
|
|
|
|
Backend *backend = static_cast<Backend*>(context);
|
|
|
|
|
2024-05-18 15:55:00 -04:00
|
|
|
switch (type) {
|
|
|
|
case VANILLA_EVENT_VIDEO:
|
|
|
|
emit backend->videoAvailable(QByteArray(data, dataLength));
|
|
|
|
break;
|
|
|
|
case VANILLA_EVENT_AUDIO:
|
|
|
|
emit backend->audioAvailable(QByteArray(data, dataLength));
|
|
|
|
break;
|
|
|
|
case VANILLA_EVENT_VIBRATE:
|
2024-05-20 19:16:40 -04:00
|
|
|
emit backend->vibrate(data != nullptr);
|
2024-05-18 15:55:00 -04:00
|
|
|
break;
|
|
|
|
}
|
2024-05-15 15:44:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Backend::Backend(QObject *parent) : QObject(parent)
|
|
|
|
{
|
2024-05-23 22:47:32 -04:00
|
|
|
// If not running as root, use pipe
|
|
|
|
m_usePipe = (geteuid() != 0);
|
|
|
|
m_pipe = nullptr;
|
|
|
|
m_pipeIn = -1;
|
|
|
|
m_pipeOut = -1;
|
2024-05-24 03:08:17 -04:00
|
|
|
m_interrupt = 0;
|
|
|
|
|
|
|
|
if (m_usePipe) {
|
|
|
|
const QString pipe_bin = QDir(QCoreApplication::applicationDirPath()).filePath(QStringLiteral("vanilla-pipe"));
|
|
|
|
m_pipe = new QProcess(this);
|
|
|
|
m_pipe->setReadChannel(QProcess::StandardError);
|
|
|
|
connect(m_pipe, &QProcess::readyReadStandardError, this, &Backend::readFromPipe, Qt::DirectConnection);
|
|
|
|
//connect(m_pipe, &QProcess::finished, this, [this](int code){printf("closed??? %i\n", code);});
|
|
|
|
m_pipe->start(QStringLiteral("pkexec"), {pipe_bin});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Backend::~Backend()
|
|
|
|
{
|
|
|
|
if (m_pipe) {
|
|
|
|
m_pipeMutex.lock();
|
|
|
|
uint8_t cc = VANILLA_PIPE_IN_QUIT;
|
|
|
|
write(m_pipeOut, &cc, sizeof(cc));
|
|
|
|
m_pipeMutex.unlock();
|
|
|
|
m_pipe->waitForFinished();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ignoreByte(int pipe)
|
|
|
|
{
|
|
|
|
uint8_t ignore;
|
|
|
|
read(pipe, &ignore, sizeof(ignore));
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeByte(int pipe, uint8_t byte)
|
|
|
|
{
|
|
|
|
write(pipe, &byte, sizeof(byte));
|
2024-05-15 15:44:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Backend::interrupt()
|
|
|
|
{
|
2024-05-24 03:08:17 -04:00
|
|
|
if (m_usePipe) {
|
|
|
|
m_pipeMutex.lock();
|
|
|
|
uint8_t cc = VANILLA_PIPE_IN_INTERRUPT;
|
|
|
|
write(m_pipeOut, &cc, sizeof(cc));
|
|
|
|
m_pipeMutex.unlock();
|
|
|
|
|
|
|
|
ignoreByte(m_pipeIn);
|
|
|
|
} else {
|
|
|
|
vanilla_stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeNullTermString(int pipe, const QString &s)
|
|
|
|
{
|
|
|
|
QByteArray sc = s.toUtf8();
|
|
|
|
write(pipe, sc.constData(), sc.size());
|
|
|
|
writeByte(pipe, 0);
|
2024-05-15 15:44:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Backend::connectToConsole(const QString &wirelessInterface)
|
|
|
|
{
|
2024-05-24 03:08:17 -04:00
|
|
|
if (m_usePipe) {
|
|
|
|
// Request pipe to connect
|
|
|
|
m_pipeMutex.lock();
|
|
|
|
writeByte(m_pipeOut, VANILLA_PIPE_IN_CONNECT);
|
|
|
|
writeNullTermString(m_pipeOut, wirelessInterface);
|
|
|
|
m_pipeMutex.unlock();
|
|
|
|
|
|
|
|
uint8_t cc;
|
|
|
|
while (true) {
|
|
|
|
ssize_t read_size = read(m_pipeIn, &cc, sizeof(cc));
|
|
|
|
if (read_size == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cc == VANILLA_PIPE_OUT_EOF) {
|
|
|
|
break;
|
|
|
|
} else if (cc == VANILLA_PIPE_OUT_DATA) {
|
|
|
|
// Read event
|
|
|
|
read(m_pipeIn, &cc, sizeof(cc));
|
|
|
|
|
|
|
|
// Read data size
|
|
|
|
uint64_t data_size;
|
|
|
|
read(m_pipeIn, &data_size, sizeof(data_size));
|
|
|
|
|
|
|
|
void *buf = malloc(data_size);
|
|
|
|
|
|
|
|
vanillaEventHandler(this, cc, (const char *) buf, data_size);
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
QByteArray wirelessInterfaceC = wirelessInterface.toUtf8();
|
|
|
|
vanilla_connect_to_console(wirelessInterfaceC.constData(), vanillaEventHandler, this);
|
|
|
|
}
|
2024-05-15 15:44:45 -04:00
|
|
|
}
|
2024-05-20 19:16:40 -04:00
|
|
|
|
|
|
|
void Backend::updateTouch(int x, int y)
|
|
|
|
{
|
2024-05-24 03:08:17 -04:00
|
|
|
if (m_usePipe) {
|
|
|
|
m_pipeMutex.lock();
|
|
|
|
writeByte(m_pipeOut, VANILLA_PIPE_IN_TOUCH);
|
|
|
|
int32_t touchX = x;
|
|
|
|
int32_t touchY = y;
|
|
|
|
write(m_pipeOut, &x, sizeof(x));
|
|
|
|
write(m_pipeOut, &y, sizeof(y));
|
|
|
|
m_pipeMutex.unlock();
|
|
|
|
|
|
|
|
ignoreByte(m_pipeIn);
|
|
|
|
} else {
|
|
|
|
vanilla_set_touch(x, y);
|
|
|
|
}
|
2024-05-23 21:47:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Backend::setButton(int button, int16_t value)
|
|
|
|
{
|
2024-05-24 03:08:17 -04:00
|
|
|
if (m_usePipe) {
|
|
|
|
m_pipeMutex.lock();
|
|
|
|
writeByte(m_pipeOut, VANILLA_PIPE_IN_BUTTON);
|
|
|
|
int32_t buttonSized = button;
|
|
|
|
write(m_pipeOut, &buttonSized, sizeof(buttonSized));
|
|
|
|
write(m_pipeOut, &value, sizeof(value));
|
|
|
|
m_pipeMutex.unlock();
|
|
|
|
|
|
|
|
ignoreByte(m_pipeIn);
|
|
|
|
} else {
|
|
|
|
vanilla_set_button(button, value);
|
|
|
|
}
|
2024-05-23 21:47:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Backend::sync(const QString &wirelessInterface, uint16_t code)
|
|
|
|
{
|
2024-05-23 22:47:32 -04:00
|
|
|
if (m_usePipe) {
|
|
|
|
// Request pipe to sync
|
|
|
|
m_pipeMutex.lock();
|
2024-05-24 03:08:17 -04:00
|
|
|
|
|
|
|
// Write control code
|
|
|
|
writeByte(m_pipeOut, VANILLA_PIPE_IN_SYNC);
|
|
|
|
|
|
|
|
// Write WPS code
|
|
|
|
write(m_pipeOut, &code, sizeof(code));
|
|
|
|
|
|
|
|
// Write wireless interface
|
|
|
|
writeNullTermString(m_pipeOut, wirelessInterface);
|
|
|
|
|
2024-05-23 22:47:32 -04:00
|
|
|
m_pipeMutex.unlock();
|
|
|
|
|
|
|
|
// See if pipe accepted our request to sync
|
2024-05-24 03:08:17 -04:00
|
|
|
uint8_t cc;
|
|
|
|
read(m_pipeIn, &cc, sizeof(cc));
|
2024-05-23 22:47:32 -04:00
|
|
|
if (cc != VANILLA_PIPE_ERR_SUCCESS) {
|
|
|
|
emit syncCompleted(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for sync status
|
2024-05-24 03:08:17 -04:00
|
|
|
read(m_pipeIn, &cc, sizeof(cc));
|
2024-05-23 22:47:32 -04:00
|
|
|
if (cc == VANILLA_PIPE_OUT_SYNC_STATE) {
|
2024-05-24 03:08:17 -04:00
|
|
|
read(m_pipeIn, &cc, sizeof(cc));
|
|
|
|
emit syncCompleted(cc == VANILLA_SUCCESS);
|
2024-05-23 22:47:32 -04:00
|
|
|
} else {
|
|
|
|
emit syncCompleted(false);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
QByteArray wirelessInterfaceC = wirelessInterface.toUtf8();
|
|
|
|
int r = vanilla_sync_with_console(wirelessInterfaceC.constData(), code);
|
|
|
|
emit syncCompleted(r == VANILLA_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-24 03:08:17 -04:00
|
|
|
void Backend::readFromPipe()
|
2024-05-23 22:47:32 -04:00
|
|
|
{
|
2024-05-24 03:08:17 -04:00
|
|
|
while (m_pipe->canReadLine()) {
|
|
|
|
QByteArray a = m_pipe->readLine().trimmed();
|
|
|
|
printf("%s\n", a.constData());
|
|
|
|
fflush(stdout);
|
|
|
|
if (m_pipeOutFilename.isEmpty()) {
|
|
|
|
m_pipeOutFilename = a;
|
|
|
|
} else if (m_pipeIn == -1) {
|
|
|
|
m_pipeIn = open(a.constData(), O_RDONLY);
|
|
|
|
m_pipeOut = open(m_pipeOutFilename.constData(), O_WRONLY);
|
|
|
|
}
|
2024-05-23 22:47:32 -04:00
|
|
|
}
|
2024-05-20 19:16:40 -04:00
|
|
|
}
|