now we get up to the SETUP of MO calls

This commit is contained in:
Harald Welte 2008-12-27 01:55:51 +00:00
parent faaa49ca51
commit 4b634544e6
6 changed files with 261 additions and 26 deletions

View File

@ -244,6 +244,22 @@ struct rsl_ie_chan_ident {
#endif
} __attribute__ ((packed));
/* Chapter 9.3.22 */
#define RLL_CAUSE_T200_EXPIRED 0x01
#define RLL_CAUSE_REEST_REQ 0x02
#define RLL_CAUSE_UNSOL_UA_RESP 0x03
#define RLL_CAUSE_UNSOL_DM_RESP 0x04
#define RLL_CAUSE_UNSOL_DM_RESP_MF 0x05
#define RLL_CAUSE_UNSOL_SPRV_RESP 0x06
#define RLL_CAUSE_SEQ_ERR 0x07
#define RLL_CAUSE_UFRM_INC_PARAM 0x08
#define RLL_CAUSE_SFRM_INC_PARAM 0x09
#define RLL_CAUSE_IFRM_INC_MBITS 0x0a
#define RLL_CAUSE_IFRM_INC_LEN 0x0b
#define RLL_CAUSE_FRM_UNIMPL 0x0c
#define RLL_CAUSE_SABM_MF 0x0d
#define RLL_CAUSE_SABM_INFO_NOTALL 0x0e
/* Chapter 9.3.26 */
#define RSL_ERRCLS_NORMAL 0x00
#define RSL_ERRCLS_RESOURCE_UNAVAIL 0x20

View File

@ -46,6 +46,7 @@ struct gsm48_imm_ass {
u_int8_t mob_alloc[0];
};
/* Chapter 10.5.1.3 */
struct gsm48_loc_area_id {
u_int8_t digits[3]; /* BCD! */
u_int16_t lac;
@ -57,7 +58,6 @@ struct gsm48_loc_upd_req {
key_seq:4;
struct gsm48_loc_area_id lai;
u_int8_t classmark1;
u_int8_t ie_mi;
u_int8_t mi_len;
u_int8_t mi[0];
} __attribute__ ((packed));
@ -70,7 +70,7 @@ struct gsm48_hdr {
} __attribute__ ((packed));
/* Section 10.2 */
#define GSM48_PDISC_CC 0x02
#define GSM48_PDISC_CC 0x03
#define GSM48_PDISC_MM 0x05
#define GSM48_PDISC_RR 0x06
#define GSM48_PDISC_MM_GPRS 0x08
@ -235,6 +235,23 @@ struct gsm48_hdr {
#define GSM_MI_TYPE_TMSI 0x04
#define GSM_MI_ODD 0x08
#define GSM48_IE_MOBILE_ID 0x17
/* Section 10.5.4.11 / Table 10.5.122 */
#define GSM48_CAUSE_CS_GSM 0x60
enum gsm48_cause_loc {
GSM48_CAUSE_LOC_USER = 0x00,
GSM48_CAUSE_LOC_PRN_S_LU = 0x01,
GSM48_CAUSE_LOC_PUN_S_LU = 0x02,
GSM48_CAUSE_LOC_TRANS_NET = 0x03,
GSM48_CAUSE_LOC_PUN_S_RU = 0x04,
GSM48_CAUSE_LOC_PRN_S_RU = 0x05,
/* not defined */
GSM48_CAUSE_LOC_INN_NET = 0x07,
GSM48_CAUSE_LOC_NET_BEYOND = 0x0a,
};
struct msgb;
struct gsm_bts;

View File

@ -57,6 +57,15 @@ static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag,
return buf;
}
static inline u_int8_t *tv16_put(u_int8_t *buf, u_int8_t tag,
u_int16_t val)
{
*buf++ = tag;
*buf++ = val >> 8;
*buf++ = val & 0xff;
return buf;
}
static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
{
u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
@ -69,6 +78,12 @@ static inline u_int8_t *msgb_tv_put(struct msgb *msg, u_int8_t tag, u_int8_t val
return tv_put(buf, tag, val);
}
static inline u_int8_t *msgb_tv16_put(struct msgb *msg, u_int8_t tag, u_int16_t val)
{
u_int8_t *buf = msgb_put(msg, 3);
return tv16_put(buf, tag, val);
}
static inline u_int8_t *msgb_tlv_push(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
{
u_int8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
@ -81,4 +96,11 @@ static inline u_int8_t *msgb_tv_push(struct msgb *msg, u_int8_t tag, u_int8_t va
return tv_put(buf, tag, val);
}
static inline u_int8_t *msgb_tv16_push(struct msgb *msg, u_int8_t tag, u_int16_t val)
{
u_int8_t *buf = msgb_push(msg, 3);
return tv16_put(buf, tag, val);
}
#endif /* _TLV_H */

View File

@ -336,6 +336,62 @@ int rsl_chan_activate_sdcch4(struct gsm_bts_trx_ts *ts, int subslot)
return rsl_chan_activate(ts->trx->bts, chan_nr, 0x00, &cm, &ci, 0x01, 0x0f, 0x00);
}
int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, u_int8_t ta)
{
struct abis_rsl_dchan_hdr *dh;
struct msgb *msg = rsl_msgb_alloc();
/* FXIME: don't hardcode these!! */
u_int8_t encr_info = 0x01;
u_int8_t ms_power = 0x0f;
u_int8_t bs_power = 0x01;
u_int8_t chan_nr = lchan2chan_nr(lchan);
u_int16_t arfcn = lchan->ts->trx->arfcn;
struct rsl_ie_chan_mode cm;
struct rsl_ie_chan_ident ci;
/* FIXME: what to do with data calls ? */
cm.dtx_dtu = 0x00;
switch (lchan->type) {
case GSM_LCHAN_SDCCH:
cm.spd_ind = RSL_CMOD_SPD_SIGN;
cm.chan_rt = RSL_CMOD_CRT_SDCCH;
cm.chan_rate = 0x00;
break;
case GSM_LCHAN_TCH_F:
cm.spd_ind = RSL_CMOD_SPD_SPEECH;
cm.chan_rt = RSL_CMOD_CRT_TCH_Bm;
cm.chan_rate = 0x11; /* speech coding alg version 2*/
break;
}
ci.chan_desc.iei = 0x64;
ci.chan_desc.chan_nr = chan_nr;
ci.chan_desc.oct3 = (TSC << 5) | ((arfcn & 0x3ff) >> 8);
ci.chan_desc.oct4 = arfcn & 0xff;
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
dh->chan_nr = chan_nr;
msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
/* For compatibility with Phase 1 */
msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
(u_int8_t *) &cm);
msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
(u_int8_t *) &ci);
/* FIXME: this shoould be optional */
#if 0
msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
(u_int8_t *) &encr_info);
msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
#endif
msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
return abis_rsl_sendmsg(msg);
}
int rsl_chan_release(struct gsm_lchan *lchan)
{
struct abis_rsl_dchan_hdr *dh;
@ -427,7 +483,7 @@ int rsl_data_request(struct msgb *msg, u_int8_t link_id)
}
/* First push the L3 IE tag and length */
msgb_tv_push(msg, RSL_IE_L3_INFO, l3_len);
msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
/* Then push the RSL header */
rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh));
@ -447,8 +503,27 @@ static int rsl_rx_chan_act_ack(struct msgb *msg)
/* BTS has confirmed channel activation, we now need
* to assign the activated channel to the MS */
if (rslh->ie_chan != RSL_IE_CHAN_NR)
return -EINVAL;
DEBUGP(DRSL, "Channel Activate ACK Channel 0x%02x\n", rslh->chan_nr);
return 0;
}
/* Chapter 8.4.3: Channel Activate NACK */
static int rsl_rx_chan_act_nack(struct msgb *msg)
{
struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
/* BTS has confirmed channel activation, we now need
* to assign the activated channel to the MS */
if (rslh->ie_chan != RSL_IE_CHAN_NR)
return -EINVAL;
DEBUGP(DRSL, "Channel Activate NACK Channel 0x%02x\n", rslh->chan_nr);
return 0;
}
static int abis_rsl_rx_dchan(struct msgb *msg)
@ -460,11 +535,11 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
switch (rslh->c.msg_type) {
case RSL_MT_CHAN_ACTIV_ACK:
DEBUGP(DRSL, "rsl_rx_dchan: Channel Activate ACK\n");
rc = rsl_rx_chan_act_ack(msg);
rc = rsl_rx_chan_act_ack(msg);
break;
case RSL_MT_CHAN_ACTIV_NACK:
DEBUGP(DRSL, "rsl_rx_dchan: Channel Activate NACK\n");
rc = rsl_rx_chan_act_nack(msg);
break;
case RSL_MT_CONN_FAIL:
DEBUGP(DRSL, "rsl_rx_dchan: Connection Fail\n");
@ -503,7 +578,7 @@ static int rsl_rx_error_rep(struct msgb *msg)
return -EINVAL;
cause_len = rslh->data[1];
printf(stdout, "RSL ERROR REPORT, Cause ");
fprintf(stdout, "RSL ERROR REPORT, Cause ");
hexdump(&rslh->data[2], cause_len);
return 0;
@ -577,11 +652,15 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %u\n",
arfcn, ts_number, subch, lchan->type);
#if 0
/* send CHANNEL ACTIVATION on RSL to BTS */
if (lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4)
rsl_chan_activate_sdcch4(lchan->ts, subch);
else
rsl_chan_activate_tch_f(lchan->ts);
#else
rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
#endif
/* create IMMEDIATE ASSIGN 04.08 messge */
memset(&ia, 0, sizeof(ia));
@ -589,7 +668,7 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
ia.proto_discr = GSM48_PDISC_RR;
ia.msg_type = GSM48_MT_RR_IMM_ASS;
ia.page_mode = GSM48_PM_NORMAL;
ia.chan_desc.chan_nr = rsl_enc_chan_nr(RSL_CHAN_SDCCH4_ACCH, subch, ts_number);
ia.chan_desc.chan_nr = lchan2chan_nr(lchan);
ia.chan_desc.h0.h = 0;
ia.chan_desc.h0.arfcn_high = arfcn >> 8;
ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
@ -633,6 +712,16 @@ static int abis_rsl_rx_cchan(struct msgb *msg)
return rc;
}
static int rsl_rx_rll_err_ind(struct msgb *msg)
{
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
u_int8_t *rlm_cause = rllh->data;
DEBUGP(DRLL, "RLL ERROR INDICATION: chan_nr=0x%02x cause=0x%02x\n",
rllh->chan_nr, rlm_cause[1]);
return 0;
}
/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
0x02, 0x06,
0x01, 0x20,
@ -648,19 +737,25 @@ static int abis_rsl_rx_rll(struct msgb *msg)
switch (rllh->c.msg_type) {
case RSL_MT_DATA_IND:
DEBUGP(DRLL, "DATA INDICATION\n");
DEBUGP(DRLL, "DATA INDICATION chan_nr=0x%02x\n", rllh->chan_nr);
/* FIXME: Verify L3 info element */
msg->l3h = &rllh->data[3];
rc = gsm0408_rcvmsg(msg);
break;
case RSL_MT_EST_IND:
DEBUGP(DRLL, "ESTABLISH INDICATION\n");
DEBUGP(DRLL, "ESTABLISH INDICATION chan_nr=0x%02x\n", rllh->chan_nr);
/* FIXME: Verify L3 info element */
msg->l3h = &rllh->data[3];
rc = gsm0408_rcvmsg(msg);
break;
case RSL_MT_ERROR_IND:
case RSL_MT_REL_IND:
DEBUGP(DRLL, "RELEASE INDICATION chan_nr=0x%02x\n", rllh->chan_nr);
lchan_free(msg->lchan);
rc = 0;
break;
case RSL_MT_ERROR_IND:
rc = rsl_rx_rll_err_ind(msg);
break;
case RSL_MT_UNIT_DATA_IND:
fprintf(stderr, "unimplemented Abis RLL message type 0x%02x\n",
rllh->c.msg_type);

View File

@ -27,6 +27,7 @@
#include <openbsc/gsm_data.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/abis_nm.h>
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
enum gsm_phys_chan_config pchan)
@ -46,6 +47,14 @@ struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
return ts;
}
static const enum abis_nm_chan_comb chcomb4pchan[] = {
[GSM_PCHAN_CCCH] = NM_CHANC_mainBCCH,
[GSM_PCHAN_CCCH_SDCCH4] = NM_CHANC_BCCCHComb,
[GSM_PCHAN_TCH_F] = NM_CHANC_TCHFull,
[GSM_PCHAN_TCH_H] = NM_CHANC_TCHHalf,
[GSM_PCHAN_SDCCH8_SACCH8C] = NM_CHANC_SDCCH,
/* FIXME: bounds check */
};
/* Allocate a logical channel (TS) */
struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
@ -58,6 +67,8 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
struct gsm_bts_trx_ts *ts = &trx->ts[j];
if (ts->pchan == GSM_PCHAN_NONE) {
ts->pchan = pchan;
/* set channel attribute on OML */
abis_nm_set_channel_attr(ts, chcomb4pchan[pchan]);
return ts;
}
}

View File

@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <openbsc/msgb.h>
#include <openbsc/debug.h>
@ -64,11 +65,11 @@ static void parse_lai(struct gsm_lai *lai, const struct gsm48_loc_area_id *lai48
static void to_bcd(u_int8_t *bcd, u_int16_t val)
{
bcd[0] = val % 10;
bcd[2] = val % 10;
val = val / 10;
bcd[1] = val % 10;
val = val / 10;
bcd[2] = val % 10;
bcd[0] = val % 10;
val = val / 10;
}
@ -82,10 +83,16 @@ static void generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
lai48->digits[1] = bcd[2];
to_bcd(bcd, mnc);
/* FIXME: do we need three-digit MNC? See Table 10.5.3 */
#if 0
lai48->digits[1] |= bcd[2] << 4;
lai48->digits[2] = bcd[0] | (bcd[1] << 4);
#else
lai48->digits[1] |= 0xf << 4;
lai48->digits[2] = bcd[1] | (bcd[2] << 4);
#endif
lai48->lac = lac;
lai48->lac = htons(lac);
}
#define TMSI_LEN 4
@ -93,12 +100,13 @@ static void generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
static void generate_mid_from_tmsi(u_int8_t *buf, u_int8_t *tmsi_bcd)
{
buf[0] = MID_TMSI_LEN;
buf[1] = 0xf0 | GSM_MI_TYPE_TMSI;
buf[2] = tmsi_bcd[0];
buf[3] = tmsi_bcd[1];
buf[4] = tmsi_bcd[2];
buf[5] = tmsi_bcd[3];
buf[0] = GSM48_IE_MOBILE_ID;
buf[1] = MID_TMSI_LEN;
buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
buf[3] = tmsi_bcd[0];
buf[4] = tmsi_bcd[1];
buf[5] = tmsi_bcd[2];
buf[6] = tmsi_bcd[3];
}
static struct msgb *gsm48_msgb_alloc(void)
@ -111,14 +119,45 @@ static int gsm0408_sendmsg(struct msgb *msg)
if (msg->lchan)
msg->trx = msg->lchan->ts->trx;
msg->l3h = msg->data;
return rsl_data_request(msg, 0);
}
static int gsm48_cc_tx_status(struct gsm_lchan *lchan)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
u_int8_t *cause, *call_state;
msg->lchan = lchan;
gh->proto_discr = GSM48_PDISC_CC;
gh->msg_type = GSM48_MT_CC_STATUS;
cause = msgb_put(msg, 3);
cause[0] = 2;
cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
cause[2] = 0x80 | 30; /* response to status inquiry */
call_state = msgb_put(msg, 1);
call_state[0] = 0xc0 | 0x00;
return gsm0408_sendmsg(msg);
}
static int gsm48_cc_rx_status_enq(struct msgb *msg)
{
return gsm48_cc_tx_status(msg->lchan);
}
static int gsm0408_rcv_cc(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t msg_type = gh->msg_type & 0xbf;
int rc = 0;
switch (gh->msg_type & 0xbf) {
switch (msg_type) {
case GSM48_MT_CC_CALL_CONF:
/* Response to SETUP */
DEBUGP(DCC, "CALL CONFIRM\n");
@ -137,18 +176,27 @@ static int gsm0408_rcv_cc(struct msgb *msg)
DEBUGP(DCC, "RELEASE\n");
/* need to respond with RELEASE_COMPLETE */
break;
case GSM48_MT_CC_EMERG_SETUP:
//DEBUGP(DCC, "EMERGENCY SETUP\n");
case GSM48_MT_CC_STATUS_ENQ:
rc = gsm48_cc_rx_status_enq(msg);
break;
case GSM48_MT_CC_DISCONNECT:
DEBUGP(DCC, "DISCONNECT\n");
break;
case GSM48_MT_CC_SETUP:
//DEBUGP(DCC, "SETUP\n");
DEBUGP(DCC, "SETUP\n");
/* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
break;
case GSM48_MT_CC_EMERG_SETUP:
DEBUGP(DCC, "EMERGENCY SETUP\n");
/* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
break;
default:
fprintf(stderr, "Unimplemented GSM 04.08 msg type 0x%02x\n",
gh->msg_type);
msg_type);
break;
}
return 0;
return rc;
}
/* Chapter 9.2.14 : Send LOCATION UPDATE REJECT */
@ -209,11 +257,12 @@ static int mm_loc_upd_req(struct msgb *msg)
mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
DEBUGP(DMM, "LUPDREQ: mi_type = 0x%02x\n", mi_type);
switch (mi_type) {
case GSM_MI_TYPE_IMSI:
/* look up subscriber based on IMSI */
subscr = subscr_get_by_imsi(&lu->mi[1]);
break;
break;
case GSM_MI_TYPE_TMSI:
/* look up the subscriber based on TMSI, request IMSI if it fails */
subscr = subscr_get_by_tmsi(&lu->mi[1]);
@ -244,6 +293,29 @@ static int mm_loc_upd_req(struct msgb *msg)
return gsm0408_loc_upd_acc(msg->lchan, subscr->tmsi);
}
static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
msg->lchan = lchan;
gh->proto_discr = GSM48_PDISC_MM;
gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
DEBUGP(DMM, "-> CM SERVICE ACK\n");
return gsm0408_sendmsg(msg);
}
static int gsm48_rx_mm_serv_req(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
DEBUGP(DMM, "CM SERVICE REQUEST\n");
return gsm48_tx_mm_serv_ack(msg->lchan);
}
static int gsm0408_rcv_mm(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
@ -259,6 +331,8 @@ static int gsm0408_rcv_mm(struct msgb *msg)
case GSM48_MT_MM_AUTH_RESP:
case GSM48_MT_MM_IMSI_DETACH_IND:
case GSM48_MT_MM_CM_SERV_REQ:
rc = gsm48_rx_mm_serv_req(msg);
break;
case GSM48_MT_MM_CM_REEST_REQ:
fprintf(stderr, "Unimplemented GSM 04.08 MM msg type 0x%02x\n",
gh->msg_type);