/* receive BCCH at RR layer */ static int bcch(struct osmocom_ms *ms, struct msgb *msg) { struct gsm48_sysinfo *s = &sysinfo; struct gsm48_system_information_type_header *sih = msgb_l3(msg); uint8_t ccch_mode; if (msgb_l3len(msg) != 23) { LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n"); return -EINVAL; } switch (sih->system_information) { case GSM48_MT_RR_SYSINFO_1: if (!memcmp(sih, s->si1_msg, sizeof(s->si1_msg))) return 0; LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n"); gsm48_decode_sysinfo1(s, (struct gsm48_system_information_type_1 *) sih, msgb_l3len(msg)); return new_sysinfo(); case GSM48_MT_RR_SYSINFO_2: if (!memcmp(sih, s->si2_msg, sizeof(s->si2_msg))) return 0; LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2\n"); gsm48_decode_sysinfo2(s, (struct gsm48_system_information_type_2 *) sih, msgb_l3len(msg)); return new_sysinfo(); case GSM48_MT_RR_SYSINFO_2bis: if (!memcmp(sih, s->si2b_msg, sizeof(s->si2b_msg))) return 0; LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2bis\n"); gsm48_decode_sysinfo2bis(s, (struct gsm48_system_information_type_2bis *) sih, msgb_l3len(msg)); return new_sysinfo(); case GSM48_MT_RR_SYSINFO_2ter: if (!memcmp(sih, s->si2t_msg, sizeof(s->si2t_msg))) return 0; LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2ter\n"); gsm48_decode_sysinfo2ter(s, (struct gsm48_system_information_type_2ter *) sih, msgb_l3len(msg)); return new_sysinfo(); case GSM48_MT_RR_SYSINFO_3: if (!memcmp(sih, s->si3_msg, sizeof(s->si3_msg))) return 0; LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 3\n"); gsm48_decode_sysinfo3(s, (struct gsm48_system_information_type_3 *) sih, msgb_l3len(msg)); ccch_mode = (s->ccch_conf == 1) ? CCCH_MODE_COMBINED : CCCH_MODE_NON_COMBINED; LOGP(DRR, LOGL_INFO, "Changing CCCH_MODE to %d\n", ccch_mode); l1ctl_tx_ccch_mode_req(ms, ccch_mode); return new_sysinfo(); case GSM48_MT_RR_SYSINFO_4: if (!memcmp(sih, s->si4_msg, sizeof(s->si4_msg))) return 0; LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n"); gsm48_decode_sysinfo4(s, (struct gsm48_system_information_type_4 *) sih, msgb_l3len(msg)); return new_sysinfo(); default: return -EINVAL; } }
static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data) { struct gsm48_system_information_type_header *si_hdr; si_hdr = (struct gsm48_system_information_type_header *) data; /* GSM 05.02 §6.3.1.3 Mapping of BCCH data */ switch (si_hdr->system_information) { case GSM48_MT_RR_SYSINFO_1: #ifdef BCCH_TC_CHECK if (tc != 0) LOGP(DRR, LOGL_ERROR, "SI1 on the wrong TC: %d\n", tc); #endif if (!app_state.has_si1) { struct gsm48_system_information_type_1 *si1 = (struct gsm48_system_information_type_1 *)data; gsm48_decode_freq_list(app_state.cell_arfcns, si1->cell_channel_description, sizeof(si1->cell_channel_description), 0xff, 0x01); app_state.has_si1 = 1; LOGP(DRR, LOGL_ERROR, "SI1 received.\n"); } break; case GSM48_MT_RR_SYSINFO_2: #ifdef BCCH_TC_CHECK if (tc != 1) LOGP(DRR, LOGL_ERROR, "SI2 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_3: #ifdef BCCH_TC_CHECK if (tc != 2 && tc != 6) LOGP(DRR, LOGL_ERROR, "SI3 on the wrong TC: %d\n", tc); #endif if (app_state.ccch_mode == CCCH_MODE_NONE) { struct gsm48_system_information_type_3 *si3 = (struct gsm48_system_information_type_3 *)data; if (si3->control_channel_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) app_state.ccch_mode = CCCH_MODE_COMBINED; else app_state.ccch_mode = CCCH_MODE_NON_COMBINED; l1ctl_tx_ccch_mode_req(ms, app_state.ccch_mode); } break; case GSM48_MT_RR_SYSINFO_4: #ifdef BCCH_TC_CHECK if (tc != 3 && tc != 7) LOGP(DRR, LOGL_ERROR, "SI4 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_5: break; case GSM48_MT_RR_SYSINFO_6: break; case GSM48_MT_RR_SYSINFO_7: #ifdef BCCH_TC_CHECK if (tc != 7) LOGP(DRR, LOGL_ERROR, "SI7 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_8: #ifdef BCCH_TC_CHECK if (tc != 3) LOGP(DRR, LOGL_ERROR, "SI8 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_9: #ifdef BCCH_TC_CHECK if (tc != 4) LOGP(DRR, LOGL_ERROR, "SI9 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_13: #ifdef BCCH_TC_CHECK if (tc != 4 && tc != 0) LOGP(DRR, LOGL_ERROR, "SI13 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_16: #ifdef BCCH_TC_CHECK if (tc != 6) LOGP(DRR, LOGL_ERROR, "SI16 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_17: #ifdef BCCH_TC_CHECK if (tc != 2) LOGP(DRR, LOGL_ERROR, "SI17 on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_2bis: #ifdef BCCH_TC_CHECK if (tc != 5) LOGP(DRR, LOGL_ERROR, "SI2bis on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_2ter: #ifdef BCCH_TC_CHECK if (tc != 5 && tc != 4) LOGP(DRR, LOGL_ERROR, "SI2ter on the wrong TC: %d\n", tc); #endif break; case GSM48_MT_RR_SYSINFO_5bis: break; case GSM48_MT_RR_SYSINFO_5ter: break; default: LOGP(DRR, LOGL_ERROR, "Unknown SI: %d\n", si_hdr->system_information); break; }; }
static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data) { struct gsm48_system_information_type_header *si_hdr; si_hdr = (struct gsm48_system_information_type_header *) data; /* GSM 05.02 §6.3.1.3 Mapping of BCCH data */ switch (si_hdr->system_information) { case GSM48_MT_RR_SYSINFO_1: fprintf(stderr, "\tSI1"); #ifdef BCCH_TC_CHECK if (tc != 0) fprintf(stderr, " on wrong TC"); #endif if (!app_state.has_si1) { struct gsm48_system_information_type_1 *si1 = (struct gsm48_system_information_type_1 *)data; gsm48_decode_freq_list(&app_state.cell_arfcns, si1->cell_channel_description, sizeof(si1->cell_channel_description), 0xff, 0x01); app_state.has_si1 = 1; } break; case GSM48_MT_RR_SYSINFO_2: fprintf(stderr, "\tSI2"); #ifdef BCCH_TC_CHECK if (tc != 1) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_3: fprintf(stderr, "\tSI3"); #ifdef BCCH_TC_CHECK if (tc != 2 && tc != 6) fprintf(stderr, " on wrong TC"); #endif if (app_state.ccch_mode == CCCH_MODE_NONE) { struct gsm48_system_information_type_3 *si3 = (struct gsm48_system_information_type_3 *)data; if (si3->control_channel_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) app_state.ccch_mode = CCCH_MODE_COMBINED; else app_state.ccch_mode = CCCH_MODE_NON_COMBINED; l1ctl_tx_ccch_mode_req(ms, app_state.ccch_mode); } break; case GSM48_MT_RR_SYSINFO_4: fprintf(stderr, "\tSI4"); #ifdef BCCH_TC_CHECK if (tc != 3 && tc != 7) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_5: fprintf(stderr, "\tSI5"); break; case GSM48_MT_RR_SYSINFO_6: fprintf(stderr, "\tSI6"); break; case GSM48_MT_RR_SYSINFO_7: fprintf(stderr, "\tSI7"); #ifdef BCCH_TC_CHECK if (tc != 7) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_8: fprintf(stderr, "\tSI8"); #ifdef BCCH_TC_CHECK if (tc != 3) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_9: fprintf(stderr, "\tSI9"); #ifdef BCCH_TC_CHECK if (tc != 4) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_13: fprintf(stderr, "\tSI13"); #ifdef BCCH_TC_CHECK if (tc != 4 && tc != 0) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_16: fprintf(stderr, "\tSI16"); #ifdef BCCH_TC_CHECK if (tc != 6) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_17: fprintf(stderr, "\tSI17"); #ifdef BCCH_TC_CHECK if (tc != 2) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_2bis: fprintf(stderr, "\tSI2bis"); #ifdef BCCH_TC_CHECK if (tc != 5) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_2ter: fprintf(stderr, "\tSI2ter"); #ifdef BCCH_TC_CHECK if (tc != 5 && tc != 4) fprintf(stderr, " on wrong TC"); #endif break; case GSM48_MT_RR_SYSINFO_5bis: fprintf(stderr, "\tSI5bis"); break; case GSM48_MT_RR_SYSINFO_5ter: fprintf(stderr, "\tSI5ter"); break; default: fprintf(stderr, "\tUnknown SI"); break; }; fprintf(stderr, "\n"); }