#!/usr/bin/env python # ############################################################################### # Copyright (C) 2013-2026 Cortney T. Buffington, N0MJS # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################### # IPSC Protocol Constants and Bitmasks -- merged from ipsc_const.py and ipsc_mask.py # Known IPSC Message Types CALL_CONFIRMATION = b'\x05' TXT_MESSAGE_ACK = b'\x54' CALL_MON_STATUS = b'\x61' CALL_MON_RPT = b'\x62' REPEATER_BLOCKED = b'\x63' # signal interference / BSI blocking event XCMP_XNL = b'\x70' GROUP_VOICE = b'\x80' PVT_VOICE = b'\x81' GROUP_DATA = b'\x83' PVT_DATA = b'\x84' RPT_WAKE_UP = b'\x85' CALL_INTERRUPT_REQ = b'\x86' # call interrupt request MASTER_REG_REQ = b'\x90' MASTER_REG_REPLY = b'\x91' PEER_LIST_REQ = b'\x92' PEER_LIST_REPLY = b'\x93' PEER_REG_REQ = b'\x94' PEER_REG_REPLY = b'\x95' MASTER_ALIVE_REQ = b'\x96' MASTER_ALIVE_REPLY = b'\x97' PEER_ALIVE_REQ = b'\x98' PEER_ALIVE_REPLY = b'\x99' DE_REG_REQ = b'\x9A' DE_REG_REPLY = b'\x9B' SYSTEM_MAP_REQ = b'\x9C' # system topology query; purpose not fully known SYSTEM_MAP_REPLY = b'\x9D' UNKNOWN_9E = b'\x9E' # possibly extended peer registration WIRELINE = b'\xB2' # MNIS data sub-protocol REMOTE_PROG_REQ = b'\xE0' # CPS remote programming session request REMOTE_PROG_REPLY = b'\xE1' OPCODE_0xF0 = b'\xF0' # observed, benign, no response needed # IPSC Version Information IPSC_VER_14 = b'\x00' IPSC_VER_15 = b'\x00' IPSC_VER_15A = b'\x00' IPSC_VER_16 = b'\x01' IPSC_VER_17 = b'\x02' IPSC_VER_18 = b'\x02' IPSC_VER_19 = b'\x03' IPSC_VER_22 = b'\x04' LINK_TYPE_IPSC = b'\x04' # IPSC Version field used in registration packets IPSC_VER = LINK_TYPE_IPSC + IPSC_VER_17 + LINK_TYPE_IPSC + IPSC_VER_16 # GROUP_VOICE burst type byte values (data[GV_BURST_TYPE_OFF] returns int in Python 3) VOICE_HEAD = 0x01 VOICE_TERM = 0x02 SLOT1_VOICE = 0x0A SLOT2_VOICE = 0x8A # GROUP_VOICE packet field offsets GV_CALL_INFO_OFF = 17 # timeslot/end flags byte GV_RTP_TS_OFF = 22 # 4-byte RTP timestamp (8 kHz clock, +480 per burst) GV_BURST_TYPE_OFF = 30 # burst type byte (see VOICE_HEAD / SLOT1_VOICE etc.) GV_BE_FLAG = 0x16 # data[32] value that identifies a burst-E superframe GV_BE_LC_FLCO_OFF = 56 # FLCO field within burst-E embedded LC GV_MIN_LEN = 33 # minimum valid GROUP_VOICE packet length FLCO_GROUP = 0x00 # FLCO value for a group voice call (not Talker Alias) # Packet type membership lists ANY_PEER_REQUIRED = [GROUP_VOICE, PVT_VOICE, GROUP_DATA, PVT_DATA, CALL_MON_STATUS, CALL_MON_RPT, REPEATER_BLOCKED, CALL_INTERRUPT_REQ, XCMP_XNL, RPT_WAKE_UP, DE_REG_REQ] PEER_REQUIRED = [PEER_ALIVE_REQ, PEER_ALIVE_REPLY, PEER_REG_REQ, PEER_REG_REPLY] MASTER_REQUIRED = [PEER_LIST_REPLY, MASTER_ALIVE_REPLY] USER_PACKETS = [GROUP_VOICE, PVT_VOICE, GROUP_DATA, PVT_DATA] # RCM Timeslot constants TS = {b'\x00': '1', b'\x01': '2'} # DMR ID range constants (matches hblink3) ID_MIN = 1 ID_MAX = 16776415 PEER_MAX = 4294967295 # --------------------------------------------------------------------------- # IPSC Bitmasks (from ipsc_mask.py) # --------------------------------------------------------------------------- # LINKING STATUS byte flags # xx.. .... Peer Operational (01 = operational) # ..xx .... Peer MODE: 00=No Radio, 01=Analog, 10=Digital # .... xx.. IPSC Slot 1: 10=on, 01=off # .... ..xx IPSC Slot 2: 10=on, 01=off PEER_OP_MSK = 0b01000000 PEER_MODE_MSK = 0b00110000 PEER_MODE_ANALOG = 0b00010000 PEER_MODE_DIGITAL = 0b00100000 IPSC_TS1_MSK = 0b00001100 IPSC_TS2_MSK = 0b00000011 # SERVICE FLAGS byte 3 CSBK_MSK = 0b10000000 RPT_MON_MSK = 0b01000000 CON_APP_MSK = 0b00100000 # SERVICE FLAGS byte 4 XNL_STAT_MSK = 0b10000000 XNL_MSTR_MSK = 0b01000000 XNL_SLAVE_MSK = 0b00100000 PKT_AUTH_MSK = 0b00010000 DATA_CALL_MSK = 0b00001000 VOICE_CALL_MSK = 0b00000100 MSTR_PEER_MSK = 0b00000001 # TIMESLOT CALL & STATUS byte (GV_CALL_INFO_OFF = byte 17 of voice/data packets) # .x.. .... End flag (0=in-progress, 1=end) # ..x. .... Timeslot (0=TS1, 1=TS2) END_MSK = 0b01000000 TS_CALL_MSK = 0b00100000 # RTP header bitmasks RTP_VER_MSK = 0b11000000 RTP_PAD_MSK = 0b00100000 RTP_EXT_MSK = 0b00010000 RTP_CSIC_MSK = 0b00001111 RTP_MRKR_MSK = 0b10000000 RTP_PAY_TYPE_MSK = 0b01111111