1 /* Synchronous part of GSM Layer 1: API to Layer2+ */
3 /* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <byteorder.h>
32 #include <osmocore/msgb.h>
33 #include <osmocore/protocol/gsm_04_08.h>
34 #include <comm/sercomm.h>
36 #include <layer1/sync.h>
37 #include <layer1/async.h>
38 #include <layer1/mframe_sched.h>
39 #include <layer1/prim.h>
40 #include <layer1/tpu_window.h>
42 #include <abb/twl3025.h>
43 #include <rf/trf6151.h>
45 #include <l1ctl_proto.h>
47 /* the size we will allocate struct msgb* for HDLC */
49 #define L3_MSG_SIZE (sizeof(struct l1ctl_hdr)+sizeof(struct l1ctl_info_dl)+sizeof(struct l1ctl_data_ind) + L3_MSG_HEAD)
51 void l1_queue_for_l2(struct msgb *msg)
53 /* forward via serial for now */
54 sercomm_sendmsg(SC_DLCI_L1A_L23, msg);
57 static enum mframe_task chan_nr2mf_task(uint8_t chan_nr)
59 uint8_t cbits = chan_nr >> 3;
60 uint8_t tn = chan_nr & 0x7;
65 return (tn & 1) ? MF_TASK_TCH_F_ODD : MF_TASK_TCH_F_EVEN;
66 } else if ((cbits & 0x1e) == 0x02) {
67 lch_idx = cbits & 0x1;
68 return MF_TASK_TCH_H_0 + lch_idx;
69 } else if ((cbits & 0x1c) == 0x04) {
70 lch_idx = cbits & 0x3;
71 return MF_TASK_SDCCH4_0 + lch_idx;
72 } else if ((cbits & 0x18) == 0x08) {
73 lch_idx = cbits & 0x7;
74 return MF_TASK_SDCCH8_0 + lch_idx;
76 } else if (cbits == 0x10) {
77 /* FIXME: when to do extended BCCH? */
78 return MF_TASK_BCCH_NORM;
79 } else if (cbits == 0x11 || cbits == 0x12) {
80 /* FIXME: how to decide CCCH norm/extd? */
81 return MF_TASK_BCCH_CCCH;
87 static int chan_nr2dchan_type(uint8_t chan_nr)
89 uint8_t cbits = chan_nr >> 3;
92 return GSM_DCHAN_TCH_F;
93 } else if ((cbits & 0x1e) == 0x02) {
94 return GSM_DCHAN_TCH_H;
95 } else if ((cbits & 0x1c) == 0x04) {
96 return GSM_DCHAN_SDCCH_4;
97 } else if ((cbits & 0x18) == 0x08) {
98 return GSM_DCHAN_SDCCH_8;
100 return GSM_DCHAN_UNKNOWN;
103 static int chan_nr_is_tch(uint8_t chan_nr)
105 return ((chan_nr >> 3) == 0x01 || /* TCH/F */
106 ((chan_nr >> 3) & 0x1e) == 0x02); /* TCH/H */
109 static void audio_set_enabled(int enabled)
111 twl3025_unit_enable(TWL3025_UNIT_VUL, enabled);
112 twl3025_unit_enable(TWL3025_UNIT_VDL, enabled);
115 struct msgb *l1ctl_msgb_alloc(uint8_t msg_type)
118 struct l1ctl_hdr *l1h;
120 msg = msgb_alloc_headroom(L3_MSG_SIZE, L3_MSG_HEAD, "l1ctl");
123 puts("OOPS. Out of buffers...\n");
128 l1h = (struct l1ctl_hdr *) msgb_put(msg, sizeof(*l1h));
129 l1h->msg_type = msg_type;
132 msg->l1h = (uint8_t *)l1h;
137 struct msgb *l1_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr,
140 struct l1ctl_info_dl *dl;
141 struct msgb *msg = l1ctl_msgb_alloc(msg_type);
143 dl = (struct l1ctl_info_dl *) msgb_put(msg, sizeof(*dl));
144 dl->frame_nr = htonl(fn);
146 dl->band_arfcn = htons(arfcn);
151 /* receive a L1CTL_FBSB_REQ from L23 */
152 static void l1ctl_rx_fbsb_req(struct msgb *msg)
154 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
155 struct l1ctl_fbsb_req *sync_req = (struct l1ctl_fbsb_req *) l1h->data;
157 if (sizeof(*sync_req) > msg->len) {
158 printf("Short sync msg. %u\n", msg->len);
162 printd("L1CTL_FBSB_REQ (arfcn=%u, flags=0x%x)\n",
163 ntohs(sync_req->band_arfcn), sync_req->flags);
165 /* reset scheduler and hardware */
168 /* pre-set the CCCH mode */
169 l1s.serving_cell.ccch_mode = sync_req->ccch_mode;
171 printd("Starting FCCH Recognition\n");
172 l1s_fbsb_req(1, sync_req);
175 /* receive a L1CTL_DM_EST_REQ from L23 */
176 static void l1ctl_rx_dm_est_req(struct msgb *msg)
178 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
179 struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
180 struct l1ctl_dm_est_req *est_req = (struct l1ctl_dm_est_req *) ul->payload;
182 printd("L1CTL_DM_EST_REQ (arfcn=%u, chan_nr=0x%02x, tsc=%u)\n",
183 ntohs(est_req->h0.band_arfcn), ul->chan_nr, est_req->tsc);
185 /* configure dedicated channel state */
186 l1s.dedicated.type = chan_nr2dchan_type(ul->chan_nr);
187 l1s.dedicated.tsc = est_req->tsc;
188 l1s.dedicated.tn = ul->chan_nr & 0x7;
189 l1s.dedicated.h = est_req->h;
193 l1s.dedicated.h1.hsn = est_req->h1.hsn;
194 l1s.dedicated.h1.maio = est_req->h1.maio;
195 l1s.dedicated.h1.n = est_req->h1.n;
196 for (i=0; i<est_req->h1.n; i++)
197 l1s.dedicated.h1.ma[i] = ntohs(est_req->h1.ma[i]);
199 l1s.dedicated.h0.arfcn = ntohs(est_req->h0.band_arfcn);
203 if (chan_nr_is_tch(ul->chan_nr)) {
205 l1a_tch_mode_set(est_req->tch_mode);
208 l1s.tch_sync = 1; /* can be set without locking */
211 audio_set_enabled(est_req->tch_mode != GSM48_CMODE_SIGN);
214 /* figure out which MF tasks to enable */
215 l1a_mftask_set(1 << chan_nr2mf_task(ul->chan_nr));
218 /* receive a L1CTL_DM_FREQ_REQ from L23 */
219 static void l1ctl_rx_dm_freq_req(struct msgb *msg)
221 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
222 struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
223 struct l1ctl_dm_freq_req *freq_req =
224 (struct l1ctl_dm_freq_req *) ul->payload;
226 printd("L1CTL_DM_FREQ_REQ (arfcn=%u, tsc=%u)\n",
227 ntohs(freq_req->h0.band_arfcn), freq_req->tsc);
229 /* configure dedicated channel state */
230 l1s.dedicated.st_tsc = freq_req->tsc;
231 l1s.dedicated.st_h = freq_req->h;
235 l1s.dedicated.st_h1.hsn = freq_req->h1.hsn;
236 l1s.dedicated.st_h1.maio = freq_req->h1.maio;
237 l1s.dedicated.st_h1.n = freq_req->h1.n;
238 for (i=0; i<freq_req->h1.n; i++)
239 l1s.dedicated.st_h1.ma[i] = ntohs(freq_req->h1.ma[i]);
241 l1s.dedicated.st_h0.arfcn = ntohs(freq_req->h0.band_arfcn);
244 l1a_freq_req(ntohs(freq_req->fn));
247 /* receive a L1CTL_CRYPTO_REQ from L23 */
248 static void l1ctl_rx_crypto_req(struct msgb *msg)
250 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
251 struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
252 struct l1ctl_crypto_req *cr = (struct l1ctl_crypto_req *) ul->payload;
253 uint8_t key_len = msg->len - sizeof(*l1h) - sizeof(*ul) - sizeof(*cr);
255 printd("L1CTL_CRYPTO_REQ (algo=A5/%u, len=%u)\n", cr->algo, key_len);
257 if (cr->algo && key_len != 8) {
258 printd("L1CTL_CRYPTO_REQ -> Invalid key\n");
262 dsp_load_ciph_param(cr->algo, cr->key);
265 /* receive a L1CTL_DM_REL_REQ from L23 */
266 static void l1ctl_rx_dm_rel_req(struct msgb *msg)
268 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
269 struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
271 printd("L1CTL_DM_REL_REQ\n");
273 l1s.dedicated.type = GSM_DCHAN_NONE;
274 l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_MAIN]);
275 l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_SACCH]);
276 l1a_meas_msgb_set(NULL);
277 dsp_load_ciph_param(0, NULL);
278 l1a_tch_mode_set(GSM48_CMODE_SIGN);
279 audio_set_enabled(0);
282 /* receive a L1CTL_PARAM_REQ from L23 */
283 static void l1ctl_rx_param_req(struct msgb *msg)
285 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
286 struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
287 struct l1ctl_par_req *par_req = (struct l1ctl_par_req *) ul->payload;
289 printd("L1CTL_PARAM_REQ (ta=%d, tx_power=%d)\n", par_req->ta,
292 l1s.ta = par_req->ta;
293 l1s.tx_power = par_req->tx_power;
296 /* receive a L1CTL_RACH_REQ from L23 */
297 static void l1ctl_rx_rach_req(struct msgb *msg)
299 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
300 struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
301 struct l1ctl_rach_req *rach_req = (struct l1ctl_rach_req *) ul->payload;
303 printd("L1CTL_RACH_REQ (ra=0x%02x, offset=%d combined=%d)\n",
304 rach_req->ra, ntohs(rach_req->offset), rach_req->combined);
306 l1a_rach_req(ntohs(rach_req->offset), rach_req->combined,
310 /* receive a L1CTL_DATA_REQ from L23 */
311 static void l1ctl_rx_data_req(struct msgb *msg)
313 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
314 struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
315 struct l1ctl_data_ind *data_ind = (struct l1ctl_data_ind *) ul->payload;
316 struct llist_head *tx_queue;
318 printd("L1CTL_DATA_REQ (link_id=0x%02x)\n", ul->link_id);
320 msg->l3h = data_ind->data;
321 if (ul->link_id & 0x40) {
322 struct gsm48_hdr *gh = (struct gsm48_hdr *)(data_ind->data + 5);
323 if (gh->proto_discr == GSM48_PDISC_RR
324 && gh->msg_type == GSM48_MT_RR_MEAS_REP) {
325 printd("updating measurement report\n");
326 l1a_meas_msgb_set(msg);
329 tx_queue = &l1s.tx_queue[L1S_CHAN_SACCH];
331 tx_queue = &l1s.tx_queue[L1S_CHAN_MAIN];
333 printd("ul=%p, ul->payload=%p, data_ind=%p, data_ind->data=%p l3h=%p\n",
334 ul, ul->payload, data_ind, data_ind->data, msg->l3h);
336 l1a_txq_msgb_enq(tx_queue, msg);
339 /* receive a L1CTL_PM_REQ from L23 */
340 static void l1ctl_rx_pm_req(struct msgb *msg)
342 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
343 struct l1ctl_pm_req *pm_req = (struct l1ctl_pm_req *) l1h->data;
345 switch (pm_req->type) {
348 l1s.pm.range.arfcn_start =
349 ntohs(pm_req->range.band_arfcn_from);
350 l1s.pm.range.arfcn_next =
351 ntohs(pm_req->range.band_arfcn_from);
352 l1s.pm.range.arfcn_end =
353 ntohs(pm_req->range.band_arfcn_to);
354 printf("L1CTL_PM_REQ start=%u end=%u\n",
355 l1s.pm.range.arfcn_start, l1s.pm.range.arfcn_end);
359 l1s_pm_test(1, l1s.pm.range.arfcn_next);
362 /* Transmit a L1CTL_RESET_IND or L1CTL_RESET_CONF */
363 void l1ctl_tx_reset(uint8_t msg_type, uint8_t reset_type)
365 struct msgb *msg = l1ctl_msgb_alloc(msg_type);
366 struct l1ctl_reset *reset_resp;
367 reset_resp = (struct l1ctl_reset *)
368 msgb_put(msg, sizeof(*reset_resp));
369 reset_resp->type = reset_type;
371 l1_queue_for_l2(msg);
374 /* receive a L1CTL_RESET_REQ from L23 */
375 static void l1ctl_rx_reset_req(struct msgb *msg)
377 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
378 struct l1ctl_reset *reset_req =
379 (struct l1ctl_reset *) l1h->data;
381 switch (reset_req->type) {
382 case L1CTL_RES_T_FULL:
383 printf("L1CTL_RESET_REQ: FULL!\n");
386 audio_set_enabled(0);
387 l1ctl_tx_reset(L1CTL_RESET_CONF, reset_req->type);
389 case L1CTL_RES_T_SCHED:
390 printf("L1CTL_RESET_REQ: SCHED!\n");
391 l1ctl_tx_reset(L1CTL_RESET_CONF, reset_req->type);
392 sched_gsmtime_reset();
395 printf("unknown L1CTL_RESET_REQ type\n");
400 /* Transmit a L1CTL_CCCH_MODE_CONF */
401 static void l1ctl_tx_ccch_mode_conf(uint8_t ccch_mode)
403 struct msgb *msg = l1ctl_msgb_alloc(L1CTL_CCCH_MODE_CONF);
404 struct l1ctl_ccch_mode_conf *mode_conf;
405 mode_conf = (struct l1ctl_ccch_mode_conf *)
406 msgb_put(msg, sizeof(*mode_conf));
407 mode_conf->ccch_mode = ccch_mode;
409 l1_queue_for_l2(msg);
412 /* receive a L1CTL_CCCH_MODE_REQ from L23 */
413 static void l1ctl_rx_ccch_mode_req(struct msgb *msg)
415 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
416 struct l1ctl_ccch_mode_req *ccch_mode_req =
417 (struct l1ctl_ccch_mode_req *) l1h->data;
418 uint8_t ccch_mode = ccch_mode_req->ccch_mode;
420 /* pre-set the CCCH mode */
421 l1s.serving_cell.ccch_mode = ccch_mode;
424 mframe_disable(MF_TASK_CCCH_COMB);
425 mframe_disable(MF_TASK_CCCH);
427 if (ccch_mode == CCCH_MODE_COMBINED)
428 mframe_enable(MF_TASK_CCCH_COMB);
429 else if (ccch_mode == CCCH_MODE_NON_COMBINED)
430 mframe_enable(MF_TASK_CCCH);
432 l1ctl_tx_ccch_mode_conf(ccch_mode);
435 /* Transmit a L1CTL_TCH_MODE_CONF */
436 static void l1ctl_tx_tch_mode_conf(uint8_t tch_mode)
438 struct msgb *msg = l1ctl_msgb_alloc(L1CTL_TCH_MODE_CONF);
439 struct l1ctl_tch_mode_conf *mode_conf;
440 mode_conf = (struct l1ctl_tch_mode_conf *)
441 msgb_put(msg, sizeof(*mode_conf));
442 mode_conf->tch_mode = tch_mode;
444 l1_queue_for_l2(msg);
447 /* receive a L1CTL_TCH_MODE_REQ from L23 */
448 static void l1ctl_rx_tch_mode_req(struct msgb *msg)
450 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
451 struct l1ctl_tch_mode_req *tch_mode_req =
452 (struct l1ctl_tch_mode_req *) l1h->data;
453 uint8_t tch_mode = tch_mode_req->tch_mode;
455 printd("L1CTL_TCH_MODE_REQ (mode=0x%02x)\n", tch_mode);
456 tch_mode = l1a_tch_mode_set(tch_mode);
458 audio_set_enabled(tch_mode != GSM48_CMODE_SIGN);
460 l1s.tch_sync = 1; /* Needed for audio to work */
462 l1ctl_tx_tch_mode_conf(tch_mode);
465 #include <calypso/sim.h>
467 void sim_apdu(uint16_t len, uint8_t *data);
469 static void l1ctl_sim_req(struct msgb *msg)
471 uint16_t len = msg->len - sizeof(struct l1ctl_hdr);
472 uint8_t *data = msg->data + sizeof(struct l1ctl_hdr);
474 #if 1 /* for debugging only */
477 printf("SIM Request (%u): ", len);
478 for (i = 0; i < len; i++)
479 printf("%02x ", data[i]);
487 /* callback from SERCOMM when L2 sends a message to L1 */
488 static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
490 struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
495 printf("l1a_l23_rx_cb (%u): ", msg->len);
496 for (i = 0; i < msg->len; i++)
497 printf("%02x ", msg->data[i]);
502 msg->l1h = msg->data;
504 if (sizeof(*l1h) > msg->len) {
505 printf("l1a_l23_cb: Short message. %u\n", msg->len);
509 switch (l1h->msg_type) {
511 l1ctl_rx_fbsb_req(msg);
513 case L1CTL_DM_EST_REQ:
514 l1ctl_rx_dm_est_req(msg);
516 case L1CTL_DM_REL_REQ:
517 l1ctl_rx_dm_rel_req(msg);
519 case L1CTL_PARAM_REQ:
520 l1ctl_rx_param_req(msg);
522 case L1CTL_DM_FREQ_REQ:
523 l1ctl_rx_dm_freq_req(msg);
525 case L1CTL_CRYPTO_REQ:
526 l1ctl_rx_crypto_req(msg);
529 l1ctl_rx_rach_req(msg);
532 l1ctl_rx_data_req(msg);
533 /* we have to keep the msgb, not free it! */
536 l1ctl_rx_pm_req(msg);
538 case L1CTL_RESET_REQ:
539 l1ctl_rx_reset_req(msg);
541 case L1CTL_CCCH_MODE_REQ:
542 l1ctl_rx_ccch_mode_req(msg);
544 case L1CTL_TCH_MODE_REQ:
545 l1ctl_rx_tch_mode_req(msg);
558 void l1a_l23api_init(void)
560 sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb);