#include #include #include #include #include #include #include bool M17CheckCRC(uint8_t* data, int len) { // TODO: Implement return true; } const char* M17DataTypesTxt[4] = { "Unknown", "Data", "Voice", "Voice & Data" }; const char* M17EncryptionTypesTxt[4] = { "None", "AES", "Scrambler", "Unknown" }; M17LSF M17DecodeLSF(uint8_t* _lsf) { M17LSF lsf; // Extract CRC lsf.rawCRC = 0; for (int i = 0; i < 16; i++) { lsf.rawCRC |= (((uint16_t)_lsf[(i + 48 + 48 + 16 + 112) / 8] >> (7 - (i % 8))) & 1) << (15 - i); } // Check CRC mobilinkd::CRC16 crc16; crc16.reset(); for (int i = 0; i < 28; i++) { crc16(_lsf[i]); } if (crc16.get() != lsf.rawCRC) { lsf.valid = false; return lsf; } lsf.valid = true; // Extract DST lsf.rawDst = 0; for (int i = 0; i < 48; i++) { lsf.rawDst |= (((uint64_t)_lsf[i / 8] >> (7 - (i % 8))) & 1) << (47 - i); } // Extract SRC lsf.rawSrc = 0; for (int i = 0; i < 48; i++) { lsf.rawSrc |= (((uint64_t)_lsf[(i + 48) / 8] >> (7 - (i % 8))) & 1) << (47 - i); } // Extract TYPE lsf.rawType = 0; for (int i = 0; i < 16; i++) { lsf.rawType |= (((uint16_t)_lsf[(i + 48 + 48) / 8] >> (7 - (i % 8))) & 1) << (15 - i); } // Extract META memcpy(lsf.meta, &_lsf[14], 14); // Decode DST if (lsf.rawDst == 0) { lsf.dst = "Invalid"; } else if (lsf.rawDst <= 262143999999999) { char buf[128]; decode_callsign_base40(lsf.rawDst, buf); lsf.dst = buf; } else if (lsf.rawDst == 0xFFFFFFFFFFFF) { lsf.dst = "Broadcast"; } else { char buf[128]; sprintf(buf, "%" PRIX64, lsf.rawDst); lsf.dst = buf; } // Decode SRC if (lsf.rawSrc == 0 || lsf.rawSrc == 0xFFFFFFFFFFFF) { lsf.src = "Invalid"; } else if (lsf.rawSrc <= 262143999999999) { char buf[128]; decode_callsign_base40(lsf.rawSrc, buf); lsf.src = buf; } else { char buf[128]; sprintf(buf, "%" PRIX64, lsf.rawSrc); lsf.src = buf; } // Decode TYPE lsf.isStream = (lsf.rawType >> 0) & 0b1; lsf.dataType = (M17DataType)((lsf.rawType >> 1) & 0b11); lsf.encryptionType = (M17EncryptionType)((lsf.rawType >> 3) & 0b11); lsf.encryptionSubType = (lsf.rawType >> 5) & 0b11; lsf.channelAccessNum = (lsf.rawType >> 7) & 0b1111; return lsf; }