@@ -42,7 +42,7 @@ class AACPManager {
4242 const val CONTROL_COMMAND : Byte = 0x09
4343 const val EAR_DETECTION : Byte = 0x06
4444 const val CONVERSATION_AWARENESS : Byte = 0x4B
45- const val DEVICE_METADATA : Byte = 0x1D
45+ const val INFORMATION : Byte = 0x1D
4646 const val RENAME : Byte = 0x1E
4747 const val HEADTRACKING : Byte = 0x17
4848 const val PROXIMITY_KEYS_REQ : Byte = 0x30
@@ -181,6 +181,20 @@ class AACPManager {
181181 val info2 : Byte ,
182182 var type : String?
183183 )
184+
185+ data class AirPodsInformation (
186+ val name : String ,
187+ val modelNumber : String ,
188+ val manufacturer : String ,
189+ val serialNumber : String ,
190+ val version1 : String ,
191+ val version2 : String ,
192+ val hardwareRevision : String ,
193+ val updaterIdentifier : String ,
194+ val leftSerialNumber : String ,
195+ val rightSerialNumber : String ,
196+ val version3 : String
197+ )
184198 }
185199
186200 var controlCommandStatusList: MutableList <ControlCommandStatus > =
@@ -239,7 +253,7 @@ class AACPManager {
239253 fun onEarDetectionReceived (earDetection : ByteArray )
240254 fun onConversationAwarenessReceived (conversationAwareness : ByteArray )
241255 fun onControlCommandReceived (controlCommand : ByteArray )
242- fun onDeviceMetadataReceived ( deviceMetadata : ByteArray )
256+ fun onDeviceInformationReceived ( deviceInformation : AirPodsInformation )
243257 fun onHeadTrackingReceived (headTracking : ByteArray )
244258 fun onUnknownPacketReceived (packet : ByteArray )
245259 fun onProximityKeysReceived (proximityKeys : ByteArray )
@@ -481,10 +495,6 @@ class AACPManager {
481495 callback?.onConversationAwarenessReceived(packet)
482496 }
483497
484- Opcodes .DEVICE_METADATA -> {
485- callback?.onDeviceMetadataReceived(packet)
486- }
487-
488498 Opcodes .HEADTRACKING -> {
489499 if (packet.size < 70 ) {
490500 Log .w(
@@ -584,8 +594,14 @@ class AACPManager {
584594 eqData = FloatArray (8 ) { i -> eq1.get(i) }
585595 Log .d(TAG , " EQ Data set to: ${eqData.toList()} , eqOnPhone: $eqOnPhone , eqOnMedia: $eqOnMedia " )
586596 }
587-
597+
598+ Opcodes .INFORMATION -> {
599+ Log .e(TAG , " Parsing Information Packet" )
600+ val information = parseInformationPacket(packet)
601+ callback?.onDeviceInformationReceived(information)
602+ }
588603 else -> {
604+ Log .d(TAG , " Unknown opcode received: ${opcode.toHexString()} " )
589605 callback?.onUnknownPacketReceived(packet)
590606 }
591607 }
@@ -1218,4 +1234,39 @@ class AACPManager {
12181234 connectedDevices = listOf ()
12191235 audioSource = null
12201236 }
1237+
1238+ fun parseInformationPacket (packet : ByteArray ): AirPodsInformation {
1239+ val data = packet.sliceArray(6 until packet.size)
1240+
1241+ var index = 0
1242+ while (index < data.size && data[index] != 0x00 .toByte()) index++
1243+
1244+ val strings = mutableListOf<String >()
1245+ while (index < data.size) {
1246+ // skip 0x00 bytes
1247+ while (index < data.size && data[index] == 0x00 .toByte()) index++
1248+ if (index >= data.size) break
1249+ val start = index
1250+ // find next 0x00 byte
1251+ while (index < data.size && data[index] != 0x00 .toByte()) index++
1252+ val str = data.sliceArray(start until index).decodeToString()
1253+ strings.add(str)
1254+ }
1255+
1256+ strings.removeAt(0 ) // I'm too lazy to adjust, just removing the first empty string
1257+
1258+ return AirPodsInformation (
1259+ name = strings.getOrNull(0 ) ? : " " ,
1260+ modelNumber = strings.getOrNull(1 ) ? : " " ,
1261+ manufacturer = strings.getOrNull(2 ) ? : " " ,
1262+ serialNumber = strings.getOrNull(3 ) ? : " " ,
1263+ version1 = strings.getOrNull(4 ) ? : " " ,
1264+ version2 = strings.getOrNull(5 ) ? : " " ,
1265+ hardwareRevision = strings.getOrNull(6 ) ? : " " ,
1266+ updaterIdentifier = strings.getOrNull(7 ) ? : " " ,
1267+ leftSerialNumber = strings.getOrNull(8 ) ? : " " ,
1268+ rightSerialNumber = strings.getOrNull(9 ) ? : " " ,
1269+ version3 = strings.getOrNull(10 ) ? : " " ,
1270+ )
1271+ }
12211272}
0 commit comments