Merge branch 'holger/merge-on-waves-msc'
This commit is contained in:
commit
304222b614
|
@ -42,7 +42,11 @@ struct gsm48_req_ref {
|
||||||
t3_low:3;
|
t3_low:3;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* Chapter 9.1.5 */
|
/*
|
||||||
|
* Chapter 9.1.5/9.1.6
|
||||||
|
*
|
||||||
|
* For 9.1.6 the chan_desc has the meaning of 10.5.2.5a
|
||||||
|
*/
|
||||||
struct gsm48_chan_mode_modify {
|
struct gsm48_chan_mode_modify {
|
||||||
struct gsm48_chan_desc chan_desc;
|
struct gsm48_chan_desc chan_desc;
|
||||||
u_int8_t mode;
|
u_int8_t mode;
|
||||||
|
@ -59,6 +63,15 @@ enum gsm48_chan_mode {
|
||||||
GSM48_CMODE_DATA_3k6 = 0x23,
|
GSM48_CMODE_DATA_3k6 = 0x23,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Chapter 9.1.2 */
|
||||||
|
struct gsm48_ass_cmd {
|
||||||
|
/* Semantic is from 10.5.2.5a */
|
||||||
|
struct gsm48_chan_desc chan_desc;
|
||||||
|
u_int8_t power_command;
|
||||||
|
u_int8_t data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
/* Chapter 9.1.18 */
|
/* Chapter 9.1.18 */
|
||||||
struct gsm48_imm_ass {
|
struct gsm48_imm_ass {
|
||||||
u_int8_t l2_plen;
|
u_int8_t l2_plen;
|
||||||
|
@ -727,6 +740,7 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan);
|
||||||
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
|
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
|
||||||
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
|
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
|
||||||
u_int8_t apdu_len, const u_int8_t *apdu);
|
u_int8_t apdu_len, const u_int8_t *apdu);
|
||||||
|
int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_class);
|
||||||
|
|
||||||
int bsc_upqueue(struct gsm_network *net);
|
int bsc_upqueue(struct gsm_network *net);
|
||||||
|
|
||||||
|
@ -744,4 +758,7 @@ int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv);
|
||||||
int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
|
int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
|
||||||
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr);
|
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr);
|
||||||
|
|
||||||
|
int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode);
|
||||||
|
int gsm48_rx_rr_modif_ack(struct msgb *msg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -239,6 +239,7 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
|
||||||
return lchan;
|
return lchan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See Table 10.5.25 of GSM04.08 */
|
||||||
u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
|
u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
|
||||||
{
|
{
|
||||||
struct gsm_bts_trx_ts *ts = lchan->ts;
|
struct gsm_bts_trx_ts *ts = lchan->ts;
|
||||||
|
|
|
@ -1087,34 +1087,6 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
||||||
return gsm0408_authorize(lchan, msg);
|
return gsm0408_authorize(lchan, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
|
|
||||||
int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
|
|
||||||
{
|
|
||||||
struct msgb *msg = gsm48_msgb_alloc();
|
|
||||||
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
|
|
||||||
struct gsm48_chan_mode_modify *cmm =
|
|
||||||
(struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
|
|
||||||
u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
|
|
||||||
|
|
||||||
DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
|
|
||||||
|
|
||||||
lchan->tch_mode = mode;
|
|
||||||
msg->lchan = lchan;
|
|
||||||
gh->proto_discr = GSM48_PDISC_RR;
|
|
||||||
gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
|
|
||||||
|
|
||||||
/* fill the channel information element, this code
|
|
||||||
* should probably be shared with rsl_rx_chan_rqd() */
|
|
||||||
cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
|
|
||||||
cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
|
|
||||||
cmm->chan_desc.h0.h = 0;
|
|
||||||
cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
|
|
||||||
cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
|
|
||||||
cmm->mode = mode;
|
|
||||||
|
|
||||||
return gsm48_sendmsg(msg, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static u_int8_t to_bcd8(u_int8_t val)
|
static u_int8_t to_bcd8(u_int8_t val)
|
||||||
{
|
{
|
||||||
|
@ -1615,11 +1587,7 @@ static int gsm0408_rcv_rr(struct msgb *msg)
|
||||||
rc = gsm48_rx_rr_pag_resp(msg);
|
rc = gsm48_rx_rr_pag_resp(msg);
|
||||||
break;
|
break;
|
||||||
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
|
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
|
||||||
DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
|
rc = gsm48_rx_rr_modif_ack(msg);
|
||||||
/* We've successfully modified the MS side of the channel,
|
|
||||||
* now go on to modify the BTS side of the channel */
|
|
||||||
msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
|
|
||||||
rc = rsl_chan_mode_modify_req(msg->lchan);
|
|
||||||
break;
|
break;
|
||||||
case GSM48_MT_RR_STATUS:
|
case GSM48_MT_RR_STATUS:
|
||||||
rc = gsm48_rx_rr_status(msg);
|
rc = gsm48_rx_rr_status(msg);
|
||||||
|
@ -3167,22 +3135,11 @@ static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
|
||||||
return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
|
return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
|
static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
|
||||||
{
|
{
|
||||||
struct gsm_mncc *mode = arg;
|
struct gsm_mncc *mode = arg;
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
|
return gsm48_lchan_modify(trans->lchan, mode->lchan_mode);
|
||||||
if (rc < 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* FIXME: we not only need to do this after mode modify, but
|
|
||||||
* also after channel activation */
|
|
||||||
if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
|
|
||||||
mode->lchan_mode != GSM48_CMODE_SIGN)
|
|
||||||
rc = rsl_ipacc_bind(trans->lchan);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct downstate {
|
static struct downstate {
|
||||||
|
@ -3240,7 +3197,7 @@ static struct downstate {
|
||||||
MNCC_REL_REQ, gsm48_cc_tx_release},
|
MNCC_REL_REQ, gsm48_cc_tx_release},
|
||||||
/* special */
|
/* special */
|
||||||
{ALL_STATES,
|
{ALL_STATES,
|
||||||
MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
|
MNCC_LCHAN_MODIFY, _gsm48_lchan_modify},
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DOWNSLLEN \
|
#define DOWNSLLEN \
|
||||||
|
|
|
@ -482,3 +482,116 @@ int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
|
||||||
return rsl_encryption_cmd(msg);
|
return rsl_encryption_cmd(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Chapter 9.1.2: Assignment Command */
|
||||||
|
int gsm48_send_rr_ass_cmd(struct gsm_lchan *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_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);
|
||||||
|
|
||||||
|
msg->lchan = lchan;
|
||||||
|
gh->proto_discr = GSM48_PDISC_RR;
|
||||||
|
gh->msg_type = GSM48_MT_RR_ASS_CMD;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill the channel information element, this code
|
||||||
|
* should probably be shared with rsl_rx_chan_rqd(),
|
||||||
|
* gsm48_tx_chan_mode_modify. But beware that 10.5.2.5
|
||||||
|
* 10.5.2.5.a have slightly different semantic for
|
||||||
|
* 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;
|
||||||
|
ass->power_command = power_command;
|
||||||
|
|
||||||
|
return gsm48_sendmsg(msg, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
|
||||||
|
int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
|
||||||
|
{
|
||||||
|
struct msgb *msg = gsm48_msgb_alloc();
|
||||||
|
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
|
||||||
|
struct gsm48_chan_mode_modify *cmm =
|
||||||
|
(struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
|
||||||
|
u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
|
||||||
|
|
||||||
|
DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
|
||||||
|
|
||||||
|
lchan->tch_mode = mode;
|
||||||
|
msg->lchan = lchan;
|
||||||
|
gh->proto_discr = GSM48_PDISC_RR;
|
||||||
|
gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
|
||||||
|
|
||||||
|
/* fill the channel information element, this code
|
||||||
|
* should probably be shared with rsl_rx_chan_rqd() */
|
||||||
|
cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
|
||||||
|
cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
|
||||||
|
cmm->chan_desc.h0.h = 0;
|
||||||
|
cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
|
||||||
|
cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
|
||||||
|
cmm->mode = mode;
|
||||||
|
|
||||||
|
return gsm48_sendmsg(msg, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* FIXME: we not only need to do this after mode modify, but
|
||||||
|
* also after channel activation */
|
||||||
|
if (is_ipaccess_bts(lchan->ts->trx->bts) && lchan_mode != GSM48_CMODE_SIGN)
|
||||||
|
rc = rsl_ipacc_bind(lchan);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gsm48_rx_rr_modif_ack(struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||||
|
struct gsm48_chan_mode_modify *mod =
|
||||||
|
(struct gsm48_chan_mode_modify *) gh->data;
|
||||||
|
|
||||||
|
DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
|
||||||
|
|
||||||
|
if (mod->mode != msg->lchan->tch_mode) {
|
||||||
|
DEBUGP(DRR, "CHANNEL MODE change failed. Wanted: %d Got: %d\n",
|
||||||
|
msg->lchan->tch_mode, mod->mode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update the channel type */
|
||||||
|
switch (mod->mode) {
|
||||||
|
case GSM48_CMODE_SIGN:
|
||||||
|
msg->lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_SPEECH_V1:
|
||||||
|
case GSM48_CMODE_SPEECH_EFR:
|
||||||
|
case GSM48_CMODE_SPEECH_AMR:
|
||||||
|
msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
|
||||||
|
break;
|
||||||
|
case GSM48_CMODE_DATA_14k5:
|
||||||
|
case GSM48_CMODE_DATA_12k0:
|
||||||
|
case GSM48_CMODE_DATA_6k0:
|
||||||
|
case GSM48_CMODE_DATA_3k6:
|
||||||
|
msg->lchan->rsl_cmode = RSL_CMOD_SPD_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We've successfully modified the MS side of the channel,
|
||||||
|
* now go on to modify the BTS side of the channel */
|
||||||
|
return rsl_chan_mode_modify_req(msg->lchan);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue