Esempio n. 1
0
static void decode_d_mle_sysinfo(struct tetra_mle_si_decoded *msid, const uint8_t *bits)
{
	const uint8_t *cur = bits;

	msid->la = bits_to_uint(cur, 14); cur += 14;
	msid->subscr_class = bits_to_uint(cur, 16); cur += 16;
	msid->bs_service_details = bits_to_uint(cur, 12); cur += 12;
}
Esempio n. 2
0
static int rx_tmv_unitdata_ind(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
{
	struct tmv_unitdata_param *tup = &tmvp->u.unitdata;
	struct msgb *msg = tmvp->oph.msg;
	uint8_t pdu_type = bits_to_uint(msg->l1h, 2);
	const char *pdu_name;
	struct msgb *gsmtap_msg;

	if (tup->lchan == TETRA_LC_BSCH)
		pdu_name = "SYNC";
	else if (tup->lchan == TETRA_LC_AACH)
		pdu_name = "ACCESS-ASSIGN";
	else {
		pdu_type = bits_to_uint(msg->l1h, 2);
		pdu_name = tetra_get_macpdu_name(pdu_type);
	}

	printf("TMV-UNITDATA.ind %s %s CRC=%u %s\n",
		tetra_tdma_time_dump(&tup->tdma_time),
		tetra_get_lchan_name(tup->lchan),
		tup->crc_ok, pdu_name);

	if (!tup->crc_ok)
		return 0;

	gsmtap_msg = tetra_gsmtap_makemsg(&tup->tdma_time, tup->lchan,
					  tup->tdma_time.tn,
					  /* FIXME: */ 0, 0, 0,
					msg->l1h, msgb_l1len(msg));
	if (gsmtap_msg)
		tetra_gsmtap_sendmsg(gsmtap_msg);

	switch (tup->lchan) {
	case TETRA_LC_AACH:
		rx_aach(tmvp, tms);
		break;
	case TETRA_LC_BNCH:
	case TETRA_LC_UNKNOWN:
	case TETRA_LC_SCH_F:
		switch (pdu_type) {
		case TETRA_PDU_T_BROADCAST:
			rx_bcast(tmvp, tms);
			break;
		case TETRA_PDU_T_MAC_RESOURCE:
			rx_resrc(tmvp, tms);
			break;
		case TETRA_PDU_T_MAC_SUPPL:
			rx_suppl(tmvp, tms);
			break;
		case TETRA_PDU_T_MAC_FRAG_END:
			if (msg->l1h[3] == TETRA_MAC_FRAGE_FRAG) {
				printf("FRAG/END FRAG: ");
				msg->l2h = msg->l1h+4;
				rx_tm_sdu(tms, msg, 100 /*FIXME*/);
				printf("\n");
			} else
				printf("FRAG/END END\n");
			break;
		default:
			printf("STRANGE pdu=%u\n", pdu_type);
			break;
		}
		break;
	case TETRA_LC_BSCH:
		break;
	default:
		printf("STRANGE lchan=%u\n", tup->lchan);
		break;
	}

	return 0;
}
Esempio n. 3
0
/* Receive TL-SDU (LLC SDU == MLE PDU) */
static int rx_tl_sdu(struct tetra_mac_state *tms, struct msgb *msg, unsigned int len)
{
	uint8_t *bits = msg->l3h;
	uint8_t mle_pdisc = bits_to_uint(bits, 3);

	printf("TL-SDU(%s): %s", tetra_get_mle_pdisc_name(mle_pdisc),
		osmo_ubit_dump(bits, len));
	switch (mle_pdisc) {
	case TMLE_PDISC_MM:
		printf(" %s", tetra_get_mm_pdut_name(bits_to_uint(bits+3, 4), 0));
		break;
	case TMLE_PDISC_CMCE:
		printf(" %s", tetra_get_cmce_pdut_name(bits_to_uint(bits+3, 5), 0));
		break;
	case TMLE_PDISC_SNDCP:
		printf(" %s", tetra_get_sndcp_pdut_name(bits_to_uint(bits+3, 4), 0));
		printf(" NSAPI=%u PCOMP=%u, DCOMP=%u",
			bits_to_uint(bits+3+4, 4),
			bits_to_uint(bits+3+4+4, 4),
			bits_to_uint(bits+3+4+4+4, 4));
		printf(" V%u, IHL=%u",
			bits_to_uint(bits+3+4+4+4+4, 4),
			4*bits_to_uint(bits+3+4+4+4+4+4, 4));
		printf(" Proto=%u",
			bits_to_uint(bits+3+4+4+4+4+4+4+64, 8));
		break;
	case TMLE_PDISC_MLE:
		printf(" %s", tetra_get_mle_pdut_name(bits_to_uint(bits+3, 3), 0));
		break;
	default:
		break;
	}
	return len;
}
Esempio n. 4
0
/* 21.5.2 */
static int decode_chan_alloc(struct tetra_chan_alloc_decoded *cad, const uint8_t *bits)
{
	const uint8_t *cur = bits;

	cad->type = 		bits_to_uint(cur, 2); cur += 2;
	cad->timeslot = 	bits_to_uint(cur, 4); cur += 4;
	cad->ul_dl = 		bits_to_uint(cur, 2); cur += 2;
	cad->clch_perm = 	*cur++;
	cad->cell_chg_f = 	*cur++;
	cad->carrier_nr = 	bits_to_uint(cur, 12); cur += 12;

	cad->ext_carr_pres =	*cur++;
	if (cad->ext_carr_pres) {
		cad->ext_carr.freq_band =	bits_to_uint(cur, 4); cur += 4;
		cad->ext_carr.freq_offset =	bits_to_uint(cur, 2); cur += 2;
		cad->ext_carr.duplex_spc =	bits_to_uint(cur, 3); cur += 3;
		cad->ext_carr.reverse_oper =	bits_to_uint(cur, 1); cur += 1;
	}
	cad->monit_pattern =	bits_to_uint(cur, 2); cur += 2;
	if (cad->monit_pattern == 0) {
		cad->monit_patt_f18 =	bits_to_uint(cur, 2);
		cur += 2;
	}
	if (cad->ul_dl == 0) {
		cad->aug.ul_dl_ass =	bits_to_uint(cur, 2); cur += 2;
		cad->aug.bandwidth =	bits_to_uint(cur, 3); cur += 3;
		cad->aug.modulation =	bits_to_uint(cur, 3); cur += 3;
		cad->aug.max_ul_qam =	bits_to_uint(cur, 3); cur += 3;
		cur += 3; /* reserved */
		cad->aug.conf_chan_stat=bits_to_uint(cur, 3); cur += 3;
		cad->aug.bs_imbalance =	bits_to_uint(cur, 4); cur += 4;
		cad->aug.bs_tx_rel =	bits_to_uint(cur, 5); cur += 5;
		cad->aug.napping_sts =	bits_to_uint(cur, 2); cur += 2;
		if (cad->aug.napping_sts == 1)
			cur += 11; /* napping info 21.5.2c */
		cur += 4; /* reserved */
		if (*cur++)
			cur += 16;
		if (*cur++)
			cur += 16;
		cur++;
	}
	return cur - bits;
}
Esempio n. 5
0
void macpdu_decode_sysinfo(struct tetra_si_decoded *sid, const uint8_t *si_bits)
{
	const uint8_t *cur = si_bits + 4;

	sid->main_carrier = bits_to_uint(cur, 12); cur += 12;
	sid->freq_band = bits_to_uint(cur, 4); cur += 4;
	sid->freq_offset = bits_to_uint(cur, 2); cur += 2;
	sid->duplex_spacing = bits_to_uint(cur, 3); cur += 3;
	sid->reverse_operation = *cur++;
	sid->num_of_csch = bits_to_uint(cur, 2); cur +=2;
	sid->ms_txpwr_max_cell = bits_to_uint(cur, 3); cur += 3;
	sid->rxlev_access_min = bits_to_uint(cur, 4); cur += 4;
	sid->access_parameter = bits_to_uint(cur, 4); cur += 4;
	sid->radio_dl_timeout = bits_to_uint(cur, 4); cur += 4;
	sid->cck_valid_no_hf = *cur++;
	if (sid->cck_valid_no_hf)
		sid->cck_id = bits_to_uint(cur, 16);
	else
		sid->hyperframe_number = bits_to_uint(cur, 16);
	cur += 16;
	/* FIXME: more */
	decode_d_mle_sysinfo(&sid->mle_si, si_bits + 124-42);
}
Esempio n. 6
0
/* Section 21.4.7.2 ACCESS-ASSIGN PDU */
void macpdu_decode_access_assign(struct tetra_acc_ass_decoded *aad, const uint8_t *bits, int f18)
{
	uint8_t field1, field2;
	aad->hdr = bits_to_uint(bits, 2);
	field1 = bits_to_uint(bits+2, 6);
	field2 = bits_to_uint(bits+8, 6);

	if (f18 == 0) {
		switch (aad->hdr) {
		case TETRA_ACC_ASS_DLCC_ULCO:
			/* Field 1 and Field2 are Access fields */
			decode_access_field(&aad->access[0], field1);
			decode_access_field(&aad->access[1], field2);
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS1;
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS2;
			break;
		case TETRA_ACC_ASS_DLF1_ULCA:
			/* Field1: DL usage marker */
			aad->dl_usage = field1;
			aad->pres |= TETRA_ACC_ASS_PRES_DL_USAGE;
			/* Field2: Access field */
			decode_access_field(&aad->access[1], field2);
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS2;
			break;
		case TETRA_ACC_ASS_DLF1_ULAO:
			/* Field1: DL usage marker */
			aad->dl_usage = field1;
			aad->pres |= TETRA_ACC_ASS_PRES_DL_USAGE;
			/* Field2: Access field */
			decode_access_field(&aad->access[1], field2);
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS2;
			break;
		case TETRA_ACC_ASS_DLF1_ULF1:
			/* Field1: DL usage marker */
			aad->dl_usage = field1;
			aad->pres |= TETRA_ACC_ASS_PRES_DL_USAGE;
			/* Field2: UL usage marker */
			aad->ul_usage = field2;
			aad->pres |= TETRA_ACC_ASS_PRES_UL_USAGE;
			break;
		}
	} else {
		switch (aad->hdr) {
		case TETRA_ACC_ASS_ULCO:
			/* Field1 and Field2: Access field */
			decode_access_field(&aad->access[0], field1);
			decode_access_field(&aad->access[1], field2);
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS1;
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS2;
			break;
		case TETRA_ACC_ASS_ULCA:
			/* Field1 and Field2: Access field */
			decode_access_field(&aad->access[0], field1);
			decode_access_field(&aad->access[1], field2);
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS1;
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS2;
			break;
		case TETRA_ACC_ASS_ULAO:
			/* Field1 and Field2: Access field */
			decode_access_field(&aad->access[0], field1);
			decode_access_field(&aad->access[1], field2);
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS1;
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS2;
			break;
		case TETRA_ACC_ASS_ULCA2:
			/* Field1: Traffic usage marker (UMt) */
			/* FIXME */
			/* Field2: Access field */
			decode_access_field(&aad->access[1], field2);
			aad->pres |= TETRA_ACC_ASS_PRES_ACCESS2;
			break;
		}
	}
}
Esempio n. 7
0
/* Section 21.4.3.1 MAC-RESOURCE */
int macpdu_decode_resource(struct tetra_resrc_decoded *rsd, const uint8_t *bits)
{
	const uint8_t *cur = bits + 4;

	rsd->encryption_mode = bits_to_uint(cur, 2); cur += 2;
	rsd->rand_acc_flag = *cur++;
	rsd->macpdu_length = decode_length(bits_to_uint(cur, 6)); cur += 6;
	rsd->addr.type = bits_to_uint(cur, 3); cur += 3;
	switch (rsd->addr.type) {
	case ADDR_TYPE_NULL:
		return 0;
		break;
	case ADDR_TYPE_SSI:
	case ADDR_TYPE_USSI:
	case ADDR_TYPE_SMI:
		rsd->addr.ssi = bits_to_uint(cur, 24);
		break;
	case ADDR_TYPE_EVENT_LABEL:
		rsd->addr.event_label = bits_to_uint(cur, 10);
		break;
	case ADDR_TYPE_SSI_EVENT:
	case ADDR_TYPE_SMI_EVENT:
		rsd->addr.ssi = bits_to_uint(cur, 24);
		rsd->addr.event_label = bits_to_uint(cur+24, 10);
		break;
	case ADDR_TYPE_SSI_USAGE:
		rsd->addr.ssi = bits_to_uint(cur, 24);
		rsd->addr.usage_marker = bits_to_uint(cur+24, 6);
		break;
	default:
		return -EINVAL;
		break;
	}
	cur += addr_len_by_type[rsd->addr.type];
	/* no intermediate napping in pi/4 */
	rsd->power_control_pres = *cur++;
	if (rsd->power_control_pres)
		cur += 4;
	rsd->slot_granting.pres = *cur++;
	if (rsd->slot_granting.pres) {
#if 0
		/* check for multiple slot granting flag (can only exist in QAM) */
		if (*cur++) {
			cur += 0; //FIXME;
		} else {
#endif
			rsd->slot_granting.nr_slots =
				decode_nr_slots(bits_to_uint(cur, 4));
			cur += 4;
			rsd->slot_granting.delay = bits_to_uint(cur, 4);
			cur += 4;
#if 0
		}
#endif
	}
	rsd->chan_alloc_pres = *cur++;
	/* FIXME: If encryption is enabled, Channel Allocation is encrypted !!! */
	if (rsd->chan_alloc_pres)
		cur += decode_chan_alloc(&rsd->cad, cur);
	/* FIXME: TM-SDU */

	return cur - bits;
}