Files
librepods/linux/BluetoothHandler.cpp
2025-01-25 03:12:23 +05:30

109 lines
5.3 KiB
C++

#include "BluetoothHandler.h"
#include "PacketDefinitions.h"
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(bluetoothHandler, "bluetoothHandler")
#define LOG_INFO(msg) qCInfo(bluetoothHandler) << "\033[32m" << msg << "\033[0m"
#define LOG_WARN(msg) qCWarning(bluetoothHandler) << "\033[33m" << msg << "\033[0m"
#define LOG_ERROR(msg) qCCritical(bluetoothHandler) << "\033[31m" << msg << "\033[0m"
#define LOG_DEBUG(msg) qCDebug(bluetoothHandler) << "\033[34m" << msg << "\033[0m"
BluetoothHandler::BluetoothHandler() {
discoveryAgent = new QBluetoothDeviceDiscoveryAgent();
discoveryAgent->setLowEnergyDiscoveryTimeout(5000);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothHandler::onDeviceDiscovered);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &BluetoothHandler::onDiscoveryFinished);
discoveryAgent->start();
LOG_INFO("BluetoothHandler initialized and started device discovery");
}
void BluetoothHandler::connectToDevice(const QBluetoothDeviceInfo &device) {
if (socket && socket->isOpen() && socket->peerAddress() == device.address()) {
LOG_INFO("Already connected to the device: " << device.name());
return;
}
LOG_INFO("Connecting to device: " << device.name());
QBluetoothSocket *localSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol);
connect(localSocket, &QBluetoothSocket::connected, this, [this, localSocket]() {
LOG_INFO("Connected to device, sending initial packets");
discoveryAgent->stop();
QByteArray handshakePacket = QByteArray::fromHex("00000400010002000000000000000000");
QByteArray setSpecificFeaturesPacket = QByteArray::fromHex("040004004d00ff00000000000000");
QByteArray requestNotificationsPacket = QByteArray::fromHex("040004000f00ffffffffff");
qint64 bytesWritten = localSocket->write(handshakePacket);
LOG_DEBUG("Handshake packet written: " << handshakePacket.toHex() << ", bytes written: " << bytesWritten);
QByteArray airpodsConnectedPacket = QByteArray::fromHex("000400010001");
phoneSocket->write(airpodsConnectedPacket);
LOG_DEBUG("AIRPODS_CONNECTED packet written: " << airpodsConnectedPacket.toHex());
connect(localSocket, &QBluetoothSocket::bytesWritten, this, [this, localSocket, setSpecificFeaturesPacket, requestNotificationsPacket](qint64 bytes) {
LOG_INFO("Bytes written: " << bytes);
if (bytes > 0) {
static int step = 0;
switch (step) {
case 0:
localSocket->write(setSpecificFeaturesPacket);
LOG_DEBUG("Set specific features packet written: " << setSpecificFeaturesPacket.toHex());
step++;
break;
case 1:
localSocket->write(requestNotificationsPacket);
LOG_DEBUG("Request notifications packet written: " << requestNotificationsPacket.toHex());
step++;
break;
}
}
});
connect(localSocket, &QBluetoothSocket::readyRead, this, [this, localSocket]() {
QByteArray data = localSocket->readAll();
LOG_DEBUG("Data received: " << data.toHex());
parseData(data);
relayPacketToPhone(data);
});
});
connect(localSocket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::errorOccurred), this, [this, localSocket](QBluetoothSocket::SocketError error) {
LOG_ERROR("Socket error: " << error << ", " << localSocket->errorString());
});
localSocket->connectToService(device.address(), QBluetoothUuid("74ec2172-0bad-4d01-8f77-997b2be0722a"));
socket = localSocket;
connectedDeviceMacAddress = device.address().toString().replace(":", "_");
}
void BluetoothHandler::parseData(const QByteArray &data) {
LOG_DEBUG("Parsing data: " << data.toHex() << "Size: " << data.size());
if (data.size() == 11 && data.startsWith(QByteArray::fromHex("0400040009000D"))) {
int mode = data[7] - 1;
LOG_INFO("Noise control mode: " << mode);
if (mode >= 0 && mode <= 3) {
emit noiseControlModeChanged(mode);
} else {
LOG_ERROR("Invalid noise control mode value received: " << mode);
}
} else if (data.size() == 8 && data.startsWith(QByteArray::fromHex("040004000600"))) {
bool primaryInEar = data[6] == 0x00;
bool secondaryInEar = data[7] == 0x00;
QString earDetectionStatus = QString("Primary: %1, Secondary: %2")
.arg(primaryInEar ? "In Ear" : "Out of Ear")
.arg(secondaryInEar ? "In Ear" : "Out of Ear");
LOG_INFO("Ear detection status: " << earDetectionStatus);
emit earDetectionStatusChanged(earDetectionStatus);
} else if (data.size() == 22 && data.startsWith(QByteArray::fromHex("040004000400"))) {
int leftLevel = data[9];
int rightLevel = data[14];
int caseLevel = data[19];
QString batteryStatus = QString("Left: %1%, Right: %2%, Case: %3%")
.arg(leftLevel)
.arg(rightLevel)
.arg(caseLevel);
LOG_INFO("Battery status: " << batteryStatus);
emit batteryStatusChanged(batteryStatus);
} else if (data.size() == 10 &&