layer2: Make it possible to disable or increase the number of RA bursts
[osmocom-bb.git] / src / host / layer23 / src / misc / cell_log.c
1 /* Cell Scanning code for OsmocomBB */
2
3 /* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
4  *
5  * All Rights Reserved
6  *
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.
11  *
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.
16  *
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.
20  *
21  */
22
23 #include <stdio.h>
24 #include <stdint.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <errno.h>
29
30 #include <l1ctl_proto.h>
31
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>
39
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"
48
49 #define READ_WAIT       2, 0
50 #define RACH_WAIT       0, 900000
51 #define MIN_RXLEV       -106
52 #define MAX_DIST        2000
53
54 enum {
55         SCAN_STATE_PM,
56         SCAN_STATE_SYNC,
57         SCAN_STATE_READ,
58         SCAN_STATE_RACH,
59 };
60
61 /* ranges of bands */
62 static uint16_t band_range[][2] = {{0, 124}, {512, 885}, {955, 1023}, {0, 0}};
63
64 #define INFO_FLG_PM     1
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
72
73 static struct osmocom_ms *ms;
74 static struct timer_list timer;
75
76 static struct pm_info {
77         uint16_t flags;
78         int8_t rxlev;
79 } pm[1024];
80
81 static int started = 0;
82 static int state;
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;
87 static int arfcn;
88 static int rach_count;
89 static FILE *logfp = NULL;
90 extern char *logname;
91 extern int RACH_MAX;
92
93
94 static struct gsm48_sysinfo sysinfo;
95
96 static struct log_si {
97         uint16_t flags;
98         uint8_t bsic;
99         int8_t rxlev;
100         uint16_t mcc, mnc, lac, cellid;
101         uint8_t ta;
102         double latitude, longitude;
103 } log_si;
104
105 struct rach_ref {
106         uint8_t valid;
107         uint8_t cr;
108         uint8_t t1, t2, t3;
109 } rach_ref;
110
111 #define LOGFILE(fmt, args...) \
112         fprintf(logfp, fmt, ## args);
113 #define LOGFLUSH() \
114         fflush(logfp);
115
116 static void start_sync(void);
117 static void start_rach(void);
118 static void start_pm(void);
119
120 static void log_gps(void)
121 {
122         if (!gps.enable || !gps.valid)
123                 return;
124         LOGFILE("position %.8f %.8f\n", gps.longitude, gps.latitude);
125 }
126
127 static void log_time(void)
128 {
129         time_t now;
130
131         if (gps.enable && gps.valid)
132                 now = gps.gmt;
133         else
134                 time(&now);
135         LOGFILE("time %lu\n", now);
136 }
137
138 static void log_frame(char *tag, uint8_t *data)
139 {
140         int i;
141
142         LOGFILE("%s", tag);
143         for (i = 0; i < 23; i++)
144                 LOGFILE(" %02x", *data++);
145         LOGFILE("\n");
146 }
147
148 static void log_pm(void)
149 {
150         int count = 0, i;
151
152         LOGFILE("[power]\n");
153         log_time();
154         log_gps();
155         for (i = 0; i <= 1023; i++) {
156                 if ((pm[i].flags & INFO_FLG_PM)) {
157                         if (!count)
158                                 LOGFILE("arfcn %d", i);
159                         LOGFILE(" %d", pm[i].rxlev);
160                         count++;
161                         if (count == 12) {
162                                 LOGFILE("\n");
163                                 count = 0;
164                         }
165                 } else {
166                         if (count) {
167                                 LOGFILE("\n");
168                                 count = 0;
169                         }
170                 }
171         }
172         if (count)
173                 LOGFILE("\n");
174
175         LOGFILE("\n");
176         LOGFLUSH();
177 }
178
179 static void log_sysinfo(void)
180 {
181         struct rx_meas_stat *meas = &ms->meas;
182         struct gsm48_sysinfo *s = &sysinfo;
183         int8_t rxlev;
184         char ta_str[32] = "";
185
186         if (log_si.ta != 0xff)
187                 sprintf(ta_str, " TA=%d", log_si.ta);
188
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);
192
193         LOGFILE("[sysinfo]\n");
194         LOGFILE("arfcn %d\n", s->arfcn);
195         log_time();
196         log_gps();
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);
200         if (s->si1)
201                 log_frame("si1", s->si1_msg);
202         if (s->si2)
203                 log_frame("si2", s->si2_msg);
204         if (s->si2bis)
205                 log_frame("si2bis", s->si2b_msg);
206         if (s->si2ter)
207                 log_frame("si2ter", s->si2t_msg);
208         if (s->si3)
209                 log_frame("si3", s->si3_msg);
210         if (s->si4)
211                 log_frame("si4", s->si4_msg);
212         if (log_si.ta != 0xff)
213                 LOGFILE("ta %d\n", log_si.ta);
214
215         LOGFILE("\n");
216         LOGFLUSH();
217 }
218
219 static void timeout_cb(void *arg)
220 {
221         switch (state) {
222         case SCAN_STATE_READ:
223                 LOGP(DRR, LOGL_INFO, "Timeout reading BCCH\n");
224                 start_sync();
225                 break;
226         case SCAN_STATE_RACH:
227                 LOGP(DRR, LOGL_INFO, "Timeout on RACH\n");
228                 rach_count++;
229                 start_rach();
230                 break;
231         }
232 }
233
234 static void stop_timer(void)
235 {
236         if (bsc_timer_pending(&timer))
237                 bsc_del_timer(&timer);
238 }
239
240 static void start_timer(int sec, int micro)
241 {
242         stop_timer();
243         timer.cb = timeout_cb;
244         timer.data = ms;
245         bsc_schedule_timer(&timer, sec, micro);
246 }
247
248 static void start_rach(void)
249 {
250         struct gsm48_sysinfo *s = &sysinfo;
251         uint8_t chan_req_val, chan_req_mask;
252         struct msgb *nmsg;
253         struct abis_rsl_cchan_hdr *ncch;
254
255         if (rach_count == RACH_MAX) {
256                 log_sysinfo();
257                 start_sync();
258                 return;
259         }
260
261         state = SCAN_STATE_RACH;
262
263         if (s->neci) {
264                 chan_req_mask = 0x0f;
265                 chan_req_val = 0x01;
266                 LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x "
267                         "(OTHER with NECI)\n", chan_req_val);
268         } else {
269                 chan_req_mask = 0x1f;
270                 chan_req_val = 0xe0;
271                 LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x (OTHER no NECI)\n",
272                         chan_req_val);
273         }
274
275         rach_ref.valid = 0;
276         rach_ref.cr = random();
277         rach_ref.cr &= chan_req_mask;
278         rach_ref.cr |= chan_req_val;
279
280         nmsg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM,
281                 RSL_ALLOC_HEADROOM, "GSM 04.06 RSL");
282         if (!nmsg)
283                 return;
284         nmsg->l2h = nmsg->data;
285         ncch = (struct abis_rsl_cchan_hdr *) msgb_put(nmsg, sizeof(*ncch)
286                                                         + 4 + 2 + 2);
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;
292         ncch->data[3] = 0;
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 */
297
298         start_timer(RACH_WAIT);
299
300         rslms_recvmsg(nmsg, ms);
301 }
302
303 static void start_sync(void)
304 {
305         int rxlev = -128;
306         int i, dist = 0;
307         char dist_str[32] = "";
308
309         arfcn = 0xffff;
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) {
314                                 rxlev = pm[i].rxlev;
315                                 arfcn = i;
316                         }
317                 }
318         }
319         /* if GPS becomes valid, like after exitting a tunnel */
320         if (!pm_gps_valid && gps.valid) {
321                 pm_gps_valid = 1;
322                 geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z, gps.longitude,
323                         gps.latitude);
324         }
325         if (pm_gps_valid && gps.valid) {
326                 double x, y, z;
327
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);
331         }
332         if (dist > MAX_DIST || arfcn == 0xffff || rxlev < min_rxlev) {
333                 memset(pm, 0, sizeof(pm));
334                 pm_index = 0;
335                 sync_count = 0;
336                 start_pm();
337                 return;
338         }
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,
347                 CCCH_MODE_NONE);
348 }
349
350 static void start_pm(void)
351 {
352         uint16_t from, to;
353
354         state = SCAN_STATE_PM;
355         from = band_range[pm_index][0];
356         to = band_range[pm_index][1];
357
358         if (from == 0 && to == 0) {
359                 LOGP(DSUM, LOGL_INFO, "Measurement done\n");
360                 pm_gps_valid = gps.enable && gps.valid;
361                 if (pm_gps_valid)
362                         geo2space(&pm_gps_x, &pm_gps_y, &pm_gps_z,
363                                 gps.longitude, gps.latitude);
364                 log_pm();
365                 start_sync();
366                 return;
367         }
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);
371 }
372
373 static int signal_cb(unsigned int subsys, unsigned int signal,
374                      void *handler_data, void *signal_data)
375 {
376         struct osmobb_meas_res *mr;
377         struct osmobb_fbsb_res *fr;
378         uint16_t index;
379
380         if (subsys != SS_L1CTL)
381                 return 0;
382
383         switch (signal) {
384         case S_L1CTL_PM_RES:
385                 mr = signal_data;
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)
390                         sync_count++;
391 //              printf("rxlev %d = %d (sync_count %d)\n", index, pm[index].rxlev, sync_count);
392                 break;
393         case S_L1CTL_PM_DONE:
394                 pm_index++;
395                 start_pm();
396                 break;
397         case S_L1CTL_FBSB_RESP:
398                 fr = signal_data;
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");
407                 break;
408         case S_L1CTL_FBSB_ERR:
409                 LOGP(DRR, LOGL_INFO, "Sync failed\n");
410                 start_sync();
411                 break;
412         case S_L1CTL_RESET:
413                 if (started)
414                         break;
415                 started = 1;
416                 memset(pm, 0, sizeof(pm));
417                 pm_index = 0;
418                 sync_count = 0;
419                 start_pm();
420         }
421         return 0;
422 }
423
424 static int ta_result(uint8_t ta)
425 {
426         stop_timer();
427
428         if (ta == 0xff)
429                 LOGP(DSUM, LOGL_INFO, "Got assignment reject\n");
430         else {
431                 LOGP(DSUM, LOGL_DEBUG, "Got assignment TA = %d\n", ta);
432                 log_si.ta = ta;
433         }
434
435         log_sysinfo();
436         start_sync();
437
438         return 0;
439 }
440
441 /* match request reference agains request */
442 static int match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref)
443 {
444         uint8_t ia_t1, ia_t2, ia_t3;
445
446         /* filter confirmed RACH requests only */
447         if (rach_ref.valid && ref->ra == rach_ref.cr) {
448                 ia_t1 = ref->t1;
449                 ia_t2 = ref->t2;
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,
455                                         ia_t3);
456                         return 1;
457                 } else
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);
462         }
463
464         return 0;
465 }
466
467 /* 9.1.18 IMMEDIATE ASSIGNMENT is received */
468 static int imm_ass(struct osmocom_ms *ms, struct msgb *msg)
469 {
470         struct gsm48_imm_ass *ia = msgb_l3(msg);
471
472         LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT:\n");
473
474         if (state != SCAN_STATE_RACH) {
475                 LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
476                 return 0;
477         }
478
479         /* request ref */
480         if (match_ra(ms, &ia->req_ref)) {
481                 return ta_result(ia->timing_advance);
482         }
483         LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
484
485         return 0;
486 }
487
488 /* 9.1.19 IMMEDIATE ASSIGNMENT EXTENDED is received */
489 static int imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
490 {
491         struct gsm48_imm_ass_ext *ia = msgb_l3(msg);
492
493         LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT EXTENDED:\n");
494
495         if (state != SCAN_STATE_RACH) {
496                 LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
497                 return 0;
498         }
499
500         /* request ref 1 */
501         if (match_ra(ms, &ia->req_ref1)) {
502                 return ta_result(ia->timing_advance1);
503         }
504         /* request ref 2 */
505         if (match_ra(ms, &ia->req_ref2)) {
506                 return ta_result(ia->timing_advance2);
507         }
508         LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
509
510         return 0;
511 }
512
513 /* 9.1.20 IMMEDIATE ASSIGNMENT REJECT is received */
514 static int imm_ass_rej(struct osmocom_ms *ms, struct msgb *msg)
515 {
516         struct gsm48_imm_ass_rej *ia = msgb_l3(msg);
517         int i;
518         struct gsm48_req_ref *req_ref;
519
520         LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT:\n");
521
522         if (state != SCAN_STATE_RACH) {
523                 LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
524                 return 0;
525         }
526
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);
535                 }
536         }
537
538         return 0;
539 }
540
541 /* receive CCCH at RR layer */
542 static int pch_agch(struct osmocom_ms *ms, struct msgb *msg)
543 {
544         struct gsm48_system_information_type_header *sih = msgb_l3(msg);
545
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:
550                 return 0;
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);
557         default:
558                 return -EINVAL;
559         }
560 }
561
562 /* check if sysinfo is complete, change to RACH state */
563 static int new_sysinfo(void)
564 {
565         struct gsm48_sysinfo *s = &sysinfo;
566
567         /* restart timer */
568         start_timer(READ_WAIT);
569
570         /* mandatory */
571         if (!s->si1 || !s->si2 || !s->si3 || !s->si4) {
572                 LOGP(DRR, LOGL_INFO, "not all mandatory SI received\n");
573                 return 0;
574         }
575
576         /* extended band */
577         if (s->nb_ext_ind_si2 && !s->si2bis) {
578                 LOGP(DRR, LOGL_INFO, "extended ba, but si2bis not received\n");
579                 return 0;
580         }
581
582         /* 2ter */
583         if (s->si2ter_ind && !s->si2ter) {
584                 LOGP(DRR, LOGL_INFO, "si2ter_ind, but si2ter not received\n");
585                 return 0;
586         }
587
588         LOGP(DRR, LOGL_INFO, "Sysinfo complete\n");
589
590         stop_timer();
591
592         rach_count = 0;
593         start_rach();
594
595         return 0;
596 }
597
598 /* receive BCCH at RR layer */
599 static int bcch(struct osmocom_ms *ms, struct msgb *msg)
600 {
601         struct gsm48_sysinfo *s = &sysinfo;
602         struct gsm48_system_information_type_header *sih = msgb_l3(msg);
603         uint8_t ccch_mode;
604
605         if (msgb_l3len(msg) != 23) {
606                 LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n");
607                 return -EINVAL;
608         }
609         switch (sih->system_information) {
610         case GSM48_MT_RR_SYSINFO_1:
611                 if (!memcmp(sih, s->si1_msg, sizeof(s->si1_msg)))
612                         return 0;
613                 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n");
614                 gsm48_decode_sysinfo1(s,
615                         (struct gsm48_system_information_type_1 *) sih,
616                         msgb_l3len(msg));
617                 return new_sysinfo();
618         case GSM48_MT_RR_SYSINFO_2:
619                 if (!memcmp(sih, s->si2_msg, sizeof(s->si2_msg)))
620                         return 0;
621                 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2\n");
622                 gsm48_decode_sysinfo2(s,
623                         (struct gsm48_system_information_type_2 *) sih,
624                         msgb_l3len(msg));
625                 return new_sysinfo();
626         case GSM48_MT_RR_SYSINFO_2bis:
627                 if (!memcmp(sih, s->si2b_msg, sizeof(s->si2b_msg)))
628                         return 0;
629                 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2bis\n");
630                 gsm48_decode_sysinfo2bis(s,
631                         (struct gsm48_system_information_type_2bis *) sih,
632                         msgb_l3len(msg));
633                 return new_sysinfo();
634         case GSM48_MT_RR_SYSINFO_2ter:
635                 if (!memcmp(sih, s->si2t_msg, sizeof(s->si2t_msg)))
636                         return 0;
637                 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2ter\n");
638                 gsm48_decode_sysinfo2ter(s,
639                         (struct gsm48_system_information_type_2ter *) sih,
640                         msgb_l3len(msg));
641                 return new_sysinfo();
642         case GSM48_MT_RR_SYSINFO_3:
643                 if (!memcmp(sih, s->si3_msg, sizeof(s->si3_msg)))
644                         return 0;
645                 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 3\n");
646                 gsm48_decode_sysinfo3(s,
647                         (struct gsm48_system_information_type_3 *) sih,
648                         msgb_l3len(msg));
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)))
656                         return 0;
657                 LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n");
658                 gsm48_decode_sysinfo4(s,
659                         (struct gsm48_system_information_type_4 *) sih,
660                         msgb_l3len(msg));
661                 return new_sysinfo();
662         default:
663                 return -EINVAL;
664         }
665 }
666
667 static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
668 {
669         struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
670         struct tlv_parsed tv;
671         uint8_t ch_type, ch_subch, ch_ts;
672         
673         DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
674                 rllh->chan_nr, rllh->link_id);
675
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");
679                 return -EIO;
680         }
681         msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
682
683         if (state != SCAN_STATE_READ && state != SCAN_STATE_RACH) {
684                 return -EINVAL;
685         }
686
687         rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
688         switch (ch_type) {
689         case RSL_CHAN_PCH_AGCH:
690                 return pch_agch(ms, msg);
691         case RSL_CHAN_BCCH:
692                 return bcch(ms, msg);
693 #if 0
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);
699 #endif
700         default:
701                 LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n",
702                         rllh->chan_nr);
703                 return -EINVAL;
704         }
705 }
706
707 static int rcv_rll(struct osmocom_ms *ms, struct msgb *msg)
708 {
709         struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
710         int msg_type = rllh->c.msg_type;
711
712         if (msg_type == RSL_MT_UNIT_DATA_IND) {
713                 unit_data_ind(ms, msg);
714         } else
715                 LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
716
717         msgb_free(msg);
718
719         return 0;
720 }
721
722 int chan_conf(struct osmocom_ms *ms, struct msgb *msg)
723 {
724         struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
725         struct gsm48_req_ref *ref = (struct gsm48_req_ref *) (ch->data + 1);
726
727         if (msgb_l2len(msg) < sizeof(*ch) + sizeof(*ref)) {
728                 LOGP(DRR, LOGL_ERROR, "CHAN_CNF too slort\n");
729                 return -EINVAL;
730         }
731
732         rach_ref.valid = 1;
733         rach_ref.t1 = ref->t1;
734         rach_ref.t2 = ref->t2;
735         rach_ref.t3 = ref->t3_low | (ref->t3_high << 3);
736
737         return 0;
738 }
739
740 static int rcv_cch(struct osmocom_ms *ms, struct msgb *msg)
741 {
742         struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
743         int msg_type = ch->c.msg_type;
744         int rc;
745
746         LOGP(DRSL, LOGL_INFO, "Received '%s' from layer1\n",
747                 get_rsl_name(msg_type));
748
749         if (state == SCAN_STATE_RACH && msg_type == RSL_MT_CHAN_CONF) {
750                 rc = chan_conf(ms, msg);
751                 msgb_free(msg);
752                 return rc;
753         }
754
755         LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
756         msgb_free(msg);
757         return 0;
758 }
759
760 static int rcv_rsl(struct msgb *msg, struct osmocom_ms *ms)
761 {
762         struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
763         int rc = 0;
764
765         switch (rslh->msg_discr & 0xfe) {
766         case ABIS_RSL_MDISC_RLL:
767                 rc = rcv_rll(ms, msg);
768                 break;
769         case ABIS_RSL_MDISC_COM_CHAN:
770                 rc = rcv_cch(ms, msg);
771                 break;
772         default:
773                 LOGP(DRSL, LOGL_NOTICE, "unknown RSLms msg_discr 0x%02x\n",
774                         rslh->msg_discr);
775                 msgb_free(msg);
776                 rc = -EINVAL;
777                 break;
778         }
779
780         return rc;
781 }
782
783 int scan_init(struct osmocom_ms *_ms)
784 {
785         ms = _ms;
786         register_signal_handler(SS_L1CTL, &signal_cb, NULL);
787         memset(&timer, 0, sizeof(timer));
788         osmol2_register_handler(ms, &rcv_rsl);
789         gps.enable = 1;
790         gps_init();
791         if (gps_open())
792                 gps.enable = 0;
793
794         if (!strcmp(logname, "-"))
795                 logfp = stdout;
796         else
797                 logfp = fopen(logname, "a");
798         if (!logfp) {
799                 fprintf(stderr, "Failed to open logfile '%s'\n", logname);
800                 scan_exit();
801                 return -errno;
802         }
803         LOGP(DSUM, LOGL_INFO, "Scanner initialized\n");
804
805         return 0;
806 }
807
808 int scan_exit(void)
809 {
810         LOGP(DSUM, LOGL_INFO, "Scanner exit\n");
811         if (gps.valid)
812                 gps_close();
813         if (logfp)
814                 fclose(logfp);
815         unregister_signal_handler(SS_L1CTL, &signal_cb, NULL);
816         stop_timer();
817
818         return 0;
819 }