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