blob: 9292f2388eaa31f68c37c6b549bc1835ad1d93ac [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;
273 if (bits_len - offs < 0)
274 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;
334 if (bits_len - offs < 0)
335 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:
582 trau_bits[28] = 0;
583 trau_bits[29] = 0;
584 break;
585 case ER_UL_CHMOD_AB:
586 trau_bits[28] = 0;
587 trau_bits[29] = 1;
588 break;
589 case ER_UL_CHMOD_AB_UNKN:
590 trau_bits[28] = 1;
591 trau_bits[29] = 0;
592 break;
593 case ER_UL_CHMOD_VOID:
594 trau_bits[28] = 1;
595 trau_bits[29] = 1;
596 break;
597 default:
598 return -EINVAL;
599 }
600
601 /* Timing offset (E5-E12, 8 bit value, MSB first) */
602 osmo_pbit2ubit_ext(trau_bits, 30, (pbit_t *) &ind->timing_offset, 0, 8, 0);
603
604 /* Power control (E13-E16, 4 bit value, MSB first, 2dB steps) */
605 osmo_pbit2ubit_ext(trau_bits, 38, (pbit_t *) &ind->atten_db, 4, 4, 0);
606
607 /* Parity (odd) over coding scheme, demodulation, timing offset and
608 * power control bits (E1-E16) */
609 trau_bits[42] = calc_parity(trau_bits + 26, 16);
610
611 /* Data bits */
612 switch (ind->cs_hdr) {
613 case CS_OR_HDR_CS1:
614 osmo_pbit2ubit_ext(trau_bits, 43, (pbit_t *) ind->data, 0, 184, 1);
615 osmo_crc16gen_set_bits(&cs1_crc16, trau_bits + 43, 184, trau_bits + 43 + 184);
616 break;
617 case CS_OR_HDR_CS2:
618 osmo_pbit2ubit_ext(trau_bits, 43, (pbit_t *) ind->data, 0, 271, 1);
619 break;
620 default:
621 /* NOTE: The 16K TRAU frames do not have enough bandwidth to
622 * support coding schemes other than CS1 and CS2 */
623 return -EINVAL;
624 }
625
626 return set_timing_ajustment_bits_16(trau_bits, ind->tav);
627}
628
629/*! encode an 16k Ericsson GPRS (GSL) TRAU frame.
630 * \param[out] bits caller-allocated memory for unpacked output bits (320+4).
631 * \param[in] fr input data structure describing TRAU frame.
632 * \return number of bits encoded. */
633int er_gprs_trau_frame_encode_16k(ubit_t *bits, struct er_gprs_trau_frame *fr)
634{
635 /* Prepare frame: first 16 bits set 0, remaining bits set to 1 */
636 memset(bits, 0, 16);
637 memset(bits + 16, 1, 320 + 4 - 16);
638
639 switch (fr->type) {
640 case ER_GPRS_TRAU_FT_SYNC:
641 return enc_pcu_sync_ind_16(bits, &fr->u.pcu_sync_ind);
642 case ER_GPRS_TRAU_FT_DATA:
643 return enc_pcu_data_ind_16(bits, &fr->u.pcu_data_ind);
644 default:
645 return -EINVAL;
646 }
647
648 return -EINVAL;
649}
650
651static int dec_ccu_sync_ind_16(struct er_ccu_sync_ind *ind, const ubit_t *trau_bits)
652{
653 /* 16kbps CCU-SYNC-IND TRAU frame format:
654 * Direction: CCU => PCU
655 *
656 * (bit 0) 0 0 0 0 0 0 0 0
657 * 0 0 0 0 0 0 0 0
658 * 1 C1 C2 C3 C4 C5 C6 C7
659 * C8 PC E1 PE 1 1 1 1
660 * 1 0 0 0 0 0 0 0
661 * 0 D13 D14 D15 D16 D17 D18 D19 PSEQ (offset 41)
662 * 1 D20 D21 D22 D23 D24 D25 D26
663 * D27 D28 D29 D30 D31 D32 D33 D34
664 * 1 1 1 1 1 1 1 1
665 * 1 1 1 1 1 1 1 1
666 * 1 1 1 1 1 1 1 1
667 * 1 D58 D59 D60 D61 D62 D63 D64 AFN UL (offset 89)
668 * 1 D65 D66 D67 D68 D69 D70 D71
669 * D72 D73 D74 D75 D76 D77 D78 D79
670 * 1 1 1 1 1 1 1 1
671 * 1 1 1 1 1 1 1 1
672 * 1 1 1 1 1 1 1 1
673 * 1 D103 D104 D105 D106 D107 D108 D109 AFN DL (offset 137)
674 * 1 D110 D111 D112 D113 D114 D115 D116
675 * D117 D118 D119 D120 D121 D122 D123 D124
676 * 1 1 1 1 1 1 1 1
677 * 1 1 1 ...
678 * ... 1 1 1
679 * 1 1 1 1 1 1 1 1
680 * 1 1 1 1 1 1 TA1 TA2 (bit 319)
681 * TA3* TA4*
682 *
683 * "*" = additional TA bits to delay the frame
684 * C = Control bits
685 * D = Data bits
686 * E = Extended control bits
687 * PC = Parity over C-Bits (odd)
688 * PE = Parity over extended control bits (odd) */
689
690 size_t i;
691
692 /* Validate sync pattern (extended) */
693 for (i = 0; i < 19; i++) {
694 if (trau_bits[16 + i * 16] != 1) {
695 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-16: invalid sync pattern (T1 at position %zu != 1)\n", i);
696 return -EINVAL;
697 }
698 }
699
700 /* Validate C-Bits */
701 if (calc_parity(trau_bits + 17, 8) != trau_bits[25]) {
702 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-16: invalid parity (C1-C8)\n");
703 return -EINVAL;
704 }
705
706 /* TAV (C7-C9) */
707 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 22, 2, 1);
708
709 /* Downlink frame error, DFE (C8) */
710 if (trau_bits[24] == 0)
711 ind->dfe = true;
712
713 /* Check (odd) parity of E1 bit */
714 if (trau_bits[26] != ((~trau_bits[27]) & 1)) {
715 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-16: invalid parity (E1)\n");
716 return -EINVAL;
717 }
718
719 /* Downlink Block error, DBE (E1) */
720 if (trau_bits[26] == 0)
721 ind->dbe = true;
722
723 /* D bits */
724 ind->pseq = get_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), 41, 22);
725 ind->afn_ul = get_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), 89, 22);
726 ind->afn_dl = get_trau_uint32(trau_bits, 320, T_bits_16, sizeof(T_bits_16), 137, 22);
727
728 return 0;
729}
730
731static int dec_ccu_data_ind_16(struct er_ccu_data_ind *ind, const ubit_t *trau_bits)
732{
733 /* 16kbps CCU-DATA-IND TRAU frame format:
734 * Direction: CCU => PCU
735 *
736 * (bit 0) 0 0 0 0 0 0 0 0
737 * 0 0 0 0 0 0 0 0
738 * 1 C1 C2 C3 C4 C5 C6 C7
739 * PC E1 E2 E3 E4 E5 E6 E7
740 * E8 E9 E10 E11 E12 E13 E14 E15
741 * E16 E17 E18 E19 PE D1 D2 D3
742 * D4 D5 D6 D7 D8 D9 D10 D11
743 * D12 D13 D14 ...
744 * ... D267 D268 D269
745 * D270 D271 D272 D273 TA1 TA2 TA3 TA4 (bit 319)
746 * TA5* TA6* TA7* TA8*
747 *
748 * C = Control bits
749 * D = Data bits
750 * E = Extended control bits
751 * PC = Parity over C-Bits (odd)
752 * PE = Parity over extended control bits (odd) */
753
754 uint8_t sfq = 0;
755 uint8_t eadd = 0;
756 uint8_t e_2_4 = 0;
757 int rc;
758 int i;
759
760 /* Validate C-Bits */
761 if (calc_parity(trau_bits + 17, 7) != trau_bits[24]) {
762 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid parity (C1-C7)\n");
763 return -EINVAL;
764 }
765
766 /* TAV (C6-C7) */
767 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 22, 2, 1);
768
769 /* Validate E-Bits */
770 if (calc_parity(trau_bits + 25, 19) != trau_bits[44]) {
771 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid parity (E1-E19)\n");
772 return -EINVAL;
773 }
774
775 /* Downlink block error (E1) */
776 if (trau_bits[25] == 0)
777 ind->dbe = true;
778
779 /* Coding scheme (E2-E4) */
780 osmo_ubit2pbit_ext((pbit_t *) &e_2_4, 5, trau_bits, 26, 3, 0);
781 switch (e_2_4) {
782 case 0:
783 ind->cs_hdr = CS_OR_HDR_CS1;
784 break;
785 case 1:
786 ind->cs_hdr = CS_OR_HDR_CS2;
787 break;
788 case 4:
789 ind->cs_hdr = CS_OR_HDR_AB;
790 break;
791 default:
792 /* 16kbps timeslots only support CS1, CS2 and AB are supported,
793 * due to bandwidth limitations. */
794 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid codec status (E2-E4)\n");
795 return -EINVAL;
796 }
797
798 /* Soft frame quality SFQ (E5-E7, 0 in case of AB) */
799 osmo_ubit2pbit_ext((pbit_t *) &sfq, 5, trau_bits, 29, 3, 0);
800 ind->u.gprs.block_qual = sfq;
801
802 /* Parity Check (E8, 1 in case of AB) */
803 ind->u.gprs.parity_ok = trau_bits[32];
804
805 /* RX-LEV (E9-E14, 63 in case of AB) */
806 osmo_ubit2pbit_ext((pbit_t *) &ind->rx_lev, 2, trau_bits, 33, 6, 0);
807
808 /* Estimated access delay (E15-E17, 0 in case of AB) */
809 osmo_ubit2pbit_ext((pbit_t *) &eadd, 5, trau_bits, 39, 3, 0);
810 switch (eadd) {
811 case 0:
812 /* <2 or less */
813 ind->est_acc_del_dev = -3;
814 break;
815 case 1:
816 ind->est_acc_del_dev = -1;
817 break;
818 case 2:
819 ind->est_acc_del_dev = 1;
820 break;
821 case 4:
822 ind->est_acc_del_dev = 2;
823 break;
824 case 5:
825 /* >2 or more */
826 ind->est_acc_del_dev = 3;
827 break;
828 case 6:
829 ind->est_acc_del_dev = 0;
830 break;
831 case 7:
832 ind->est_acc_del_dev = -2;
833 break;
834 default:
835 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid estimated access delay (E15-E17)\n");
836 return -EINVAL;
837 }
838
839 /* Data bits */
840 switch (ind->cs_hdr) {
841 case CS_OR_HDR_CS1:
842 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 45, 184, 1);
843 rc = osmo_crc16gen_check_bits(&cs1_crc16, trau_bits + 45, 184, trau_bits + 45 + 184);
844 if (rc != 0) {
845 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: CRC error in CS1 block\n");
846 return -EINVAL;
847 }
848 ind->data_len = 23;
849 break;
850 case CS_OR_HDR_CS2:
851 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 45, 271, 1);
852 ind->data_len = 34;
853 break;
854 case CS_OR_HDR_AB:
855 /* Note: The useful data starts at D4 and is byte-aligned inside the TRAU frame.
856 * The data string contains 4 items, each 8 bytes long, 32 bytes total. */
857 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 48, 256, 1);
858 ind->data_len = 32;
859
860 for (i = 0; i < 4; i++) {
861 rc = decode_ab(&ind->ab[i], ind->data + i * 8);
862 if (rc < 0)
863 return -EINVAL;
864 }
865 break;
866 default:
867 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-16: invalid cs_hdr set\n");
868 return -EINVAL;
869 }
870
871 return 0;
872};
873
874/*! decode an 16k Ericsson GPRS (GSL) TRAU frame.
875 * \param[out] fr caller-allocated output data structure.
876 * \param[in] bits unpacked input bits (320).
877 * \return 0 on success; negative in case of error. */
878int er_gprs_trau_frame_decode_16k(struct er_gprs_trau_frame *fr, const ubit_t *bits)
879{
880 uint8_t c_1_5 = 0;
881 const ubit_t expected_sync_pattern[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
882 int rc;
883
884 memset(fr, 0, sizeof(*fr));
885
886 /* Validate sync pattern */
887 if (memcmp(bits, expected_sync_pattern, ARRAY_SIZE(expected_sync_pattern)) != 0) {
888 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-16: invalid sync pattern (T0)\n");
889 return -EINVAL;
890 }
891
892 /* Determine frame type */
893 osmo_ubit2pbit_ext((pbit_t *) &c_1_5, 0, bits, 17, 5, 1);
894
895 switch (c_1_5) {
896 case PCU_TRAU_ER_FT_CCU_SYNC_IND:
897 fr->type = ER_GPRS_TRAU_FT_SYNC;
898 rc = dec_ccu_sync_ind_16(&fr->u.ccu_sync_ind, bits);
899 break;
900 case PCU_TRAU_ER_FT_DATA_IND:
901 fr->type = ER_GPRS_TRAU_FT_DATA;
902 rc = dec_ccu_data_ind_16(&fr->u.ccu_data_ind, bits);
903 break;
904 default:
905 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-16: invalid frame type (%02x)\n", c_1_5);
906 rc = -EINVAL;
907 }
908
909 /* Ensure that we exit with predictable data in case of error. */
910 if (rc < 0)
911 memset(fr, 0, sizeof(*fr));
912
913 return rc;
914}
915
916/* Extract the CPS field from a given block, block must have minimum length of 5 bytes.
917 * See also: 3GPP TS 44.060, section 10.3a.3 and section 10.3a.4 */
918static int cps_from_mcs_block(uint8_t *block, enum er_cs_or_hdr cs_hdr, bool uplink)
919{
920 uint8_t cps;
921
922 if (uplink) {
923 switch (cs_hdr) {
924 case CS_OR_HDR_HDR1:
925 cps = block[4] & 0x1f;
926 break;
927 case CS_OR_HDR_HDR2:
928 cps = (block[2] >> 6) & 0x3;
929 cps |= block[3] << 2 & 0x4;
930 break;
931 case CS_OR_HDR_HDR3:
932 cps = (block[2] >> 6) & 0x3;
933 cps |= block[3] << 2 & 0xC;
934 break;
935 default:
936 return -EINVAL;
937 }
938 } else {
939 switch (cs_hdr) {
940 case CS_OR_HDR_HDR1:
941 cps = (block[4] >> 3) & 0x1f;
942 break;
943 case CS_OR_HDR_HDR2:
944 cps = (block[3] >> 1) & 0x07;
945 break;
946 case CS_OR_HDR_HDR3:
947 cps = (block[3] >> 1) & 0x0f;
948 break;
949 default:
950 return -EINVAL;
951 }
952 }
953
954 return cps;
955}
956
957/* Determine the MCS block type from a given CPS value.
958 * See also: 3GPP TS 44.060, section 10.4.8a */
959static int mcs_from_cps(uint8_t cps, enum er_cs_or_hdr cs_hdr)
960{
961 switch (cs_hdr) {
962 case CS_OR_HDR_HDR1:
963 if (cps <= 0x0A)
964 return 9;
965 if (cps <= 0x13)
966 return 8;
967 if (cps <= 0x1C)
968 return 7;
969 return -EINVAL;
970 break;
971 case CS_OR_HDR_HDR2:
972 if (cps <= 0x03 || cps == 0x06 || cps == 0x07)
973 return 6;
974 if (cps == 4 || cps == 5)
975 return 5;
976 return -EINVAL;
977 break;
978 case CS_OR_HDR_HDR3:
979 if (cps <= 0x02)
980 return 4;
981 if (cps <= 0x08)
982 return 3;
983 if (cps == 0x09 || cps == 0x0A || cps == 0x0D || cps == 0x0E)
984 return 2;
985 if (cps == 0x0B || cps == 0x0C)
986 return 1;
987 return -EINVAL;
988 break;
989 default:
990 return -EINVAL;
991 }
992}
993
994static int enc_pcu_sync_ind_64(ubit_t *trau_bits, struct er_pcu_sync_ind *ind)
995{
996 /* 64kbps PCU-SYNC-IND TRAU frame format:
997 * Direction: PCU => CCU
998 *
999 * (bit 0) 0 0 0 0 0 0 0 0
1000 * 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 * 1 C1 C2 C3 C4 C5 C6 C7
1008 * C8 PC 1 1 1 1 1 1
1009 * 1 1 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 D96 D97 D98 D99 D100 D101
1021 * D102 D103 D104 D105 D106 D107 D108 D109
1022 * D110 D111 D112 D113 D114 D115 D116 D117
1023 * 1 1 1 1 1 1 1 1
1024 * 1 1 1 1 1 1 1 1
1025 * D133 D134 D135 D136 D137 D138 D139 D140
1026 * D141 D142 D143 D144 D145 D146 D147 D148
1027 * 1 1 1 1 1 1 1 1
1028 * 1 1 D159 D160 D161 D162 D163 D164
1029 * D165 D166 D167 D168 D169 D170 D171 D172
1030 * D173 D174 D175 D176 D177 D178 D179 D180
1031 * 1 1 1 1 1 1 1 1
1032 * 1 1 1 1 1 1 1 1
1033 * D196 D197 D198 D199 D200 D201 D202 D203
1034 * D204 D205 D206 D207 D208 D209 D210 D211
1035 * 1 1 1 1 1 1 1 1
1036 * 1 1 D222 D223 D224 D225 D226 D227
1037 * D228 D229 D230 D231 D232 D233 D234 D235
1038 * D236 D237 D238 D239 D340 D241 D242 D243
1039 * 1 1 1 1 1 1 1 1
1040 * 1 1 1 1 1 1 1 1
1041 * D259 D260 D261 D262 D263 D264 D265 D266
1042 * D267 D268 D269 D270 D271 D272 D273 D274
1043 * 1 1 1 1 1 1 1 1
1044 * 1 1 1 ...
1045 * ... 1 1 1
1046 * 1 1 1 1 1 1 1 1
1047 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1048 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1049 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1050 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1051 *
1052 * "*" = additional TA bits to delay the frame
1053 * C = Control bits
1054 * D = Data bits
1055 * E = Extended control bits
1056 * PC = Parity over C-Bits (odd)
1057 * PE = Parity over extended control bits (odd) */
1058
1059 pbit_t c_1_5 = PCU_TRAU_ER_FT_PCU_SYNC_IND;
1060 int rc;
1061
1062 /* C-Bits */
1063 osmo_pbit2ubit_ext(trau_bits, 65, &c_1_5, 0, 5, 1);
1064 osmo_pbit2ubit_ext(trau_bits, 70, (pbit_t *) &ind->tav, 0, 2, 1);
1065 if (ind->ul_frame_err == false)
1066 trau_bits[73] = 1;
1067 trau_bits[74] = calc_parity(trau_bits + 65, 8);
1068
1069 /* Set unused D-Bits to 1 */
1070 memset(trau_bits + 76, 1, 1280 - 76 - 16);
1071
1072 /* D-Bits */
1073 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->pseq, 170, 22);
1074 if (rc < 0)
1075 return -EINVAL;
1076 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->ss, 208, 16);
1077 if (rc < 0)
1078 return -EINVAL;
1079 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->fn_ul, 234, 22);
1080 if (rc < 0)
1081 return -EINVAL;
1082 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->fn_ss, 272, 15);
1083 if (rc < 0)
1084 return -EINVAL;
1085 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->fn_dl, 298, 22);
1086 if (rc < 0)
1087 return -EINVAL;
1088 rc = put_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), ind->ls, 336, 16);
1089 if (rc < 0)
1090 return -EINVAL;
1091
1092 return set_timing_ajustment_bits_64(trau_bits, ind->tav);
1093}
1094
1095int enc_pcu_data_ind_64(ubit_t *trau_bits, struct er_pcu_data_ind *ind, uint8_t mcs)
1096{
1097 /* 64kbps PCU-DATA-IND TRAU frame format:
1098 * Direction: PCU => CCU
1099 *
1100 * (bit 0) 0 0 0 0 0 0 0 0
1101 * 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 * 1 C1 C2 C3 C4 C5 C6 C7
1109 * C8 PC E1 E2 E3 E4 E5 E6
1110 * E7 E8 E9 E10 E11 E12 E13 E14
1111 * E15 E16 E17 E18 E19 E20 E21 E22
1112 * E23 E24 E25 E26 E27 E28 E29 E30
1113 * E31 E32 E33 E34 E35 E36 PE S1
1114 * S2 S3 S4 S5 S6 S7 S8 S9
1115 * S10 S11 S12 S13 S14 S15 S16 S17
1116 * S18 S19 S20 S21 D1 D2 D3 D4
1117 * D5 D6 D7 D8 D9 D10 D11 D12
1118 * D13 D14 D15 D16 D17 D18 D19 D20
1119 * D21 D22 D23 ...
1120 * ... D1130 D1131 D1132
1121 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1122 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1123 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1124 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1125 *
1126 * C = Control bits
1127 * D = Data bits
1128 * E = Extended control bits
1129 * PC = Parity over C-Bits (odd)
1130 * PE = Parity over extended control bits (odd) */
1131
1132 pbit_t c_1_5 = PCU_TRAU_ER_FT_DATA_IND;
1133
1134 /* C-Bits */
1135 osmo_pbit2ubit_ext(trau_bits, 65, &c_1_5, 0, 5, 1);
1136 osmo_pbit2ubit_ext(trau_bits, 70, (pbit_t *) &ind->tav, 0, 2, 1);
1137 if (ind->ul_frame_err == false)
1138 trau_bits[73] = 1;
1139 trau_bits[74] = calc_parity(trau_bits + 65, 8);
1140
1141 /* Set coding scheme (E1-E3) */
1142 switch (ind->cs_hdr) {
1143 case CS_OR_HDR_CS1:
1144 trau_bits[74] = 0;
1145 trau_bits[75] = 0;
1146 trau_bits[76] = 1;
1147 break;
1148 case CS_OR_HDR_CS2:
1149 trau_bits[74] = 0;
1150 trau_bits[75] = 1;
1151 trau_bits[76] = 0;
1152 break;
1153 case CS_OR_HDR_CS3:
1154 trau_bits[74] = 0;
1155 trau_bits[75] = 1;
1156 trau_bits[76] = 1;
1157 break;
1158 case CS_OR_HDR_CS4:
1159 trau_bits[74] = 1;
1160 trau_bits[75] = 0;
1161 trau_bits[76] = 0;
1162 break;
1163 case CS_OR_HDR_HDR1:
1164 trau_bits[74] = 1;
1165 trau_bits[75] = 0;
1166 trau_bits[76] = 1;
1167 break;
1168 case CS_OR_HDR_HDR2:
1169 trau_bits[74] = 1;
1170 trau_bits[75] = 1;
1171 trau_bits[76] = 0;
1172 break;
1173 case CS_OR_HDR_HDR3:
1174 trau_bits[74] = 1;
1175 trau_bits[75] = 1;
1176 trau_bits[76] = 1;
1177 break;
1178 default:
1179 /* NOTE: Access bursts (AB) are uplink-only. */
1180 return -EINVAL;
1181 }
1182
1183 /* Set demodulation in uplink (E4-E6) */
1184 switch (ind->ul_chan_mode) {
1185 case ER_UL_CHMOD_VOID:
1186 trau_bits[77] = 0;
1187 trau_bits[78] = 0;
1188 trau_bits[79] = 0;
1189 break;
1190 case ER_UL_CHMOD_NB_GMSK:
1191 trau_bits[77] = 0;
1192 trau_bits[78] = 0;
1193 trau_bits[79] = 1;
1194 break;
1195 case ER_UL_CHMOD_NB_UNKN:
1196 trau_bits[77] = 0;
1197 trau_bits[78] = 1;
1198 trau_bits[79] = 0;
1199 break;
1200 case ER_UL_CHMOD_AB:
1201 trau_bits[77] = 0;
1202 trau_bits[78] = 1;
1203 trau_bits[79] = 1;
1204 break;
1205 case ER_UL_CHMOD_AB_UNKN:
1206 trau_bits[77] = 1;
1207 trau_bits[78] = 0;
1208 trau_bits[79] = 0;
1209 break;
1210 default:
1211 return -EINVAL;
1212 }
1213
1214 /* Timing offset (E7-E14, 8 bit value, MSB first) */
1215 osmo_pbit2ubit_ext(trau_bits, 80, (pbit_t *) &ind->timing_offset, 0, 8, 0);
1216
1217 /* Power control (E33-E36, 4 bit value, MSB first, 2dB steps) */
1218 osmo_pbit2ubit_ext(trau_bits, 106, (pbit_t *) &ind->atten_db, 4, 4, 0);
1219
1220 /* Parity (odd) over coding scheme, demodulation, timing offset and
1221 * power control bits (E1-E36) */
1222 trau_bits[110] = calc_parity(trau_bits + 74, 36);
1223
1224 /* Data bits */
1225 switch (ind->cs_hdr) {
1226 case CS_OR_HDR_CS1:
1227 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 184, 1);
1228 osmo_crc16gen_set_bits(&cs1_crc16, trau_bits + 132, 184, trau_bits + 132 + 184);
1229 break;
1230 case CS_OR_HDR_CS2:
1231 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 271, 1);
1232 break;
1233 case CS_OR_HDR_CS3:
1234 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 315, 1);
1235 break;
1236 case CS_OR_HDR_CS4:
1237 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 431, 1);
1238 break;
1239 case CS_OR_HDR_HDR1:
1240 case CS_OR_HDR_HDR2:
1241 case CS_OR_HDR_HDR3:
1242 switch (mcs) {
1243 case 1:
1244 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 209, 1);
1245 break;
1246 case 2:
1247 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 257, 1);
1248 break;
1249 case 3:
1250 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 329, 1);
1251 break;
1252 case 4:
1253 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 385, 1);
1254 break;
1255 case 5:
1256 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 478, 1);
1257 break;
1258 case 6:
1259 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 622, 1);
1260 break;
1261 case 7:
1262 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 940, 1);
1263 break;
1264 case 8:
1265 osmo_pbit2ubit_ext(trau_bits, 132, (pbit_t *) ind->data, 0, 1132, 1);
1266 break;
1267 }
1268 break;
1269 default:
1270 /* NOTE: The 16K TRAU frames do not have enough bandwidth to
1271 * support coding schemes other than CS1 and CS2 */
1272 return -EINVAL;
1273 }
1274
1275 return set_timing_ajustment_bits_64(trau_bits, ind->tav);
1276}
1277
1278int enc_pcu_data_ind_64_mcs9(ubit_t *trau_bits, struct er_pcu_data_ind *ind)
1279{
1280 /* 64kbps PCU-DATA-IND (MCS9) TRAU frame format:
1281 * Direction: PCU => CCU
1282 *
1283 * (bit 0) 0 0 0 0 0 0 0 0
1284 * 0 0 0 0 0 0 0 0
1285 * 1 D1 D2 D3 D4 D5 D6 D7
1286 * D8 D9 D10 D11 D12 D13 D14 D15
1287 * D16 D17 D18 D19 D20 D21 D22 D23
1288 * D24 D25 D26 D27 D28 D29 D30 D31
1289 * D32 D33 D34 D35 D36 D37 D38 D39
1290 * D40 D41 D42 D43 D44 D45 D46 D47
1291 * D48 C1 C2 C3 C4 C5 C6 C7
1292 * C8 PC E1 E2 E3 E4 E5 E6
1293 * E7 E8 E9 PE D49 D50 D51 D52
1294 * D53 D54 D55 D56 D57 D58 D59 D60
1295 * D61 D62 D63 D64 D65 D66 D67 D68
1296 * D69 D70 D71 ...
1297 * ... D1226 D1227 D1228
1298 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1299 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1300 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1301 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1302 *
1303 * C = Control bits
1304 * D = Data bits
1305 * E = Extended control bits
1306 * PC = Parity over C-Bits (odd)
1307 * PE = Parity over extended control bits (odd) */
1308
1309 pbit_t c_1_5 = PCU_TRAU_ER_FT_DATA9_IND;
1310
1311 /* NOTE: The ericsson MCS9 64K TRAU format uses a different sync
1312 * pattern than the other 64K TRAU frame formats. To make room for
1313 * the additional bits in MCS9 only the first 16 bits are T0 bits. */
1314 trau_bits[16] = 1;
1315
1316 /* Fill headroom that normally would have T0 and T1 bits with data
1317 * bits */
1318 osmo_pbit2ubit_ext(trau_bits, 17, (pbit_t *) ind->data, 0, 48, 1);
1319
1320 /* C-Bits */
1321 osmo_pbit2ubit_ext(trau_bits, 65, &c_1_5, 0, 5, 1);
1322 osmo_pbit2ubit_ext(trau_bits, 70, (pbit_t *) &ind->tav, 0, 2, 1);
1323 if (ind->ul_frame_err == false)
1324 trau_bits[73] = 1;
1325 trau_bits[74] = calc_parity(trau_bits + 65, 8);
1326
1327 /* Set demodulation in uplink (E1-E3) */
1328 switch (ind->ul_chan_mode) {
1329 case ER_UL_CHMOD_VOID:
1330 trau_bits[74] = 0;
1331 trau_bits[75] = 0;
1332 trau_bits[76] = 0;
1333 break;
1334 case ER_UL_CHMOD_NB_GMSK:
1335 trau_bits[74] = 0;
1336 trau_bits[75] = 0;
1337 trau_bits[76] = 1;
1338 break;
1339 case ER_UL_CHMOD_NB_UNKN:
1340 trau_bits[74] = 0;
1341 trau_bits[75] = 1;
1342 trau_bits[76] = 0;
1343 break;
1344 case ER_UL_CHMOD_AB:
1345 trau_bits[74] = 0;
1346 trau_bits[75] = 1;
1347 trau_bits[76] = 1;
1348 break;
1349 case ER_UL_CHMOD_AB_UNKN:
1350 trau_bits[74] = 1;
1351 trau_bits[75] = 0;
1352 trau_bits[76] = 0;
1353 break;
1354 default:
1355 return -EINVAL;
1356 }
1357
1358 /* E4-E5 are spare bits? */
1359
1360 /* Power control (E6-E9, 4 bit value, MSB first, 2dB steps) */
1361 osmo_pbit2ubit_ext(trau_bits, 79, (pbit_t *) &ind->atten_db, 4, 4, 0);
1362
1363 /* Parity (odd) over coding scheme, demodulation, timing offset and
1364 * power control bits (E1-E9) */
1365 trau_bits[83] = calc_parity(trau_bits + 74, 9);
1366
1367 /* Fill the rest of the block with data bits */
1368 osmo_pbit2ubit_ext(trau_bits, 84, (pbit_t *) ind->data + 6, 0, 1180, 1);
1369
1370 return set_timing_ajustment_bits_64(trau_bits, ind->tav);
1371}
1372
1373/*! encode an 64k Ericsson GPRS (GSL) TRAU frame.
1374 * \param[out] bits caller-allocated memory for unpacked output bits (1280+16).
1375 * \param[in] fr input data structure describing TRAU frame.
1376 * \return number of bits encoded. */
1377int er_gprs_trau_frame_encode_64k(ubit_t *bits, struct er_gprs_trau_frame *fr)
1378{
1379 int cps;
1380 int mcs = 0;
1381 enum er_cs_or_hdr cs;
1382
1383 /* Prepare frame: first 16 bits set 0, remaining bits set to 1 */
1384 memset(bits, 0, 64);
1385 memset(bits + 64, 1, 1280 + 16 - 64);
1386
1387 switch (fr->type) {
1388 case ER_GPRS_TRAU_FT_SYNC:
1389 return enc_pcu_sync_ind_64(bits, &fr->u.pcu_sync_ind);
1390 case ER_GPRS_TRAU_FT_DATA:
1391 cs = fr->u.pcu_data_ind.cs_hdr;
1392 if (cs == CS_OR_HDR_HDR1 || cs == CS_OR_HDR_HDR2 || cs == CS_OR_HDR_HDR3) {
1393 cps = cps_from_mcs_block(fr->u.pcu_data_ind.data, cs, false);
1394 if (cps < 0)
1395 return -EINVAL;
1396 mcs = mcs_from_cps((uint8_t) cps, cs);
1397 if (mcs < 0)
1398 return -EINVAL;
1399 }
1400
1401 if (mcs < 9)
1402 return enc_pcu_data_ind_64(bits, &fr->u.pcu_data_ind, mcs);
1403 else
1404 return enc_pcu_data_ind_64_mcs9(bits, &fr->u.pcu_data_ind);
1405 default:
1406 return -EINVAL;
1407 }
1408
1409 return -EINVAL;
1410}
1411
1412static int dec_ccu_sync_ind_64(struct er_ccu_sync_ind *ind, const ubit_t *trau_bits)
1413{
1414 /* 64kbps CCU-SYNC-IND TRAU frame format:
1415 * Direction: CCU => PCU
1416 *
1417 * (bit 0) 0 0 0 0 0 0 0 0
1418 * 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 * 1 C1 C2 C3 C4 C5 C6 C7
1426 * C8 PC E1 PE 1 1 1 1
1427 * 1 1 1 1 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 D94 D95 D96 D97 D98 D99
1439 * D100 D101 D102 D103 D104 D105 D106 D107
1440 * D108 D109 D110 D111 D112 D113 D114 D115
1441 * 1 1 1 1 1 1 1 1
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 D157 D158 D159 D160 D161 D162
1447 * D163 D164 D165 D166 D167 D168 D169 D170
1448 * D171 D172 D173 D174 D175 D176 D177 D178
1449 * 1 1 1 1 1 1 1 1
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 D220 D221 D222 D223 D224 D225
1455 * D226 D227 D228 D229 D230 D231 D232 D233
1456 * D234 D235 D236 D237 D238 D239 D240 D241
1457 * 1 1 1 1 1 1 1 1
1458 * 1 1 1 ...
1459 * ... 1 1 1
1460 * 1 1 1 1 1 1 1 1
1461 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1462 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1463 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1464 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1465 *
1466 * "*" = additional TA bits to delay the frame
1467 * C = Control bits
1468 * D = Data bits
1469 * E = Extended control bits
1470 * PC = Parity over C-Bits (odd)
1471 * PE = Parity over extended control bits (odd) */
1472
1473 size_t i;
1474
1475 /* Validate sync pattern (extended) */
1476 for (i = 0; i < 19; i++) {
1477 if (trau_bits[64 + i * 64] != 1) {
1478 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-64: invalid sync pattern (T1 at position %zu != 1)\n", i);
1479 return -EINVAL;
1480 }
1481 }
1482
1483 /* Validate C-Bits */
1484 if (calc_parity(trau_bits + 65, 8) != trau_bits[73]) {
1485 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-64: invalid parity (C1-C8)\n");
1486 return -EINVAL;
1487 }
1488
1489 /* TAV (C6-C7) */
1490 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 70, 2, 1);
1491
1492 /* Downlink frame error, DFE (C8) */
1493 if (trau_bits[72] == 0)
1494 ind->dfe = true;
1495
1496 /* Check (odd) parity of E1 bit */
1497 if (trau_bits[74] != ((~trau_bits[75]) & 1)) {
1498 LOGP(DLINP, LOGL_ERROR, "CCU-SYNC-IND-64: invalid parity (E1)\n");
1499 return -EINVAL;
1500 }
1501
1502 /* Downlink Block error, DBE (E1) */
1503 if (trau_bits[74] == 0)
1504 ind->dbe = true;
1505
1506 /* D bits */
1507 ind->pseq = get_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), 170, 22);
1508 ind->afn_ul = get_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), 234, 22);
1509 ind->afn_dl = get_trau_uint32(trau_bits, 1280, T_bits_64, sizeof(T_bits_64), 298, 22);
1510
1511 return 0;
1512}
1513
1514static int dec_ccu_data_ind_64(struct er_ccu_data_ind *ind, const ubit_t *trau_bits)
1515{
1516 /* 64kbps CCU-DATA-IND TRAU frame format:
1517 * Direction: CCU => PCU
1518 *
1519 * (bit 0) 0 0 0 0 0 0 0 0
1520 * 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 * 1 C1 C2 C3 C4 C5 C6 C7
1528 * PC E1 E2 E3 E4 E5 E6 E7
1529 * E8 E9 E10 E11 E12 E13 E14 E15
1530 * E16 E17 E18 E19 E20 E21 E22 E23
1531 * E24 E25 E26 E27 E28 E29 E30 E31
1532 * E32 E33 E34 E35 E36 E37 E38 E39
1533 * E40 E41 E42 E43 E44 E45 E46 E47
1534 * E48 E49 E50 E51 E52 E53 E54 E55
1535 * E56 E57 PE S1 S2 S3 D1 D2
1536 * D3 D4 D5 D6 D7 D8 D9 D10
1537 * D11 D12 D13 D14 D15 D16 D17 D18
1538 * D19 D20 D21 ...
1539 * ... D1136 D1137 D1138
1540 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1541 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1542 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1543 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1544 *
1545 * C = Control bits
1546 * D = Data bits
1547 * E = Extended control bits
1548 * PC = Parity over C-Bits (odd)
1549 * PE = Parity over extended control bits (odd) */
1550 uint8_t sfq = 0;
1551 uint8_t eadd = 0;
1552 uint8_t e_2_4 = 0;
1553 uint8_t mean_bep = 0;
1554 uint8_t cv_bep = 0;
1555 int cps;
1556 int mcs = 0;
1557 int rc;
1558 int i;
1559
1560 /* Validate C-Bits */
1561 if (calc_parity(trau_bits + 65, 7) != trau_bits[72]) {
1562 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (C1-C7)\n");
1563 return -EINVAL;
1564 }
1565
1566 /* TAV (C6-C7) */
1567 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 70, 2, 1);
1568
1569 /* Validate E-Bits */
1570 if (calc_parity(trau_bits + 73, 57) != trau_bits[130]) {
1571 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (E1-E57)\n");
1572 return -EINVAL;
1573 }
1574
1575 /* Downlink block error (E1) */
1576 if (trau_bits[73] == 0)
1577 ind->dbe = true;
1578
1579 /* Coding scheme (E2-E4) */
1580 osmo_ubit2pbit_ext((pbit_t *) &e_2_4, 5, trau_bits, 74, 3, 0);
1581 switch (e_2_4) {
1582 case 0:
1583 ind->cs_hdr = CS_OR_HDR_AB;
1584 break;
1585 case 1:
1586 ind->cs_hdr = CS_OR_HDR_CS1;
1587 break;
1588 case 2:
1589 ind->cs_hdr = CS_OR_HDR_CS2;
1590 break;
1591 case 3:
1592 ind->cs_hdr = CS_OR_HDR_CS3;
1593 break;
1594 case 4:
1595 ind->cs_hdr = CS_OR_HDR_CS4;
1596 break;
1597 case 5:
1598 ind->cs_hdr = CS_OR_HDR_HDR1;
1599 break;
1600 case 6:
1601 ind->cs_hdr = CS_OR_HDR_HDR2;
1602 break;
1603 case 7:
1604 ind->cs_hdr = CS_OR_HDR_HDR3;
1605 break;
1606 default:
1607 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid codec status (E2-E4)\n");
1608 return -EINVAL;
1609 }
1610
1611 /* RX-LEV (E5-E10, 63 in case of AB) */
1612 osmo_ubit2pbit_ext((pbit_t *) &ind->rx_lev, 2, trau_bits, 77, 6, 0);
1613
1614 /* Estimated access delay (E11-E13, 0 in case of AB) */
1615 osmo_ubit2pbit_ext((pbit_t *) &eadd, 5, trau_bits, 83, 3, 0);
1616 switch (eadd) {
1617 case 0:
1618 /* <2 or less */
1619 ind->est_acc_del_dev = -3;
1620 break;
1621 case 1:
1622 ind->est_acc_del_dev = -1;
1623 break;
1624 case 2:
1625 ind->est_acc_del_dev = 1;
1626 break;
1627 case 4:
1628 ind->est_acc_del_dev = 2;
1629 break;
1630 case 5:
1631 /* >2 or more */
1632 ind->est_acc_del_dev = 3;
1633 break;
1634 case 6:
1635 ind->est_acc_del_dev = 0;
1636 break;
1637 case 7:
1638 ind->est_acc_del_dev = -2;
1639 break;
1640 default:
1641 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid estimated access delay (E11-E13)\n");
1642 return -EINVAL;
1643 }
1644
1645 if (ind->cs_hdr == CS_OR_HDR_CS1 || ind->cs_hdr == CS_OR_HDR_CS2 || ind->cs_hdr == CS_OR_HDR_CS3
1646 || ind->cs_hdr == CS_OR_HDR_CS4) {
1647 /* Soft frame quality SFQ (E14-E16, 0 in case of AB) */
1648 osmo_ubit2pbit_ext((pbit_t *) &sfq, 5, trau_bits, 86, 3, 0);
1649 ind->u.gprs.block_qual = sfq;
1650
1651 /* Parity Check (E17, 1 in case of AB) */
1652 ind->u.gprs.parity_ok = trau_bits[89];
1653
1654 } else {
1655 /* Mean BEP (E14-E20) */
1656 osmo_ubit2pbit_ext((pbit_t *) &mean_bep, 1, trau_bits, 86, 7, 0);
1657 ind->u.egprs.mean_bep = mean_bep;
1658
1659 /* CV BEP (E21-E23) */
1660 osmo_ubit2pbit_ext((pbit_t *) &cv_bep, 5, trau_bits, 93, 3, 0);
1661 ind->u.egprs.mean_bep = cv_bep;
1662
1663 /* RLC/MAC header quality (E24) */
1664 if (trau_bits[96] == 0) {
1665 ind->u.egprs.hdr_good = true;
1666
1667 /* Data block quality (E25/E26) */
1668 if (trau_bits[97] == 0)
1669 ind->u.egprs.data_good[0] = true;
1670 if (trau_bits[98] == 0)
1671 ind->u.egprs.data_good[1] = true;
1672 } else {
1673 /* A bad RLC/MAC header always means that the the data blocks
1674 * cannot be valid. */
1675 ind->u.egprs.data_good[0] = false;
1676 ind->u.egprs.data_good[1] = false;
1677 }
1678
1679 }
1680
1681 /* Data bits */
1682 switch (ind->cs_hdr) {
1683 case CS_OR_HDR_CS1:
1684 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 184, 1);
1685 rc = osmo_crc16gen_check_bits(&cs1_crc16, trau_bits + 134, 184, trau_bits + 134 + 184);
1686 if (rc != 0) {
1687 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: CRC error in CS1 block\n");
1688 return -EINVAL;
1689 }
1690 ind->data_len = 23;
1691 break;
1692 case CS_OR_HDR_CS2:
1693 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 271, 1);
1694 ind->data_len = 34;
1695 break;
1696 case CS_OR_HDR_CS3:
1697 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 315, 1);
1698 ind->data_len = 40;
1699 break;
1700 case CS_OR_HDR_CS4:
1701 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 431, 1);
1702 ind->data_len = 54;
1703 break;
1704 case CS_OR_HDR_HDR1:
1705 case CS_OR_HDR_HDR2:
1706 case CS_OR_HDR_HDR3:
1707 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 40, 1);
1708 cps = cps_from_mcs_block(ind->data, ind->cs_hdr, true);
1709 if (cps < 0) {
1710 LOGP(DLINP, LOGL_NOTICE,
1711 "CCU-DATA-IND-64: unable to read CPS from data block, bad data block received?\n");
1712 break;
1713 }
1714 mcs = mcs_from_cps((uint8_t) cps, ind->cs_hdr);
1715 if (mcs < 0) {
1716 LOGP(DLINP, LOGL_NOTICE,
1717 "CCU-DATA-IND-64: unable to determine coding scheme (MCS) from CPS, bad data block received?\n");
1718 break;
1719 }
1720
1721 /* Note: receiving noise (and eventually bad CPS field, may
1722 * happen from time to time and is not an error condition. */
1723
1724 switch (mcs) {
1725 case 1:
1726 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 209, 1);
1727 ind->data_len = 27;
1728 break;
1729 case 2:
1730 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 257, 1);
1731 ind->data_len = 33;
1732 break;
1733 case 3:
1734 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 329, 1);
1735 ind->data_len = 42;
1736 break;
1737 case 4:
1738 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 385, 1);
1739 ind->data_len = 49;
1740 break;
1741 case 5:
1742 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 487, 1);
1743 ind->data_len = 61;
1744 break;
1745 case 6:
1746 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 631, 1);
1747 ind->data_len = 79;
1748 break;
1749 case 7:
1750 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 946, 1);
1751 ind->data_len = 119;
1752 break;
1753 case 8:
1754 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 134, 1138, 1);
1755 ind->data_len = 143;
1756 break;
1757 default:
1758 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid cs_hdr set\n");
1759 return -EINVAL;
1760 }
1761 break;
1762 case CS_OR_HDR_AB:
1763 /* Note: The useful data starts at D13 and is byte-aligned inside the TRAU frame.
1764 * The data string contains 4 items, each 8 bytes long, 32 bytes total. */
1765 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, trau_bits, 144, 256, 1);
1766 ind->data_len = 32;
1767
1768 for (i = 0; i < 4; i++) {
1769 rc = decode_ab(&ind->ab[i], ind->data + i * 8);
1770 if (rc < 0)
1771 return -EINVAL;
1772 }
1773 break;
1774 default:
1775 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid cs_hdr set\n");
1776 return -EINVAL;
1777 }
1778
1779 return 0;
1780};
1781
1782static int dec_ccu_data_ind_64_mcs9(struct er_ccu_data_ind *ind, const ubit_t *trau_bits)
1783{
1784 /* 64kbps CCU-DATA-IND (MCS9) TRAU frame format:
1785 * Direction: CCU => PCU
1786 *
1787 * (bit 0) 0 0 0 0 0 0 0 0
1788 * 0 0 0 0 0 0 0 0
1789 * 1 D1 D2 D3 D4 D5 D6 D7
1790 * D8 D9 D10 D11 D12 D13 D14 D15
1791 * D16 D17 D18 D19 D20 D21 D22 D23
1792 * D24 D25 D26 D27 D28 D29 D30 D31
1793 * D32 D33 D34 D35 D36 D37 D38 D39
1794 * D40 D41 D42 D43 D44 D45 D46 D47
1795 * D48 C1 C2 C3 C4 C5 C6 C7
1796 * PC E1 E2 E3 E4 E5 E6 E7
1797 * E8 E9 E10 E11 E12 E13 E14 E15
1798 * E16 E17 E18 E19 E20 E21 E22 E23
1799 * PE S1 S2 D49 D50 D51 D52 D53
1800 * D54 D55 D56 D57 D58 D59 D60 D61
1801 * D62 D63 D64 ...
1802 * ... D1219 D1220 D1221
1803 * TA1 TA2 TA3 TA4 TA5 TA6 TA7 TA8
1804 * TA9 TA10 TA11 TA12 TA13 TA14 TA15 TA16 (bit 1279)
1805 * TA17* TA18* TA19* TA20* TA21* TA22* TA23* TA24*
1806 * TA25* TA26* TA27* TA28* TA29* TA30* TA31* TA32*
1807 *
1808 * C = Control bits
1809 * D = Data bits
1810 * E = Extended control bits
1811 * PC = Parity over C-Bits (odd)
1812 * PE = Parity over extended control bits (odd) */
1813
1814 ubit_t block[1234];
1815 uint8_t eadd = 0;
1816 uint8_t mean_bep = 0;
1817 uint8_t cv_bep = 0;
1818
1819 /* Validate C-Bits */
1820 if (calc_parity(trau_bits + 65, 7) != trau_bits[72]) {
1821 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (C1-C7)\n");
1822 return -EINVAL;
1823 }
1824
1825 /* TAV (C6-C7) */
1826 osmo_ubit2pbit_ext((pbit_t *) &ind->tav, 0, trau_bits, 70, 2, 1);
1827
1828 /* Validate E-Bits */
1829 if (calc_parity(trau_bits + 73, 23) != trau_bits[96]) {
1830 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid parity (E1-E23)\n");
1831 return -EINVAL;
1832 }
1833
1834 /* Downlink block error (E1) */
1835 if (trau_bits[73] == 0)
1836 ind->dbe = true;
1837
1838 /* MCS9 uses CS header type 1 */
1839 ind->cs_hdr = CS_OR_HDR_HDR1;
1840
1841 /* RX-LEV (E2-E7) */
1842 osmo_ubit2pbit_ext((pbit_t *) &ind->rx_lev, 2, trau_bits, 74, 6, 0);
1843
1844 /* Estimated access delay (E8-E10) */
1845 osmo_ubit2pbit_ext((pbit_t *) &eadd, 5, trau_bits, 80, 3, 0);
1846 switch (eadd) {
1847 case 0:
1848 /* <2 or less */
1849 ind->est_acc_del_dev = -3;
1850 break;
1851 case 1:
1852 ind->est_acc_del_dev = -1;
1853 break;
1854 case 2:
1855 ind->est_acc_del_dev = 1;
1856 break;
1857 case 4:
1858 ind->est_acc_del_dev = 2;
1859 break;
1860 case 5:
1861 /* >2 or more */
1862 ind->est_acc_del_dev = 3;
1863 break;
1864 case 6:
1865 ind->est_acc_del_dev = 0;
1866 break;
1867 case 7:
1868 ind->est_acc_del_dev = -2;
1869 break;
1870 default:
1871 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid estimated access delay (E11-E13)\n");
1872 return -EINVAL;
1873 }
1874
1875 /* Mean BEP (E11-E17) */
1876 osmo_ubit2pbit_ext((pbit_t *) &mean_bep, 1, trau_bits, 83, 7, 0);
1877 ind->u.egprs.mean_bep = mean_bep;
1878
1879 /* CV BEP (E18-E20) */
1880 osmo_ubit2pbit_ext((pbit_t *) &cv_bep, 5, trau_bits, 90, 3, 0);
1881 ind->u.egprs.mean_bep = cv_bep;
1882
1883 /* RLC/MAC header quality (E21) */
1884 if (trau_bits[93] == 0) {
1885 ind->u.egprs.hdr_good = true;
1886
1887 /* Data block quality (E22/E23) */
1888 if (trau_bits[94] == 0)
1889 ind->u.egprs.data_good[0] = true;
1890 if (trau_bits[95] == 0)
1891 ind->u.egprs.data_good[1] = true;
1892 } else {
1893 /* A bad RLC/MAC header always means that the the data blocks
1894 * cannot be valid. */
1895 ind->u.egprs.data_good[0] = false;
1896 ind->u.egprs.data_good[1] = false;
1897 }
1898
1899 /* For capacity reasons the following fields are stripped from the
1900 * header: Spare, RSB, CPS. This means we have to restore those
1901 * fields to get a valid MCS9 block. See also: 3GPP TS 44.060,
1902 * section 10.3a.4.1 */
1903 memcpy(block, trau_bits + 17, 32);
1904 block[32] = 0; /* CPS 0 */
1905 block[33] = 0; /* CPS 1 */
1906 block[34] = 0; /* CPS 2 */
1907 block[35] = 0; /* CPS 3 */
1908 block[36] = 0; /* CPS 4 */
1909 block[37] = 0; /* RSB (not a resent block - guessed) */
1910 block[38] = trau_bits[49]; /* PI */
1911 block[39] = 0; /* Spare */
1912 block[40] = 0; /* Spare */
1913 block[41] = 0; /* Spare */
1914 block[42] = 0; /* Spare */
1915 block[43] = 0; /* Spare */
1916 block[44] = 0; /* Spare */
1917 block[45] = 0; /* Spare */
1918 memcpy(block + 45, trau_bits + 50, 15);
1919 memcpy(block + 45, trau_bits + 99, 1173);
1920
1921 osmo_ubit2pbit_ext((pbit_t *) &ind->data, 0, block, 0, sizeof(block), 1);
1922
1923 return 0;
1924}
1925
1926/*! decode an 64k Ericsson GPRS (GSL) TRAU frame.
1927 * \param[out] fr caller-allocated output data structure.
1928 * \param[in] bits unpacked input bits (1280).
1929 * \return 0 on success; negative in case of error. */
1930int er_gprs_trau_frame_decode_64k(struct er_gprs_trau_frame *fr, const ubit_t *bits)
1931{
1932 uint8_t c_1_5 = 0;
1933 const ubit_t expected_sync_pattern[] = {
1934 0, 0, 0, 0, 0, 0, 0, 0,
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 1,
1943 };
1944 const ubit_t expected_sync_pattern_mcs9[] = {
1945 0, 0, 0, 0, 0, 0, 0, 0,
1946 0, 0, 0, 0, 0, 0, 0, 0,
1947 1,
1948 };
1949 int rc;
1950
1951 memset(fr, 0, sizeof(*fr));
1952
1953 /* Determine frame type */
1954 osmo_ubit2pbit_ext((pbit_t *) &c_1_5, 0, bits, 65, 5, 1);
1955
1956 /* Validate sync patern */
1957 switch (c_1_5) {
1958 case PCU_TRAU_ER_FT_CCU_SYNC_IND:
1959 case PCU_TRAU_ER_FT_DATA_IND:
1960 if (memcmp(bits, expected_sync_pattern, ARRAY_SIZE(expected_sync_pattern)) != 0) {
1961 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-64: invalid sync pattern (T0,T1)\n");
1962 return -EINVAL;
1963 }
1964 break;
1965 case PCU_TRAU_ER_FT_DATA9_IND:
1966 if (memcmp(bits, expected_sync_pattern_mcs9, ARRAY_SIZE(expected_sync_pattern_mcs9)) != 0) {
1967 LOGP(DLINP, LOGL_ERROR, "CCU-DATA-IND-64: invalid sync pattern (T0,T1)\n");
1968 return -EINVAL;
1969 }
1970 break;
1971 default:
1972 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-64: invalid frame type (%02x)\n", c_1_5);
1973 rc = -EINVAL;
1974 }
1975
1976 /* Decode frame */
1977 switch (c_1_5) {
1978 case PCU_TRAU_ER_FT_CCU_SYNC_IND:
1979 fr->type = ER_GPRS_TRAU_FT_SYNC;
1980 rc = dec_ccu_sync_ind_64(&fr->u.ccu_sync_ind, bits);
1981 break;
1982 case PCU_TRAU_ER_FT_DATA_IND:
1983 fr->type = ER_GPRS_TRAU_FT_DATA;
1984 rc = dec_ccu_data_ind_64(&fr->u.ccu_data_ind, bits);
1985 break;
1986 case PCU_TRAU_ER_FT_DATA9_IND:
1987 fr->type = ER_GPRS_TRAU_FT_DATA;
1988 rc = dec_ccu_data_ind_64_mcs9(&fr->u.ccu_data_ind, bits);
1989 break;
1990 default:
1991 LOGP(DLINP, LOGL_ERROR, "CCU-XXXX-IND-64: invalid frame type (%02x)\n", c_1_5);
1992 rc = -EINVAL;
1993 }
1994
1995 /* Ensure that we exit with predictable data in case of error. */
1996 if (rc < 0)
1997 memset(fr, 0, sizeof(*fr));
1998
1999 return rc;
2000}