1 /* Cell Scanning code for OsmocomBB */
3 /* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
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 <l1ctl_proto.h>
32 #include <osmocore/logging.h>
33 #include <osmocore/timer.h>
34 #include <osmocore/signal.h>
35 #include <osmocore/msgb.h>
36 #include <osmocore/gsm_utils.h>
37 #include <osmocore/protocol/gsm_04_08.h>
38 #include <osmocore/rsl.h>
40 #include <osmocom/bb/common/l1ctl.h>
41 #include <osmocom/bb/common/osmocom_data.h>
42 #include <osmocom/bb/common/lapdm.h>
43 #include <osmocom/bb/common/logging.h>
44 #include <osmocom/bb/common/networks.h>
45 #include <osmocom/bb/common/gps.h>
46 #include <osmocom/bb/misc/cell_log.h>
47 #include "../../../gsmmap/geo.h"
49 #define READ_WAIT 2, 0
50 #define RACH_WAIT 0, 900000
51 #define MIN_RXLEV -106
62 static uint16_t band_range[][2] = {{0, 124}, {512, 885}, {955, 1023}, {0, 0}};
65 #define INFO_FLG_SYNC 2
66 #define INFO_FLG_SI1 4
67 #define INFO_FLG_SI2 8
68 #define INFO_FLG_SI2bis 16
69 #define INFO_FLG_SI2ter 32
70 #define INFO_FLG_SI3 64
71 #define INFO_FLG_SI4 128
73 static struct osmocom_ms *ms;
74 static struct timer_list timer;
76 static struct pm_info {
81 static int started = 0;
83 static int8_t min_rxlev = MIN_RXLEV;
84 static int sync_count;
85 static int pm_index, pm_gps_valid;
86 static double pm_gps_x, pm_gps_y, pm_gps_z;
88 static int rach_count;
89 static FILE *logfp = NULL;
94 static struct gsm48_sysinfo sysinfo;
96 static struct log_si {
100 uint16_t mcc, mnc, lac, cellid;
102 double latitude, longitude;
111 #define LOGFILE(fmt, args...) \
112 fprintf(logfp, fmt, ## args);
116 static void start_sync(void);
117 static void start_rach(void);
118 static void start_pm(void);
120 static void log_gps(void)
122 if (!gps.enable || !gps.valid)
124 LOGFILE("position %.8f %.8f\n", gps.longitude, gps.latitude);
127 static void log_time(void)
131 if (gps.enable && gps.valid)
135 LOGFILE("time %lu\n", now);
138 static void log_frame(char *tag, uint8_t *data)
143 for (i = 0; i < 23; i++)
144 LOGFILE(" %02x", *data++);
148 static void log_pm(void)
152 LOGFILE("[power]\n");
155 for (i = 0; i <= 1023; i++) {
156 if ((pm[i].flags & INFO_FLG_PM)) {
158 LOGFILE("arfcn %d", i);
159 LOGFILE(" %d", pm[i].rxlev);
179 static void log_sysinfo(void)
181 struct rx_meas_stat *meas = &ms->meas;
182 struct gsm48_sysinfo *s = &sysinfo;
184 char ta_str[32] = "";
186 if (log_si.ta != 0xff)
187 sprintf(ta_str, " TA=%d", log_si.ta);
189 LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC=%s MNC=%s (%s, %s)%s\n",
190 arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
191 gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);
193 LOGFILE("[sysinfo]\n");
194 LOGFILE("arfcn %d\n", s->arfcn);
197 LOGFILE("bsic %d,%d\n", s->bsic >> 3, s->bsic & 7);
198 rxlev = meas->rxlev / meas->frames - 110;
199 LOGFILE("rxlev %d\n", rxlev);
201 log_frame("si1", s->si1_msg);
203 log_frame("si2", s->si2_msg);
205 log_frame("si2bis", s->si2b_msg);
207 log_frame("si2ter", s->si2t_msg);
209 log_frame("si3", s->si3_msg);
211 log_frame("si4", s->si4_msg);
212 if (log_si.ta != 0xff)
213 LOGFILE("ta %d\n", log_si.ta);
219 static void timeout_cb(void *arg)
222 case SCAN_STATE_READ:
223 LOGP(DRR, LOGL_INFO, "Timeout reading BCCH\n");
226 case SCAN_STATE_RACH:
227 LOGP(DRR, LOGL_INFO, "Timeout on RACH\n");
234 static void stop_timer(void)
236 if (bsc_timer_pending(&timer))
237 bsc_del_timer(&timer);
240 static void start_timer(int sec, int micro)
243 timer.cb = timeout_cb;
245 bsc_schedule_timer(&timer, sec, micro);
248 static void start_rach(void)
250 struct gsm48_sysinfo *s = &sysinfo;
251 uint8_t chan_req_val, chan_req_mask;
253 struct abis_rsl_cchan_hdr *ncch;
255 if (rach_count == RACH_MAX) {
261 state = SCAN_STATE_RACH;
264 chan_req_mask = 0x0f;
266 LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x "
267 "(OTHER with NECI)\n", chan_req_val);
269 chan_req_mask = 0x1f;
271 LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x (OTHER no NECI)\n",
276 rach_ref.cr = random();
277 rach_ref.cr &= chan_req_mask;
278 rach_ref.cr |= chan_req_val;
280 nmsg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM,
281 RSL_ALLOC_HEADROOM, "GSM 04.06 RSL");
284 nmsg->l2h = nmsg->data;
285 ncch = (struct abis_rsl_cchan_hdr *) msgb_put(nmsg, sizeof(*ncch)
287 rsl_init_cchan_hdr(ncch, RSL_MT_CHAN_RQD);
288 ncch->chan_nr = RSL_CHAN_RACH;
289 ncch->data[0] = RSL_IE_REQ_REFERENCE;
290 ncch->data[1] = rach_ref.cr;
291 ncch->data[2] = (s->ccch_conf == 1) << 7;
293 ncch->data[4] = RSL_IE_ACCESS_DELAY;
294 ncch->data[5] = 0; /* no delay */
295 ncch->data[6] = RSL_IE_MS_POWER;
296 ncch->data[7] = 0; /* full power */
298 start_timer(RACH_WAIT);
300 rslms_recvmsg(nmsg, ms);
303 static void start_sync(void)
307 char dist_str[32] = "";
310 for (i = 0; i <= 1023; i++) {
311 if ((pm[i].flags & INFO_FLG_PM)
312 && !(pm[i].flags & INFO_FLG_SYNC)) {
313 if (pm[i].rxlev > rxlev) {
319 /* if GPS becomes valid, like after exitting a tunnel */
320 if (!pm_gps_valid && gps.valid) {
322 geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z, gps.longitude,
325 if (pm_gps_valid && gps.valid) {
328 geo2space(&x, &y, &z, gps.longitude, gps.latitude);
329 dist = distinspace(pm_gps_x, pm_gps_y, pm_gps_z, x, y, z);
330 sprintf(dist_str, " dist %d", (int)dist);
332 if (dist > MAX_DIST || arfcn == 0xffff || rxlev < min_rxlev) {
333 memset(pm, 0, sizeof(pm));
339 pm[arfcn].flags |= INFO_FLG_SYNC;
340 LOGP(DSUM, LOGL_INFO, "Sync ARFCN %d (rxlev %d, %d syncs "
341 "left)%s\n", arfcn, pm[arfcn].rxlev, sync_count--, dist_str);
342 memset(&sysinfo, 0, sizeof(sysinfo));
343 sysinfo.arfcn = arfcn;
344 state = SCAN_STATE_SYNC;
345 l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
346 l1ctl_tx_fbsb_req(ms, arfcn, L1CTL_FBSB_F_FB01SB, 100, 0,
350 static void start_pm(void)
354 state = SCAN_STATE_PM;
355 from = band_range[pm_index][0];
356 to = band_range[pm_index][1];
358 if (from == 0 && to == 0) {
359 LOGP(DSUM, LOGL_INFO, "Measurement done\n");
360 pm_gps_valid = gps.enable && gps.valid;
362 geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z,
363 gps.longitude, gps.latitude);
368 LOGP(DSUM, LOGL_INFO, "Measure from %d to %d\n", from, to);
369 l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
370 l1ctl_tx_pm_req_range(ms, from, to);
373 static int signal_cb(unsigned int subsys, unsigned int signal,
374 void *handler_data, void *signal_data)
376 struct osmobb_meas_res *mr;
377 struct osmobb_fbsb_res *fr;
380 if (subsys != SS_L1CTL)
386 index = mr->band_arfcn & 0x3ff;
387 pm[index].flags |= INFO_FLG_PM;
388 pm[index].rxlev = mr->rx_lev - 110;
389 if (pm[index].rxlev >= min_rxlev)
391 // printf("rxlev %d = %d (sync_count %d)\n", index, pm[index].rxlev, sync_count);
393 case S_L1CTL_PM_DONE:
397 case S_L1CTL_FBSB_RESP:
399 sysinfo.bsic = fr->bsic;
400 state = SCAN_STATE_READ;
401 memset(&ms->meas, 0, sizeof(ms->meas));
402 memset(&log_si, 0, sizeof(log_si));
403 log_si.flags |= INFO_FLG_SYNC;
404 log_si.ta = 0xff; /* invalid */
405 start_timer(READ_WAIT);
406 LOGP(DRR, LOGL_INFO, "Synchronized, start reading\n");
408 case S_L1CTL_FBSB_ERR:
409 LOGP(DRR, LOGL_INFO, "Sync failed\n");
416 memset(pm, 0, sizeof(pm));
424 static int ta_result(uint8_t ta)
429 LOGP(DSUM, LOGL_INFO, "Got assignment reject\n");
431 LOGP(DSUM, LOGL_DEBUG, "Got assignment TA = %d\n", ta);
441 /* match request reference agains request */
442 static int match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref)
444 uint8_t ia_t1, ia_t2, ia_t3;
446 /* filter confirmed RACH requests only */
447 if (rach_ref.valid && ref->ra == rach_ref.cr) {
450 ia_t3 = (ref->t3_high << 3) | ref->t3_low;
451 if (ia_t1 == rach_ref.t1 && ia_t2 == rach_ref.t2
452 && ia_t3 == rach_ref.t3) {
453 LOGP(DRR, LOGL_INFO, "request %02x matches "
454 "(fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2,
458 LOGP(DRR, LOGL_INFO, "request %02x matches but not "
459 "frame number (IMM.ASS fn=%d,%d,%d != RACH "
460 "fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2, ia_t3,
461 rach_ref.t1, rach_ref.t2, rach_ref.t3);
467 /* 9.1.18 IMMEDIATE ASSIGNMENT is received */
468 static int imm_ass(struct osmocom_ms *ms, struct msgb *msg)
470 struct gsm48_imm_ass *ia = msgb_l3(msg);
472 LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT:\n");
474 if (state != SCAN_STATE_RACH) {
475 LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
480 if (match_ra(ms, &ia->req_ref)) {
481 return ta_result(ia->timing_advance);
483 LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
488 /* 9.1.19 IMMEDIATE ASSIGNMENT EXTENDED is received */
489 static int imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
491 struct gsm48_imm_ass_ext *ia = msgb_l3(msg);
493 LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT EXTENDED:\n");
495 if (state != SCAN_STATE_RACH) {
496 LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
501 if (match_ra(ms, &ia->req_ref1)) {
502 return ta_result(ia->timing_advance1);
505 if (match_ra(ms, &ia->req_ref2)) {
506 return ta_result(ia->timing_advance2);
508 LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
513 /* 9.1.20 IMMEDIATE ASSIGNMENT REJECT is received */
514 static int imm_ass_rej(struct osmocom_ms *ms, struct msgb *msg)
516 struct gsm48_imm_ass_rej *ia = msgb_l3(msg);
518 struct gsm48_req_ref *req_ref;
520 LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT:\n");
522 if (state != SCAN_STATE_RACH) {
523 LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
527 for (i = 0; i < 4; i++) {
528 /* request reference */
529 req_ref = (struct gsm48_req_ref *)
530 (((uint8_t *)&ia->req_ref1) + i * 4);
531 LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT "
532 "(ref 0x%02x)\n", req_ref->ra);
533 if (match_ra(ms, req_ref)) {
534 return ta_result(0xff);
541 /* receive CCCH at RR layer */
542 static int pch_agch(struct osmocom_ms *ms, struct msgb *msg)
544 struct gsm48_system_information_type_header *sih = msgb_l3(msg);
546 switch (sih->system_information) {
547 case GSM48_MT_RR_PAG_REQ_1:
548 case GSM48_MT_RR_PAG_REQ_2:
549 case GSM48_MT_RR_PAG_REQ_3:
551 case GSM48_MT_RR_IMM_ASS:
552 return imm_ass(ms, msg);
553 case GSM48_MT_RR_IMM_ASS_EXT:
554 return imm_ass_ext(ms, msg);
555 case GSM48_MT_RR_IMM_ASS_REJ:
556 return imm_ass_rej(ms, msg);
562 /* check if sysinfo is complete, change to RACH state */
563 static int new_sysinfo(void)
565 struct gsm48_sysinfo *s = &sysinfo;
568 start_timer(READ_WAIT);
571 if (!s->si1 || !s->si2 || !s->si3 || !s->si4) {
572 LOGP(DRR, LOGL_INFO, "not all mandatory SI received\n");
577 if (s->nb_ext_ind_si2 && !s->si2bis) {
578 LOGP(DRR, LOGL_INFO, "extended ba, but si2bis not received\n");
583 if (s->si2ter_ind && !s->si2ter) {
584 LOGP(DRR, LOGL_INFO, "si2ter_ind, but si2ter not received\n");
588 LOGP(DRR, LOGL_INFO, "Sysinfo complete\n");
598 /* receive BCCH at RR layer */
599 static int bcch(struct osmocom_ms *ms, struct msgb *msg)
601 struct gsm48_sysinfo *s = &sysinfo;
602 struct gsm48_system_information_type_header *sih = msgb_l3(msg);
605 if (msgb_l3len(msg) != 23) {
606 LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n");
609 switch (sih->system_information) {
610 case GSM48_MT_RR_SYSINFO_1:
611 if (!memcmp(sih, s->si1_msg, sizeof(s->si1_msg)))
613 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n");
614 gsm48_decode_sysinfo1(s,
615 (struct gsm48_system_information_type_1 *) sih,
617 return new_sysinfo();
618 case GSM48_MT_RR_SYSINFO_2:
619 if (!memcmp(sih, s->si2_msg, sizeof(s->si2_msg)))
621 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2\n");
622 gsm48_decode_sysinfo2(s,
623 (struct gsm48_system_information_type_2 *) sih,
625 return new_sysinfo();
626 case GSM48_MT_RR_SYSINFO_2bis:
627 if (!memcmp(sih, s->si2b_msg, sizeof(s->si2b_msg)))
629 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2bis\n");
630 gsm48_decode_sysinfo2bis(s,
631 (struct gsm48_system_information_type_2bis *) sih,
633 return new_sysinfo();
634 case GSM48_MT_RR_SYSINFO_2ter:
635 if (!memcmp(sih, s->si2t_msg, sizeof(s->si2t_msg)))
637 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2ter\n");
638 gsm48_decode_sysinfo2ter(s,
639 (struct gsm48_system_information_type_2ter *) sih,
641 return new_sysinfo();
642 case GSM48_MT_RR_SYSINFO_3:
643 if (!memcmp(sih, s->si3_msg, sizeof(s->si3_msg)))
645 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 3\n");
646 gsm48_decode_sysinfo3(s,
647 (struct gsm48_system_information_type_3 *) sih,
649 ccch_mode = (s->ccch_conf == 1) ? CCCH_MODE_COMBINED :
650 CCCH_MODE_NON_COMBINED;
651 LOGP(DRR, LOGL_INFO, "Changing CCCH_MODE to %d\n", ccch_mode);
652 l1ctl_tx_ccch_mode_req(ms, ccch_mode);
653 return new_sysinfo();
654 case GSM48_MT_RR_SYSINFO_4:
655 if (!memcmp(sih, s->si4_msg, sizeof(s->si4_msg)))
657 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n");
658 gsm48_decode_sysinfo4(s,
659 (struct gsm48_system_information_type_4 *) sih,
661 return new_sysinfo();
667 static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
669 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
670 struct tlv_parsed tv;
671 uint8_t ch_type, ch_subch, ch_ts;
673 DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
674 rllh->chan_nr, rllh->link_id);
676 rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
677 if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
678 DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
681 msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
683 if (state != SCAN_STATE_READ && state != SCAN_STATE_RACH) {
687 rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
689 case RSL_CHAN_PCH_AGCH:
690 return pch_agch(ms, msg);
692 return bcch(ms, msg);
694 case RSL_CHAN_Bm_ACCHs:
695 case RSL_CHAN_Lm_ACCHs:
696 case RSL_CHAN_SDCCH4_ACCH:
697 case RSL_CHAN_SDCCH8_ACCH:
698 return rx_acch(ms, msg);
701 LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n",
707 static int rcv_rll(struct osmocom_ms *ms, struct msgb *msg)
709 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
710 int msg_type = rllh->c.msg_type;
712 if (msg_type == RSL_MT_UNIT_DATA_IND) {
713 unit_data_ind(ms, msg);
715 LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
722 int chan_conf(struct osmocom_ms *ms, struct msgb *msg)
724 struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
725 struct gsm48_req_ref *ref = (struct gsm48_req_ref *) (ch->data + 1);
727 if (msgb_l2len(msg) < sizeof(*ch) + sizeof(*ref)) {
728 LOGP(DRR, LOGL_ERROR, "CHAN_CNF too slort\n");
733 rach_ref.t1 = ref->t1;
734 rach_ref.t2 = ref->t2;
735 rach_ref.t3 = ref->t3_low | (ref->t3_high << 3);
740 static int rcv_cch(struct osmocom_ms *ms, struct msgb *msg)
742 struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
743 int msg_type = ch->c.msg_type;
746 LOGP(DRSL, LOGL_INFO, "Received '%s' from layer1\n",
747 get_rsl_name(msg_type));
749 if (state == SCAN_STATE_RACH && msg_type == RSL_MT_CHAN_CONF) {
750 rc = chan_conf(ms, msg);
755 LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
760 static int rcv_rsl(struct msgb *msg, struct osmocom_ms *ms)
762 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
765 switch (rslh->msg_discr & 0xfe) {
766 case ABIS_RSL_MDISC_RLL:
767 rc = rcv_rll(ms, msg);
769 case ABIS_RSL_MDISC_COM_CHAN:
770 rc = rcv_cch(ms, msg);
773 LOGP(DRSL, LOGL_NOTICE, "unknown RSLms msg_discr 0x%02x\n",
783 int scan_init(struct osmocom_ms *_ms)
786 register_signal_handler(SS_L1CTL, &signal_cb, NULL);
787 memset(&timer, 0, sizeof(timer));
788 osmol2_register_handler(ms, &rcv_rsl);
794 if (!strcmp(logname, "-"))
797 logfp = fopen(logname, "a");
799 fprintf(stderr, "Failed to open logfile '%s'\n", logname);
803 LOGP(DSUM, LOGL_INFO, "Scanner initialized\n");
810 LOGP(DSUM, LOGL_INFO, "Scanner exit\n");
815 unregister_signal_handler(SS_L1CTL, &signal_cb, NULL);