diff --git a/src/host/layer23/include/osmocom/gsm322.h b/src/host/layer23/include/osmocom/gsm322.h index 6cb1677bf..3a275b125 100755 --- a/src/host/layer23/include/osmocom/gsm322.h +++ b/src/host/layer23/include/osmocom/gsm322.h @@ -191,5 +191,8 @@ int gsm322_dump_ba_list(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc, void (*print)(void *, const char *, ...), void *priv); void start_cs_timer(struct gsm322_cellsel *cs, int sec, int micro); void start_loss_timer(struct gsm322_cellsel *cs, int sec, int micro); +extern const char *plmn_a_state_names[]; +extern const char *plmn_m_state_names[]; +extern const char *cs_state_names[]; #endif /* _GSM322_H */ diff --git a/src/host/layer23/include/osmocom/gsm48_mm.h b/src/host/layer23/include/osmocom/gsm48_mm.h index ad71ce0d2..22c598357 100644 --- a/src/host/layer23/include/osmocom/gsm48_mm.h +++ b/src/host/layer23/include/osmocom/gsm48_mm.h @@ -221,5 +221,7 @@ struct msgb *gsm48_mmxx_msgb_alloc(int msg_type, uint32_t ref, uint8_t transaction_id); const char *get_mmr_name(int value); const char *get_mmxx_name(int value); +extern const char *gsm48_mm_state_names[]; +extern const char *gsm48_mm_substate_names[]; #endif /* _GSM48_MM_H */ diff --git a/src/host/layer23/include/osmocom/gsm48_rr.h b/src/host/layer23/include/osmocom/gsm48_rr.h index cde5433b2..4fc7547a8 100644 --- a/src/host/layer23/include/osmocom/gsm48_rr.h +++ b/src/host/layer23/include/osmocom/gsm48_rr.h @@ -154,5 +154,6 @@ int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc, int gsm48_rr_enc_cm2(struct osmocom_ms *ms, struct gsm48_classmark2 *cm); int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg); int gsm48_rr_los(struct osmocom_ms *ms); +extern const char *gsm48_rr_state_names[]; #endif /* _GSM48_RR_H */ diff --git a/src/host/layer23/src/gsm48_cc.c b/src/host/layer23/src/gsm48_cc.c index 7a56366fa..386fe80be 100644 --- a/src/host/layer23/src/gsm48_cc.c +++ b/src/host/layer23/src/gsm48_cc.c @@ -246,7 +246,6 @@ static void new_cc_state(struct gsm_trans *trans, int state) static void gsm48_cc_timeout(void *arg) { struct gsm_trans *trans = arg; - struct osmocom_ms *ms = trans->ms; int disconnect = 0, release = 0, abort = 1; int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER; int mo_location = GSM48_CAUSE_LOC_PRN_S_LU; @@ -1817,46 +1816,63 @@ static struct downstate { /* mobile originating call establishment */ {SBIT(GSM_CSTATE_NULL), /* 5.2.1 */ MNCC_SETUP_REQ, gsm48_cc_init_mm}, + {SBIT(GSM_CSTATE_MM_CONNECTION_PEND), /* 5.2.1 */ MNCC_REL_REQ, gsm48_cc_abort_mm}, + /* mobile terminating call establishment */ {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.3.1 */ MNCC_CALL_CONF_REQ, gsm48_cc_tx_call_conf}, + {SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* 5.2.2.3.2 */ MNCC_ALERT_REQ, gsm48_cc_tx_alerting}, + {SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* 5.2.2.5 */ MNCC_SETUP_RSP, gsm48_cc_tx_connect}, + /* signalling during call */ {SBIT(GSM_CSTATE_ACTIVE), /* 5.3.1 */ MNCC_NOTIFY_REQ, gsm48_cc_tx_notify}, + {ALL_STATES, /* 5.5.7.1 */ MNCC_START_DTMF_REQ, gsm48_cc_tx_start_dtmf}, + {ALL_STATES, /* 5.5.7.3 */ MNCC_STOP_DTMF_REQ, gsm48_cc_tx_stop_dtmf}, + {SBIT(GSM_CSTATE_ACTIVE), MNCC_HOLD_REQ, gsm48_cc_tx_hold}, + {SBIT(GSM_CSTATE_ACTIVE), MNCC_RETRIEVE_REQ, gsm48_cc_tx_retrieve}, + {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), MNCC_FACILITY_REQ, gsm48_cc_tx_facility}, + {SBIT(GSM_CSTATE_ACTIVE), MNCC_USERINFO_REQ, gsm48_cc_tx_userinfo}, + /* clearing */ {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_DISCONNECT_IND) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_REQ), /* 5.4.3.1 */ MNCC_DISC_REQ, gsm48_cc_tx_disconnect}, + {SBIT(GSM_CSTATE_INITIATED), MNCC_REJ_REQ, gsm48_cc_tx_release_compl}, + {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ), /* ??? */ MNCC_REL_REQ, gsm48_cc_tx_release}, + /* modify */ {SBIT(GSM_CSTATE_ACTIVE), MNCC_MODIFY_REQ, gsm48_cc_tx_modify}, + {SBIT(GSM_CSTATE_MO_ORIG_MODIFY), MNCC_MODIFY_RSP, gsm48_cc_tx_modify_complete}, + {SBIT(GSM_CSTATE_MO_ORIG_MODIFY), MNCC_MODIFY_REJ, gsm48_cc_tx_modify_reject}, }; @@ -1923,56 +1939,78 @@ static struct datastate { /* mobile originating call establishment */ {SBIT(GSM_CSTATE_INITIATED), /* 5.2.1.3 */ GSM48_MT_CC_CALL_PROC, gsm48_cc_rx_call_proceeding}, + {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC) | SBIT(GSM_CSTATE_CALL_DELIVERED), /* 5.2.1.4.1 */ MNCC_PROGRESS_REQ, gsm48_cc_rx_progress}, + {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC), /* 5.2.1.5 */ GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting}, + {SBIT(GSM_CSTATE_INITIATED) | SBIT(GSM_CSTATE_MO_CALL_PROC) | SBIT(GSM_CSTATE_CALL_DELIVERED), /* 5.2.1.6 */ GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect}, + /* mobile terminating call establishment */ {SBIT(GSM_CSTATE_NULL), /* 5.2.2.1 */ GSM48_MT_CC_SETUP, gsm48_cc_rx_setup}, + {SBIT(GSM_CSTATE_CALL_PRESENT), /* 5.2.2.6 */ GSM48_MT_CC_CONNECT_ACK, gsm48_cc_rx_connect_ack}, + /* signalling during call */ {SBIT(GSM_CSTATE_ACTIVE), /* 5.3.1 */ GSM48_MT_CC_NOTIFY, gsm48_cc_rx_notify}, + {ALL_STATES, /* 8.4 */ GSM48_MT_CC_STATUS_ENQ, gsm48_cc_rx_status_enq}, + {ALL_STATES, /* 5.5.7.2 */ GSM48_MT_CC_START_DTMF_ACK, gsm48_cc_rx_start_dtmf_ack}, + {ALL_STATES, /* 5.5.7.2 */ GSM48_MT_CC_START_DTMF_REJ, gsm48_cc_rx_start_dtmf_rej}, + {ALL_STATES, /* 5.5.7.4 */ GSM48_MT_CC_STOP_DTMF_ACK, gsm48_cc_rx_stop_dtmf_ack}, + {SBIT(GSM_CSTATE_ACTIVE), GSM48_MT_CC_HOLD_ACK, gsm48_cc_rx_hold_ack}, + {SBIT(GSM_CSTATE_ACTIVE), GSM48_MT_CC_HOLD_REJ, gsm48_cc_rx_hold_rej}, + {SBIT(GSM_CSTATE_ACTIVE), GSM48_MT_CC_RETR_ACK, gsm48_cc_rx_retrieve_ack}, + {SBIT(GSM_CSTATE_ACTIVE), GSM48_MT_CC_RETR_REJ, gsm48_cc_rx_retrieve_rej}, + {ALL_STATES - SBIT(GSM_CSTATE_NULL), GSM48_MT_CC_FACILITY, gsm48_cc_rx_facility}, + {SBIT(GSM_CSTATE_ACTIVE), GSM48_MT_CC_USER_INFO, gsm48_cc_rx_userinfo}, + /* clearing */ {ALL_STATES - SBIT(GSM_CSTATE_NULL) - SBIT(GSM_CSTATE_RELEASE_REQ) - SBIT(GSM_CSTATE_DISCONNECT_IND), /* 5.4.4.1.1 */ GSM48_MT_CC_DISCONNECT, gsm48_cc_rx_disconnect}, + {ALL_STATES - SBIT(GSM_CSTATE_NULL), /* 5.4.3.3 & 5.4.5!!!*/ GSM48_MT_CC_RELEASE, gsm48_cc_rx_release}, + {ALL_STATES, /* 5.4.4.1.3 */ GSM48_MT_CC_RELEASE_COMPL, gsm48_cc_rx_release_compl}, + /* modify */ {SBIT(GSM_CSTATE_ACTIVE), GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify}, + {SBIT(GSM_CSTATE_MO_TERM_MODIFY), GSM48_MT_CC_MODIFY_COMPL, gsm48_cc_rx_modify_complete}, + {SBIT(GSM_CSTATE_MO_TERM_MODIFY), GSM48_MT_CC_MODIFY_REJECT, gsm48_cc_rx_modify_reject}, }; diff --git a/src/host/layer23/src/gsm48_mm.c b/src/host/layer23/src/gsm48_mm.c index 9f08520c0..4b2e723d5 100644 --- a/src/host/layer23/src/gsm48_mm.c +++ b/src/host/layer23/src/gsm48_mm.c @@ -819,45 +819,45 @@ static int gsm48_mm_to_rr(struct osmocom_ms *ms, struct msgb *msg, * state transition */ -static const char *gsm48_mm_state_names[] = { +const char *gsm48_mm_state_names[] = { "NULL", "undefined 1", "undefined 2", - "LOC_UPD_INIT", + "location updating initiated", "undefined 4", - "WAIT_OUT_MM_CONN", - "MM_CONN_ACTIVE", - "IMSI_DETACH_INIT", - "PROCESS_CM_SERV_P", - "WAIT_NETWORK_CMD", - "LOC_UPD_REJ", + "wait for outgoing MM connection", + "MM connection active", + "IMSI detach initiated", + "process CM service prompt", + "wait for network command", + "location updating reject", "undefined 11", "undefined 12", - "WAIT_RR_CONN_LUPD", - "WAIT_RR_CONN_MM_CON", - "WAIT_RR_CONN_IMSI_D", + "wait for RR connection (location updating)", + "wait for RR connection (MM connection)", + "wait for RR connection (IMSI detach)", "undefined 16", - "WAIT_REEST", - "WAIT_RR_ACTIVE", - "MM_IDLE", - "WAIT_ADD_OUT_MM_CON", + "wait for re-establishment", + "wait for RR connection active", + "MM idle", + "wait for additional outgoing MM connection", "MM_CONN_ACTIVE_VGCS", "WAIT_RR_CONN_VGCS", - "LOC_UPD_PEND", - "IMSI_DETACH_PEND", - "RR_CONN_RELEASE_NA" + "location updating pending", + "IMSI detach pending", + "RR connection release not allowed" }; -static const char *gsm48_mm_substate_names[] = { +const char *gsm48_mm_substate_names[] = { "NULL", - "NORMAL_SERVICE", - "ATTEMPT_UPDATE", - "LIMITED_SERVICE", - "NO_IMSI", - "NO_CELL_AVAIL", - "LOC_UPD_NEEDED", - "PLMN_SEARCH", - "PLMN_SEARCH_NORMAL", + "normal service", + "attempting to update", + "limited service", + "no IMSI", + "no cell available", + "location updating needed", + "PLMN search", + "PLMN search (normal)", "RX_VGCS_NORMAL", "RX_VGCS_LIMITED" }; diff --git a/src/host/layer23/src/gsm48_rr.c b/src/host/layer23/src/gsm48_rr.c index ed0328450..ef1389363 100644 --- a/src/host/layer23/src/gsm48_rr.c +++ b/src/host/layer23/src/gsm48_rr.c @@ -192,11 +192,11 @@ static int gsm48_decode_ba_range(const uint8_t *ba, uint8_t ba_len, * state transition */ -static const char *gsm48_rr_state_names[] = { - "IDLE", - "CONN PEND", - "DEDICATED", - "REL PEND", +const char *gsm48_rr_state_names[] = { + "idle", + "connection pending", + "dedicated", + "release pending", }; static void new_rr_state(struct gsm48_rrlayer *rr, int state) @@ -2507,54 +2507,6 @@ static int gsm48_match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref) return 0; } -/* 9.1.3 sending ASSIGNMENT COMPLETE */ -static int gsm48_rr_tx_ass_cpl(struct osmocom_ms *ms, uint8_t cause) -{ - struct msgb *nmsg; - struct gsm48_hdr *gh; - struct gsm48_ass_cpl *ac; - - LOGP(DRR, LOGL_INFO, "ASSIGNMENT COMPLETE (cause #%d)\n", cause); - - nmsg = gsm48_l3_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh)); - ac = (struct gsm48_ass_cpl *) msgb_put(nmsg, sizeof(*ac)); - - gh->proto_discr = GSM48_PDISC_RR; - gh->msg_type = GSM48_MT_RR_ASS_COMPL; - - /* RR_CAUSE */ - ac->rr_cause = cause; - - return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg); -} - -/* 9.1.4 sending ASSIGNMENT FAILURE */ -static int gsm48_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause) -{ - struct msgb *nmsg; - struct gsm48_hdr *gh; - struct gsm48_ass_fail *af; - - LOGP(DRR, LOGL_INFO, "ASSIGNMENT FAILURE (cause #%d)\n", cause); - - nmsg = gsm48_l3_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh)); - af = (struct gsm48_ass_fail *) msgb_put(nmsg, sizeof(*af)); - - gh->proto_discr = GSM48_PDISC_RR; - gh->msg_type = GSM48_MT_RR_ASS_COMPL; - - /* RR_CAUSE */ - af->rr_cause = cause; - - return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg); -} - /* 9.1.18 IMMEDIATE ASSIGNMENT is received */ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg) { @@ -3117,6 +3069,145 @@ static int gsm48_rr_rx_chan_rel(struct osmocom_ms *ms, struct msgb *msg) return gsm48_send_rsl(ms, RSL_MT_REL_REQ, nmsg); } +/* + * assignment and handover + */ + +/* 9.1.3 sending ASSIGNMENT COMPLETE */ +static int gsm48_rr_tx_ass_cpl(struct osmocom_ms *ms, uint8_t cause) +{ + struct msgb *nmsg; + struct gsm48_hdr *gh; + struct gsm48_ass_cpl *ac; + + LOGP(DRR, LOGL_INFO, "ASSIGNMENT COMPLETE (cause #%d)\n", cause); + + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh)); + ac = (struct gsm48_ass_cpl *) msgb_put(nmsg, sizeof(*ac)); + + gh->proto_discr = GSM48_PDISC_RR; + gh->msg_type = GSM48_MT_RR_ASS_COMPL; + + /* RR_CAUSE */ + ac->rr_cause = cause; + + return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg); +} + +/* 9.1.4 sending ASSIGNMENT FAILURE */ +static int gsm48_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause) +{ + struct msgb *nmsg; + struct gsm48_hdr *gh; + struct gsm48_ass_fail *af; + + LOGP(DRR, LOGL_INFO, "ASSIGNMENT FAILURE (cause #%d)\n", cause); + + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh)); + af = (struct gsm48_ass_fail *) msgb_put(nmsg, sizeof(*af)); + + gh->proto_discr = GSM48_PDISC_RR; + gh->msg_type = GSM48_MT_RR_ASS_COMPL; + + /* RR_CAUSE */ + af->rr_cause = cause; + + return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg); +} + +/* 9.1.2 ASSIGNMENT COMMAND is received */ +static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg) +{ +// struct gsm48_rrlayer *rr = &ms->rrlayer; + struct gsm48_hdr *gh = msgb_l3(msg); + struct gsm48_ass_cmd *ac = (struct gsm48_ass_cmd *)gh->data; + int payload_len = msgb_l3len(msg) - sizeof(*gh) - sizeof(*ac); + struct tlv_parsed tp; + struct gsm48_rr_cd cd; + + LOGP(DRR, LOGL_INFO, "ASSIGNMENT COMMAND\n"); + + memset(&cd, 0, sizeof(cd)); + + if (payload_len < 0) { + LOGP(DRR, LOGL_NOTICE, "Short read of ASSIGNMENT COMMAND message.\n"); + return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + } + tlv_parse(&tp, &gsm48_rr_att_tlvdef, ac->data, payload_len, 0, 0); + +#if 0 + /* channel description */ + memcpy(&cd.chan_desc, &ac->chan_desc, sizeof(chan_desc)); + /* power command */ + cd.power_command = ac->power_command; + /* frequency list, after timer */ + tlv_copy(&cd.fl, sizeof(fl_after), &tp, GSM48_IE_FRQLIST_AFTER); + /* cell channel description */ + tlv_copy(&cd.ccd, sizeof(ccd), &tp, GSM48_IE_CELL_CH_DESC); + /* multislot allocation */ + tlv_copy(&cd.multia, sizeof(ma), &tp, GSM48_IE_MSLOT_DESC); + /* channel mode */ + tlv_copy(&cd.chanmode, sizeof(chanmode), &tp, GSM48_IE_CHANMODE_1); + /* mobile allocation, after time */ + tlv_copy(&cd.moba_after, sizeof(moba_after), &tp, GSM48_IE_MOB_AL_AFTER); + /* starting time */ + tlv_copy(&cd.start, sizeof(start), &tp, GSM_IE_START_TIME); + /* frequency list, before time */ + tlv_copy(&cd.fl_before, sizeof(fl_before), &tp, GSM48_IE_FRQLIST_BEFORE); + /* channel description, before time */ + tlv_copy(&cd.chan_desc_before, sizeof(cd_before), &tp, GSM48_IE_CHDES_1_BEFORE); + /* frequency channel sequence, before time */ + tlv_copy(&cd.fcs_before, sizeof(fcs_before), &tp, GSM48_IE_FRQSEQ_BEFORE); + /* mobile allocation, before time */ + tlv_copy(&cd.moba_before, sizeof(moba_before), &tp, GSM48_IE_MOB_AL_BEFORE); + /* cipher mode setting */ + if (TLVP_PRESENT(&tp, GSM48_IE_CIP_MODE_SET)) + cd.cipher = *TLVP_VAL(&tp, GSM48_IE_CIP_MODE_SET); + else + cd.cipher = 0; + + if (no CA) { + LOGP(DRR, LOGL_INFO, "No current cell allocation available.\n"); + return gsm48_rr_tx_ass_fail(ms, GSM48_GSM48_RR_CAUSE_NO_CELL_ALLOC_A); + } + + if (not supported) { + LOGP(DRR, LOGL_INFO, "New channel is not supported.\n"); + return gsm48_rr_tx_ass_fail(ms, GSM48_RR_CAUSE_CHAN_MODE_UNACCEPT); + } + + if (freq not supported) { + LOGP(DRR, LOGL_INFO, "New frequency is not supported.\n"); + return gsm48_rr_tx_ass_fail(ms, GSM48_RR_CAUSE_FREQ_NOT_IMPL); + } + + /* store current channel descriptions, to return in case of failure */ + memcpy(&rr->chan_last, &rr->chan_desc, sizeof(*cd)); + /* copy new description */ + memcpy(&rr->chan_desc, cd, sizeof(cd)); + + /* start suspension of current link */ + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + gsm48_send_rsl(ms, RSL_MT_SUSP_REQ, msg); + + /* change into special assignment suspension state */ + rr->assign_susp_state = 1; + rr->resume_last_state = 0; +#else + return gsm48_rr_tx_ass_fail(ms, GSM48_RR_CAUSE_FREQ_NOT_IMPL); +#endif + + return 0; +} + /* * radio ressource requests */ @@ -3285,10 +3376,10 @@ static int gsm48_rr_data_ind(struct osmocom_ms *ms, struct msgb *msg) case GSM48_MT_RR_ADD_ASS: rc = gsm48_rr_rx_add_ass(ms, msg); break; -#if 0 case GSM48_MT_RR_ASS_CMD: rc = gsm48_rr_rx_ass_cmd(ms, msg); break; +#if 0 case GSM48_MT_RR_CIP_MODE_CMD: rc = gsm48_rr_rx_cip_mode_cmd(ms, msg); break; @@ -3787,12 +3878,6 @@ incomplete todo: -add support structure -initialize support structure - -queue messages (rslms_data_req) if channel changes - -flush rach msg in all cases: during sending, after its done, and when aborted stop timers on abort wird beim abbruch immer der gepufferte cm-service-request entfernt, auch beim verschicken?: measurement reports @@ -3800,15 +3885,6 @@ todo rr_sync_ind when receiving ciph, re ass, channel mode modify todo change procedures, release procedure -during procedures, like "channel assignment" or "handover", rr requests must be queued -they must be dequeued when complete -they queue must be flushed when rr fails - -#include -#include -#include -#include - static int gsm48_rr_act_req(struct osmocom_ms *ms, struct gsm48_rr *rrmsg) { } @@ -3839,87 +3915,6 @@ static int tlv_copy(void *dest, int dest_len, struct tlv_parsed *tp, uint8_t ie) return 0; } -static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg) -{ - struct gsm48_rrlayer *rr = ms->rrlayer; - struct gsm48_hdr *gh = msgb_l3(msg); - struct gsm48_ass_cmd *ac = (struct gsm48_ass_cmd *)gh->data; - int payload_len = msgb_l3len(msg) - sizeof(*gh) - sizeof(*ac); - struct tlv_parsed tp; - struct gsm48_rr_chan_desc cd; - struct msgb *nmsg; - - memset(&cd, 0, sizeof(cd)); - - if (payload_len < 0) { - LOGP(DRR, LOGL_NOTICE, "Short read of ASSIGNMENT COMMAND message.\n"); - return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC); - } - tlv_parse(&tp, &gsm48_rr_att_tlvdef, ac->data, payload_len, 0, 0); - - /* channel description */ - memcpy(&cd.chan_desc, &ac->chan_desc, sizeof(chan_desc)); - /* power command */ - cd.power_command = ac->power_command; - /* frequency list, after timer */ - tlv_copy(&cd.fl, sizeof(fl_after), &tp, GSM48_IE_FRQLIST_AFTER); - /* cell channel description */ - tlv_copy(&cd.ccd, sizeof(ccd), &tp, GSM48_IE_CELL_CH_DESC); - /* multislot allocation */ - tlv_copy(&cd.multia, sizeof(ma), &tp, GSM48_IE_MSLOT_DESC); - /* channel mode */ - tlv_copy(&cd.chanmode, sizeof(chanmode), &tp, GSM48_IE_CHANMODE_1); - /* mobile allocation, after time */ - tlv_copy(&cd.moba_after, sizeof(moba_after), &tp, GSM48_IE_MOB_AL_AFTER); - /* starting time */ - tlv_copy(&cd.start, sizeof(start), &tp, GSM_IE_START_TIME); - /* frequency list, before time */ - tlv_copy(&cd.fl_before, sizeof(fl_before), &tp, GSM48_IE_FRQLIST_BEFORE); - /* channel description, before time */ - tlv_copy(&cd.chan_desc_before, sizeof(cd_before), &tp, GSM48_IE_CHDES_1_BEFORE); - /* frequency channel sequence, before time */ - tlv_copy(&cd.fcs_before, sizeof(fcs_before), &tp, GSM48_IE_FRQSEQ_BEFORE); - /* mobile allocation, before time */ - tlv_copy(&cd.moba_before, sizeof(moba_before), &tp, GSM48_IE_MOB_AL_BEFORE); - /* cipher mode setting */ - if (TLVP_PRESENT(&tp, GSM48_IE_CIP_MODE_SET)) - cd.cipher = *TLVP_VAL(&tp, GSM48_IE_CIP_MODE_SET); - else - cd.cipher = 0; - - if (no CA) { - LOGP(DRR, LOGL_INFO, "No current cell allocation available.\n"); - return gsm48_rr_tx_rr_status(ms, GSM48_RR_CAUSE_NO_CELL_ALLOC_A); - } - - if (not supported) { - LOGP(DRR, LOGL_INFO, "New channel is not supported.\n"); - return gsm48_rr_tx_rr_status(ms, RR_CAUSE_CHAN_MODE_UNACCEPT); - } - - if (freq not supported) { - LOGP(DRR, LOGL_INFO, "New frequency is not supported.\n"); - return gsm48_rr_tx_rr_status(ms, RR_CAUSE_FREQ_NOT_IMPLEMENTED); - } - - /* store current channel descriptions, to return in case of failure */ - memcpy(&rr->chan_last, &rr->chan_desc, sizeof(*cd)); - /* copy new description */ - memcpy(&rr->chan_desc, cd, sizeof(cd)); - - /* start suspension of current link */ - nmsg = gsm48_l3_msgb_alloc(); - if (!nmsg) - return -ENOMEM; - gsm48_send_rsl(ms, RSL_MT_SUSP_REQ, msg); - - /* change into special assignment suspension state */ - rr->assign_susp_state = 1; - rr->resume_last_state = 0; - - return 0; -} - /* decode "Cell Description" (10.5.2.2) */ static int gsm48_decode_cell_desc(struct gsm48_cell_desc *cd, uint16_t *arfcn, uint8_t *ncc uint8_t *bcc) @@ -3953,7 +3948,7 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg) struct gsm48_ho_cmd *ho = (struct gsm48_ho_cmd *)gh->data; int payload_len = msgb_l3len(msg) - sizeof(*gh) - wirklich sizeof(*ho); struct tlv_parsed tp; - struct gsm48_rr_chan_desc cd; + struct gsm48_rr_cd cd; struct msgb *nmsg; memset(&cd, 0, sizeof(cd)); @@ -4012,7 +4007,7 @@ static int gsm48_rr_estab_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg) rr->resume_last_state = 0; gsm48_rr_tx_ass_cpl(ms, GSM48_RR_CAUSE_NORMAL); } else { - gsm48_rr_tx_ass_fail(ms, RR_CAUSE_PROTO_ERR_UNSPEC); + gsm48_rr_tx_ass_fail(ms, GSM48_RR_CAUSE_PROTO_ERR_UNSPEC); } /* transmit queued frames during ho / ass transition */ gsm48_rr_dequeue_down(ms); diff --git a/src/host/layer23/src/vty_interface.c b/src/host/layer23/src/vty_interface.c index 3e9216694..5d43e9710 100644 --- a/src/host/layer23/src/vty_interface.c +++ b/src/host/layer23/src/vty_interface.c @@ -29,8 +29,11 @@ #include #include +#include #include #include +#include +#include int mncc_call(struct osmocom_ms *ms, char *number); int mncc_hangup(struct osmocom_ms *ms); @@ -128,6 +131,54 @@ DEFUN(show_support, show_support_cmd, "show support [ms_name]", return CMD_SUCCESS; } +static void gsm_states_dump(struct osmocom_ms *ms, struct vty *vty) +{ + struct gsm_trans *trans; + + vty_out(vty, "Current state of MS '%s'%s", ms->name, VTY_NEWLINE); + if (ms->settings.plmn_mode == PLMN_MODE_AUTO) + vty_out(vty, " automatic network selection: %s%s", + plmn_a_state_names[ms->plmn.state], VTY_NEWLINE); + else + vty_out(vty, " manual network selection: %s%s", + plmn_m_state_names[ms->plmn.state], VTY_NEWLINE); + vty_out(vty, " cell selection: %s%s", + cs_state_names[ms->cellsel.state], VTY_NEWLINE); + vty_out(vty, " radio ressource layer: %s%s", + gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE); + vty_out(vty, " mobility management layer: %s", + gsm48_mm_state_names[ms->mmlayer.state]); + if (ms->mmlayer.state == GSM48_MM_ST_MM_IDLE) + vty_out(vty, ", %s", + gsm48_mm_substate_names[ms->mmlayer.substate]); + vty_out(vty, "%s", VTY_NEWLINE); + llist_for_each_entry(trans, &ms->trans_list, entry) { + vty_out(vty, " call control: %s%s", + gsm48_cc_state_name(trans->cc.state), VTY_NEWLINE); + } +} + +DEFUN(show_states, show_states_cmd, "show states [ms_name]", + SHOW_STR "Display current states of given MS\n" + "Name of MS (see \"show ms\")") +{ + struct osmocom_ms *ms; + + if (argc) { + ms = get_ms(argv[0], vty); + if (!ms) + return CMD_WARNING; + gsm_states_dump(ms, vty); + } else { + llist_for_each_entry(ms, &ms_list, entity) { + gsm_states_dump(ms, vty); + vty_out(vty, "%s", VTY_NEWLINE); + } + } + + return CMD_SUCCESS; +} + DEFUN(show_subscr, show_subscr_cmd, "show subscriber [ms_name]", SHOW_STR "Display information about subscriber\n" "Name of MS (see \"show ms\")") @@ -694,6 +745,8 @@ int ms_vty_init(void) install_element(VIEW_NODE, &show_subscr_cmd); install_element(ENABLE_NODE, &show_support_cmd); install_element(VIEW_NODE, &show_support_cmd); + install_element(ENABLE_NODE, &show_states_cmd); + install_element(VIEW_NODE, &show_states_cmd); install_element(ENABLE_NODE, &show_cell_cmd); install_element(VIEW_NODE, &show_cell_cmd); install_element(ENABLE_NODE, &show_cell_si_cmd);