/* 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;
	};
}
Exemple #3
0
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");
}