Пример #1
0
void repeaters_store_voice_frame_to_echo_buf(repeater_t *repeater, ipscpacket_t *ipscpacket) {
	repeater_echo_buf_t *new_echo_buf_entry;
	dmrpacket_payload_voice_bits_t *voice_bits;

	if (repeater == NULL || ipscpacket == NULL)
		return;

	new_echo_buf_entry = (repeater_echo_buf_t *)malloc(sizeof(repeater_echo_buf_t));
	if (new_echo_buf_entry == NULL) {
		console_log("  error: can't allocate memory for new echo buffer entry\n");
		return;
	}

	console_log(LOGLEVEL_REPEATERS LOGLEVEL_DEBUG "repeaters [%s]: storing ts%u voice frame to echo buf\n", repeaters_get_display_string_for_ip(&repeater->ipaddr),
		ipscpacket->timeslot);

	voice_bits = dmrpacket_extract_voice_bits(&ipscpacket->payload_bits);
	base_bitstobytes(voice_bits->raw.bits, sizeof(dmrpacket_payload_voice_bits_t), new_echo_buf_entry->voice_bytes.bytes, sizeof(dmrpacket_payload_voice_bits_t)/8);
	new_echo_buf_entry->next = NULL;

	if (repeater->slot[ipscpacket->timeslot-1].echo_buf_last_entry == NULL) {
		repeater->slot[ipscpacket->timeslot-1].echo_buf_last_entry = repeater->slot[ipscpacket->timeslot-1].echo_buf_first_entry = new_echo_buf_entry;
	} else {
		// Putting the new entry to the end of the linked list.
		repeater->slot[ipscpacket->timeslot-1].echo_buf_last_entry->next = new_echo_buf_entry;
		repeater->slot[ipscpacket->timeslot-1].echo_buf_last_entry = new_echo_buf_entry;
	}
}
Пример #2
0
dmrpacket_sync_type_t dmrpacket_get_sync_type(dmrpacket_payload_sync_bits_t *sync_bits) {
    // See DMR AI spec. page 89.
    static uint8_t sync_bs_sourced_voice[6] = { 0x75, 0x5F, 0xD7, 0xDF, 0x75, 0xF7 };
    static uint8_t sync_bs_sourced_data[6] = { 0xDF, 0xF5, 0x7D, 0x75, 0xDF, 0x5D };
    static uint8_t sync_ms_sourced_voice[6] = { 0x7F, 0x7D, 0x5D, 0xD5, 0x7D, 0xFD };
    static uint8_t sync_ms_sourced_data[6] = { 0xD5, 0xD7, 0xF7, 0x7F, 0xD7, 0x57 };
    static uint8_t sync_ms_sourced_rc[6] = { 0x77, 0xD5, 0x5F, 0x7D, 0xFD, 0x77 };
    static uint8_t sync_direct_voice_ts1[6] = { 0x5D, 0x57, 0x7F, 0x77, 0x57, 0xFF };
    static uint8_t sync_direct_data_ts1[6] = { 0xF7, 0xFD, 0xD5, 0xDD, 0xFD, 0x55 };
    static uint8_t sync_direct_voice_ts2[6] = { 0x7D, 0xFF, 0xD5, 0xF5, 0x5D, 0x5F };
    static uint8_t sync_direct_data_ts2[6] = { 0xD7, 0x55, 0x7F, 0x5F, 0xF7, 0xF5 };
    uint8_t sync_bytes[6];

    base_bitstobytes(sync_bits->bits, sizeof(sync_bits->bits), sync_bytes, sizeof(sync_bytes));

    if (memcmp(sync_bytes, sync_bs_sourced_voice, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_BS_SOURCED_VOICE;
    else if (memcmp(sync_bytes, sync_bs_sourced_data, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_BS_SOURCED_DATA;
    else if (memcmp(sync_bytes, sync_ms_sourced_voice, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_MS_SOURCED_VOICE;
    else if (memcmp(sync_bytes, sync_ms_sourced_data, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_MS_SOURCED_DATA;
    else if (memcmp(sync_bytes, sync_ms_sourced_rc, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_MS_SOURCED_RC;
    else if (memcmp(sync_bytes, sync_direct_voice_ts1, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_DIRECT_VOICE_TS1;
    else if (memcmp(sync_bytes, sync_direct_data_ts1, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_DIRECT_DATA_TS1;
    else if (memcmp(sync_bytes, sync_direct_voice_ts2, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_DIRECT_VOICE_TS2;
    else if (memcmp(sync_bytes, sync_direct_data_ts2, sizeof(sync_bytes)) == 0)
        return DMRPACKET_SYNC_TYPE_DIRECT_DATA_TS2;
    else
        return DMRPACKET_SYNC_TYPE_UNKNOWN;
}
Пример #3
0
// See DMR AI. spec. page 67. and DMR services spec. page 53.
dmrpacket_csbk_t *dmrpacket_csbk_decode(bptc_196_96_data_bits_t *data_bits) {
	static dmrpacket_csbk_t csbk;
	uint8_t i;
	uint16_t calculated_crc = 0;
	uint16_t crc;
	uint8_t bytes[12];

	if (data_bits == NULL)
		return NULL;

	console_log(LOGLEVEL_DMRLC "  decoding csbk:\n");

	base_bitstobytes(data_bits->bits, sizeof(bptc_196_96_data_bits_t), bytes, sizeof(bytes));

	for (i = 0; i < 10; i++)
		crc_calc_crc16_ccitt(&calculated_crc, bytes[i]);
	crc_calc_crc16_ccitt_finish(&calculated_crc);

	// Inverting according to the inversion polynomial.
	calculated_crc = ~calculated_crc;
	// Applying CRC mask, see DMR AI spec. page 143.
	calculated_crc ^= 0xa5a5;

	crc = bytes[10] << 8 | bytes[11];
	console_log(LOGLEVEL_DMRLC "    crc: %.4x calculated: %.4x (%s)\n", crc, calculated_crc, calculated_crc != crc ? "error" : "ok");
	if (calculated_crc != crc)
		return NULL;

	if (bytes[0] & 0b01000000) {
		console_log(LOGLEVEL_DMRLC "    error: protect flag is not 0\n");
		return NULL;
	}
	if (bytes[1] != 0) {
		console_log(LOGLEVEL_DMRLC "    error: feature set id is not 0\n");
		return NULL;
	}

	csbk.last_block = (bytes[0] & 0b10000000) > 0;
	console_log(LOGLEVEL_DMRLC "    last block: %u\n", csbk.last_block);
	csbk.dst_id = bytes[4] << 16 | bytes[5] << 8 | bytes[6];
	console_log(LOGLEVEL_DMRLC "    dst id: %u\n", csbk.dst_id);
	csbk.src_id = bytes[7] << 16 | bytes[8] << 8 | bytes[9];
	console_log(LOGLEVEL_DMRLC "    src id: %u\n", csbk.src_id);

	csbk.csbko = bytes[0] & 0b111111;
	console_log(LOGLEVEL_DMRLC "    csbko: %s (%.2x)\n", dmrpacket_csbk_get_readable_csbko(csbk.csbko), csbk.csbko);
	switch (csbk.csbko) {
		case DMRPACKET_CSBKO_BS_OUTBOUND_ACTIVATION: // No important params to parse.
			break;
		case DMRPACKET_CSBKO_UNIT_TO_UNIT_VOICE_SERVICE_REQUEST:
			csbk.data.unit_to_unit_voice_service_request.service_options = bytes[2];
			console_log(LOGLEVEL_DMRLC "      service options: 0x%.2x\n", csbk.data.unit_to_unit_voice_service_request.service_options);
			break;
		case DMRPACKET_CSBKO_UNIT_TO_UNIT_VOICE_SERVICE_ANSWER_RESPONSE:
			csbk.data.unit_to_unit_voice_service_answer_response.service_options = bytes[2];
			console_log(LOGLEVEL_DMRLC "      service options: 0x%.2x\n", csbk.data.unit_to_unit_voice_service_answer_response.service_options);
			csbk.data.unit_to_unit_voice_service_answer_response.answer_response = bytes[3];
			console_log(LOGLEVEL_DMRLC "      answer response: 0x%.2x\n", csbk.data.unit_to_unit_voice_service_answer_response.answer_response);
			break;
		case DMRPACKET_CSBKO_NEGATIVE_ACKNOWLEDGE_RESPONSE:
			csbk.data.negative_acknowledge_response.source_type = ((bytes[2] & 0b01000000) > 0);
			console_log(LOGLEVEL_DMRLC "      source type: %u", csbk.data.negative_acknowledge_response.source_type);
			csbk.data.negative_acknowledge_response.service_type = bytes[2] & 0b111111;
			console_log(LOGLEVEL_DMRLC "      service type: 0x%.2x\n", csbk.data.negative_acknowledge_response.service_type);
			csbk.data.negative_acknowledge_response.reason_code = bytes[3];
			console_log(LOGLEVEL_DMRLC "      reason code: 0x%.2x\n", csbk.data.negative_acknowledge_response.reason_code);
			break;
		case DMRPACKET_CSBKO_PREAMBLE:
			csbk.data.preamble.data_follows = ((bytes[2] & 0b10000000) > 0);
			console_log(LOGLEVEL_DMRLC "      data follows: %u\n", csbk.data.preamble.data_follows);
			csbk.data.preamble.dst_is_group = ((bytes[2] & 0b01000000) > 0);
			console_log(LOGLEVEL_DMRLC "      dst is group: %u\n", csbk.data.preamble.dst_is_group);
			csbk.data.preamble.csbk_blocks_to_follow = bytes[3];
			console_log(LOGLEVEL_DMRLC "      blocks to follow: %u\n", csbk.data.preamble.csbk_blocks_to_follow);
			break;
		default:
			console_log(LOGLEVEL_DMRLC "      unknown csbko\n");
			return NULL;
	}

	return &csbk;
}