blob: 3a5a6d5760d54799ebd441e784d8a1fe6a740dd0 [file] [log] [blame]
Philipp Maierb0575352022-09-01 17:48:38 +02001/*
2 * (C) 2022 by sysmocom - s.f.m.c. GmbH
3 * Author: Philipp Maier <pmaier@sysmocom.de>
4 * All Rights Reserved
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <stdio.h>
21#include <stdint.h>
22#include <errno.h>
23#include <osmocom/core/msgb.h>
24#include <osmocom/core/bitvec.h>
25#include <osmocom/core/crc16gen.h>
26#include <osmocom/core/logging.h>
27#include <arpa/inet.h>
28#include <osmocom/trau/trau_pcu_ericsson.h>
29#include <osmocom/gsm/gsm0502.h>
30
31#define E1_TRAU_BITS_MSGB 2048
32
33/* CRC polynom for CS1 TRAU frame protection: X^16+X^12+X^5+1 */
34const struct osmo_crc16gen_code cs1_crc16 = { 16, 0x1021, 0, 0xffff };
35
36/* Frame Type C-bits: C1..C5 */
37#define PCU_TRAU_ER_FT_PCU_SYNC_IND 0x0F
38#define PCU_TRAU_ER_FT_CCU_SYNC_IND 0x15
39#define PCU_TRAU_ER_FT_DATA_IND 0x1A
40#define PCU_TRAU_ER_FT_DATA9_IND 0x04
41
42const ubit_t T_bits_16[] = {
43 1, 1, 1, 1, 1, 1, 1, 1,
44 1, 1, 1, 1, 1, 1, 1, 1,
45 1, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0,
47 1, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0,
49 1, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0,
51 1, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0,
53 1, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0,
55 1, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0,
57 1, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0,
59 1, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 0, 0,
61 1, 0, 0, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0,
63 1, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0,
65 1, 0, 0, 0, 0, 0, 0, 0,
66 0, 0, 0, 0, 0, 0, 0, 0,
67 1, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0,
69 1, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0,
71 1, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0,
73 1, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0,
75 1, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0,
77 1, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0,
79 1, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0,
81 1, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, /* (+8 variable bits) */
84};
85
86const ubit_t T_bits_64[] = {
87 1, 1, 1, 1, 1, 1, 1, 1,
88 1, 1, 1, 1, 1, 1, 1, 1,
89 1, 1, 1, 1, 1, 1, 1, 1,
90 1, 1, 1, 1, 1, 1, 1, 1,
91 1, 1, 1, 1, 1, 1, 1, 1,
92 1, 1, 1, 1, 1, 1, 1, 1,
93 1, 1, 1, 1, 1, 1, 1, 1,
94 1, 1, 1, 1, 1, 1, 1, 1,
95 1, 0, 0, 0, 0, 0, 0, 0,
96 0, 0, 0, 0, 0, 0, 0, 0,
97 0, 0, 0, 0, 0, 0, 0, 0,
98 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0,
101 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0,
103 1, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0,
106 0, 0, 0, 0, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0,
108 0, 0, 0, 0, 0, 0, 0, 0,
109 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0,
111 1, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0,
113 0, 0, 0, 0, 0, 0, 0, 0,
114 0, 0, 0, 0, 0, 0, 0, 0,
115 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 0, 0, 0, 0, 0, 0, 0,
117 0, 0, 0, 0, 0, 0, 0, 0,
118 0, 0, 0, 0, 0, 0, 0, 0,
119 1, 0, 0, 0, 0, 0, 0, 0,
120 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0,
127 1, 0, 0, 0, 0, 0, 0, 0,
128 0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0,
135 1, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 0, 0, 0,
141 0, 0, 0, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0, 0,
143 1, 0, 0, 0, 0, 0, 0, 0,
144 0, 0, 0, 0, 0, 0, 0, 0,
145 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0,
147 0, 0, 0, 0, 0, 0, 0, 0,
148 0, 0, 0, 0, 0, 0, 0, 0,
149 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 0, 0, 0, 0, 0,
151 1, 0, 0, 0, 0, 0, 0, 0,
152 0, 0, 0, 0, 0, 0, 0, 0,
153 0, 0, 0, 0, 0, 0, 0, 0,
154 0, 0, 0, 0, 0, 0, 0, 0,
155 0, 0, 0, 0, 0, 0, 0, 0,
156 0, 0, 0, 0, 0, 0, 0, 0,
157 0, 0, 0, 0, 0, 0, 0, 0,
158 0, 0, 0, 0, 0, 0, 0, 0,
159 1, 0, 0, 0, 0, 0, 0, 0,
160 0, 0, 0, 0, 0, 0, 0, 0,
161 0, 0, 0, 0, 0, 0, 0, 0,
162 0, 0, 0, 0, 0, 0, 0, 0,
163 0, 0, 0, 0, 0, 0, 0, 0,
164 0, 0, 0, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, 0, 0, 0,
166 0, 0, 0, 0, 0, 0, 0, 0,
167 1, 0, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0, 0,
173 0, 0, 0, 0, 0, 0, 0, 0,
174 0, 0, 0, 0, 0, 0, 0, 0,
175 1, 0, 0, 0, 0, 0, 0, 0,
176 0, 0, 0, 0, 0, 0, 0, 0,
177 0, 0, 0, 0, 0, 0, 0, 0,
178 0, 0, 0, 0, 0, 0, 0, 0,
179 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0, 0, 0, 0,
182 0, 0, 0, 0, 0, 0, 0, 0,
183 1, 0, 0, 0, 0, 0, 0, 0,
184 0, 0, 0, 0, 0, 0, 0, 0,
185 0, 0, 0, 0, 0, 0, 0, 0,
186 0, 0, 0, 0, 0, 0, 0, 0,
187 0, 0, 0, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, 0,
190 0, 0, 0, 0, 0, 0, 0, 0,
191 1, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0, 0, 0, 0,
194 0, 0, 0, 0, 0, 0, 0, 0,
195 0, 0, 0, 0, 0, 0, 0, 0,
196 0, 0, 0, 0, 0, 0, 0, 0,
197 0, 0, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0,
199 1, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 0, 0, 0,
205 0, 0, 0, 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0, 0, 0, 0,
207 1, 0, 0, 0, 0, 0, 0, 0,
208 0, 0, 0, 0, 0, 0, 0, 0,
209 0, 0, 0, 0, 0, 0, 0, 0,
210 0, 0, 0, 0, 0, 0, 0, 0,
211 0, 0, 0, 0, 0, 0, 0, 0,
212 0, 0, 0, 0, 0, 0, 0, 0,
213 0, 0, 0, 0, 0, 0, 0, 0,
214 0, 0, 0, 0, 0, 0, 0, 0,
215 1, 0, 0, 0, 0, 0, 0, 0,
216 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0,
220 0, 0, 0, 0, 0, 0, 0, 0,
221 0, 0, 0, 0, 0, 0, 0, 0,
222 0, 0, 0, 0, 0, 0, 0, 0,
223 1, 0, 0, 0, 0, 0, 0, 0,
224 0, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0,
226 0, 0, 0, 0, 0, 0, 0, 0,
227 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0,
230 0, 0, 0, 0, 0, 0, 0, 0,
231 1, 0, 0, 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0,
234 0, 0, 0, 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0, 0, 0, 0,
236 0, 0, 0, 0, 0, 0, 0, 0,
237 0, 0, 0, 0, 0, 0, 0, 0,
238 0, 0, 0, 0, 0, 0, 0, 0,
239 1, 0, 0, 0, 0, 0, 0, 0,
240 0, 0, 0, 0, 0, 0, 0, 0,
241 0, 0, 0, 0, 0, 0, 0, 0,
242 0, 0, 0, 0, 0, 0, 0, 0,
243 0, 0, 0, 0, 0, 0, 0, 0,
244 0, 0, 0, 0, 0, 0, 0, 0,
245 0, 0, 0, 0, 0, 0, 0, 0,
246 0, 0, 0, 0, 0, 0, 0, 0,
247 0, 0, 0, 0, 0, 0, 0, 0,
248 0, 0, 0, 0, 0, 0, 0, 0, /* (+16 variable bits) */
249};
250
251/* Calc an odd parity bit over a given number of bits */
252static ubit_t calc_parity(const ubit_t *bits, size_t len)
253{
254 size_t i;
255 ubit_t par = 1;
256 for (i = 0; i < len; i++)
257 par ^= bits[i];
258 return par;
259}
260
261/* Put data to TRAU frame, skip T bits */
262static int put_trau_data(ubit_t *bits, size_t bits_len,
263 const ubit_t *bits_map, size_t bits_map_len, const ubit_t *bits_in, size_t offs, size_t len)
264{
265 size_t bit_count = 0;
266 size_t i = 0;
267
268 /* The bits map must always cover all bits, so it must not be shorter
269 * then the bits we are about to parse. Also the offset must not be
270 * greater then the length of the bits */
271 if (bits_len > bits_map_len)
272 return -EINVAL;
Philipp Maier8142f7a2023-01-31 14:26:18 +0100273 if (bits_len <= offs)
Philipp Maierb0575352022-09-01 17:48:38 +0200274 return -EINVAL;
275
276 /* Advance to the position where the data is stored */
277 bits += offs;
278 bits_len -= offs;
279 bits_map += offs;
280 bits_map_len -= offs;
281
282 do {
283 /* Do not exceed bits or bits_map */
284 if (bit_count > bits_len)
285 return -EINVAL;
286 if (bit_count > bits_map_len)
287 return -EINVAL;
288
289 /* Do not exceed output buffer */
290 if (i > bits_len)
291 return -EINVAL;
292
293 /* skip positions that have already bits set. */
294 if (*bits_map == 0) {
295 *bits = *bits_in;
296 bits_in++;
297 i++;
298 }
299
300 bit_count++;
301 bits++;
302 bits_map++;
303
304 } while (i < len);
305
306 return 0;
307}
308
309/* Put an uint32 value to TRAU frame */
310static int put_trau_uint32(ubit_t *bits, size_t bits_len,
311 const ubit_t *bits_map, size_t bits_map_len, uint32_t value, size_t offs, size_t len)
312{
313 ubit_t buf[32];
314
315 OSMO_ASSERT(len < 32);
316
317 memset(buf, 0, sizeof(buf));
318 value = htonl(value);
319 osmo_pbit2ubit_ext(buf, 0, (ubit_t *) &value, 32 - len, len, 0);
320 return put_trau_data(bits, bits_len, bits_map, bits_map_len, buf, offs, len);
321}
322
323/* Get data from TRAU frame, ignore T bits */
324static int get_trau_data(ubit_t *bits_out, size_t bits_out_len,
325 const ubit_t *bits, size_t bits_len,
326 const ubit_t *bits_map, size_t bits_map_len, size_t offs, size_t len)
327{
328 size_t bit_count = 0;
329 size_t i = 0;
330
331 /* (see above) */
332 if (bits_len > bits_map_len)
333 return -EINVAL;
Philipp Maier8142f7a2023-01-31 14:26:18 +0100334 if (bits_len <= offs)
Philipp Maierb0575352022-09-01 17:48:38 +0200335 return -EINVAL;
336
337 /* Advance to the position where the data is located */
338 bits += offs;
339 bits_map += offs;
340 bits_len -= offs;
341 bits_map_len -= offs;
342
343 /* Extract bits from TRAU frame */
344 do {
345 /* Do not exceed bits or bits_map */
346 if (bit_count > bits_len)
347 return -EINVAL;
348 if (bit_count > bits_map_len)
349 return -EINVAL;
350
351 /* Do not exceed output buffer */
352 if (i > bits_out_len)
353 return -EINVAL;
354
355 if (*bits_map == 0) {
356 *bits_out = *bits;
357 bits_out++;
358 i++;
359 }
360
361 bit_count++;
362 bits++;
363 bits_map++;
364
365 } while (i < len);
366
367 return 0;
368}
369
370/* Get an uint32 value from TRAU frame */
371static uint32_t get_trau_uint32(const ubit_t *bits, size_t bits_len,
372 const ubit_t *bits_map, size_t bits_map_len, size_t offs, uint8_t len)
373{
374 ubit_t buf[32];
375 uint32_t result = 0;
376 int rc;
377
378 OSMO_ASSERT(len < 32);
379
380 memset(buf, 0, sizeof(buf));
381 rc = get_trau_data(buf, sizeof(buf), bits, bits_len, bits_map, bits_map_len, offs, len);
382
383 if (rc < 0)
384 return 0;
385
386 osmo_ubit2pbit_ext((pbit_t *) &result, 32 - len, buf, 0, len, 0);
387 result = ntohl(result);
388
389 return result;
390}
391
392/* Set Time adjustment bits, add 4 more bits in case of delay */
393static int set_timing_ajustment_bits_16(ubit_t *trau_bits, enum time_adj_val tav)
394{
395 /* Note: This sets the tail bits and returns the final length of the final length of the TRAU frame. The caller
396 * must then make sure that the frame is transitted with the returned length to achieve correct timing
397 * alignment. */
398
399 switch (tav) {
400 case TIME_ADJ_NONE:
401 return 320;
402 case TIME_ADJ_DELAY_250us:
403 return 320 + 4;
404 case TIME_ADJ_ADVANCE_250us:
405 /* Note: the 16 removed bits are not transmitted. */
406 return 320 - 4;
407 }
408
409 return -EINVAL;
410}
411
412/* Set Time adjustment bits, add 16 more bits in case of delay */
413static int set_timing_ajustment_bits_64(ubit_t *trau_bits, enum time_adj_val tav)
414{
415 /* (see comment above) */
416
417 switch (tav) {
418 case TIME_ADJ_NONE:
419 return 1280;
420 case TIME_ADJ_DELAY_250us:
421 return 1280 + 16;
422 case TIME_ADJ_ADVANCE_250us:
423 /* Note: the 16 removed bits are not transmitted. */
424 return 1280 - 16;
425 }
426
427 return -EINVAL;
428}
429
430/* Decode an 8-byte access burst data structure */
431static int decode_ab(struct er_gprs_ab *ab, uint8_t *ab_bytes)
432{
433 memset(ab, 0, sizeof(*ab));
434
435 /* Type 1/2 specific fields */
436 if ((ab_bytes[0] & 0x1f) == 0x1f) {
437 ab->ab_type = 1;
438 ab->u.type_1.crc = ab_bytes[0] >> 5 & 0x07;
439 ab->u.type_1.burst_qual = ab_bytes[2];
440 ab->u.type_1.frame_qual = ab_bytes[3];
441 } else if ((ab_bytes[0] & 0x1f) == 0) {
442 ab->ab_type = 2;
443 ab->u.type_2.abi = ab_bytes[0] >> 5 & 0x07;
444 ab->u.type_2.type = ab_bytes[3] >> 6 & 0x03;
445 } else
446 return -EINVAL;
447
448 /* Common fields */
449 ab->rxlev = ab_bytes[1];
450 ab->acc_delay = (ab_bytes[4] << 2) & 0x0300;
451 ab->acc_delay |= ab_bytes[5];
452 ab->data = (ab_bytes[6] << 3) & 0x0700;
453 ab->data |= ab_bytes[7];
454
455 return 0;
456}
457
458static int enc_pcu_sync_ind_16(ubit_t *trau_bits, struct er_pcu_sync_ind *ind)
459{
460 /* 16kbps PCU-SYNC-IND TRAU frame format:
461 * Direction: PCU => CCU
462 *
463 * (bit 0) 0 0 0 0 0 0 0 0
464 * 0 0 0 0 0 0 0 0
465 * 1 C1 C2 C3 C4 C5 C6 C7
466 * C8 PC 0. 0 0 0 0 0
467 * 1 0 0 0 0 0 0 0
468 * 0 D15 D16 D17 D18 D19 D20 D21 PSEQ (offset 41)
469 * 1 D22 D23 D24 D25 D26 D27 D28
470 * D29 D30 D31 D32 D33 D34 D35 D36
471 * 1 D37 D38 D39 D40 D41 D42 D43 SS (offset 65)
472 * D44 D45 D46 D47 D48 D49 D50 D51
473 * 1 1 1 1 1 1 1 1
474 * 1 D60 D61 D62 D63 D64 D65 D66 FN UL (offset 89)
475 * 1 D67 D68 D69 D70 D71 D72 D73
476 * D74 D75 D76 D77 D78 D79 D80 D81
477 * 1 D82 D83 D84 D85 D86 D87 D88 FN SS (offset 113)
478 * D89 D90 D91 D92 D93 D94 D95 D96
479 * 1 1 1 1 1 1 1 1
480 * 1 D105 D106 D107 D108 D109 D110 D111 FN DL (offset 137)
481 * 1 D112 D113 D114 D115 D116 D117 D118
482 * D119 D120 D121 D122 D123 D124 D125 D126
483 * 1 D127 D128 D129 D130 D131 D132 D133 LS (offset 161)
484 * D134 D135 D136 D137 D138 D139 D140 D141
485 * 1 1 1 1 1 1 1 1
486 * 1 1 1 ...
487 * ... 1 1 1
488 * 1 1 1 1 1 1 1 1
489 * 1 1 1 1 TA1 TA2 TA3 TA4 (bit 319)
490 * TA5* TA6* TA7* TA8*
491 *
492 * "*" = additional TA bits to delay the frame
493 * C = Control bits
494 * D = Data bits
495 * PC = Parity over C-Bits (odd) */
496
497 pbit_t c_1_5 = PCU_TRAU_ER_FT_PCU_SYNC_IND;
498 int rc;
499
500 /* C-Bits */
501 osmo_pbit2ubit_ext(trau_bits, 17, &c_1_5, 0, 5, 1);
502 osmo_pbit2ubit_ext(trau_bits, 22, (pbit_t *) &ind->tav, 0, 2, 1);
503 if (ind->ul_frame_err == false)
504 trau_bits[24] = 1;
505 trau_bits[25] = calc_parity(trau_bits + 17, 8);
506
507 /* D-Bits */
508 rc = put_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), ind->pseq, 41, 22);
509 if (rc < 0)
510 return -EINVAL;
511 rc = put_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), ind->ss, 65, 15);
512 if (rc < 0)
513 return -EINVAL;
514 rc = put_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), ind->fn_ul, 89, 22);
515 if (rc < 0)
516 return -EINVAL;
517 rc = put_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), ind->fn_ss, 113, 15);
518 if (rc < 0)
519 return -EINVAL;
520 rc = put_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), ind->fn_dl, 137, 22);
521 if (rc < 0)
522 return -EINVAL;
523 rc = put_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), ind->ls, 161, 15);
524 if (rc < 0)
525 return -EINVAL;
526
527 return set_timing_ajustment_bits_16(trau_bits, ind->tav);
528}
529
530int enc_pcu_data_ind_16(ubit_t *trau_bits, struct er_pcu_data_ind *ind)
531{
532 /* 16kbps PCU-DATA-IND TRAU frame format:
533 * Direction: PCU => CCU
534 *
535 * (bit 0) 0 0 0 0 0 0 0 0
536 * 0 0 0 0 0 0 0 0
537 * 1 C1 C2 C3 C4 C5 C6 C7
538 * C8 PC E1 E2 E3 E4 E5 E6
539 * E7 E8 E9 E10 E11 E12 E13 E14
540 * E15 E16 PE D1 D2 D3 D4 D5
541 * D6 D7 D8 D9 D10 D11 D12 D13
542 * D14 D15 D16 ...
543 * ... D267 D268 D269
544 * D270 D271 D272 D273 TA1 TA2 TA3 TA4 (bit 319)
545 * TA5* TA6* TA7* TA8*
546 *
547 * C = Control bits
548 * D = Data bits
549 * E = Extended control bits
550 * PC = Parity over C-Bits (odd)
551 * PE = Parity over extended control bits (odd) */
552
553 pbit_t c_1_5 = PCU_TRAU_ER_FT_DATA_IND;
554
555 /* C-Bits */
556 osmo_pbit2ubit_ext(trau_bits, 17, &c_1_5, 0, 5, 1);
557 osmo_pbit2ubit_ext(trau_bits, 22, (pbit_t *) &ind->tav, 0, 2, 1);
558 if (ind->ul_frame_err == false)
559 trau_bits[24] = 1;
560 trau_bits[25] = calc_parity(trau_bits + 17, 8);
561
562 /* Set coding scheme (E1-E2) */
563 switch (ind->cs_hdr) {
564 case CS_OR_HDR_CS1:
565 trau_bits[26] = 0;
566 trau_bits[27] = 0;
567 break;
568 case CS_OR_HDR_CS2:
569 trau_bits[26] = 0;
570 trau_bits[27] = 1;
571 break;
572 default:
573 /* NOTE: The 16K TRAU frames do not have enough bandwidth to
574 * support coding schemes other than CS1 and CS2 */
575 /* NOTE: Access bursts (AB) are uplink-only. */
576 return -EINVAL;
577 }
578
579 /* Set demodulation in uplink (E3-E4) */
580 switch (ind->ul_chan_mode) {
581 case ER_UL_CHMOD_NB_GMSK:
Philipp Maier1950af72023-02-03 17:36:09 +0100582 case ER_UL_CHMOD_NB_UNKN:
Philipp Maierb0575352022-09-01 17:48:38 +0200583 trau_bits[28] = 0;
584 trau_bits[29] = 0;
585 break;
586 case ER_UL_CHMOD_AB:
587 trau_bits[28] = 0;
588 trau_bits[29] = 1;
589 break;
590 case ER_UL_CHMOD_AB_UNKN:
591 trau_bits[28] = 1;
592 trau_bits[29] = 0;
593 break;
594 case ER_UL_CHMOD_VOID:
595 trau_bits[28] = 1;
596 trau_bits[29] = 1;
597 break;
598 default:
599 return -EINVAL;
600 }
601
602 /* Timing offset (E5-E12, 8 bit value, MSB first) */
603 osmo_pbit2ubit_ext(trau_bits, 30, (pbit_t *) &ind->timing_offset, 0, 8, 0);
604
605 /* Power control (E13-E16, 4 bit value, MSB first, 2dB steps) */
606 osmo_pbit2ubit_ext(trau_bits, 38, (pbit_t *) &ind->atten_db, 4, 4, 0);
607
608 /* Parity (odd) over coding scheme, demodulation, timing offset and
609 * power control bits (E1-E16) */
610 trau_bits[42] = calc_parity(trau_bits + 26, 16);
611
612 /* Data bits */
613 switch (ind->cs_hdr) {
614 case CS_OR_HDR_CS1:
615 osmo_pbit2ubit_ext(trau_bits, 43, (pbit_t *) ind->data, 0, 184, 1);
616 osmo_crc16gen_set_bits(&cs1_crc16, trau_bits + 43, 184, trau_bits + 43 + 184);
617 break;
618 case CS_OR_HDR_CS2:
619 osmo_pbit2ubit_ext(trau_bits, 43, (pbit_t *) ind->data, 0, 271, 1);
620 break;
621 default:
622 /* NOTE: The 16K TRAU frames do not have enough bandwidth to
623 * support coding schemes other than CS1 and CS2 */
624 return -EINVAL;
625 }
626
627 return set_timing_ajustment_bits_16(trau_bits, ind->tav);
628}
629
630/*! encode an 16k Ericsson GPRS (GSL) TRAU frame.
631 * \param[out] bits caller-allocated memory for unpacked output bits (320+4).
632 * \param[in] fr input data structure describing TRAU frame.
633 * \return number of bits encoded. */
634int er_gprs_trau_frame_encode_16k(ubit_t *bits, struct er_gprs_trau_frame *fr)
635{
636 /* Prepare frame: first 16 bits set 0, remaining bits set to 1 */
637 memset(bits, 0, 16);
638 memset(bits + 16, 1, 320 + 4 - 16);
639
640 switch (fr->type) {
641 case ER_GPRS_TRAU_FT_SYNC:
642 return enc_pcu_sync_ind_16(bits, &fr->u.pcu_sync_ind);
643 case ER_GPRS_TRAU_FT_DATA:
644 return enc_pcu_data_ind_16(bits, &fr->u.pcu_data_ind);
645 default:
646 return -EINVAL;
647 }
648
649 return -EINVAL;
650}
651
652static int dec_ccu_sync_ind_16(struct er_ccu_sync_ind *ind, const ubit_t *trau_bits)
653{
654 /* 16kbps CCU-SYNC-IND TRAU frame format:
655 * Direction: CCU => PCU
656 *
657 * (bit 0) 0 0 0 0 0 0 0 0
658 * 0 0 0 0 0 0 0 0
659 * 1 C1 C2 C3 C4 C5 C6 C7
660 * C8 PC E1 PE 1 1 1 1
661 * 1 0 0 0 0 0 0 0
662 * 0 D13 D14 D15 D16 D17 D18 D19 PSEQ (offset 41)
663 * 1 D20 D21 D22 D23 D24 D25 D26
664 * D27 D28 D29 D30 D31 D32 D33 D34
665 * 1 1 1 1 1 1 1 1
666 * 1 1 1 1 1 1 1 1
667 * 1 1 1 1 1 1 1 1
668 * 1 D58 D59 D60 D61 D62 D63 D64 AFN UL (offset 89)
669 * 1 D65 D66 D67 D68 D69 D70 D71
670 * D72 D73 D74 D75 D76 D77 D78 D79
671 * 1 1 1 1 1 1 1 1
672 * 1 1 1 1 1 1 1 1
673 * 1 1 1 1 1 1 1 1
674 * 1 D103 D104 D105 D106 D107 D108 D109 AFN DL (offset 137)
675 * 1 D110 D111 D112 D113 D114 D115 D116
676 * D117 D118 D119 D120 D121 D122 D123 D124
677 * 1 1 1 1 1 1 1 1
678 * 1 1 1 ...
679 * ... 1 1 1
680 * 1 1 1 1 1 1 1 1
681 * 1 1 1 1 1 1 TA1 TA2 (bit 319)
682 * TA3* TA4*
683 *
684 * "*" = additional TA bits to delay the frame
685 * C = Control bits
686 * D = Data bits
687 * E = Extended control bits
688 * PC = Parity over C-Bits (odd)
689 * PE = Parity over extended control bits (odd) */
690
691 size_t i;
692
693 /* Validate sync pattern (extended) */
694 for (i = 0; i < 19; i++) {
695 if (trau_bits[16 + i * 16] != 1) {
696 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-16: invalid sync pattern (T1 at position %zu != 1)\n", i);
697 return -EINVAL;
698 }
699 }
700
701 /* Validate C-Bits */
702 if (calc_parity(trau_bits + 17, 8) != trau_bits[25]) {
703 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-16: invalid parity (C1-C8)\n");
704 return -EINVAL;
705 }
706
707 /* TAV (C7-C9) */
708 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 22, 2, 1);
709
710 /* Downlink frame error, DFE (C8) */
711 if (trau_bits[24] == 0)
712 ind->dfe = true;
713
714 /* Check (odd) parity of E1 bit */
715 if (trau_bits[26] != ((~trau_bits[27]) & 1)) {
716 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-16: invalid parity (E1)\n");
717 return -EINVAL;
718 }
719
720 /* Downlink Block error, DBE (E1) */
721 if (trau_bits[26] == 0)
722 ind->dbe = true;
723
724 /* D bits */
725 ind->pseq = get_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), 41, 22);
726 ind->afn_ul = get_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), 89, 22);
727 ind->afn_dl = get_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), 137, 22);
728
729 return 0;
730}
731
732static int dec_ccu_data_ind_16(struct er_ccu_data_ind *ind, const ubit_t *trau_bits)
733{
734 /* 16kbps CCU-DATA-IND TRAU frame format:
735 * Direction: CCU => PCU
736 *
737 * (bit 0) 0 0 0 0 0 0 0 0
738 * 0 0 0 0 0 0 0 0
739 * 1 C1 C2 C3 C4 C5 C6 C7
740 * PC E1 E2 E3 E4 E5 E6 E7
741 * E8 E9 E10 E11 E12 E13 E14 E15
742 * E16 E17 E18 E19 PE D1 D2 D3
743 * D4 D5 D6 D7 D8 D9 D10 D11
744 * D12 D13 D14 ...
745 * ... D267 D268 D269
746 * D270 D271 D272 D273 TA1 TA2 TA3 TA4 (bit 319)
747 * TA5* TA6* TA7* TA8*
748 *
749 * C = Control bits
750 * D = Data bits
751 * E = Extended control bits
752 * PC = Parity over C-Bits (odd)
753 * PE = Parity over extended control bits (odd) */
754
755 uint8_t sfq = 0;
756 uint8_t eadd = 0;
757 uint8_t e_2_4 = 0;
758 int rc;
759 int i;
760
761 /* Validate C-Bits */
762 if (calc_parity(trau_bits + 17, 7) != trau_bits[24]) {
763 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid parity (C1-C7)\n");
764 return -EINVAL;
765 }
766
767 /* TAV (C6-C7) */
768 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 22, 2, 1);
769
770 /* Validate E-Bits */
771 if (calc_parity(trau_bits + 25, 19) != trau_bits[44]) {
772 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid parity (E1-E19)\n");
773 return -EINVAL;
774 }
775
776 /* Downlink block error (E1) */
777 if (trau_bits[25] == 0)
778 ind->dbe = true;
779
780 /* Coding scheme (E2-E4) */
781 osmo_ubit2pbit_ext((pbit_t *) &e_2_4, 5, trau_bits, 26, 3, 0);
782 switch (e_2_4) {
783 case 0:
784 ind->cs_hdr = CS_OR_HDR_CS1;
785 break;
786 case 1:
787 ind->cs_hdr = CS_OR_HDR_CS2;
788 break;
789 case 4:
790 ind->cs_hdr = CS_OR_HDR_AB;
791 break;
792 default:
793 /* 16kbps timeslots only support CS1, CS2 and AB are supported,
794 * due to bandwidth limitations. */
795 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid codec status (E2-E4)\n");
796 return -EINVAL;
797 }
798
799 /* Soft frame quality SFQ (E5-E7, 0 in case of AB) */
800 osmo_ubit2pbit_ext((pbit_t *) &sfq, 5, trau_bits, 29, 3, 0);
801 ind->u.gprs.block_qual = sfq;
802
803 /* Parity Check (E8, 1 in case of AB) */
804 ind->u.gprs.parity_ok = trau_bits[32];
805
806 /* RX-LEV (E9-E14, 63 in case of AB) */
807 osmo_ubit2pbit_ext((pbit_t *) &ind->rx_lev, 2, trau_bits, 33, 6, 0);
808
809 /* Estimated access delay (E15-E17, 0 in case of AB) */
810 osmo_ubit2pbit_ext((pbit_t *) &eadd, 5, trau_bits, 39, 3, 0);
811 switch (eadd) {
812 case 0:
813 /* <2 or less */
814 ind->est_acc_del_dev = -3;
815 break;
816 case 1:
817 ind->est_acc_del_dev = -1;
818 break;
819 case 2:
820 ind->est_acc_del_dev = 1;
821 break;
822 case 4:
823 ind->est_acc_del_dev = 2;
824 break;
825 case 5:
826 /* >2 or more */
827 ind->est_acc_del_dev = 3;
828 break;
829 case 6:
830 ind->est_acc_del_dev = 0;
831 break;
832 case 7:
833 ind->est_acc_del_dev = -2;
834 break;
835 default:
836 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid estimated access delay (E15-E17)\n");
837 return -EINVAL;
838 }
839
840 /* Data bits */
841 switch (ind->cs_hdr) {
842 case CS_OR_HDR_CS1:
843 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 45, 184, 1);
844 rc = osmo_crc16gen_check_bits(&cs1_crc16, trau_bits + 45, 184, trau_bits + 45 + 184);
845 if (rc != 0) {
846 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: CRC error in CS1 block\n");
847 return -EINVAL;
848 }
849 ind->data_len = 23;
850 break;
851 case CS_OR_HDR_CS2:
852 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 45, 271, 1);
853 ind->data_len = 34;
854 break;
855 case CS_OR_HDR_AB:
856 /* Note: The useful data starts at D4 and is byte-aligned inside the TRAU frame.
857 * The data string contains 4 items, each 8 bytes long, 32 bytes total. */
858 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 48, 256, 1);
859 ind->data_len = 32;
860
861 for (i = 0; i < 4; i++) {
862 rc = decode_ab(&ind->ab[i], ind->data + i * 8);
863 if (rc < 0)
864 return -EINVAL;
865 }
866 break;
867 default:
868 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid cs_hdr set\n");
869 return -EINVAL;
870 }
871
872 return 0;
873};
874
875/*! decode an 16k Ericsson GPRS (GSL) TRAU frame.
876 * \param[out] fr caller-allocated output data structure.
877 * \param[in] bits unpacked input bits (320).
878 * \return 0 on success; negative in case of error. */
879int er_gprs_trau_frame_decode_16k(struct er_gprs_trau_frame *fr, const ubit_t *bits)
880{
881 uint8_t c_1_5 = 0;
882 const ubit_t expected_sync_pattern[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
883 int rc;
884
885 memset(fr, 0, sizeof(*fr));
886
887 /* Validate sync pattern */
888 if (memcmp(bits, expected_sync_pattern, ARRAY_SIZE(expected_sync_pattern)) != 0) {
889 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-16: invalid sync pattern (T0)\n");
890 return -EINVAL;
891 }
892
893 /* Determine frame type */
894 osmo_ubit2pbit_ext((pbit_t *) &c_1_5, 0, bits, 17, 5, 1);
895
896 switch (c_1_5) {
897 case PCU_TRAU_ER_FT_CCU_SYNC_IND:
898 fr->type = ER_GPRS_TRAU_FT_SYNC;
899 rc = dec_ccu_sync_ind_16(&fr->u.ccu_sync_ind, bits);
900 break;
901 case PCU_TRAU_ER_FT_DATA_IND:
902 fr->type = ER_GPRS_TRAU_FT_DATA;
903 rc = dec_ccu_data_ind_16(&fr->u.ccu_data_ind, bits);
904 break;
905 default:
906 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-16: invalid frame type (%02x)\n", c_1_5);
907 rc = -EINVAL;
908 }
909
910 /* Ensure that we exit with predictable data in case of error. */
911 if (rc < 0)
912 memset(fr, 0, sizeof(*fr));
913
914 return rc;
915}
916
917/* Extract the CPS field from a given block, block must have minimum length of 5 bytes.
918 * See also: 3GPP TS 44.060, section 10.3a.3 and section 10.3a.4 */
919static int cps_from_mcs_block(uint8_t *block, enum er_cs_or_hdr cs_hdr, bool uplink)
920{
921 uint8_t cps;
922
923 if (uplink) {
924 switch (cs_hdr) {
925 case CS_OR_HDR_HDR1:
926 cps = block[4] & 0x1f;
927 break;
928 case CS_OR_HDR_HDR2:
929 cps = (block[2] >> 6) & 0x3;
930 cps |= block[3] << 2 & 0x4;
931 break;
932 case CS_OR_HDR_HDR3:
933 cps = (block[2] >> 6) & 0x3;
934 cps |= block[3] << 2 & 0xC;
935 break;
936 default:
937 return -EINVAL;
938 }
939 } else {
940 switch (cs_hdr) {
941 case CS_OR_HDR_HDR1:
942 cps = (block[4] >> 3) & 0x1f;
943 break;
944 case CS_OR_HDR_HDR2:
945 cps = (block[3] >> 1) & 0x07;
946 break;
947 case CS_OR_HDR_HDR3:
948 cps = (block[3] >> 1) & 0x0f;
949 break;
950 default:
951 return -EINVAL;
952 }
953 }
954
955 return cps;
956}
957
958/* Determine the MCS block type from a given CPS value.
959 * See also: 3GPP TS 44.060, section 10.4.8a */
960static int mcs_from_cps(uint8_t cps, enum er_cs_or_hdr cs_hdr)
961{
962 switch (cs_hdr) {
963 case CS_OR_HDR_HDR1:
964 if (cps <= 0x0A)
965 return 9;
966 if (cps <= 0x13)
967 return 8;
968 if (cps <= 0x1C)
969 return 7;
970 return -EINVAL;
971 break;
972 case CS_OR_HDR_HDR2:
973 if (cps <= 0x03 || cps == 0x06 || cps == 0x07)
974 return 6;
975 if (cps == 4 || cps == 5)
976 return 5;
977 return -EINVAL;
978 break;
979 case CS_OR_HDR_HDR3:
980 if (cps <= 0x02)
981 return 4;
982 if (cps <= 0x08)
983 return 3;
984 if (cps == 0x09 || cps == 0x0A || cps == 0x0D || cps == 0x0E)
985 return 2;
986 if (cps == 0x0B || cps == 0x0C)
987 return 1;
988 return -EINVAL;
989 break;
990 default:
991 return -EINVAL;
992 }
993}
994
995static int enc_pcu_sync_ind_64(ubit_t *trau_bits, struct er_pcu_sync_ind *ind)
996{
997 /* 64kbps PCU-SYNC-IND TRAU frame format:
998 * Direction: PCU => CCU
999 *
1000 * (bit 0) 0 0 0 0 0 0 0 0
1001 * 0 0 0 0 0 0 0 0
1002 * 0 0 0 0 0 0 0 0
1003 * 0 0 0 0 0 0 0 0
1004 * 0 0 0 0 0 0 0 0
1005 * 0 0 0 0 0 0 0 0
1006 * 0 0 0 0 0 0 0 0
1007 * 0 0 0 0 0 0 0 0
1008 * 1 C1 C2 C3 C4 C5 C6 C7
1009 * C8 PC 1 1 1 1 1 1
1010 * 1 1 1 1 1 1 1 1
1011 * 1 1 1 1 1 1 1 1
1012 * 1 1 1 1 1 1 1 1
1013 * 1 1 1 1 1 1 1 1
1014 * 1 1 1 1 1 1 1 1
1015 * 1 1 1 1 1 1 1 1
1016 * 1 1 1 1 1 1 1 1
1017 * 1 1 1 1 1 1 1 1
1018 * 1 1 1 1 1 1 1 1
1019 * 1 1 1 1 1 1 1 1
1020 * 1 1 1 1 1 1 1 1
1021 * 1 1 D96 D97 D98 D99 D100 D101
1022 * D102 D103 D104 D105 D106 D107 D108 D109
1023 * D110 D111 D112 D113 D114 D115 D116 D117
1024 * 1 1 1 1 1 1 1 1
1025 * 1 1 1 1 1 1 1 1
1026 * D133 D134 D135 D136 D137 D138 D139 D140
1027 * D141 D142 D143 D144 D145 D146 D147 D148
1028 * 1 1 1 1 1 1 1 1
1029 * 1 1 D159 D160 D161 D162 D163 D164
1030 * D165 D166 D167 D168 D169 D170 D171 D172
1031 * D173 D174 D175 D176 D177 D178 D179 D180
1032 * 1 1 1 1 1 1 1 1
1033 * 1 1 1 1 1 1 1 1
1034 * D196 D197 D198 D199 D200 D201 D202 D203
1035 * D204 D205 D206 D207 D208 D209 D210 D211
1036 * 1 1 1 1 1 1 1 1
1037 * 1 1 D222 D223 D224 D225 D226 D227
1038 * D228 D229 D230 D231 D232 D233 D234 D235
1039 * D236 D237 D238 D239 D340 D241 D242 D243
1040 * 1 1 1 1 1 1 1 1
1041 * 1 1 1 1 1 1 1 1
1042 * D259 D260 D261 D262 D263 D264 D265 D266
1043 * D267 D268 D269 D270 D271 D272 D273 D274
1044 * 1 1 1 1 1 1 1 1
1045 * 1 1 1 ...
1046 * ... 1 1 1
1047 * 1 1 1 1 1 1 1 1
1048 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1049 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1050 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1051 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1052 *
1053 * "*" = additional TA bits to delay the frame
1054 * C = Control bits
1055 * D = Data bits
1056 * E = Extended control bits
1057 * PC = Parity over C-Bits (odd)
1058 * PE = Parity over extended control bits (odd) */
1059
1060 pbit_t c_1_5 = PCU_TRAU_ER_FT_PCU_SYNC_IND;
1061 int rc;
1062
1063 /* C-Bits */
1064 osmo_pbit2ubit_ext(trau_bits, 65, &c_1_5, 0, 5, 1);
1065 osmo_pbit2ubit_ext(trau_bits, 70, (pbit_t *) &ind->tav, 0, 2, 1);
1066 if (ind->ul_frame_err == false)
1067 trau_bits[73] = 1;
1068 trau_bits[74] = calc_parity(trau_bits + 65, 8);
1069
1070 /* Set unused D-Bits to 1 */
1071 memset(trau_bits + 76, 1, 1280 - 76 - 16);
1072
1073 /* D-Bits */
1074 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->pseq, 170, 22);
1075 if (rc < 0)
1076 return -EINVAL;
1077 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->ss, 208, 16);
1078 if (rc < 0)
1079 return -EINVAL;
1080 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->fn_ul, 234, 22);
1081 if (rc < 0)
1082 return -EINVAL;
1083 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->fn_ss, 272, 15);
1084 if (rc < 0)
1085 return -EINVAL;
1086 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->fn_dl, 298, 22);
1087 if (rc < 0)
1088 return -EINVAL;
1089 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->ls, 336, 16);
1090 if (rc < 0)
1091 return -EINVAL;
1092
1093 return set_timing_ajustment_bits_64(trau_bits, ind->tav);
1094}
1095
1096int enc_pcu_data_ind_64(ubit_t *trau_bits, struct er_pcu_data_ind *ind, uint8_t mcs)
1097{
1098 /* 64kbps PCU-DATA-IND TRAU frame format:
1099 * Direction: PCU => CCU
1100 *
1101 * (bit 0) 0 0 0 0 0 0 0 0
1102 * 0 0 0 0 0 0 0 0
1103 * 0 0 0 0 0 0 0 0
1104 * 0 0 0 0 0 0 0 0
1105 * 0 0 0 0 0 0 0 0
1106 * 0 0 0 0 0 0 0 0
1107 * 0 0 0 0 0 0 0 0
1108 * 0 0 0 0 0 0 0 0
1109 * 1 C1 C2 C3 C4 C5 C6 C7
1110 * C8 PC E1 E2 E3 E4 E5 E6
1111 * E7 E8 E9 E10 E11 E12 E13 E14
1112 * E15 E16 E17 E18 E19 E20 E21 E22
1113 * E23 E24 E25 E26 E27 E28 E29 E30
1114 * E31 E32 E33 E34 E35 E36 PE S1
1115 * S2 S3 S4 S5 S6 S7 S8 S9
1116 * S10 S11 S12 S13 S14 S15 S16 S17
1117 * S18 S19 S20 S21 D1 D2 D3 D4
1118 * D5 D6 D7 D8 D9 D10 D11 D12
1119 * D13 D14 D15 D16 D17 D18 D19 D20
1120 * D21 D22 D23 ...
1121 * ... D1130 D1131 D1132
1122 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1123 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1124 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1125 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1126 *
1127 * C = Control bits
1128 * D = Data bits
1129 * E = Extended control bits
1130 * PC = Parity over C-Bits (odd)
1131 * PE = Parity over extended control bits (odd) */
1132
1133 pbit_t c_1_5 = PCU_TRAU_ER_FT_DATA_IND;
1134
1135 /* C-Bits */
1136 osmo_pbit2ubit_ext(trau_bits, 65, &c_1_5, 0, 5, 1);
1137 osmo_pbit2ubit_ext(trau_bits, 70, (pbit_t *) &ind->tav, 0, 2, 1);
1138 if (ind->ul_frame_err == false)
1139 trau_bits[73] = 1;
1140 trau_bits[74] = calc_parity(trau_bits + 65, 8);
1141
1142 /* Set coding scheme (E1-E3) */
1143 switch (ind->cs_hdr) {
1144 case CS_OR_HDR_CS1:
1145 trau_bits[74] = 0;
1146 trau_bits[75] = 0;
1147 trau_bits[76] = 1;
1148 break;
1149 case CS_OR_HDR_CS2:
1150 trau_bits[74] = 0;
1151 trau_bits[75] = 1;
1152 trau_bits[76] = 0;
1153 break;
1154 case CS_OR_HDR_CS3:
1155 trau_bits[74] = 0;
1156 trau_bits[75] = 1;
1157 trau_bits[76] = 1;
1158 break;
1159 case CS_OR_HDR_CS4:
1160 trau_bits[74] = 1;
1161 trau_bits[75] = 0;
1162 trau_bits[76] = 0;
1163 break;
1164 case CS_OR_HDR_HDR1:
1165 trau_bits[74] = 1;
1166 trau_bits[75] = 0;
1167 trau_bits[76] = 1;
1168 break;
1169 case CS_OR_HDR_HDR2:
1170 trau_bits[74] = 1;
1171 trau_bits[75] = 1;
1172 trau_bits[76] = 0;
1173 break;
1174 case CS_OR_HDR_HDR3:
1175 trau_bits[74] = 1;
1176 trau_bits[75] = 1;
1177 trau_bits[76] = 1;
1178 break;
1179 default:
1180 /* NOTE: Access bursts (AB) are uplink-only. */
1181 return -EINVAL;
1182 }
1183
1184 /* Set demodulation in uplink (E4-E6) */
1185 switch (ind->ul_chan_mode) {
1186 case ER_UL_CHMOD_VOID:
1187 trau_bits[77] = 0;
1188 trau_bits[78] = 0;
1189 trau_bits[79] = 0;
1190 break;
1191 case ER_UL_CHMOD_NB_GMSK:
1192 trau_bits[77] = 0;
1193 trau_bits[78] = 0;
1194 trau_bits[79] = 1;
1195 break;
1196 case ER_UL_CHMOD_NB_UNKN:
1197 trau_bits[77] = 0;
1198 trau_bits[78] = 1;
1199 trau_bits[79] = 0;
1200 break;
1201 case ER_UL_CHMOD_AB:
1202 trau_bits[77] = 0;
1203 trau_bits[78] = 1;
1204 trau_bits[79] = 1;
1205 break;
1206 case ER_UL_CHMOD_AB_UNKN:
1207 trau_bits[77] = 1;
1208 trau_bits[78] = 0;
1209 trau_bits[79] = 0;
1210 break;
1211 default:
1212 return -EINVAL;
1213 }
1214
1215 /* Timing offset (E7-E14, 8 bit value, MSB first) */
1216 osmo_pbit2ubit_ext(trau_bits, 80, (pbit_t *) &ind->timing_offset, 0, 8, 0);
1217
1218 /* Power control (E33-E36, 4 bit value, MSB first, 2dB steps) */
1219 osmo_pbit2ubit_ext(trau_bits, 106, (pbit_t *) &ind->atten_db, 4, 4, 0);
1220
1221 /* Parity (odd) over coding scheme, demodulation, timing offset and
1222 * power control bits (E1-E36) */
1223 trau_bits[110] = calc_parity(trau_bits + 74, 36);
1224
1225 /* Data bits */
1226 switch (ind->cs_hdr) {
1227 case CS_OR_HDR_CS1:
1228 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 184, 1);
1229 osmo_crc16gen_set_bits(&cs1_crc16, trau_bits + 132, 184, trau_bits + 132 + 184);
1230 break;
1231 case CS_OR_HDR_CS2:
1232 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 271, 1);
1233 break;
1234 case CS_OR_HDR_CS3:
1235 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 315, 1);
1236 break;
1237 case CS_OR_HDR_CS4:
1238 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 431, 1);
1239 break;
1240 case CS_OR_HDR_HDR1:
1241 case CS_OR_HDR_HDR2:
1242 case CS_OR_HDR_HDR3:
1243 switch (mcs) {
1244 case 1:
1245 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 209, 1);
1246 break;
1247 case 2:
1248 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 257, 1);
1249 break;
1250 case 3:
1251 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 329, 1);
1252 break;
1253 case 4:
1254 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 385, 1);
1255 break;
1256 case 5:
1257 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 478, 1);
1258 break;
1259 case 6:
1260 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 622, 1);
1261 break;
1262 case 7:
1263 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 940, 1);
1264 break;
1265 case 8:
1266 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 1132, 1);
1267 break;
1268 }
1269 break;
1270 default:
1271 /* NOTE: The 16K TRAU frames do not have enough bandwidth to
1272 * support coding schemes other than CS1 and CS2 */
1273 return -EINVAL;
1274 }
1275
1276 return set_timing_ajustment_bits_64(trau_bits, ind->tav);
1277}
1278
1279int enc_pcu_data_ind_64_mcs9(ubit_t *trau_bits, struct er_pcu_data_ind *ind)
1280{
1281 /* 64kbps PCU-DATA-IND (MCS9) TRAU frame format:
1282 * Direction: PCU => CCU
1283 *
1284 * (bit 0) 0 0 0 0 0 0 0 0
1285 * 0 0 0 0 0 0 0 0
1286 * 1 D1 D2 D3 D4 D5 D6 D7
1287 * D8 D9 D10 D11 D12 D13 D14 D15
1288 * D16 D17 D18 D19 D20 D21 D22 D23
1289 * D24 D25 D26 D27 D28 D29 D30 D31
1290 * D32 D33 D34 D35 D36 D37 D38 D39
1291 * D40 D41 D42 D43 D44 D45 D46 D47
1292 * D48 C1 C2 C3 C4 C5 C6 C7
1293 * C8 PC E1 E2 E3 E4 E5 E6
1294 * E7 E8 E9 PE D49 D50 D51 D52
1295 * D53 D54 D55 D56 D57 D58 D59 D60
1296 * D61 D62 D63 D64 D65 D66 D67 D68
1297 * D69 D70 D71 ...
1298 * ... D1226 D1227 D1228
1299 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1300 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1301 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1302 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1303 *
1304 * C = Control bits
1305 * D = Data bits
1306 * E = Extended control bits
1307 * PC = Parity over C-Bits (odd)
1308 * PE = Parity over extended control bits (odd) */
1309
1310 pbit_t c_1_5 = PCU_TRAU_ER_FT_DATA9_IND;
1311
1312 /* NOTE: The ericsson MCS9 64K TRAU format uses a different sync
1313 * pattern than the other 64K TRAU frame formats. To make room for
1314 * the additional bits in MCS9 only the first 16 bits are T0 bits. */
1315 trau_bits[16] = 1;
1316
1317 /* Fill headroom that normally would have T0 and T1 bits with data
1318 * bits */
1319 osmo_pbit2ubit_ext(trau_bits, 17, (pbit_t *) ind->data, 0, 48, 1);
1320
1321 /* C-Bits */
1322 osmo_pbit2ubit_ext(trau_bits, 65, &c_1_5, 0, 5, 1);
1323 osmo_pbit2ubit_ext(trau_bits, 70, (pbit_t *) &ind->tav, 0, 2, 1);
1324 if (ind->ul_frame_err == false)
1325 trau_bits[73] = 1;
1326 trau_bits[74] = calc_parity(trau_bits + 65, 8);
1327
1328 /* Set demodulation in uplink (E1-E3) */
1329 switch (ind->ul_chan_mode) {
1330 case ER_UL_CHMOD_VOID:
1331 trau_bits[74] = 0;
1332 trau_bits[75] = 0;
1333 trau_bits[76] = 0;
1334 break;
1335 case ER_UL_CHMOD_NB_GMSK:
1336 trau_bits[74] = 0;
1337 trau_bits[75] = 0;
1338 trau_bits[76] = 1;
1339 break;
1340 case ER_UL_CHMOD_NB_UNKN:
1341 trau_bits[74] = 0;
1342 trau_bits[75] = 1;
1343 trau_bits[76] = 0;
1344 break;
1345 case ER_UL_CHMOD_AB:
1346 trau_bits[74] = 0;
1347 trau_bits[75] = 1;
1348 trau_bits[76] = 1;
1349 break;
1350 case ER_UL_CHMOD_AB_UNKN:
1351 trau_bits[74] = 1;
1352 trau_bits[75] = 0;
1353 trau_bits[76] = 0;
1354 break;
1355 default:
1356 return -EINVAL;
1357 }
1358
1359 /* E4-E5 are spare bits? */
1360
1361 /* Power control (E6-E9, 4 bit value, MSB first, 2dB steps) */
1362 osmo_pbit2ubit_ext(trau_bits, 79, (pbit_t *) &ind->atten_db, 4, 4, 0);
1363
1364 /* Parity (odd) over coding scheme, demodulation, timing offset and
1365 * power control bits (E1-E9) */
1366 trau_bits[83] = calc_parity(trau_bits + 74, 9);
1367
1368 /* Fill the rest of the block with data bits */
1369 osmo_pbit2ubit_ext(trau_bits, 84, (pbit_t *) ind->data + 6, 0, 1180, 1);
1370
1371 return set_timing_ajustment_bits_64(trau_bits, ind->tav);
1372}
1373
1374/*! encode an 64k Ericsson GPRS (GSL) TRAU frame.
1375 * \param[out] bits caller-allocated memory for unpacked output bits (1280+16).
1376 * \param[in] fr input data structure describing TRAU frame.
1377 * \return number of bits encoded. */
1378int er_gprs_trau_frame_encode_64k(ubit_t *bits, struct er_gprs_trau_frame *fr)
1379{
1380 int cps;
1381 int mcs = 0;
1382 enum er_cs_or_hdr cs;
1383
1384 /* Prepare frame: first 16 bits set 0, remaining bits set to 1 */
1385 memset(bits, 0, 64);
1386 memset(bits + 64, 1, 1280 + 16 - 64);
1387
1388 switch (fr->type) {
1389 case ER_GPRS_TRAU_FT_SYNC:
1390 return enc_pcu_sync_ind_64(bits, &fr->u.pcu_sync_ind);
1391 case ER_GPRS_TRAU_FT_DATA:
1392 cs = fr->u.pcu_data_ind.cs_hdr;
1393 if (cs == CS_OR_HDR_HDR1 || cs == CS_OR_HDR_HDR2 || cs == CS_OR_HDR_HDR3) {
1394 cps = cps_from_mcs_block(fr->u.pcu_data_ind.data, cs, false);
1395 if (cps < 0)
1396 return -EINVAL;
1397 mcs = mcs_from_cps((uint8_t) cps, cs);
1398 if (mcs < 0)
1399 return -EINVAL;
1400 }
1401
1402 if (mcs < 9)
1403 return enc_pcu_data_ind_64(bits, &fr->u.pcu_data_ind, mcs);
1404 else
1405 return enc_pcu_data_ind_64_mcs9(bits, &fr->u.pcu_data_ind);
1406 default:
1407 return -EINVAL;
1408 }
1409
1410 return -EINVAL;
1411}
1412
1413static int dec_ccu_sync_ind_64(struct er_ccu_sync_ind *ind, const ubit_t *trau_bits)
1414{
1415 /* 64kbps CCU-SYNC-IND TRAU frame format:
1416 * Direction: CCU => PCU
1417 *
1418 * (bit 0) 0 0 0 0 0 0 0 0
1419 * 0 0 0 0 0 0 0 0
1420 * 0 0 0 0 0 0 0 0
1421 * 0 0 0 0 0 0 0 0
1422 * 0 0 0 0 0 0 0 0
1423 * 0 0 0 0 0 0 0 0
1424 * 0 0 0 0 0 0 0 0
1425 * 0 0 0 0 0 0 0 0
1426 * 1 C1 C2 C3 C4 C5 C6 C7
1427 * C8 PC E1 PE 1 1 1 1
1428 * 1 1 1 1 1 1 1 1
1429 * 1 1 1 1 1 1 1 1
1430 * 1 1 1 1 1 1 1 1
1431 * 1 1 1 1 1 1 1 1
1432 * 1 1 1 1 1 1 1 1
1433 * 1 1 1 1 1 1 1 1
1434 * 1 1 1 1 1 1 1 1
1435 * 1 1 1 1 1 1 1 1
1436 * 1 1 1 1 1 1 1 1
1437 * 1 1 1 1 1 1 1 1
1438 * 1 1 1 1 1 1 1 1
1439 * 1 1 D94 D95 D96 D97 D98 D99
1440 * D100 D101 D102 D103 D104 D105 D106 D107
1441 * D108 D109 D110 D111 D112 D113 D114 D115
1442 * 1 1 1 1 1 1 1 1
1443 * 1 1 1 1 1 1 1 1
1444 * 1 1 1 1 1 1 1 1
1445 * 1 1 1 1 1 1 1 1
1446 * 1 1 1 1 1 1 1 1
1447 * 1 1 D157 D158 D159 D160 D161 D162
1448 * D163 D164 D165 D166 D167 D168 D169 D170
1449 * D171 D172 D173 D174 D175 D176 D177 D178
1450 * 1 1 1 1 1 1 1 1
1451 * 1 1 1 1 1 1 1 1
1452 * 1 1 1 1 1 1 1 1
1453 * 1 1 1 1 1 1 1 1
1454 * 1 1 1 1 1 1 1 1
1455 * 1 1 D220 D221 D222 D223 D224 D225
1456 * D226 D227 D228 D229 D230 D231 D232 D233
1457 * D234 D235 D236 D237 D238 D239 D240 D241
1458 * 1 1 1 1 1 1 1 1
1459 * 1 1 1 ...
1460 * ... 1 1 1
1461 * 1 1 1 1 1 1 1 1
1462 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1463 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1464 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1465 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1466 *
1467 * "*" = additional TA bits to delay the frame
1468 * C = Control bits
1469 * D = Data bits
1470 * E = Extended control bits
1471 * PC = Parity over C-Bits (odd)
1472 * PE = Parity over extended control bits (odd) */
1473
1474 size_t i;
1475
1476 /* Validate sync pattern (extended) */
1477 for (i = 0; i < 19; i++) {
1478 if (trau_bits[64 + i * 64] != 1) {
1479 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-64: invalid sync pattern (T1 at position %zu != 1)\n", i);
1480 return -EINVAL;
1481 }
1482 }
1483
1484 /* Validate C-Bits */
1485 if (calc_parity(trau_bits + 65, 8) != trau_bits[73]) {
1486 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-64: invalid parity (C1-C8)\n");
1487 return -EINVAL;
1488 }
1489
1490 /* TAV (C6-C7) */
1491 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 70, 2, 1);
1492
1493 /* Downlink frame error, DFE (C8) */
1494 if (trau_bits[72] == 0)
1495 ind->dfe = true;
1496
1497 /* Check (odd) parity of E1 bit */
1498 if (trau_bits[74] != ((~trau_bits[75]) & 1)) {
1499 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-64: invalid parity (E1)\n");
1500 return -EINVAL;
1501 }
1502
1503 /* Downlink Block error, DBE (E1) */
1504 if (trau_bits[74] == 0)
1505 ind->dbe = true;
1506
1507 /* D bits */
1508 ind->pseq = get_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), 170, 22);
1509 ind->afn_ul = get_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), 234, 22);
1510 ind->afn_dl = get_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), 298, 22);
1511
1512 return 0;
1513}
1514
1515static int dec_ccu_data_ind_64(struct er_ccu_data_ind *ind, const ubit_t *trau_bits)
1516{
1517 /* 64kbps CCU-DATA-IND TRAU frame format:
1518 * Direction: CCU => PCU
1519 *
1520 * (bit 0) 0 0 0 0 0 0 0 0
1521 * 0 0 0 0 0 0 0 0
1522 * 0 0 0 0 0 0 0 0
1523 * 0 0 0 0 0 0 0 0
1524 * 0 0 0 0 0 0 0 0
1525 * 0 0 0 0 0 0 0 0
1526 * 0 0 0 0 0 0 0 0
1527 * 0 0 0 0 0 0 0 0
1528 * 1 C1 C2 C3 C4 C5 C6 C7
1529 * PC E1 E2 E3 E4 E5 E6 E7
1530 * E8 E9 E10 E11 E12 E13 E14 E15
1531 * E16 E17 E18 E19 E20 E21 E22 E23
1532 * E24 E25 E26 E27 E28 E29 E30 E31
1533 * E32 E33 E34 E35 E36 E37 E38 E39
1534 * E40 E41 E42 E43 E44 E45 E46 E47
1535 * E48 E49 E50 E51 E52 E53 E54 E55
1536 * E56 E57 PE S1 S2 S3 D1 D2
1537 * D3 D4 D5 D6 D7 D8 D9 D10
1538 * D11 D12 D13 D14 D15 D16 D17 D18
1539 * D19 D20 D21 ...
1540 * ... D1136 D1137 D1138
1541 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1542 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1543 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1544 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1545 *
1546 * C = Control bits
1547 * D = Data bits
1548 * E = Extended control bits
1549 * PC = Parity over C-Bits (odd)
1550 * PE = Parity over extended control bits (odd) */
1551 uint8_t sfq = 0;
1552 uint8_t eadd = 0;
1553 uint8_t e_2_4 = 0;
1554 uint8_t mean_bep = 0;
1555 uint8_t cv_bep = 0;
1556 int cps;
1557 int mcs = 0;
1558 int rc;
1559 int i;
1560
1561 /* Validate C-Bits */
1562 if (calc_parity(trau_bits + 65, 7) != trau_bits[72]) {
1563 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (C1-C7)\n");
1564 return -EINVAL;
1565 }
1566
1567 /* TAV (C6-C7) */
1568 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 70, 2, 1);
1569
1570 /* Validate E-Bits */
1571 if (calc_parity(trau_bits + 73, 57) != trau_bits[130]) {
1572 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (E1-E57)\n");
1573 return -EINVAL;
1574 }
1575
1576 /* Downlink block error (E1) */
1577 if (trau_bits[73] == 0)
1578 ind->dbe = true;
1579
1580 /* Coding scheme (E2-E4) */
1581 osmo_ubit2pbit_ext((pbit_t *) &e_2_4, 5, trau_bits, 74, 3, 0);
1582 switch (e_2_4) {
1583 case 0:
1584 ind->cs_hdr = CS_OR_HDR_AB;
1585 break;
1586 case 1:
1587 ind->cs_hdr = CS_OR_HDR_CS1;
1588 break;
1589 case 2:
1590 ind->cs_hdr = CS_OR_HDR_CS2;
1591 break;
1592 case 3:
1593 ind->cs_hdr = CS_OR_HDR_CS3;
1594 break;
1595 case 4:
1596 ind->cs_hdr = CS_OR_HDR_CS4;
1597 break;
1598 case 5:
1599 ind->cs_hdr = CS_OR_HDR_HDR1;
1600 break;
1601 case 6:
1602 ind->cs_hdr = CS_OR_HDR_HDR2;
1603 break;
1604 case 7:
1605 ind->cs_hdr = CS_OR_HDR_HDR3;
1606 break;
1607 default:
1608 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid codec status (E2-E4)\n");
1609 return -EINVAL;
1610 }
1611
1612 /* RX-LEV (E5-E10, 63 in case of AB) */
1613 osmo_ubit2pbit_ext((pbit_t *) &ind->rx_lev, 2, trau_bits, 77, 6, 0);
1614
1615 /* Estimated access delay (E11-E13, 0 in case of AB) */
1616 osmo_ubit2pbit_ext((pbit_t *) &eadd, 5, trau_bits, 83, 3, 0);
1617 switch (eadd) {
1618 case 0:
1619 /* <2 or less */
1620 ind->est_acc_del_dev = -3;
1621 break;
1622 case 1:
1623 ind->est_acc_del_dev = -1;
1624 break;
1625 case 2:
1626 ind->est_acc_del_dev = 1;
1627 break;
1628 case 4:
1629 ind->est_acc_del_dev = 2;
1630 break;
1631 case 5:
1632 /* >2 or more */
1633 ind->est_acc_del_dev = 3;
1634 break;
1635 case 6:
1636 ind->est_acc_del_dev = 0;
1637 break;
1638 case 7:
1639 ind->est_acc_del_dev = -2;
1640 break;
1641 default:
1642 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid estimated access delay (E11-E13)\n");
1643 return -EINVAL;
1644 }
1645
1646 if (ind->cs_hdr == CS_OR_HDR_CS1 || ind->cs_hdr == CS_OR_HDR_CS2 || ind->cs_hdr == CS_OR_HDR_CS3
1647 || ind->cs_hdr == CS_OR_HDR_CS4) {
1648 /* Soft frame quality SFQ (E14-E16, 0 in case of AB) */
1649 osmo_ubit2pbit_ext((pbit_t *) &sfq, 5, trau_bits, 86, 3, 0);
1650 ind->u.gprs.block_qual = sfq;
1651
1652 /* Parity Check (E17, 1 in case of AB) */
1653 ind->u.gprs.parity_ok = trau_bits[89];
1654
1655 } else {
1656 /* Mean BEP (E14-E20) */
1657 osmo_ubit2pbit_ext((pbit_t *) &mean_bep, 1, trau_bits, 86, 7, 0);
1658 ind->u.egprs.mean_bep = mean_bep;
1659
1660 /* CV BEP (E21-E23) */
1661 osmo_ubit2pbit_ext((pbit_t *) &cv_bep, 5, trau_bits, 93, 3, 0);
1662 ind->u.egprs.mean_bep = cv_bep;
1663
1664 /* RLC/MAC header quality (E24) */
1665 if (trau_bits[96] == 0) {
1666 ind->u.egprs.hdr_good = true;
1667
1668 /* Data block quality (E25/E26) */
1669 if (trau_bits[97] == 0)
1670 ind->u.egprs.data_good[0] = true;
1671 if (trau_bits[98] == 0)
1672 ind->u.egprs.data_good[1] = true;
1673 } else {
1674 /* A bad RLC/MAC header always means that the the data blocks
1675 * cannot be valid. */
1676 ind->u.egprs.data_good[0] = false;
1677 ind->u.egprs.data_good[1] = false;
1678 }
1679
1680 }
1681
1682 /* Data bits */
1683 switch (ind->cs_hdr) {
1684 case CS_OR_HDR_CS1:
1685 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 184, 1);
1686 rc = osmo_crc16gen_check_bits(&cs1_crc16, trau_bits + 134, 184, trau_bits + 134 + 184);
1687 if (rc != 0) {
1688 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: CRC error in CS1 block\n");
1689 return -EINVAL;
1690 }
1691 ind->data_len = 23;
1692 break;
1693 case CS_OR_HDR_CS2:
1694 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 271, 1);
1695 ind->data_len = 34;
1696 break;
1697 case CS_OR_HDR_CS3:
1698 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 315, 1);
1699 ind->data_len = 40;
1700 break;
1701 case CS_OR_HDR_CS4:
1702 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 431, 1);
1703 ind->data_len = 54;
1704 break;
1705 case CS_OR_HDR_HDR1:
1706 case CS_OR_HDR_HDR2:
1707 case CS_OR_HDR_HDR3:
1708 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 40, 1);
1709 cps = cps_from_mcs_block(ind->data, ind->cs_hdr, true);
1710 if (cps < 0) {
1711 LOGP(DLINP, LOGL_NOTICE,
1712 "CCU-DATA-IND-64: unable to read CPS from data block, bad data block received?\n");
1713 break;
1714 }
1715 mcs = mcs_from_cps((uint8_t) cps, ind->cs_hdr);
1716 if (mcs < 0) {
1717 LOGP(DLINP, LOGL_NOTICE,
1718 "CCU-DATA-IND-64: unable to determine coding scheme (MCS) from CPS, bad data block received?\n");
1719 break;
1720 }
1721
1722 /* Note: receiving noise (and eventually bad CPS field, may
1723 * happen from time to time and is not an error condition. */
1724
1725 switch (mcs) {
1726 case 1:
1727 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 209, 1);
1728 ind->data_len = 27;
1729 break;
1730 case 2:
1731 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 257, 1);
1732 ind->data_len = 33;
1733 break;
1734 case 3:
1735 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 329, 1);
1736 ind->data_len = 42;
1737 break;
1738 case 4:
1739 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 385, 1);
1740 ind->data_len = 49;
1741 break;
1742 case 5:
1743 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 487, 1);
1744 ind->data_len = 61;
1745 break;
1746 case 6:
1747 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 631, 1);
1748 ind->data_len = 79;
1749 break;
1750 case 7:
1751 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 946, 1);
1752 ind->data_len = 119;
1753 break;
1754 case 8:
1755 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 1138, 1);
1756 ind->data_len = 143;
1757 break;
1758 default:
1759 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid cs_hdr set\n");
1760 return -EINVAL;
1761 }
1762 break;
1763 case CS_OR_HDR_AB:
1764 /* Note: The useful data starts at D13 and is byte-aligned inside the TRAU frame.
1765 * The data string contains 4 items, each 8 bytes long, 32 bytes total. */
1766 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 144, 256, 1);
1767 ind->data_len = 32;
1768
1769 for (i = 0; i < 4; i++) {
1770 rc = decode_ab(&ind->ab[i], ind->data + i * 8);
1771 if (rc < 0)
1772 return -EINVAL;
1773 }
1774 break;
1775 default:
1776 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid cs_hdr set\n");
1777 return -EINVAL;
1778 }
1779
1780 return 0;
1781};
1782
1783static int dec_ccu_data_ind_64_mcs9(struct er_ccu_data_ind *ind, const ubit_t *trau_bits)
1784{
1785 /* 64kbps CCU-DATA-IND (MCS9) TRAU frame format:
1786 * Direction: CCU => PCU
1787 *
1788 * (bit 0) 0 0 0 0 0 0 0 0
1789 * 0 0 0 0 0 0 0 0
1790 * 1 D1 D2 D3 D4 D5 D6 D7
1791 * D8 D9 D10 D11 D12 D13 D14 D15
1792 * D16 D17 D18 D19 D20 D21 D22 D23
1793 * D24 D25 D26 D27 D28 D29 D30 D31
1794 * D32 D33 D34 D35 D36 D37 D38 D39
1795 * D40 D41 D42 D43 D44 D45 D46 D47
1796 * D48 C1 C2 C3 C4 C5 C6 C7
1797 * PC E1 E2 E3 E4 E5 E6 E7
1798 * E8 E9 E10 E11 E12 E13 E14 E15
1799 * E16 E17 E18 E19 E20 E21 E22 E23
1800 * PE S1 S2 D49 D50 D51 D52 D53
1801 * D54 D55 D56 D57 D58 D59 D60 D61
1802 * D62 D63 D64 ...
1803 * ... D1219 D1220 D1221
1804 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1805 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1806 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1807 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1808 *
1809 * C = Control bits
1810 * D = Data bits
1811 * E = Extended control bits
1812 * PC = Parity over C-Bits (odd)
1813 * PE = Parity over extended control bits (odd) */
1814
1815 ubit_t block[1234];
1816 uint8_t eadd = 0;
1817 uint8_t mean_bep = 0;
1818 uint8_t cv_bep = 0;
1819
1820 /* Validate C-Bits */
1821 if (calc_parity(trau_bits + 65, 7) != trau_bits[72]) {
1822 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (C1-C7)\n");
1823 return -EINVAL;
1824 }
1825
1826 /* TAV (C6-C7) */
1827 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 70, 2, 1);
1828
1829 /* Validate E-Bits */
1830 if (calc_parity(trau_bits + 73, 23) != trau_bits[96]) {
1831 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (E1-E23)\n");
1832 return -EINVAL;
1833 }
1834
1835 /* Downlink block error (E1) */
1836 if (trau_bits[73] == 0)
1837 ind->dbe = true;
1838
1839 /* MCS9 uses CS header type 1 */
1840 ind->cs_hdr = CS_OR_HDR_HDR1;
1841
1842 /* RX-LEV (E2-E7) */
1843 osmo_ubit2pbit_ext((pbit_t *) &ind->rx_lev, 2, trau_bits, 74, 6, 0);
1844
1845 /* Estimated access delay (E8-E10) */
1846 osmo_ubit2pbit_ext((pbit_t *) &eadd, 5, trau_bits, 80, 3, 0);
1847 switch (eadd) {
1848 case 0:
1849 /* <2 or less */
1850 ind->est_acc_del_dev = -3;
1851 break;
1852 case 1:
1853 ind->est_acc_del_dev = -1;
1854 break;
1855 case 2:
1856 ind->est_acc_del_dev = 1;
1857 break;
1858 case 4:
1859 ind->est_acc_del_dev = 2;
1860 break;
1861 case 5:
1862 /* >2 or more */
1863 ind->est_acc_del_dev = 3;
1864 break;
1865 case 6:
1866 ind->est_acc_del_dev = 0;
1867 break;
1868 case 7:
1869 ind->est_acc_del_dev = -2;
1870 break;
1871 default:
1872 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid estimated access delay (E11-E13)\n");
1873 return -EINVAL;
1874 }
1875
1876 /* Mean BEP (E11-E17) */
1877 osmo_ubit2pbit_ext((pbit_t *) &mean_bep, 1, trau_bits, 83, 7, 0);
1878 ind->u.egprs.mean_bep = mean_bep;
1879
1880 /* CV BEP (E18-E20) */
1881 osmo_ubit2pbit_ext((pbit_t *) &cv_bep, 5, trau_bits, 90, 3, 0);
1882 ind->u.egprs.mean_bep = cv_bep;
1883
1884 /* RLC/MAC header quality (E21) */
1885 if (trau_bits[93] == 0) {
1886 ind->u.egprs.hdr_good = true;
1887
1888 /* Data block quality (E22/E23) */
1889 if (trau_bits[94] == 0)
1890 ind->u.egprs.data_good[0] = true;
1891 if (trau_bits[95] == 0)
1892 ind->u.egprs.data_good[1] = true;
1893 } else {
1894 /* A bad RLC/MAC header always means that the the data blocks
1895 * cannot be valid. */
1896 ind->u.egprs.data_good[0] = false;
1897 ind->u.egprs.data_good[1] = false;
1898 }
1899
1900 /* For capacity reasons the following fields are stripped from the
1901 * header: Spare, RSB, CPS. This means we have to restore those
1902 * fields to get a valid MCS9 block. See also: 3GPP TS 44.060,
1903 * section 10.3a.4.1 */
1904 memcpy(block, trau_bits + 17, 32);
1905 block[32] = 0; /* CPS 0 */
1906 block[33] = 0; /* CPS 1 */
1907 block[34] = 0; /* CPS 2 */
1908 block[35] = 0; /* CPS 3 */
1909 block[36] = 0; /* CPS 4 */
1910 block[37] = 0; /* RSB (not a resent block - guessed) */
1911 block[38] = trau_bits[49]; /* PI */
1912 block[39] = 0; /* Spare */
1913 block[40] = 0; /* Spare */
1914 block[41] = 0; /* Spare */
1915 block[42] = 0; /* Spare */
1916 block[43] = 0; /* Spare */
1917 block[44] = 0; /* Spare */
1918 block[45] = 0; /* Spare */
1919 memcpy(block + 45, trau_bits + 50, 15);
1920 memcpy(block + 45, trau_bits + 99, 1173);
1921
1922 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, block, 0, sizeof(block), 1);
1923
1924 return 0;
1925}
1926
1927/*! decode an 64k Ericsson GPRS (GSL) TRAU frame.
1928 * \param[out] fr caller-allocated output data structure.
1929 * \param[in] bits unpacked input bits (1280).
1930 * \return 0 on success; negative in case of error. */
1931int er_gprs_trau_frame_decode_64k(struct er_gprs_trau_frame *fr, const ubit_t *bits)
1932{
1933 uint8_t c_1_5 = 0;
1934 const ubit_t expected_sync_pattern[] = {
1935 0, 0, 0, 0, 0, 0, 0, 0,
1936 0, 0, 0, 0, 0, 0, 0, 0,
1937 0, 0, 0, 0, 0, 0, 0, 0,
1938 0, 0, 0, 0, 0, 0, 0, 0,
1939 0, 0, 0, 0, 0, 0, 0, 0,
1940 0, 0, 0, 0, 0, 0, 0, 0,
1941 0, 0, 0, 0, 0, 0, 0, 0,
1942 0, 0, 0, 0, 0, 0, 0, 0,
1943 1,
1944 };
1945 const ubit_t expected_sync_pattern_mcs9[] = {
1946 0, 0, 0, 0, 0, 0, 0, 0,
1947 0, 0, 0, 0, 0, 0, 0, 0,
1948 1,
1949 };
1950 int rc;
1951
1952 memset(fr, 0, sizeof(*fr));
1953
1954 /* Determine frame type */
1955 osmo_ubit2pbit_ext((pbit_t *) &c_1_5, 0, bits, 65, 5, 1);
1956
1957 /* Validate sync patern */
1958 switch (c_1_5) {
1959 case PCU_TRAU_ER_FT_CCU_SYNC_IND:
1960 case PCU_TRAU_ER_FT_DATA_IND:
1961 if (memcmp(bits, expected_sync_pattern, ARRAY_SIZE(expected_sync_pattern)) != 0) {
1962 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-64: invalid sync pattern (T0,T1)\n");
1963 return -EINVAL;
1964 }
1965 break;
1966 case PCU_TRAU_ER_FT_DATA9_IND:
1967 if (memcmp(bits, expected_sync_pattern_mcs9, ARRAY_SIZE(expected_sync_pattern_mcs9)) != 0) {
1968 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid sync pattern (T0,T1)\n");
1969 return -EINVAL;
1970 }
1971 break;
1972 default:
1973 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-64: invalid frame type (%02x)\n", c_1_5);
1974 rc = -EINVAL;
1975 }
1976
1977 /* Decode frame */
1978 switch (c_1_5) {
1979 case PCU_TRAU_ER_FT_CCU_SYNC_IND:
1980 fr->type = ER_GPRS_TRAU_FT_SYNC;
1981 rc = dec_ccu_sync_ind_64(&fr->u.ccu_sync_ind, bits);
1982 break;
1983 case PCU_TRAU_ER_FT_DATA_IND:
1984 fr->type = ER_GPRS_TRAU_FT_DATA;
1985 rc = dec_ccu_data_ind_64(&fr->u.ccu_data_ind, bits);
1986 break;
1987 case PCU_TRAU_ER_FT_DATA9_IND:
1988 fr->type = ER_GPRS_TRAU_FT_DATA;
1989 rc = dec_ccu_data_ind_64_mcs9(&fr->u.ccu_data_ind, bits);
1990 break;
1991 default:
1992 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-64: invalid frame type (%02x)\n", c_1_5);
1993 rc = -EINVAL;
1994 }
1995
1996 /* Ensure that we exit with predictable data in case of error. */
1997 if (rc < 0)
1998 memset(fr, 0, sizeof(*fr));
1999
2000 return rc;
2001}