aboutsummaryrefslogtreecommitdiffstats
path: root/src/gsm/iuup_crc.c
blob: 1cefe5a333ba4d7dfc46118e975f47c6fd138681 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdint.h>
#include <stdio.h>

#include <osmocom/core/crc8gen.h>
#include <osmocom/core/crc16gen.h>

static const struct osmo_crc8gen_code iuup_hdr_crc_code = {
	.bits = 6,
	.poly = 47,
	.init = 0,
	.remainder = 0,
};

static const struct osmo_crc16gen_code iuup_data_crc_code = {
	.bits = 10,
	.poly = 563,
	.init = 0,
	.remainder = 0,
};

static int iuup_get_payload_offset(const uint8_t *iuup_pdu)
{
	uint8_t pdu_type = iuup_pdu[0] >> 4;
	switch (pdu_type) {
	case 0:
	case 14:
		return 4;
	case 1:
		return 3;
	default:
		return -1;
	}
}

int osmo_iuup_compute_payload_crc(const uint8_t *iuup_pdu, unsigned int pdu_len)
{
	ubit_t buf[1024*8];
	uint8_t pdu_type;
	int offset, payload_len_bytes;

	if (pdu_len < 1)
		return -1;

	pdu_type = iuup_pdu[0] >> 4;

	/* Type 1 has no CRC */
	if (pdu_type == 1)
		return 0;

	offset = iuup_get_payload_offset(iuup_pdu, pdu_len);
	if (offset < 0)
		return offset;

	if (pdu_len < offset)
		return -1;

	payload_len_bytes = pdu_eln - offset;
	osmo_pbit2ubit(buf, iuup_pdu+offset, payload_len_bytes*8);
	return osmo_crc16gen_compute_bits(&iuup_data_crc_code, buf, payload_len_bytes*8);
}

int osmo_iuup_compute_header_crc(const uint8_t *iuup_pdu, unsigned int pdu_len)
{
	ubit_t buf[2*8];

	if (pdu_len < 2)
		return -1;

	osmo_pbit2ubit(buf, iuup_pdu, 2*8);
	return osmo_crc8gen_compute_bits(&iuup_hdr_crc_code, buf, 2*8);
}

#if 0
/* Frame 29 of MobileOriginatingCall_AMR.cap */
const uint8_t iuup_frame29[] = {
	0x02, 0x00, 0x7d, 0x27, 0x55, 0x00, 0x88, 0xb6, 0x66, 0x79, 0xe1, 0xe0,
	0x01, 0xe7, 0xcf, 0xf0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


int main(int argc, char **argv)
{
	ubit_t buf[1024*8];
	int rc;

	osmo_pbit2ubit(buf, iuup_frame29, 2*8);
	rc = osmo_crc8gen_compute_bits(&iuup_hdr_crc_code, buf, 2*8);
	printf("Header CRC = 0x%02x\n", rc);

	osmo_pbit2ubit(buf, iuup_frame29+4, 31*8);
	rc = osmo_crc16gen_compute_bits(&iuup_data_crc_code, buf, 31*8);
	printf("Payload CRC = 0x%03x\n", rc);
}
#endif