diff --git a/src/tetra_mac_pdu.c b/src/tetra_mac_pdu.c index b525dca..58a8845 100644 --- a/src/tetra_mac_pdu.c +++ b/src/tetra_mac_pdu.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -140,6 +141,28 @@ static int decode_nr_slots(uint8_t in) return dec_tbl[in & 0xf]; } +#define MACPDU_LEN_2ND_STOLEN -1 +#define MACPDU_LEN_START_FRAG -2 + +static int decode_length(unsigned int length_ind) +{ + /* FIXME: Y2/Z2 for non-pi4 DQPSK */ + unsigned int y2 = 1, z2 = 1; + + if (length_ind == 0 || length_ind == 0x3b || length_ind == 0x3c) + return -EINVAL; + else if (length_ind <= 0x12) + return y2 * length_ind; + else if (length_ind <= 0x3a) + return (18 * y2 + (length_ind - 18) * z2); + else if (length_ind == 0x3e) + return MACPDU_LEN_2ND_STOLEN; + else if (length_ind == 0x3f) + return MACPDU_LEN_START_FRAG; + else + return -EINVAL; +} + /* Section 21.4.3.1 MAC-RESOURCE */ int macpdu_decode_resource(struct tetra_resrc_decoded *rsd, const uint8_t *bits) { @@ -147,8 +170,7 @@ int macpdu_decode_resource(struct tetra_resrc_decoded *rsd, const uint8_t *bits) rsd->encryption_mode = bits_to_uint(cur, 2); cur += 2; rsd->rand_acc_flag = *cur++; - /* FIXME: Y2/... octet calculation */ - rsd->length_ind = bits_to_uint(cur, 6); cur += 6; + 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: diff --git a/src/tetra_mac_pdu.h b/src/tetra_mac_pdu.h index 3360938..74608a6 100644 --- a/src/tetra_mac_pdu.h +++ b/src/tetra_mac_pdu.h @@ -202,7 +202,7 @@ struct tetra_addr { struct tetra_resrc_decoded { uint8_t encryption_mode; uint8_t rand_acc_flag; - uint8_t length_ind; + int macpdu_length; struct tetra_addr addr; uint8_t power_control_pres; diff --git a/src/tetra_upper_mac.c b/src/tetra_upper_mac.c index bb5812a..a493bab 100644 --- a/src/tetra_upper_mac.c +++ b/src/tetra_upper_mac.c @@ -114,8 +114,8 @@ static void rx_resrc(struct tetra_tmvsap_prim *tmvp) memset(&rsd, 0, sizeof(rsd)); tmpdu_offset = macpdu_decode_resource(&rsd, tup->mac_block); - printf("RESOURCE Encr=%u, Length_ind=%u Addr=%s ", - rsd.encryption_mode, rsd.length_ind, + printf("RESOURCE Encr=%u, Length=%d Addr=%s ", + rsd.encryption_mode, rsd.macpdu_length, tetra_addr_dump(&rsd.addr)); if (rsd.chan_alloc_pres) @@ -125,8 +125,8 @@ static void rx_resrc(struct tetra_tmvsap_prim *tmvp) printf("SlotGrant=%u/%u\n", rsd.slot_granting.nr_slots, rsd.slot_granting.delay); - if (rsd.length_ind && rsd.encryption_mode == 0) { - int len_bits = rsd.length_ind*8; + if (rsd.macpdu_length > 0 && rsd.encryption_mode == 0) { + int len_bits = rsd.macpdu_length*8; if (tup->mac_block + tmpdu_offset + len_bits > tup->mac_block + tup->mac_block_len) len_bits = tup->mac_block_len - tmpdu_offset;