Ejemplo n.º 1
0
/**
 * @brief Handler for received L1CTL_DM_EST_REQ from L23.
 *
 * -- dedicated mode established request --
 *
 * @param [in] msg the received message.
 *
 * Handle state change from idle to dedicated mode.
 *
 */
void l1ctl_rx_dm_est_req(struct l1_model_ms *ms, struct msgb *msg)
{
	struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
	struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
	struct l1ctl_dm_est_req *est_req = (struct l1ctl_dm_est_req *) ul->payload;
	uint8_t rsl_chantype, subslot, timeslot;

	rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);

	LOGPMS(DL1C, LOGL_INFO, ms, "Rx L1CTL_DM_EST_REQ (chan_nr=0x%02x, tn=%u, ss=%u)\n",
		ul->chan_nr, timeslot, subslot);

	ms->state.dedicated.chan_type = rsl_chantype;
	ms->state.dedicated.tn = timeslot;
	ms->state.dedicated.subslot = subslot;
	ms->state.state = MS_STATE_DEDICATED;

	/* TCH config */
	if (rsl_chantype == RSL_CHAN_Bm_ACCHs || rsl_chantype == RSL_CHAN_Lm_ACCHs) {
		ms->state.tch_mode = est_req->tch_mode;
		l1_model_tch_mode_set(ms, est_req->tch_mode);
		ms->state.audio_mode = est_req->audio_mode;
		/* TODO: configure audio hardware for encoding /
		 * decoding / recording / playing voice */
	}
}
Ejemplo n.º 2
0
int process_handle_burst(struct session_info *s, struct l1ctl_burst_ind *bi)
{
	int ul;
	//int len;
	//uint32_t fn;
	uint8_t type, subch, ts;
	struct burst_buf *bb = 0;

	rsl_dec_chan_nr(bi->chan_nr, &type, &subch, &ts);

	//fn = ntohl(bi->frame_nr);
	ul = !!(ntohs(bi->band_arfcn) & ARFCN_UPLINK);

	//printf("fn %d ts %d ul %d snr %d ", fn, ts, ul, bi->snr);
	//printf(" sub %d\n", chan_detect(fn, ts, comb, &sub), sub);

	switch (type) {
	case RSL_CHAN_Lm_ACCHs:
		// interleaved user data and signalling
		break;
	case RSL_CHAN_Bm_ACCHs:
		if (bi->flags & BI_FLG_SACCH) {
			/* burst is SACCH/T */
			process_ccch(s, &s->saccht[ul], bi);
		} else {
			//FIXME: detect type of channel
			/* try TCH (FACCH) */
			//len = process_tch(s, bi, msg);
			/* try PDCH */
			//len = process_pdch(s, bi, msg);
		}
		break;
	case RSL_CHAN_BCCH:
		//FIXME: check fn to know which type it really is
	case RSL_CHAN_SDCCH4_ACCH:
		//FIXME: check fn to know which type it really is
	case RSL_CHAN_SDCCH8_ACCH:
		//FIXME: check fn to know which type it really is
		if (bi->flags & BI_FLG_SACCH) {
			bb = &s->sacch;
		} else {
			bb = &s->sdcch;
		}
		process_ccch(s, bb, bi);
		break;
	case RSL_CHAN_RACH:
	case RSL_CHAN_PCH_AGCH:
	default:
		printf("Type not handled! %.02x\n", type);
	}

	return 0;
}
Ejemplo n.º 3
0
static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
	struct tlv_parsed tv;
	uint8_t ch_type, ch_subch, ch_ts;
	
	DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
		rllh->chan_nr, rllh->link_id);

	rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
	if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
		DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
		return -EIO;
	}
	msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);

	if (state != SCAN_STATE_READ && state != SCAN_STATE_RACH) {
	 	return -EINVAL;
	}

	rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
	switch (ch_type) {
	case RSL_CHAN_PCH_AGCH:
		return pch_agch(ms, msg);
	case RSL_CHAN_BCCH:
		return bcch(ms, msg);
#if 0
	case RSL_CHAN_Bm_ACCHs:
	case RSL_CHAN_Lm_ACCHs:
	case RSL_CHAN_SDCCH4_ACCH:
	case RSL_CHAN_SDCCH8_ACCH:
		return rx_acch(ms, msg);
#endif
	default:
		LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n",
			rllh->chan_nr);
		return -EINVAL;
	}
}
static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
	struct tlv_parsed tv;
	uint8_t ch_type, ch_subch, ch_ts;

	DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
		rllh->chan_nr, rllh->link_id);

	rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
	if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
		DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
		return -EIO;
	}
	msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);

	rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
	switch (ch_type) {
	case RSL_CHAN_BCCH:
		return bcch(ms, msg);
	default:
		return 0;
	}
}
Ejemplo n.º 5
0
/**
 * This method used to send a l1ctl_tx_dm_est_req_h0 or
 * a l1ctl_tx_dm_est_req_h1 to the layer1 to follow this
 * assignment. The code has been removed.
 */
static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms)
{
	struct gsm48_imm_ass *ia = msgb_l3(msg);
	uint8_t ch_type, ch_subch, ch_ts;
	int rv;

	/* Discard packet TBF assignement */
	if (ia->page_mode & 0xf0)
		return 0;

	/* If we're not ready yet, or just busy ... */
	if ((!app_state.has_si1) || (app_state.dch_state != DCH_NONE))
		return 0;

	rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);

	if (!ia->chan_desc.h0.h) {
		/* Non-hopping */
		uint16_t arfcn;

		arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);

		LOGP(DRR, LOGL_NOTICE, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
			"ARFCN=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
			ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch,
			ia->chan_desc.h0.tsc);

		/* request L1 to go to dedicated mode on assigned channel */
		rv = l1ctl_tx_dm_est_req_h0(ms,
			arfcn, ia->chan_desc.chan_nr, ia->chan_desc.h0.tsc,
			GSM48_CMODE_SIGN, 0);
	} else {
		/* Hopping */
		uint8_t maio, hsn, ma_len;
		uint16_t ma[64], arfcn;
		int i, j, k;

		hsn = ia->chan_desc.h1.hsn;
		maio = ia->chan_desc.h1.maio_low | (ia->chan_desc.h1.maio_high << 2);

		LOGP(DRR, LOGL_NOTICE, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
			"HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
			ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch,
			ia->chan_desc.h1.tsc);

		/* decode mobile allocation */
		ma_len = 0;
		for (i=1, j=0; i<=1024; i++) {
			arfcn = i & 1023;
			if (app_state.cell_arfcns[arfcn].mask & 0x01) {
				k = ia->mob_alloc_len - (j>>3) - 1;
				if (ia->mob_alloc[k] & (1 << (j&7))) {
					ma[ma_len++] = arfcn;
				}
				j++;
			}
		}

		/* request L1 to go to dedicated mode on assigned channel */
		rv = l1ctl_tx_dm_est_req_h1(ms,
			maio, hsn, ma, ma_len,
			ia->chan_desc.chan_nr, ia->chan_desc.h1.tsc,
			GSM48_CMODE_SIGN, 0);
	}
Ejemplo n.º 6
0
/**
 * @brief Get the scheduled fn for a msg depending on its chan_nr and link_id.
 */
uint32_t sched_fn_ul(struct gsm_time cur_time, uint8_t chan_nr, uint8_t link_id)
{
	uint8_t chan_type, chan_ss, chan_ts;
	uint32_t sched_fn = cur_time.fn;
	uint16_t mod_102 = cur_time.fn % 2 * 51;

	rsl_dec_chan_nr(chan_nr, &chan_type, &chan_ss, &chan_ts);

	/* TODO: Replace this spaghetti monster with some lookup table */
	switch (chan_type) {
	case RSL_CHAN_Bm_ACCHs:
		switch (link_id) {
		case LID_DEDIC:
			/* dl=[0...11,13...24] ul=[0...11,13...24]
			 * skip idle frames and frames reserved for TCH_ACCH */
			if (cur_time.t2 == 12 || cur_time.t2 == 25)
				sched_fn++;
			break;
		/* dl=42, ul=42+15 */
		case LID_SACCH:
			if ((chan_ts & 1)) {
				/* Odd traffic channel timeslot -> dl=[25] ul=[25]
				 * TCH_ACCH always at the end of tch multiframe (mod 26) */
				sched_fn -= cur_time.t2;
				sched_fn += 25;
			} else {
				/* Even traffic channel timeslot -> dl=[12] ul=[12] */
				if (cur_time.t2 <= 12) {
					sched_fn -= cur_time.t2;
					sched_fn += 12;
				} else {
					sched_fn -= cur_time.t2;
					sched_fn += 26 + 12;
				}
			}
			break;
		}
		break;
	case RSL_CHAN_Lm_ACCHs:
		break; /* TCH/H not supported */
	case RSL_CHAN_SDCCH4_ACCH:
		switch (chan_ss) {
		case 0:
			switch (link_id) {
			/* dl=22, ul=22+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 22 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 22 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 22 + 15;
				}
				break;
			/* dl=42, ul=42+15 */
			case LID_SACCH:
				if (mod_102 <= 42 + 15) {
					sched_fn -= mod_102;
					sched_fn += 42 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 42 + 15;
				}
				break;
			}
			break;
		case 1:
			switch (link_id) {
			/* dl=26, ul=26+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 26 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 26 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 26 + 15;
				}
				break;
			/* dl=46, ul=46+15 */
			case LID_SACCH:
				if (mod_102 <= 46 + 15) {
					sched_fn -= mod_102;
					sched_fn += 46 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 46 + 15;
				}
				break;
			}
			break;
		case 2:
			switch (link_id) {
			/* dl=32, ul=32+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 32 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 32 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 32 + 15;
				}
				break;
			/* dl=51+42, ul=51+42+15 */
			case LID_SACCH:
				if (mod_102 <= 51 + 42 + 15) {
					sched_fn -= mod_102;
					sched_fn += 51 + 42 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 51 + 42 + 15;
				}
				break;
			}
			break;
		case 3:
			switch (link_id) {
			/* dl=36, ul=36+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 36 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 36 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 36 + 15;
				}
				break;
			/* dl=51+46, ul=51+46+15 */
			case LID_SACCH:
				if (mod_102 <= 51 + 46 + 15) {
					sched_fn -= mod_102;
					sched_fn += 51 + 46 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 51 + 46 + 15;
				}
				break;
			}
			break;
		}
		break;
	case RSL_CHAN_SDCCH8_ACCH:
		switch (chan_ss) {
		case 0:
			switch (link_id) {
			/* dl=0, ul=0+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 0 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 0 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 0 + 15;
				}
				break;
			/* dl=32, ul=32+15 */
			case LID_SACCH:
				if (mod_102 <= 32 + 15) {
					sched_fn -= mod_102;
					sched_fn += 32 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 32 + 15;
				}
				break;
			}
			break;
		case 1:
			switch (link_id) {
			/* dl=4, ul=4+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 4 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 4 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 4 + 15;
				}
				break;
			/* dl=36, ul=36+15 */
			case LID_SACCH:
				if (mod_102 <= 36 + 15) {
					sched_fn -= mod_102;
					sched_fn += 36 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 36 + 15;
				}
				break;
			}
			break;
		case 2:
			switch (link_id) {
			/* dl=8, ul=8+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 8 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 8 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 8 + 15;
				}
				break;
			/* dl=40, ul=40+15 */
			case LID_SACCH:
				if (mod_102 <= 40 + 15) {
					sched_fn -= mod_102;
					sched_fn += 40 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 40 + 15;
				}
				break;
			}
			break;
		case 3:
			switch (link_id) {
			/* dl=12, ul=12+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 12 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 12 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 12 + 15;
				}
				break;
			/* dl=44, ul=44+15 */
			case LID_SACCH:
				if (mod_102 <= 44 + 15) {
					sched_fn -= mod_102;
					sched_fn += 44 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 44 + 15;
				}
				break;
			}
			break;
		case 4:
			switch (link_id) {
			/* dl=16, ul=16+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 16 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 16 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 16 + 15;
				}
				break;
			/* dl=51+32, ul=51+32+15 */
			case LID_SACCH:
				if (mod_102 <= 51 + 32 + 15) {
					sched_fn -= mod_102;
					sched_fn += 51 + 32 + 15;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 51 + 32 + 15;
				}
				break;
			}
			break;
		case 5:
			switch (link_id) {
			/* dl=20, ul=36+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 20 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 20 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 20 + 15;
				}
				break;
			/* dl=51+36, ul=51+36+15 ==> 0 */
			case LID_SACCH:
				if (mod_102 <= 0) {
					sched_fn -= mod_102;
					sched_fn += 0;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 0;
				}
				break;
			}
			break;
		case 6:
			switch (link_id) {
			/* dl=24, ul=24+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 24 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 24 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 24 + 15;
				}
				break;
			/* dl=51+40, ul=51+40+15 ==> 4 */
			case LID_SACCH:
				if (mod_102 <= 4) {
					sched_fn -= mod_102;
					sched_fn += 4;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 4;
				}
				break;
			}
			break;
		case 7:
			switch (link_id) {
			/* dl=28, ul=28+15 */
			case LID_DEDIC:
				if (cur_time.t3 <= 28 + 15) {
					sched_fn -= cur_time.t3;
					sched_fn += 28 + 15;
				} else {
					sched_fn -= cur_time.t3;
					sched_fn += 51 + 28 + 15;
				}
				break;
			/* dl=51+44, ul=51+44+15 ==> 8 */
			case LID_SACCH:
				if (mod_102 <= 8) {
					sched_fn -= mod_102;
					sched_fn += 8;
				} else {
					sched_fn -= mod_102;
					sched_fn += 2 * 51 + 8;
				}
				break;
			}
			break;
		}
		break;
	case RSL_CHAN_RACH:
		break; /* Use virt_prim_rach.c for calculation of sched fn for rach */
	default:
		break; /* Use current fn as default */
	}
	return sched_fn;
}
Ejemplo n.º 7
0
void parse_assignment(struct gsm48_hdr *hdr, unsigned len, struct gsm_sysinfo_freq *cell_arfcns, struct gsm_assignment *ga)
{
	struct gsm48_ass_cmd *ac;
	struct gsm48_ho_cmd *hoc;
	struct gsm48_chan_desc *cd = NULL;
	int payload_len = 0; 
	uint8_t *payload_data = NULL;
	struct tlv_parsed tp;
	uint8_t *ma = 0;
	uint8_t ma_len;
	uint8_t ch_type, ch_subch, ch_ts;
	unsigned i, mask;

	if (!ga)
		return;

	memset(ga, 0, sizeof(*ga));

	/* handover */
	if (hdr->msg_type == 0x2b) {
		if (len < (sizeof(*hdr) + sizeof(*hoc))) {
			return;
		}
		hoc = (struct gsm48_ho_cmd *) hdr->data;
		cd = &hoc->chan_desc;
		payload_len = len - sizeof(*hdr) - sizeof(*hoc);
		payload_data = hoc->data;
		ga->bcch_arfcn = hoc->cell_desc.arfcn_lo;
		ga->bcch_arfcn |= (hoc->cell_desc.arfcn_hi << 8);
	}

	/* assignment */
	if (hdr->msg_type == 0x2e) {
		if (len < (sizeof(*hdr) + sizeof(*ac))) {
			return;
		}
		ac = (struct gsm48_ass_cmd *) hdr->data;
		cd = &ac->chan_desc;
		payload_len = len - sizeof(*hdr) - sizeof(*ac);
		payload_data = ac->data;
	}

	if (!cd)
		return;

	if (!payload_len)
		return;
		
	/* Parse TLV in the message */
	tlv_parse(&tp, &gsm48_rr_att_tlvdef, payload_data, payload_len, 0, 0);

	ma_len = 0;
	ma = NULL;
	mask = 0;

	/* Cell channel description */
	if (TLVP_PRESENT(&tp, GSM48_IE_CELL_CH_DESC)) {
		const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_CELL_CH_DESC);
		uint8_t len = TLVP_LEN(&tp, GSM48_IE_CELL_CH_DESC);
		gsm48_decode_freq_list(cell_arfcns, (uint8_t *) v, len, 0xff, 0x02);
		mask = 0x02;
	} else if (TLVP_PRESENT(&tp, GSM48_IE_MA_AFTER)) {
		/* Mobile allocation */
		const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_MA_AFTER);
		uint8_t len = TLVP_LEN(&tp, GSM48_IE_MA_AFTER);

		ma_len = len;
		ma = (uint8_t *) v;
		mask = 0x01;
	} else if (TLVP_PRESENT(&tp, GSM48_IE_FREQ_L_AFTER)) {
		/* Frequency list after time */
		const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_FREQ_L_AFTER);
		uint8_t len = TLVP_LEN(&tp, GSM48_IE_FREQ_L_AFTER);
		gsm48_decode_freq_list(cell_arfcns, (uint8_t *) v, len, 0xff, 0x04);
		ma_len = 0;
		ma = NULL;
		mask = 0x04;
	} else {
		/* Use the old one */
		for (i=0; i<1024; i++) {
			cell_arfcns[i].mask &= ~0x02;
			if (cell_arfcns[i].mask & 0x01) {
				cell_arfcns[i].mask |= 0x02;
				mask = 0x02;
			}
		}
	}

	/* Channel mode (HR/FR/EFR/AMR) */
	if (TLVP_PRESENT(&tp, GSM48_IE_CHANMODE_1)) {
		const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_CHANMODE_1);
		//uint8_t len = TLVP_LEN(&tp, GSM48_IE_CHANMODE_1);
		ga->chan_mode = v[0];
	}

	/* Multirate configuration */
	if (TLVP_PRESENT(&tp, GSM48_IE_MUL_RATE_CFG)) {
		const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_MUL_RATE_CFG);
		//uint8_t len = TLVP_LEN(&tp, GSM48_IE_MUL_RATE_CFG);
		ga->rate_conf = v[1];
	}

	rsl_dec_chan_nr(cd->chan_nr, &ch_type, &ch_subch, &ch_ts);

	ga->h = cd->h0.h;
	ga->chan_nr = cd->chan_nr;

	if (!ga->h) {
		/* Non-Hopping */
		uint16_t arfcn = cd->h0.arfcn_low | (cd->h0.arfcn_high << 8);

		ga->tsc = cd->h0.tsc;
		ga->h0.band_arfcn = arfcn;
	} else {
		/* Hopping */
		uint16_t arfcn;
		int i, j, k;

		ga->tsc = cd->h1.tsc;
		ga->h1.maio = cd->h1.maio_low | (cd->h1.maio_high << 2);;
		ga->h1.hsn = cd->h1.hsn;
		ga->h1.ma_len = 0;

		/* decode mobile allocation */
		if (ma) {
			if (ma_len == 0) {
				return;
			}
			for (i=1, j=0; i<=1024; i++) {
				arfcn = i & 1023;
				if (cell_arfcns[arfcn].mask & mask) {
					k = ma_len - (j>>3) - 1;
					if (ma[k] & (1 << (j&7))) {
						ga->h1.ma[ga->h1.ma_len++] = arfcn;
					}
					j++;
				}
			}
			if (ga->h1.ma_len == 0) {
				/* cell information not found */
				/* just compute ma_len */
				for (i=0; i<(ma_len*8); i++){
					int k = i/8;
	
					if (ma[k] & (1 << (i&7))) {
						ga->h1.ma_len++;
					}
				}
			}
		} else {
			for (i=1; i<=1024; i++) {
Ejemplo n.º 8
0
static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms)
{
	struct gsm48_imm_ass *ia = msgb_l3(msg);
	uint8_t ch_type, ch_subch, ch_ts;
	int rv;

	/* Discard packet TBF assignement */
	if (ia->page_mode & 0xf0)
		return 0;

	/* FIXME: compare RA and GSM time with when we sent RACH req */

	rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);

	if (!ia->chan_desc.h0.h) {
		/* Non-hopping */
		uint16_t arfcn;

		arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);

		DEBUGP(DRR, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
			"ARFCN=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
			ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch,
			ia->chan_desc.h0.tsc);

		if (ch_ts >= 4) {
			DEBUGPC(DRR, "UNSUPPORTED!\n");
			return 0;
		}

		/* request L1 to go to dedicated mode on assigned channel */
		rv = l1ctl_tx_dm_est_req_h0(ms,
			arfcn, ia->chan_desc.chan_nr, ia->chan_desc.h0.tsc);
	} else {
		/* Hopping */
		uint8_t maio, hsn, ma_len;
		uint16_t ma[64], arfcn;
		int i, j, k;

		hsn = ia->chan_desc.h1.hsn;
		maio = ia->chan_desc.h1.maio_low | (ia->chan_desc.h1.maio_high << 2);

		DEBUGP(DRR, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
			"HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
			ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch,
			ia->chan_desc.h1.tsc);

		/* decode mobile allocation */
		ma_len = 0;
		for (i=1, j=0; i<=1024; i++) {
			arfcn = i & 1023;
			if (app_state.cell_arfcns[arfcn].mask & 0x01) {
				k = ia->mob_alloc_len - (j>>3) - 1;
				if (ia->mob_alloc[k] & (1 << (j&7))) {
					ma[ma_len++] = arfcn;
				}
				j++;
			}
		}

		if (ch_ts >= 4) {
			DEBUGPC(DRR, "UNSUPPORTED!\n");
			return 0;
		}

		/* request L1 to go to dedicated mode on assigned channel */
		rv = l1ctl_tx_dm_est_req_h1(ms,
			maio, hsn, ma, ma_len,
			ia->chan_desc.chan_nr, ia->chan_desc.h1.tsc);
	}