blob: b37c7650e95a8d7fe7f602f96f783934e0851179 [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* Simple TRAU frame reflector to route voice calls */
2
3/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +01007 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
Harald Welte59b04682009-06-10 05:40:52 +08009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte0e3e88e2011-01-01 15:25:50 +010014 * GNU Affero General Public License for more details.
Harald Welte59b04682009-06-10 05:40:52 +080015 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010016 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte59b04682009-06-10 05:40:52 +080018 *
19 */
20
21#include <errno.h>
22#include <stdlib.h>
23#include <string.h>
Harald Welte59b04682009-06-10 05:40:52 +080024
25#include <openbsc/gsm_data.h>
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +020026#include <osmocom/abis/trau_frame.h>
Harald Welte59b04682009-06-10 05:40:52 +080027#include <openbsc/trau_mux.h>
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +020028#include <osmocom/abis/subchan_demux.h>
29#include <osmocom/abis/e1_input.h>
Harald Welte59b04682009-06-10 05:40:52 +080030#include <openbsc/debug.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010031#include <osmocom/core/talloc.h>
Alexander Huemer45a00142011-09-06 00:09:49 +020032#include <openbsc/trau_upqueue.h>
Andreas Eversberg2c202cd2013-12-06 16:59:10 +010033#include <osmocom/core/crcgen.h>
Andreas Eversberg02063672013-12-05 14:37:11 +010034#include <openbsc/transaction.h>
Harald Welte59b04682009-06-10 05:40:52 +080035
Holger Hans Peter Freyther16e59db2011-10-26 19:01:57 +020036/* this corresponds to the bit-lengths of the individual codec
Harald Welte9eb9b322011-07-24 02:18:13 +020037 * parameters as indicated in Table 1.1 of TS 06.10 */
38static const uint8_t gsm_fr_map[] = {
Harald Welte3971ad52009-12-19 22:23:05 +010039 6, 6, 5, 5, 4, 4, 3, 3,
40 7, 2, 2, 6, 3, 3, 3, 3,
41 3, 3, 3, 3, 3, 3, 3, 3,
42 3, 7, 2, 2, 6, 3, 3, 3,
43 3, 3, 3, 3, 3, 3, 3, 3,
44 3, 3, 7, 2, 2, 6, 3, 3,
45 3, 3, 3, 3, 3, 3, 3, 3,
46 3, 3, 3, 7, 2, 2, 6, 3,
47 3, 3, 3, 3, 3, 3, 3, 3,
48 3, 3, 3, 3
49};
50
Andreas Eversberg2c202cd2013-12-06 16:59:10 +010051
52/*
53 * EFR TRAU parity
54 *
55 * g(x) = x^3 + x^1 + 1
56 */
57static const struct osmo_crc8gen_code gsm0860_efr_crc3 = {
58 .bits = 3,
59 .poly = 0x3,
60 .init = 0x0,
61 .remainder = 0x7,
62};
63
64/* EFR parity bits */
65static inline void efr_parity_bits_1(ubit_t *check_bits, const ubit_t *d_bits)
66{
67 memcpy(check_bits + 0 , d_bits + 0, 22);
68 memcpy(check_bits + 22 , d_bits + 24, 3);
69 check_bits[25] = d_bits[28];
70}
71
72static inline void efr_parity_bits_2(ubit_t *check_bits, const ubit_t *d_bits)
73{
74 memcpy(check_bits + 0 , d_bits + 42, 10);
75 memcpy(check_bits + 10 , d_bits + 90, 2);
76}
77
78static inline void efr_parity_bits_3(ubit_t *check_bits, const ubit_t *d_bits)
79{
80 memcpy(check_bits + 0 , d_bits + 98, 5);
81 check_bits[5] = d_bits[104];
82 memcpy(check_bits + 6 , d_bits + 143, 2);
83}
84
85static inline void efr_parity_bits_4(ubit_t *check_bits, const ubit_t *d_bits)
86{
87 memcpy(check_bits + 0 , d_bits + 151, 10);
88 memcpy(check_bits + 10 , d_bits + 199, 2);
89}
90
91static inline void efr_parity_bits_5(ubit_t *check_bits, const ubit_t *d_bits)
92{
93 memcpy(check_bits + 0 , d_bits + 207, 5);
94 check_bits[5] = d_bits[213];
95 memcpy(check_bits + 6 , d_bits + 252, 2);
96}
97
Harald Welte59b04682009-06-10 05:40:52 +080098struct map_entry {
99 struct llist_head list;
100 struct gsm_e1_subslot src, dst;
101};
102
103struct upqueue_entry {
104 struct llist_head list;
105 struct gsm_network *net;
106 struct gsm_e1_subslot src;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200107 uint32_t callref;
Harald Welte59b04682009-06-10 05:40:52 +0800108};
109
110static LLIST_HEAD(ss_map);
111static LLIST_HEAD(ss_upqueue);
112
Harald Welte (local)8751ee92009-08-15 02:30:58 +0200113void *tall_map_ctx, *tall_upq_ctx;
Harald Weltea8379772009-06-20 22:36:41 +0200114
Harald Welte59b04682009-06-10 05:40:52 +0800115/* map one particular subslot to another subslot */
116int trau_mux_map(const struct gsm_e1_subslot *src,
117 const struct gsm_e1_subslot *dst)
118{
Harald Weltea8379772009-06-20 22:36:41 +0200119 struct map_entry *me;
120
Harald Weltea8379772009-06-20 22:36:41 +0200121 me = talloc(tall_map_ctx, struct map_entry);
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100122 if (!me) {
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +0200123 LOGP(DLMIB, LOGL_FATAL, "Out of memory\n");
Harald Welte59b04682009-06-10 05:40:52 +0800124 return -ENOMEM;
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100125 }
Harald Welte59b04682009-06-10 05:40:52 +0800126
127 DEBUGP(DCC, "Setting up TRAU mux map between (e1=%u,ts=%u,ss=%u) "
128 "and (e1=%u,ts=%u,ss=%u)\n",
129 src->e1_nr, src->e1_ts, src->e1_ts_ss,
130 dst->e1_nr, dst->e1_ts, dst->e1_ts_ss);
131
132 /* make sure to get rid of any stale old mappings */
133 trau_mux_unmap(src, 0);
134 trau_mux_unmap(dst, 0);
135
136 memcpy(&me->src, src, sizeof(me->src));
137 memcpy(&me->dst, dst, sizeof(me->dst));
138 llist_add(&me->list, &ss_map);
139
140 return 0;
141}
142
143int trau_mux_map_lchan(const struct gsm_lchan *src,
144 const struct gsm_lchan *dst)
145{
146 struct gsm_e1_subslot *src_ss, *dst_ss;
147
148 src_ss = &src->ts->e1_link;
149 dst_ss = &dst->ts->e1_link;
150
151 return trau_mux_map(src_ss, dst_ss);
152}
153
154
155/* unmap one particular subslot from another subslot */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200156int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref)
Harald Welte59b04682009-06-10 05:40:52 +0800157{
158 struct map_entry *me, *me2;
159 struct upqueue_entry *ue, *ue2;
160
161 if (ss)
162 llist_for_each_entry_safe(me, me2, &ss_map, list) {
163 if (!memcmp(&me->src, ss, sizeof(*ss)) ||
164 !memcmp(&me->dst, ss, sizeof(*ss))) {
165 llist_del(&me->list);
166 return 0;
167 }
168 }
169 llist_for_each_entry_safe(ue, ue2, &ss_upqueue, list) {
170 if (ue->callref == callref) {
171 llist_del(&ue->list);
172 return 0;
173 }
174 if (ss && !memcmp(&ue->src, ss, sizeof(*ss))) {
175 llist_del(&ue->list);
176 return 0;
177 }
178 }
179 return -ENOENT;
180}
181
182/* look-up an enty in the TRAU mux map */
183static struct gsm_e1_subslot *
184lookup_trau_mux_map(const struct gsm_e1_subslot *src)
185{
186 struct map_entry *me;
187
188 llist_for_each_entry(me, &ss_map, list) {
189 if (!memcmp(&me->src, src, sizeof(*src)))
190 return &me->dst;
191 if (!memcmp(&me->dst, src, sizeof(*src)))
192 return &me->src;
193 }
194 return NULL;
195}
196
197/* look-up an enty in the TRAU upqueue */
198struct upqueue_entry *
199lookup_trau_upqueue(const struct gsm_e1_subslot *src)
200{
201 struct upqueue_entry *ue;
202
203 llist_for_each_entry(ue, &ss_upqueue, list) {
204 if (!memcmp(&ue->src, src, sizeof(*src)))
205 return ue;
206 }
207 return NULL;
208}
209
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100210static const uint8_t c_bits_check_fr[] = { 0, 0, 0, 1, 0 };
211static const uint8_t c_bits_check_efr[] = { 1, 1, 0, 1, 0 };
212
213struct msgb *trau_decode_fr(uint32_t callref,
214 const struct decoded_trau_frame *tf)
215{
216 struct msgb *msg;
217 struct gsm_data_frame *frame;
218 unsigned char *data;
219 int i, j, k, l, o;
220
221 msg = msgb_alloc(sizeof(struct gsm_data_frame) + 33,
222 "GSM-DATA");
223 if (!msg)
224 return NULL;
225
226 frame = (struct gsm_data_frame *)msg->data;
227 memset(frame, 0, sizeof(struct gsm_data_frame));
228 data = frame->data;
229 data[0] = 0xd << 4;
230 /* reassemble d-bits */
231 i = 0; /* counts bits */
232 j = 4; /* counts output bits */
233 k = gsm_fr_map[0]-1; /* current number bit in element */
234 l = 0; /* counts element bits */
235 o = 0; /* offset input bits */
236 while (i < 260) {
237 data[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
Holger Hans Peter Freytherca9f9132014-07-22 12:23:03 +0200238 /* to avoid out-of-bounds access in gsm_fr_map[++l] */
239 if (i == 259)
240 break;
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100241 if (--k < 0) {
242 o += gsm_fr_map[l];
243 k = gsm_fr_map[++l]-1;
244 }
245 i++;
246 j++;
247 }
Andreas Eversberg0005a032012-01-20 20:33:37 +0100248 if (tf->c_bits[11]) /* BFI */
249 frame->msg_type = GSM_BAD_FRAME;
250 else
251 frame->msg_type = GSM_TCHF_FRAME;
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100252 frame->callref = callref;
253 msgb_put(msg, sizeof(struct gsm_data_frame) + 33);
254
255 return msg;
256}
257
258struct msgb *trau_decode_efr(uint32_t callref,
259 const struct decoded_trau_frame *tf)
260{
261 struct msgb *msg;
262 struct gsm_data_frame *frame;
263 unsigned char *data;
264 int i, j, rc;
265 ubit_t check_bits[26];
266
267 msg = msgb_alloc(sizeof(struct gsm_data_frame) + 31,
268 "GSM-DATA");
269 if (!msg)
270 return NULL;
271
272 frame = (struct gsm_data_frame *)msg->data;
273 memset(frame, 0, sizeof(struct gsm_data_frame));
274 frame->msg_type = GSM_TCHF_FRAME_EFR;
275 frame->callref = callref;
276 msgb_put(msg, sizeof(struct gsm_data_frame) + 31);
277
278 if (tf->c_bits[11]) /* BFI */
279 goto bad_frame;
280
281 data = frame->data;
282 data[0] = 0xc << 4;
283 /* reassemble d-bits */
284 for (i = 1, j = 4; i < 39; i++, j++)
285 data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
286 efr_parity_bits_1(check_bits, tf->d_bits);
287 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 26,
288 tf->d_bits + 39);
289 if (rc)
290 goto bad_frame;
291 for (i = 42, j = 42; i < 95; i++, j++)
292 data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
293 efr_parity_bits_2(check_bits, tf->d_bits);
294 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
295 tf->d_bits + 95);
296 if (rc)
297 goto bad_frame;
298 for (i = 98, j = 95; i < 148; i++, j++)
299 data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
300 efr_parity_bits_3(check_bits, tf->d_bits);
301 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
302 tf->d_bits + 148);
303 if (rc)
304 goto bad_frame;
305 for (i = 151, j = 145; i < 204; i++, j++)
306 data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
307 efr_parity_bits_4(check_bits, tf->d_bits);
308 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
309 tf->d_bits + 204);
310 if (rc)
311 goto bad_frame;
312 for (i = 207, j = 198; i < 257; i++, j++)
313 data[j/8] |= (tf->d_bits[i] << (7-(j%8)));
314 efr_parity_bits_5(check_bits, tf->d_bits);
315 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
316 tf->d_bits + 257);
317 if (rc)
318 goto bad_frame;
319
320 return msg;
321
322bad_frame:
Andreas Eversbergeca41452014-01-31 09:02:01 +0100323 frame->msg_type = GSM_BAD_FRAME;
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100324
325 return msg;
326}
Harald Welte3971ad52009-12-19 22:23:05 +0100327
Harald Welte59b04682009-06-10 05:40:52 +0800328/* we get called by subchan_demux */
329int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200330 const uint8_t *trau_bits, int num_bits)
Harald Welte59b04682009-06-10 05:40:52 +0800331{
332 struct decoded_trau_frame tf;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200333 uint8_t trau_bits_out[TRAU_FRAME_BITS];
Harald Welte59b04682009-06-10 05:40:52 +0800334 struct gsm_e1_subslot *dst_e1_ss = lookup_trau_mux_map(src_e1_ss);
335 struct subch_mux *mx;
Harald Welte03740842009-06-10 23:11:52 +0800336 struct upqueue_entry *ue;
Harald Welte59b04682009-06-10 05:40:52 +0800337 int rc;
338
339 /* decode TRAU, change it to downlink, re-encode */
340 rc = decode_trau_frame(&tf, trau_bits);
341 if (rc)
342 return rc;
343
Harald Welte03740842009-06-10 23:11:52 +0800344 if (!dst_e1_ss) {
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100345 struct msgb *msg = NULL;
Harald Welte03740842009-06-10 23:11:52 +0800346 /* frame shall be sent to upqueue */
347 if (!(ue = lookup_trau_upqueue(src_e1_ss)))
348 return -EINVAL;
349 if (!ue->callref)
350 return -EINVAL;
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100351 if (!memcmp(tf.c_bits, c_bits_check_fr, 5))
352 msg = trau_decode_fr(ue->callref, &tf);
353 else if (!memcmp(tf.c_bits, c_bits_check_efr, 5))
354 msg = trau_decode_efr(ue->callref, &tf);
355 else {
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +0200356 DEBUGPC(DLMUX, "illegal trau (C1-C5) %s\n",
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100357 osmo_hexdump(tf.c_bits, 5));
358 DEBUGPC(DLMUX, "test trau (C1-C5) %s\n",
359 osmo_hexdump(c_bits_check_efr, 5));
360 return -EINVAL;
361 }
Harald Welte03740842009-06-10 23:11:52 +0800362 if (!msg)
363 return -ENOMEM;
Harald Welte4f272cc2011-03-03 23:29:05 +0100364 trau_tx_to_mncc(ue->net, msg);
Harald Welte03740842009-06-10 23:11:52 +0800365
366 return 0;
367 }
Harald Welte59b04682009-06-10 05:40:52 +0800368
369 mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
370 if (!mx)
371 return -EINVAL;
372
373 trau_frame_up2down(&tf);
374 encode_trau_frame(trau_bits_out, &tf);
375
376 /* and send it to the muxer */
377 return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
378 TRAU_FRAME_BITS);
379}
380
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +0200381/* callback when a TRAU frame was received */
382int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len,
383 void *_priv)
384{
385 struct e1inp_ts *e1i_ts = _priv;
386 struct gsm_e1_subslot src_ss;
387
388 src_ss.e1_nr = e1i_ts->line->num;
389 src_ss.e1_ts = e1i_ts->num;
390 src_ss.e1_ts_ss = ch;
391
392 return trau_mux_input(&src_ss, data, len);
393}
394
Harald Welte59b04682009-06-10 05:40:52 +0800395/* add receiver instance for lchan and callref */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200396int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref)
Harald Welte59b04682009-06-10 05:40:52 +0800397{
398 struct gsm_e1_subslot *src_ss;
Harald Weltea8379772009-06-20 22:36:41 +0200399 struct upqueue_entry *ue;
Harald Welte59b04682009-06-10 05:40:52 +0800400
Harald Weltea8379772009-06-20 22:36:41 +0200401 ue = talloc(tall_upq_ctx, struct upqueue_entry);
Harald Welte59b04682009-06-10 05:40:52 +0800402 if (!ue)
403 return -ENOMEM;
404
405 src_ss = &lchan->ts->e1_link;
406
407 DEBUGP(DCC, "Setting up TRAU receiver (e1=%u,ts=%u,ss=%u) "
408 "and (callref 0x%x)\n",
409 src_ss->e1_nr, src_ss->e1_ts, src_ss->e1_ts_ss,
410 callref);
411
412 /* make sure to get rid of any stale old mappings */
413 trau_mux_unmap(src_ss, callref);
414
415 memcpy(&ue->src, src_ss, sizeof(ue->src));
416 ue->net = lchan->ts->trx->bts->network;
417 ue->callref = callref;
418 llist_add(&ue->list, &ss_upqueue);
419
420 return 0;
421}
422
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100423void trau_encode_fr(struct decoded_trau_frame *tf,
424 const unsigned char *data)
425{
426 int i, j, k, l, o;
427
428 /* set c-bits and t-bits */
429 tf->c_bits[0] = 1;
430 tf->c_bits[1] = 1;
431 tf->c_bits[2] = 1;
432 tf->c_bits[3] = 0;
433 tf->c_bits[4] = 0;
434 memset(&tf->c_bits[5], 0, 6);
435 memset(&tf->c_bits[11], 1, 10);
436 memset(&tf->t_bits[0], 1, 4);
437 /* reassemble d-bits */
438 i = 0; /* counts bits */
439 j = 4; /* counts input bits */
440 k = gsm_fr_map[0]-1; /* current number bit in element */
441 l = 0; /* counts element bits */
442 o = 0; /* offset output bits */
443 while (i < 260) {
444 tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
Harald Welteb0f19282014-06-23 09:48:07 +0200445 /* to avoid out-of-bounds access in gsm_fr_map[++l] */
446 if (i == 259)
447 break;
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100448 if (--k < 0) {
449 o += gsm_fr_map[l];
450 k = gsm_fr_map[++l]-1;
451 }
452 i++;
453 j++;
454 }
455}
456
457void trau_encode_efr(struct decoded_trau_frame *tf,
458 const unsigned char *data)
459{
460 int i, j;
461 ubit_t check_bits[26];
462
463 /* set c-bits and t-bits */
464 tf->c_bits[0] = 1;
465 tf->c_bits[1] = 1;
466 tf->c_bits[2] = 0;
467 tf->c_bits[3] = 1;
468 tf->c_bits[4] = 0;
469 memset(&tf->c_bits[5], 0, 6);
470 memset(&tf->c_bits[11], 1, 10);
471 memset(&tf->t_bits[0], 1, 4);
472 /* reassemble d-bits */
473 tf->d_bits[0] = 1;
474 for (i = 1, j = 4; i < 39; i++, j++)
475 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
476 efr_parity_bits_1(check_bits, tf->d_bits);
477 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 26,
478 tf->d_bits + 39);
479 for (i = 42, j = 42; i < 95; i++, j++)
480 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
481 efr_parity_bits_2(check_bits, tf->d_bits);
482 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
483 tf->d_bits + 95);
484 for (i = 98, j = 95; i < 148; i++, j++)
485 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
486 efr_parity_bits_3(check_bits, tf->d_bits);
487 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
488 tf->d_bits + 148);
489 for (i = 151, j = 145; i < 204; i++, j++)
490 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
491 efr_parity_bits_4(check_bits, tf->d_bits);
492 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
493 tf->d_bits + 204);
494 for (i = 207, j = 198; i < 257; i++, j++)
495 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
496 efr_parity_bits_5(check_bits, tf->d_bits);
497 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
498 tf->d_bits + 257);
499}
500
Harald Welte3971ad52009-12-19 22:23:05 +0100501int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
Harald Welte59b04682009-06-10 05:40:52 +0800502{
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200503 uint8_t trau_bits_out[TRAU_FRAME_BITS];
Harald Welte59b04682009-06-10 05:40:52 +0800504 struct gsm_e1_subslot *dst_e1_ss = &lchan->ts->e1_link;
505 struct subch_mux *mx;
Harald Welte3971ad52009-12-19 22:23:05 +0100506 struct decoded_trau_frame tf;
Harald Welte59b04682009-06-10 05:40:52 +0800507
508 mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
509 if (!mx)
510 return -EINVAL;
511
Harald Welte3971ad52009-12-19 22:23:05 +0100512 switch (frame->msg_type) {
513 case GSM_TCHF_FRAME:
Andreas Eversberg2c202cd2013-12-06 16:59:10 +0100514 trau_encode_fr(&tf, frame->data);
515 break;
516 case GSM_TCHF_FRAME_EFR:
517 trau_encode_efr(&tf, frame->data);
Harald Welte3971ad52009-12-19 22:23:05 +0100518 break;
519 default:
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +0200520 DEBUGPC(DLMUX, "unsupported message type %d\n",
Harald Welte3971ad52009-12-19 22:23:05 +0100521 frame->msg_type);
522 return -EINVAL;
523 }
524
525 encode_trau_frame(trau_bits_out, &tf);
Harald Welte59b04682009-06-10 05:40:52 +0800526
527 /* and send it to the muxer */
528 return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
529 TRAU_FRAME_BITS);
530}
Andreas Eversberg02063672013-12-05 14:37:11 +0100531
532/* switch trau muxer to new lchan */
533int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan)
534{
535 struct gsm_network *net = old_lchan->ts->trx->bts->network;
536 struct gsm_trans *trans;
537
538 /* look up transaction with TCH frame receive enabled */
539 llist_for_each_entry(trans, &net->trans_list, entry) {
540 if (trans->conn && trans->conn->lchan == old_lchan && trans->tch_recv) {
541 /* switch */
542 trau_recv_lchan(new_lchan, trans->callref);
543 }
544 }
545
546 return 0;
547}