11#include " main.h"
2+ #include " airpods_packets.h"
23
34#define LOG_INFO (msg ) qCInfo(airpodsApp) << " \033 [32m" << msg << " \033 [0m"
45#define LOG_WARN (msg ) qCWarning(airpodsApp) << " \033 [33m" << msg << " \033 [0m"
@@ -187,16 +188,18 @@ class AirPodsTrayApp : public QObject {
187188 QDBusConnection::systemBus ().registerService (" me.kavishdevar.aln" );
188189 }
189190
190- void notifyAndroidDevice () {
191- if (phoneSocket && phoneSocket->isOpen ()) {
192- QByteArray notificationPacket = QByteArray::fromHex (" 00040001" );
193- phoneSocket->write (notificationPacket);
194- LOG_DEBUG (" Sent notification packet to Android: " << notificationPacket.toHex ());
195- } else {
191+ void notifyAndroidDevice ()
192+ {
193+ if (phoneSocket && phoneSocket->isOpen ())
194+ {
195+ phoneSocket->write (AirPodsPackets::Phone::NOTIFICATION);
196+ LOG_DEBUG (" Sent notification packet to Android: " << AirPodsPackets::Phone::NOTIFICATION.toHex ());
197+ }
198+ else
199+ {
196200 LOG_WARN (" Phone socket is not open, cannot send notification packet" );
197201 }
198202 }
199-
200203 void onNameOwnerChanged (const QString &name, const QString &oldOwner, const QString &newOwner) {
201204 if (name == " org.bluez" ) {
202205 if (newOwner.isEmpty ()) {
@@ -257,38 +260,48 @@ public slots:
257260 }
258261 }
259262
260- void setNoiseControlMode (NoiseControlMode mode) {
263+ void setNoiseControlMode (NoiseControlMode mode)
264+ {
261265 LOG_INFO (" Setting noise control mode to: " << mode);
262266 QByteArray packet;
263- switch (mode) {
264- case Off:
265- packet = QByteArray::fromHex (" 0400040009000D01000000" );
266- break ;
267- case NoiseCancellation:
268- packet = QByteArray::fromHex (" 0400040009000D02000000" );
269- break ;
270- case Transparency:
271- packet = QByteArray::fromHex (" 0400040009000D03000000" );
272- break ;
273- case Adaptive:
274- packet = QByteArray::fromHex (" 0400040009000D04000000" );
275- break ;
267+ switch (mode)
268+ {
269+ case Off:
270+ packet = AirPodsPackets::NoiseControl::OFF;
271+ break ;
272+ case NoiseCancellation:
273+ packet = AirPodsPackets::NoiseControl::NOISE_CANCELLATION;
274+ break ;
275+ case Transparency:
276+ packet = AirPodsPackets::NoiseControl::TRANSPARENCY;
277+ break ;
278+ case Adaptive:
279+ packet = AirPodsPackets::NoiseControl::ADAPTIVE;
280+ break ;
276281 }
277- if (socket && socket->isOpen ()) {
282+ if (socket && socket->isOpen ())
283+ {
278284 socket->write (packet);
279285 LOG_DEBUG (" Noise control mode packet written: " << packet.toHex ());
280- } else {
286+ }
287+ else
288+ {
281289 LOG_ERROR (" Socket is not open, cannot write noise control mode packet" );
282290 }
283291 }
284292
285- void setConversationalAwareness (bool enabled) {
293+ void setConversationalAwareness (bool enabled)
294+ {
286295 LOG_INFO (" Setting conversational awareness to: " << (enabled ? " enabled" : " disabled" ));
287- QByteArray packet = enabled ? QByteArray::fromHex (" 0400040009002801000000" ) : QByteArray::fromHex (" 0400040009002802000000" );
288- if (socket && socket->isOpen ()) {
296+ QByteArray packet = enabled ? AirPodsPackets::ConversationalAwareness::ENABLED
297+ : AirPodsPackets::ConversationalAwareness::DISABLED;
298+ if (socket && socket->isOpen ())
299+ {
289300 socket->write (packet);
290301 LOG_DEBUG (" Conversational awareness packet written: " << packet.toHex ());
291- } else {
302+ }
303+ else
304+ {
292305 LOG_ERROR (" Socket is not open, cannot write conversational awareness packet" );
293306 }
294307 }
@@ -468,17 +481,19 @@ public slots:
468481 }
469482 }
470483
471- void onDeviceDisconnected (const QBluetoothAddress &address) {
484+ void onDeviceDisconnected (const QBluetoothAddress &address)
485+ {
472486 LOG_INFO (" Device disconnected: " << address.toString ());
473- if (socket) {
487+ if (socket)
488+ {
474489 LOG_WARN (" Socket is still open, closing it" );
475490 socket->close ();
476491 socket = nullptr ;
477492 }
478- if (phoneSocket && phoneSocket->isOpen ()) {
479- QByteArray airpodsDisconnectedPacket = QByteArray::fromHex ( " 00010000 " );
480- phoneSocket->write (airpodsDisconnectedPacket );
481- LOG_DEBUG (" AIRPODS_DISCONNECTED packet written: " << airpodsDisconnectedPacket .toHex ());
493+ if (phoneSocket && phoneSocket->isOpen ())
494+ {
495+ phoneSocket->write (AirPodsPackets::Connection::AIRPODS_DISCONNECTED );
496+ LOG_DEBUG (" AIRPODS_DISCONNECTED packet written: " << AirPodsPackets::Connection::AIRPODS_DISCONNECTED .toHex ());
482497 }
483498 }
484499
@@ -494,9 +509,9 @@ public slots:
494509 LOG_INFO (" Connected to device, sending initial packets" );
495510 discoveryAgent->stop ();
496511
497- QByteArray handshakePacket = QByteArray::fromHex ( " 00000400010002000000000000000000 " ) ;
498- QByteArray setSpecificFeaturesPacket = QByteArray::fromHex ( " 040004004d00ff00000000000000 " ) ;
499- QByteArray requestNotificationsPacket = QByteArray::fromHex ( " 040004000f00ffffffffff " ) ;
512+ QByteArray handshakePacket = AirPodsPackets::Connection::HANDSHAKE ;
513+ QByteArray setSpecificFeaturesPacket = AirPodsPackets::Connection::SET_SPECIFIC_FEATURES ;
514+ QByteArray requestNotificationsPacket = AirPodsPackets::Connection::REQUEST_NOTIFICATIONS ;
500515
501516 qint64 bytesWritten = localSocket->write (handshakePacket);
502517 LOG_DEBUG (" Handshake packet written: " << handshakePacket.toHex () << " , bytes written: " << bytesWritten);
@@ -557,10 +572,14 @@ public slots:
557572 : " In case" ;
558573 }
559574
560- void parseData (const QByteArray &data) {
575+ void parseData (const QByteArray &data)
576+ {
561577 LOG_DEBUG (" Received: " << data.toHex ());
562- if (data.size () == 11 && data.startsWith (QByteArray::fromHex (" 0400040009000D" ))) {
563- quint8 rawMode = data[7 ] - 1 ;
578+
579+ // Noise Control Mode
580+ if (data.size () == 11 && data.startsWith (AirPodsPackets::NoiseControl::HEADER))
581+ {
582+ quint8 rawMode = data[7 ] - 1 ; // Offset still needed due to protocol
564583 if (rawMode >= NoiseControlMode::MinValue && rawMode <= NoiseControlMode::MaxValue)
565584 {
566585 NoiseControlMode mode = static_cast <NoiseControlMode>(rawMode);
@@ -571,30 +590,41 @@ public slots:
571590 {
572591 LOG_ERROR (" Invalid noise control mode value received: " << rawMode);
573592 }
574- } else if (data.size () == 8 && data.startsWith (QByteArray::fromHex (" 040004000600" ))) {
593+ }
594+ // Ear Detection
595+ else if (data.size () == 8 && data.startsWith (AirPodsPackets::Parse::EAR_DETECTION))
596+ {
575597 char primary = data[6 ];
576598 char secondary = data[7 ];
577599 QString earDetectionStatus = QString (" Primary: %1, Secondary: %2" )
578- . arg ( getEarStatus (primary), getEarStatus (secondary));
600+ . arg ( getEarStatus (primary), getEarStatus (secondary));
579601 LOG_INFO (" Ear detection status: " << earDetectionStatus);
580602 emit earDetectionStatusChanged (earDetectionStatus);
581- } else if (data.size () == 22 && data.startsWith (QByteArray::fromHex (" 040004000400" ))) {
603+ }
604+ // Battery Status
605+ else if (data.size () == 22 && data.startsWith (AirPodsPackets::Parse::BATTERY_STATUS))
606+ {
582607 int leftLevel = data[9 ];
583608 int rightLevel = data[14 ];
584609 int caseLevel = data[19 ];
585610 QString batteryStatus = QString (" Left: %1%, Right: %2%, Case: %3%" )
586- .arg (leftLevel)
587- .arg (rightLevel)
588- .arg (caseLevel);
611+ .arg (leftLevel)
612+ .arg (rightLevel)
613+ .arg (caseLevel);
589614 LOG_INFO (" Battery status: " << batteryStatus);
590615 emit batteryStatusChanged (batteryStatus);
591-
592- } else if (data.size () == 10 && data.startsWith (QByteArray::fromHex (" 040004004B00020001" ))) {
616+ }
617+ // Conversational Awareness Data
618+ else if (data.size () == 10 && data.startsWith (AirPodsPackets::ConversationalAwareness::DATA_HEADER))
619+ {
593620 LOG_INFO (" Received conversational awareness data" );
594621 handleConversationalAwareness (data);
595622 }
623+ else
624+ {
625+ LOG_DEBUG (" Unrecognized packet format: " << data.toHex ());
626+ }
596627 }
597-
598628 void handleConversationalAwareness (const QByteArray &data) {
599629 LOG_DEBUG (" Handling conversational awareness data: " << data.toHex ());
600630 static int initialVolume = -1 ;
@@ -692,39 +722,52 @@ public slots:
692722 phoneSocket->connectToService (phoneAddress, QBluetoothUuid (" 1abbb9a4-10e4-4000-a75c-8953c5471342" ));
693723 }
694724
695- void relayPacketToPhone (const QByteArray &packet) {
696- if (phoneSocket && phoneSocket->isOpen ()) {
697- QByteArray header = QByteArray::fromHex (" 00040001" );
698- phoneSocket->write (header + packet);
699- } else {
725+ void relayPacketToPhone (const QByteArray &packet)
726+ {
727+ if (phoneSocket && phoneSocket->isOpen ())
728+ {
729+ phoneSocket->write (AirPodsPackets::Phone::NOTIFICATION + packet);
730+ }
731+ else
732+ {
700733 connectToPhone ();
701734 LOG_WARN (" Phone socket is not open, cannot relay packet" );
702735 }
703736 }
704737
705738 void handlePhonePacket (const QByteArray &packet) {
706- if (packet.startsWith (QByteArray::fromHex (" 00040001" ))) {
739+ if (packet.startsWith (AirPodsPackets::Phone::NOTIFICATION))
740+ {
707741 QByteArray airpodsPacket = packet.mid (4 );
708742 if (socket && socket->isOpen ()) {
709743 socket->write (airpodsPacket);
710744 LOG_DEBUG (" Relayed packet to AirPods: " << airpodsPacket.toHex ());
711745 } else {
712746 LOG_ERROR (" Socket is not open, cannot relay packet to AirPods" );
713747 }
714- } else if (packet.startsWith (QByteArray::fromHex (" 00010001" ))) {
748+ }
749+ else if (packet.startsWith (AirPodsPackets::Phone::CONNECTED))
750+ {
715751 LOG_INFO (" AirPods connected" );
716752 isConnectedLocally = true ;
717753 CrossDevice.isAvailable = false ;
718- } else if (packet.startsWith (QByteArray::fromHex (" 00010000" ))) {
754+ }
755+ else if (packet.startsWith (AirPodsPackets::Phone::DISCONNECTED))
756+ {
719757 LOG_INFO (" AirPods disconnected" );
720758 isConnectedLocally = false ;
721759 CrossDevice.isAvailable = true ;
722- } else if (packet.startsWith (QByteArray::fromHex (" 00020003" ))) {
760+ }
761+ else if (packet.startsWith (AirPodsPackets::Phone::STATUS_REQUEST))
762+ {
723763 LOG_INFO (" Connection status request received" );
724- QByteArray response = (socket && socket->isOpen ()) ? QByteArray::fromHex (" 00010001" ) : QByteArray::fromHex (" 00010000" );
764+ QByteArray response = (socket && socket->isOpen ()) ? AirPodsPackets::Phone::CONNECTED
765+ : AirPodsPackets::Phone::DISCONNECTED;
725766 phoneSocket->write (response);
726767 LOG_DEBUG (" Sent connection status response: " << response.toHex ());
727- } else if (packet.startsWith (QByteArray::fromHex (" 00020000" ))) {
768+ }
769+ else if (packet.startsWith (AirPodsPackets::Phone::DISCONNECT_REQUEST))
770+ {
728771 LOG_INFO (" Disconnect request received" );
729772 if (socket && socket->isOpen ()) {
730773 socket->close ();
@@ -737,7 +780,9 @@ public slots:
737780 isConnectedLocally = false ;
738781 CrossDevice.isAvailable = true ;
739782 }
740- } else {
783+ }
784+ else
785+ {
741786 if (socket && socket->isOpen ()) {
742787 socket->write (packet);
743788 LOG_DEBUG (" Relayed packet to AirPods: " << packet.toHex ());
@@ -787,12 +832,15 @@ public slots:
787832 playerctlProcess->start (" playerctl" , QStringList () << " --follow" << " status" );
788833 }
789834
790- void sendDisconnectRequestToAndroid () {
791- if (phoneSocket && phoneSocket->isOpen ()) {
792- QByteArray disconnectRequest = QByteArray::fromHex (" 00020000" );
793- phoneSocket->write (disconnectRequest);
794- LOG_DEBUG (" Sent disconnect request to Android: " << disconnectRequest.toHex ());
795- } else {
835+ void sendDisconnectRequestToAndroid ()
836+ {
837+ if (phoneSocket && phoneSocket->isOpen ())
838+ {
839+ phoneSocket->write (AirPodsPackets::Phone::DISCONNECT_REQUEST);
840+ LOG_DEBUG (" Sent disconnect request to Android: " << AirPodsPackets::Phone::DISCONNECT_REQUEST.toHex ());
841+ }
842+ else
843+ {
796844 LOG_WARN (" Phone socket is not open, cannot send disconnect request" );
797845 }
798846 }
0 commit comments