diff options
-rw-r--r-- | src/target/firmware/apps/rssi/main.c | 580 |
1 files changed, 544 insertions, 36 deletions
diff --git a/src/target/firmware/apps/rssi/main.c b/src/target/firmware/apps/rssi/main.c index 5d247958..ea8bbb49 100644 --- a/src/target/firmware/apps/rssi/main.c +++ b/src/target/firmware/apps/rssi/main.c @@ -47,6 +47,9 @@ #include <layer1/sync.h> #include <layer1/async.h> #include <layer1/l23_api.h> +#include <osmocom/gsm/rsl.h> +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gsm/gsm48_ie.h> enum key_codes key_code = KEY_INV; int key_pressed = 0; @@ -58,10 +61,11 @@ enum mode { MODE_MAIN, MODE_SPECTRUM, MODE_ARFCN, + MODE_SYNC, } mode = MODE_MAIN; enum mode last_mode; /* where to return after entering ARFCN */ -static uint16_t arfcn = 0; +static uint16_t arfcn = 0, ul_arfcn; int pcs = 0; int uplink = 0; int max = 0; @@ -69,6 +73,9 @@ uint8_t power, max_power; char input[5]; int cursor; +char *sync_result = NULL; +char *sync_msg = ""; + static struct band { int min, max, prev, next, freq_ul, freq_dl; } bands[] = { @@ -108,8 +115,42 @@ int tone = 0; unsigned long tone_time; int tone_on = 0; +uint8_t bsic; +uint8_t ul_levels[8], ul_max[8]; /* 8 uplink levels */ +uint8_t si_1[23]; +uint8_t si_2[23]; +uint8_t si_2bis[23]; +uint8_t si_2ter[23]; +uint8_t si_3[23]; +uint8_t si_4[23]; +uint16_t si_new = 0, ul_new; +uint16_t mcc, mnc, lac, cell_id; +int nb_num; +struct gsm_sysinfo_freq freq[1024]; +#define NEIGH_LINES ((framebuffer->height - 25) / 8) + +#define FREQ_TYPE_SERV 0x01 /* frequency of the serving cell */ +#define FREQ_TYPE_NCELL 0x1c /* frequency of the neighbor cell */ +#define FREQ_TYPE_NCELL_2 0x04 /* sub channel of SI 2 */ +#define FREQ_TYPE_NCELL_2bis 0x08 /* sub channel of SI 2bis */ +#define FREQ_TYPE_NCELL_2ter 0x10 /* sub channel of SI 2ter */ + /* UI */ +static void print_display(char *text, int *y, int c) +{ + /* skip lines, given by cursor */ + (*y)++; + if (c >= (*y)) + return; + /* skip, if end of display area is reached */ + if ((*y) - c > NEIGH_LINES) + return; + + fb_gotoxy(0, 20 + (((*y) - c - 1) << 3)); + fb_putstr(text, framebuffer->width); +} + static void refresh_display(void) { char text[16]; @@ -118,21 +159,149 @@ static void refresh_display(void) /* header */ fb_setbg(FB_COLOR_WHITE); - if (mode != MODE_SPECTRUM) { + if (mode != MODE_SPECTRUM && !(mode == MODE_SYNC && cursor < 0)) { fb_setfg(FB_COLOR_BLUE); fb_setfont(FB_FONT_HELVR08); - fb_gotoxy(0,6); + fb_gotoxy(0, 7); fb_putstr("Osmocom Monitor Tool",-1); - fb_gotoxy(0,10); - fb_setfg(FB_COLOR_BLACK); - fb_boxto(framebuffer->width-1,10); + fb_gotoxy(0, 10); + fb_setfg(FB_COLOR_GREEN); + fb_boxto(framebuffer->width - 1, 10); } fb_setfg(FB_COLOR_BLACK); fb_setfont(FB_FONT_C64); + /* SYNC / UL levels */ + if (mode == MODE_SYNC && cursor < 0) { + int i, tn, l; + int offset = (framebuffer->width - 96) >> 2; + int height = framebuffer->height - 25; + + fb_setfont(FB_FONT_HELVR08); + for (i = 0; i < 8; i++) { + if (uplink) + tn = (i + 3) & 7; /* UL is shifted by 3 */ + else + tn = i; + fb_setbg(FB_COLOR_WHITE); + fb_gotoxy(offset + 12 * i, 7); + l = (max) ? ul_max[tn] : ul_levels[tn]; + l = 110 - l; + if (l >= 100) + l -= 100; + sprintf(text, "%02d", l); + fb_putstr(text,framebuffer->width); + fb_setbg(FB_COLOR_BLACK); + fb_gotoxy(offset + 3 + 12 * i, height + 10); + fb_boxto(offset + 3 + 12 * i + 5, height + 10 - ul_levels[tn] * height / 64); + if (max) { + fb_gotoxy(offset + 3 + 12 * i, height + 10 - ul_max[tn] * height / 64); + fb_boxto(offset + 3 + 12 * i + 5, height + 10 - ul_max[tn] * height / 64); + } + } + fb_setbg(FB_COLOR_TRANSP); + if (max) { + fb_setfg(FB_COLOR_RED); + fb_gotoxy(framebuffer->width - 16, 15); + fb_putstr("max", framebuffer->width); + } + fb_setfont(FB_FONT_C64); + fb_setfg(FB_COLOR_BLUE); + fb_gotoxy(0, 16); + if (pcs && ul_arfcn >= PCS_MIN && ul_arfcn <= PCS_MAX) + sprintf(text, "%4dP", ul_arfcn); + else if (ul_arfcn >= DCS_MIN && ul_arfcn <= DCS_MAX) + sprintf(text, "%4dD", ul_arfcn); + else + sprintf(text, "%4d ", ul_arfcn); + fb_putstr(text, framebuffer->width); + fb_setbg(FB_COLOR_WHITE); + fb_setfg(FB_COLOR_BLACK); + } + + /* SYNC / SI */ + if (mode == MODE_SYNC && cursor == 0) { + fb_gotoxy(0, 20); + if (sync_msg[0] == 'o') + sprintf(text, "BSIC%d/%d %4d", bsic >> 3, bsic & 7, + power - 110); + else + sprintf(text, "Sync %s", sync_msg); + fb_putstr(text, -1); + + fb_gotoxy(0,28); + text[0] = si_1[2] ? '1' : '-'; + text[1] = ' '; + text[2] = si_2[2] ? '2' : '-'; + text[3] = ' '; + text[4] = si_2bis[2] ? '2' : '-'; + text[5] = si_2bis[2] ? 'b' : ' '; + text[6] = si_2ter[2] ? '2' : '-'; + text[7] = si_2ter[2] ? 't' : ' '; + text[8] = ' '; + text[9] = si_3[2] ? '3' : '-'; + text[10] = ' '; + text[11] = si_4[2] ? '4' : '-'; + text[12] = '\0'; + fb_putstr(text, -1); + + fb_gotoxy(0, 36); + fb_putstr("MCC MNC LAC ", -1); + fb_gotoxy(0, 44); + if (mcc) { + if ((mnc & 0x00f) == 0x00f) + sprintf(text, "%3x %02x %04x", mcc, mnc >> 4, lac); + else + sprintf(text, "%3x %03x %04x", mcc, mnc, lac); + fb_putstr(text, -1); + } else + fb_putstr("--- --- ----", -1); + fb_gotoxy(0, 52); + if (si_3[2]) { + sprintf(text, "cell id:%04x", cell_id); + fb_putstr(text, -1); + } else + fb_putstr("cell id:----", -1); + } + + /* SYNC / neighbour cells */ + if (mode == MODE_SYNC && cursor > 0) { + int i, y = 0; + + text[0] = '\0'; + for (i = 0; i < 1024; i++) { + if (freq[i].mask & FREQ_TYPE_SERV) { + if (!text[0]) + sprintf(text, "S: %4d", i); + else { + sprintf(text + 7, " %4d", i); + print_display(text, &y, cursor - 1); + text[0] = '\0'; + } + } + } + if (text[0]) + print_display(text, &y, cursor - 1); + text[0] = '\0'; + for (i = 0; i < 1024; i++) { + if (freq[i].mask & FREQ_TYPE_NCELL) { + if (!text[0]) + sprintf(text, "N: %4d", i); + else { + sprintf(text + 7, " %4d", i); + print_display(text, &y, cursor - 1); + text[0] = '\0'; + } + } + } + if (text[0]) + print_display(text, &y, cursor - 1); + nb_num = y; + } + /* ARFCN */ if (mode == MODE_MAIN || mode == MODE_ARFCN) { - fb_gotoxy(0,20); + fb_gotoxy(0, 20); if (mode == MODE_ARFCN) sprintf(text, "ARFCN %s", input); else if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) @@ -156,7 +325,7 @@ static void refresh_display(void) /* Frequency / power */ if (mode == MODE_MAIN) { int f; - + if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) { if (uplink) f = PCS_UL; @@ -168,21 +337,23 @@ static void refresh_display(void) f = band->freq_dl; f += ((arfcn - band->min) & 1023) << 1; - fb_gotoxy(0,30); + fb_gotoxy(0, 30); sprintf(text, "Freq. %d.%d", f / 10, f % 10); fb_putstr(text,framebuffer->width); - fb_gotoxy(0,40); + fb_gotoxy(0, 40); sprintf(text, "Power %d", ((max) ? max_power : power) - 110); - fb_putstr(text,framebuffer->width); + fb_putstr(text, framebuffer->width); if (max) { fb_setfont(FB_FONT_HELVR08); - fb_gotoxy(80,39); - fb_putstr("max",framebuffer->width); + fb_setfg(FB_COLOR_RED); + fb_gotoxy(framebuffer->width - 16, 39); + fb_putstr("max", framebuffer->width); fb_setfont(FB_FONT_C64); + fb_setfg(FB_COLOR_BLACK); } fb_setbg(FB_COLOR_BLACK); - fb_gotoxy(0,45); + fb_gotoxy(0, 45); fb_boxto(framebuffer->width * power / 64, 50); if (max) { fb_gotoxy(framebuffer->width * max_power / 64 ,45); @@ -195,29 +366,32 @@ static void refresh_display(void) if (mode == MODE_SPECTRUM) { int i; uint16_t a, e, p; + int height = framebuffer->height - 25; - fb_gotoxy(0,8); + fb_gotoxy(0, 8); if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) sprintf(text, "%4dP", arfcn); else if (arfcn >= DCS_MIN && arfcn <= DCS_MAX) sprintf(text, "%4dD", arfcn); else sprintf(text, "%4d ", arfcn); - sprintf(text + 5, " %d", pm_spectrum[arfcn & 1023] - 110); - fb_putstr(text,framebuffer->width); + sprintf(text + 5, " %4d", pm_spectrum[arfcn & 1023] - 110); + fb_putstr(text, -1); + fb_setfg(FB_COLOR_RED); if (max) { fb_setfont(FB_FONT_HELVR08); - fb_gotoxy(80,15); - fb_putstr("max",framebuffer->width); + fb_gotoxy(framebuffer->width - 16,15); + fb_putstr("max", framebuffer->width); fb_setfont(FB_FONT_C64); } if (pm_scale != 1) { fb_setfont(FB_FONT_HELVR08); - fb_gotoxy(1,15); + fb_gotoxy(1, 15); sprintf(text, "x%d", pm_scale); - fb_putstr(text,framebuffer->width); + fb_putstr(text, framebuffer->width); fb_setfont(FB_FONT_C64); } + fb_setfg(FB_COLOR_BLACK); if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) { a = PCS_MIN; e = PCS_MAX; @@ -225,40 +399,52 @@ static void refresh_display(void) a = band->min; e = band->max; } - for (i = 0; i < framebuffer->width - 1; i++) { + for (i = 0; i < framebuffer->width; i++) { p = (arfcn + i - (framebuffer->width >> 1)) & 1023; if ((((p - a) & 1023) & 512)) continue; if ((((e - p) & 1023) & 512)) continue; - p = (pm_spectrum[p] * pm_scale * 40 / 64); - if (p > 40) - p = 40; - fb_gotoxy(i, 50 - p); - fb_boxto(i, 50); + p = (pm_spectrum[p] * pm_scale * height / 64); + if (p > height) + p = height; + if (i == (framebuffer->width >> 1)) + fb_setfg(FB_COLOR_RED); + fb_gotoxy(i, height + 10 - p); + fb_boxto(i, height + 10); + if (i == (framebuffer->width >> 1)) + fb_setfg(FB_COLOR_BLACK); } i = framebuffer->width >> 1; fb_gotoxy(i, 0); fb_boxto(i, 4); - fb_gotoxy(i, 50); - fb_boxto(i, 54); + fb_gotoxy(i, height + 10); + fb_boxto(i, height + 14); } /* footer */ - fb_gotoxy(0,55); - fb_boxto(framebuffer->width-1,55); - fb_gotoxy(0,64); + fb_setfg(FB_COLOR_GREEN); + fb_gotoxy(0, framebuffer->height - 10); + fb_boxto(framebuffer->width-1, framebuffer->height - 10); + fb_gotoxy(0, framebuffer->height - 1); + fb_setfg(FB_COLOR_RED); if (mode == MODE_ARFCN) sprintf(text, "%s %s", (cursor) ? "del " : "back", (cursor) ? "enter" : " "); + else if (mode == MODE_SYNC && cursor < 0) + sprintf(text, "%s %s", "back", + (uplink) ? "UL" : "DL"); + else if (mode == MODE_SYNC) + sprintf(text, "%s ", "back"); else sprintf(text, "%s %s", (pcs) ? "PCS" : "DCS", (uplink) ? "UL" : "DL"); - fb_putstr(text,framebuffer->width); + fb_putstr(text, -1); + fb_setfg(FB_COLOR_BLACK); fb_setfont(FB_FONT_HELVR08); - fb_gotoxy(0,63); + fb_gotoxy(0, framebuffer->height - 2); sprintf(text, "%d", tone / 25); - fb_putstr(text,-1); + fb_putstr(text, -1); fb_flush(); } @@ -294,7 +480,7 @@ static void enter_arfcn(enum key_codes code) refresh_display(); return; } - + if (code == KEY_RIGHT_SB) { int check = 0; int i; @@ -390,6 +576,35 @@ static int inc_dec_arfcn(int inc) return 0; } +static void request_ul_levels(uint16_t a); + +static int inc_dec_ul_arfcn(int inc) +{ + uint16_t a; + + /* loop until we hit a serving cell or our current bcch arfcn */ + if (inc) { + for (a = (ul_arfcn + 1) & 1023; a != (arfcn & 1023); + a = (a + 1) & 1023) { + if ((freq[a].mask & FREQ_TYPE_SERV)) + break; + } + } else { + for (a = (ul_arfcn - 1) & 1023; a != (arfcn & 1023); + a = (a - 1) & 1023) { + if ((freq[a].mask & FREQ_TYPE_SERV)) + break; + } + } + ul_arfcn = a; + + refresh_display(); + + request_ul_levels(a); + + return 0; +} + static void toggle_dcs_pcs(void) { pcs = !pcs; @@ -400,6 +615,9 @@ static void toggle_up_down(void) { uplink = !uplink; refresh_display(); + + if (mode == MODE_SYNC && cursor < 0) + request_ul_levels(ul_arfcn); } static void toggle_spectrum(void) @@ -437,6 +655,23 @@ static void hold_max(void) refresh_display(); } +static int inc_dec_neighbour(int inc) +{ + if (inc) { + if (cursor > 0 && cursor - 1 >= (nb_num - NEIGH_LINES)) + return -EINVAL; + cursor++; + } else { + if (cursor < 0) + return -EINVAL; + cursor--; + } + + refresh_display(); + + return 0; +} + static int inc_dec_spectrum(int inc) { if (inc) { @@ -454,6 +689,9 @@ static int inc_dec_spectrum(int inc) return 0; } +static void enter_sync(void); +static void exit_sync(void); + static void handle_key_code() { /* key repeat */ @@ -493,34 +731,52 @@ static void handle_key_code() case KEY_UP: if (mode == MODE_MAIN) tone_inc_dec(1); + else if (mode == MODE_SYNC) + inc_dec_neighbour(0); else if (mode == MODE_SPECTRUM) inc_dec_spectrum(1); break; case KEY_DOWN: if (mode == MODE_MAIN) tone_inc_dec(0); + else if (mode == MODE_SYNC) + inc_dec_neighbour(1); else if (mode == MODE_SPECTRUM) inc_dec_spectrum(0); break; case KEY_RIGHT: if (mode == MODE_MAIN || mode == MODE_SPECTRUM) inc_dec_arfcn(1); + else if (mode == MODE_SYNC && cursor < 0) + inc_dec_ul_arfcn(1); break; case KEY_LEFT: if (mode == MODE_MAIN || mode == MODE_SPECTRUM) inc_dec_arfcn(0); + else if (mode == MODE_SYNC && cursor < 0) + inc_dec_ul_arfcn(0); break; case KEY_LEFT_SB: if (mode == MODE_MAIN || mode == MODE_SPECTRUM) toggle_dcs_pcs(); else if (mode == MODE_ARFCN) enter_arfcn(key_code); + else if (mode == MODE_SYNC) + exit_sync(); break; case KEY_RIGHT_SB: if (mode == MODE_MAIN || mode == MODE_SPECTRUM) toggle_up_down(); else if (mode == MODE_ARFCN) enter_arfcn(key_code); + else if (mode == MODE_SYNC && cursor < 0) + toggle_up_down(); + break; + case KEY_OK: + if (mode == MODE_MAIN || mode == MODE_SPECTRUM) + enter_sync(); + else if (mode == MODE_SYNC) + exit_sync(); break; case KEY_MENU: hold_max(); @@ -528,6 +784,8 @@ static void handle_key_code() case KEY_POWER: if (mode == MODE_ARFCN) exit_arfcn(); + else if (mode == MODE_SYNC) + exit_sync(); else if (mode == MODE_SPECTRUM) toggle_spectrum(); break; @@ -648,6 +906,190 @@ static void handle_pm(void) } } +/* sync / SI */ + +static void enter_sync(void) +{ + struct msgb *msg = l1ctl_msgb_alloc(L1CTL_FBSB_REQ); + struct l1ctl_fbsb_req *req; + uint16_t a = arfcn; + + l1s_reset(); + l1s_reset_hw(); + pm_count = 0; + pm_mode = PM_IDLE; + + req = (struct l1ctl_fbsb_req *) msgb_put(msg, sizeof(*req)); + if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) + a |= ARFCN_PCS; + req->band_arfcn = htons(a); + req->timeout = htons(100); + /* Threshold when to consider FB_MODE1: 4kHz - 1kHz */ + req->freq_err_thresh1 = htons(11000 - 1000); + /* Threshold when to consider SCH: 1kHz - 200Hz */ + req->freq_err_thresh2 = htons(1000 - 200); + /* not used yet! */ + req->num_freqerr_avg = 3; + req->flags = L1CTL_FBSB_F_FB01SB; + req->sync_info_idx = 0; + req->ccch_mode = CCCH_MODE_NONE; + l1a_l23_rx(SC_DLCI_L1A_L23, msg); + + mode = MODE_SYNC; + memset(ul_levels, 0, sizeof(ul_levels)); + si_new = 0; + ul_new = 0; + ul_arfcn = arfcn; + si_1[2] = 0; + si_2[2] = 0; + si_2bis[2] = 0; + si_2ter[2] = 0; + si_3[2] = 0; + si_4[2] = 0; + mcc = mnc = lac = 0; + memset(freq, 0, sizeof(freq)); + cursor = 0; + nb_num = 0; + sync_msg = "trying"; + refresh_display(); +} + +static void exit_sync(void) +{ + l1s_reset(); + l1s_reset_hw(); + pm_count = 0; + pm_mode = PM_IDLE; + mode = MODE_MAIN; +} + +int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *_mcc, +uint16_t *_mnc, uint16_t *_lac) +{ + *_mcc = ((lai->digits[0] & 0x0f) << 8) + | (lai->digits[0] & 0xf0) + | (lai->digits[1] & 0x0f); + *_mnc = ((lai->digits[2] & 0x0f) << 8) + | (lai->digits[2] & 0xf0) + | ((lai->digits[1] & 0xf0) >> 4); + *_lac = ntohs(lai->lac); + + return 0; +} + +static void request_ul_levels(uint16_t a) +{ + struct msgb *msg = l1ctl_msgb_alloc(L1CTL_NEIGH_PM_REQ); + struct l1ctl_neigh_pm_req *pm_req = + (struct l1ctl_neigh_pm_req *) msgb_put(msg, sizeof(*pm_req)); + int i; + + if (pcs && a >= PCS_MIN && a <= PCS_MAX) + a |= ARFCN_PCS; + if (uplink) + a |= ARFCN_UPLINK; + pm_req->n = 8; + for (i = 0; i < 8; i++) { + pm_req->band_arfcn[i] = htons(a); + pm_req->tn[i] = i; + } + l1a_l23_rx(SC_DLCI_L1A_L23, msg); +} + +static void handle_sync(void) +{ + struct gsm48_system_information_type_1 *si1; + struct gsm48_system_information_type_2 *si2; + struct gsm48_system_information_type_2bis *si2bis; + struct gsm48_system_information_type_2ter *si2ter; + struct gsm48_system_information_type_3 *si3; + struct gsm48_system_information_type_4 *si4; + + if (mode != MODE_SYNC) + return; + + /* once we synced, we take the result and request UL measurement */ + if (sync_result) { + uint16_t a = ul_arfcn; + + sync_msg = sync_result; + sync_result = NULL; + refresh_display(); + + if (sync_msg[0] != 'o') + return; + + request_ul_levels(a); + + return; + } + + if (tone_on) + return; + + /* no UL result, no SI result */ + if (!ul_new && !(si_new & 0x100)) + return; + + /* new UL result */ + if (ul_new) { + ul_new = 0; + if (cursor < 0) + refresh_display(); + return; + } + + /* decode si */ + switch (si_new & 0xff) { + case GSM48_MT_RR_SYSINFO_1: + si1 = (struct gsm48_system_information_type_1 *)si_1; + gsm48_decode_freq_list(freq, si1->cell_channel_description, + sizeof(si1->cell_channel_description), 0xce, + FREQ_TYPE_SERV); + break; + case GSM48_MT_RR_SYSINFO_2: + si2 = (struct gsm48_system_information_type_2 *)si_2; + gsm48_decode_freq_list(freq, si2->bcch_frequency_list, + sizeof(si2->bcch_frequency_list), 0xce, + FREQ_TYPE_NCELL_2); + break; + case GSM48_MT_RR_SYSINFO_2bis: + si2bis = (struct gsm48_system_information_type_2bis *)si_2bis; + gsm48_decode_freq_list(freq, si2bis->bcch_frequency_list, + sizeof(si2bis->bcch_frequency_list), 0xce, + FREQ_TYPE_NCELL_2bis); + break; + case GSM48_MT_RR_SYSINFO_2ter: + si2ter = (struct gsm48_system_information_type_2ter *)si_2ter; + gsm48_decode_freq_list(freq, si2ter->ext_bcch_frequency_list, + sizeof(si2ter->ext_bcch_frequency_list), 0x8e, + FREQ_TYPE_NCELL_2ter); + break; + case GSM48_MT_RR_SYSINFO_3: + si3 = (struct gsm48_system_information_type_3 *)si_3; + gsm48_decode_lai(&si3->lai, &mcc, &mnc, &lac); + cell_id = ntohs(si3->cell_identity); + break; + case GSM48_MT_RR_SYSINFO_4: + si4 = (struct gsm48_system_information_type_4 *)si_4; + gsm48_decode_lai(&si4->lai, &mcc, &mnc, &lac); + break; + } + + if (cursor >= 0) + refresh_display(); + + /* tone depends on successfully received BCCH */ + buzzer_volume(tone); + tone_time = jiffies; + tone_on = 1; + if ((si_new & 0xff) == 0xff) + buzzer_note(NOTE(NOTE_C, OCTAVE_2)); + else + buzzer_note(NOTE(NOTE_C, OCTAVE_5)); + si_new = 0; +} + /* Main Program */ const char *hr = "======================================================================\n"; @@ -656,6 +1098,11 @@ static void l1a_l23_tx(struct msgb *msg) { struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->l1h; struct l1ctl_pm_conf *pmr; + struct l1ctl_info_dl *dl; + struct l1ctl_fbsb_conf *sb; + uint8_t chan_type, chan_ts, chan_ss; + struct gsm48_system_information_type_header *sih; + struct l1ctl_neigh_pm_ind *pm_ind; switch (l1h->msg_type) { case L1CTL_PM_CONF: @@ -676,6 +1123,65 @@ static void l1a_l23_tx(struct msgb *msg) } l1s.tpu_offset_correction += 5000 / NUM_PM_UL; break; + case L1CTL_FBSB_CONF: + dl = (struct l1ctl_info_dl *) l1h->data; + sb = (struct l1ctl_fbsb_conf *) dl->payload; + if (sb->result == 0) + sync_result = "ok"; + else + sync_result = "error"; + bsic = sb->bsic; + break; + case L1CTL_DATA_IND: + dl = (struct l1ctl_info_dl *) l1h->data; + msg->l2h = dl->payload; + rsl_dec_chan_nr(dl->chan_nr, &chan_type, &chan_ss, &chan_ts); + if (chan_type != RSL_CHAN_BCCH) + break; + msg->l3h = msg->l2h; + + power = dl->rx_level; + if (dl->fire_crc >= 2) { + si_new = 0x1ff; /* error frame indication */ + break; + } + + /* store SI */ + sih = msgb_l3(msg); + switch (sih->system_information) { + case GSM48_MT_RR_SYSINFO_1: + memcpy(si_1, msgb_l3(msg), msgb_l3len(msg)); + break; + case GSM48_MT_RR_SYSINFO_2: + memcpy(si_2, msgb_l3(msg), msgb_l3len(msg)); + break; + case GSM48_MT_RR_SYSINFO_2bis: + memcpy(si_2bis, msgb_l3(msg), msgb_l3len(msg)); + break; + case GSM48_MT_RR_SYSINFO_2ter: + memcpy(si_2ter, msgb_l3(msg), msgb_l3len(msg)); + break; + case GSM48_MT_RR_SYSINFO_3: + memcpy(si_3, msgb_l3(msg), msgb_l3len(msg)); + break; + case GSM48_MT_RR_SYSINFO_4: + memcpy(si_4, msgb_l3(msg), msgb_l3len(msg)); + break; + } + si_new = sih->system_information | 0x100; + sercomm_sendmsg(SC_DLCI_L1A_L23, msg); + return; /* msg is freed by sercom */ + case L1CTL_NEIGH_PM_IND: + for (pm_ind = (struct l1ctl_neigh_pm_ind *) l1h->data; + (uint8_t *) pm_ind < msg->tail; pm_ind++) { + ul_levels[pm_ind->tn] = pm_ind->pm[0]; + /* hold max only, if max enabled and level is lower */ + if (!max || ul_levels[pm_ind->tn] > ul_max[pm_ind->tn]) + ul_max[pm_ind->tn] = ul_levels[pm_ind->tn]; + if (pm_ind->tn == 7) + ul_new = 1; + } + break; } msgb_free(msg); @@ -754,6 +1260,7 @@ int main(void) buzzer_volume(0); memset(pm_spectrum, 0, sizeof(pm_spectrum)); + memset(ul_max, 0, sizeof(ul_max)); /* inc 0 to 1 and refresh */ inc_dec_arfcn(1); @@ -764,6 +1271,7 @@ int main(void) handle_key_code(); l1a_l23_handler(); handle_pm(); + handle_sync(); handle_tone(); } |