comparison hr-bits/sid-count.c @ 407:183e81c8f6c0

hr-bits: sid-count program written
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 22 Jul 2024 10:00:58 +0000
parents
children 14302e075f37
comparison
equal deleted inserted replaced
406:1a852266ba74 407:183e81c8f6c0
1 /*
2 * This program reads a TCH/HS DL capture file made with FC tools
3 * and analyzes the hex string of payload bits in every frame.
4 * For each frame, this program counts how many bits in the SID field
5 * are set (both class 1 and class 2. All input lines are passed
6 * through to the output, but at the end of each line this program
7 * appends bit counts that match the conventions used in GSM 06.06
8 * swSidDetection() function.
9 */
10
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <strings.h>
17
18 static const uint8_t class1_mask[12] = {0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9,
19 0x3F, 0xC0, 0x0F, 0x78, 0x0E, 0x06};
20 static const uint8_t class2_mask[3] = {0x1F, 0xFF, 0xF0};
21
22 static char *infname, *outfname;
23 static FILE *inf, *outf;
24 static int lineno;
25 static char linebuf[80];
26 static uint8_t frame[15];
27
28 static int
29 is_hex_string_spc(str, expect_len)
30 char *str;
31 unsigned expect_len;
32 {
33 char *cp, *endp;
34
35 endp = str + expect_len;
36 for (cp = str; cp < endp; cp++) {
37 if (!isxdigit(*cp))
38 return 0;
39 }
40 if (*cp == ' ')
41 return 1;
42 else
43 return 0;
44 }
45
46 static int
47 decode_hex_digit(c)
48 {
49 int d;
50
51 if (isdigit(c))
52 d = c - '0';
53 else if (isupper(c))
54 d = c - 'A' + 10;
55 else
56 d = c - 'a' + 10;
57 return d;
58 }
59
60 static void
61 frame_from_hex()
62 {
63 char *cp;
64 uint8_t *dp;
65 unsigned n, u, l;
66
67 cp = linebuf + 18;
68 dp = frame;
69 for (n = 0; n < 15; n++) {
70 u = decode_hex_digit(*cp++);
71 l = decode_hex_digit(*cp++);
72 *dp++ = (u << 4) | l;
73 }
74 }
75
76 static unsigned
77 ones_in_byte(byte)
78 unsigned byte;
79 {
80 unsigned count;
81
82 count = 0;
83 for (; byte; byte >>= 1) {
84 if (byte & 1)
85 count++;
86 }
87 return count;
88 }
89
90 static unsigned
91 count_1_bits(data, mask, nbytes)
92 uint8_t *data, *mask;
93 unsigned nbytes;
94 {
95 unsigned n, and, accum;
96
97 accum = 0;
98 for (n = 0; n < nbytes; n++) {
99 and = *data++ & *mask++;
100 accum += ones_in_byte(and);
101 }
102 return accum;
103 }
104
105 static void
106 process_line()
107 {
108 char *cp;
109 unsigned class1_ones, class1_zeros;
110 unsigned class2_ones, class2_zeros;
111 unsigned n1n2;
112
113 cp = index(linebuf, '\n');
114 if (!cp) {
115 fprintf(stderr, "%s line %d: too long or missing newline\n",
116 infname, lineno);
117 exit(1);
118 }
119 *cp = '\0';
120 if (strncmp(linebuf, "HR ", 3)) {
121 inv: fprintf(stderr,
122 "%s line %d: format does not match HR DL capture\n",
123 infname, lineno);
124 exit(1);
125 }
126 if (!is_hex_string_spc(linebuf + 3, 4))
127 goto inv;
128 if (!is_hex_string_spc(linebuf + 8, 4))
129 goto inv;
130 if (!is_hex_string_spc(linebuf + 13, 4))
131 goto inv;
132 if (!is_hex_string_spc(linebuf + 18, 30))
133 goto inv;
134 frame_from_hex();
135
136 class1_ones = count_1_bits(frame, class1_mask, 12);
137 class1_zeros = 62 - class1_ones;
138 class2_ones = count_1_bits(frame + 12, class2_mask, 3);
139 class2_zeros = 17 - class2_ones;
140 n1n2 = class1_zeros + class2_zeros;
141
142 fprintf(outf, "%s %u %u", linebuf, class1_zeros, n1n2);
143 if (n1n2 >= 11 && n1n2 < 16)
144 fputs(" SID-1-diff", outf);
145 if (n1n2 >= 16 && n1n2 <= 25)
146 fputs(" BCI-to-BFI", outf);
147 putc('\n', outf);
148 }
149
150 main(argc, argv)
151 char **argv;
152 {
153 if (argc >= 2) {
154 infname = argv[1];
155 inf = fopen(infname, "r");
156 if (!inf) {
157 perror(infname);
158 exit(1);
159 }
160 } else {
161 inf = stdin;
162 infname = "stdin";
163 }
164
165 if (argc >= 3) {
166 outfname = argv[2];
167 outf = fopen(outfname, "w");
168 if (!outf) {
169 perror(outfname);
170 exit(1);
171 }
172 } else {
173 outf = stdout;
174 outfname = "stdout";
175 }
176
177 for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++)
178 process_line();
179
180 exit(0);
181 }