diff --git a/openbsc/doc/handover.txt b/openbsc/doc/handover.txt index 524d38625..ac19e8725 100644 --- a/openbsc/doc/handover.txt +++ b/openbsc/doc/handover.txt @@ -75,3 +75,15 @@ were achieved with the following settings: * RXQUAL >= 6: 1 dB + +== Actual Handover on a protocol level == + +After the BSC has decided a handover shall be done, it has to + +# allocate a channel at the new BTS +# allocate a handover reference +# activate the channel on the BTS side using RSL CHANNEL ACTIVATION, + indicating the HO reference +# BTS responds with CHAN ACT ACK, including GSM frame number +# BSC sends 04.08 HO CMD to MS using old BTS + diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index cd85dff8f..359aa1b39 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -90,6 +90,22 @@ struct gsm48_ass_cmd { u_int8_t data[0]; } __attribute__((packed)); +/* Chapter 10.5.2.2 */ +struct gsm48_cell_desc { + u_int8_t bcc:3, + ncc:3, + arfcn_hi:2; + u_int8_t arfcn_lo; +} __attribute__((packed)); + +/* Chapter 9.1.15 */ +struct gsm48_ho_cmd { + struct gsm48_cell_desc cell_desc; + struct gsm48_chan_desc chan_desc; + u_int8_t ho_ref; + u_int8_t power_command; + u_int8_t data[0]; +} __attribute__((packed)); /* Chapter 9.1.18 */ struct gsm48_imm_ass { diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index ad038fba6..d3e4689b5 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -519,6 +519,50 @@ int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv) return rsl_encryption_cmd(msg); } +static void gsm48_cell_desc(struct gsm48_cell_desc *cd, + const struct gsm_bts *bts) +{ + cd->ncc = (bts->bsic >> 3 & 0x7); + cd->bcc = (bts->bsic & 0x7); + cd->arfcn_hi = bts->c0->arfcn >> 8; + cd->arfcn_lo = bts->c0->arfcn & 0xff; +} + +static void gsm48_chan_desc(struct gsm48_chan_desc *cd, + const struct gsm_lchan *lchan) +{ + u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff; + + cd->chan_nr = lchan2chan_nr(lchan); + cd->h0.tsc = lchan->ts->trx->bts->tsc; + cd->h0.h = 0; + cd->h0.arfcn_high = arfcn >> 8; + cd->h0.arfcn_low = arfcn & 0xff; +} + +/* Chapter 9.1.15: Handover Command */ +int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, + struct gsm_lchan *new_lchan, u_int8_t power_command) +{ + struct msgb *msg = gsm48_msgb_alloc(); + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + struct gsm48_ho_cmd *ho = + (struct gsm48_ho_cmd *) msgb_put(msg, sizeof(*ho)); + static u_int8_t ho_ref; + + msg->lchan = old_lchan; + + /* mandatory bits */ + gsm48_cell_desc(&ho->cell_desc, new_lchan->ts->trx->bts); + gsm48_chan_desc(&ho->chan_desc, new_lchan); + ho->ho_ref = ho_ref++; + ho->power_command = power_command; + + /* FIXME: optional bits for type of synchronization? */ + + return gsm48_sendmsg(msg, NULL); +} + /* Chapter 9.1.2: Assignment Command */ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command) { @@ -526,7 +570,6 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command) struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); struct gsm48_ass_cmd *ass = (struct gsm48_ass_cmd *) msgb_put(msg, sizeof(*ass)); - u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff; DEBUGP(DRR, "-> ASSIGNMENT COMMAND tch_mode=0x%02x\n", lchan->tch_mode); @@ -542,11 +585,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command) * the chan_desc. But as long as multi-slot configurations * are not used we seem to be fine. */ - ass->chan_desc.chan_nr = lchan2chan_nr(lchan); - ass->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc; - ass->chan_desc.h0.h = 0; - ass->chan_desc.h0.arfcn_high = arfcn >> 8; - ass->chan_desc.h0.arfcn_low = arfcn & 0xff; + gsm48_chan_desc(&ass->chan_desc, lchan); ass->power_command = power_command; /* in case of multi rate we need to attach a config */