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