diff options
-rw-r--r-- | include/osmo-bts/oml.h | 1 | ||||
-rw-r--r-- | src/common/oml.c | 5 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/oml.c | 70 |
3 files changed, 72 insertions, 4 deletions
diff --git a/include/osmo-bts/oml.h b/include/osmo-bts/oml.h index 92695cae..4281fd32 100644 --- a/include/osmo-bts/oml.h +++ b/include/osmo-bts/oml.h @@ -10,6 +10,7 @@ int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type); int oml_mo_opstart_ack(struct gsm_abis_mo *mo); int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause); int oml_mo_statechg_ack(struct gsm_abis_mo *mo); +int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause); /* Change the state and send STATE CHG REP */ int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state); diff --git a/src/common/oml.c b/src/common/oml.c index 1c38c666..bf174b5f 100644 --- a/src/common/oml.c +++ b/src/common/oml.c @@ -299,6 +299,11 @@ int oml_mo_statechg_ack(struct gsm_abis_mo *mo) return oml_mo_send_msg(mo, msg, NM_MT_CHG_ADM_STATE_ACK); } +int oml_mo_statechg_nack(struct gsm_abis_mo *mo, uint8_t nack_cause) +{ + return oml_mo_fom_ack_nack(mo, NM_MT_CHG_ADM_STATE, nack_cause); +} + int oml_mo_opstart_ack(struct gsm_abis_mo *mo) { return oml_mo_fom_ack_nack(mo, NM_MT_OPSTART, 0); diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c index 822453f5..c87acb66 100644 --- a/src/osmo-bts-sysmo/oml.c +++ b/src/osmo-bts-sysmo/oml.c @@ -326,10 +326,31 @@ int bts_model_trx_close(struct gsm_bts_trx *trx) return l1if_gsm_req_compl(fl1h, msg, trx_close_compl_cb); } +static int trx_rf_lock(struct gsm_bts_trx *trx, int locked) +{ + struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); + uint8_t mute[8]; + int i; + + for (i = 0; i < ARRAY_SIZE(mute); ++i) + mute[i] = locked ? 1 : 0; + + return l1if_mute_rf(fl1h, mute); +} + int oml_mo_rf_lock_chg(struct gsm_abis_mo *mo, uint8_t mute_state[8], int success) { - return 0; + if (success) { + /* assume mute_state[i] == mute_state[k] */ + mo->nm_state.administrative = + mute_state[0] ? NM_STATE_LOCKED : NM_STATE_UNLOCKED; + mo->procedure_pending = 0; + return oml_mo_statechg_ack(mo); + } else { + mo->procedure_pending = 0; + return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); + } } static int ts_connect(struct gsm_bts_trx_ts *ts) @@ -1461,9 +1482,50 @@ int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj, uint8_t adm_state) { - /* blindly accept all state changes */ - mo->nm_state.administrative = adm_state; - return oml_mo_statechg_ack(mo); + int rc = -EINVAL; + int granted = 0; + + switch (mo->obj_class) { + case NM_OC_RADIO_CARRIER: + + if (mo->procedure_pending) { + LOGP(DL1C, LOGL_ERROR, "Discarding adm change command: " + "pending procedure on RC %d\n", + ((struct gsm_bts_trx *)obj)->nr); + return 0; + } + mo->procedure_pending = 1; + switch (adm_state) { + case NM_STATE_LOCKED: + rc = trx_rf_lock(obj, 1); + break; + case NM_STATE_UNLOCKED: + rc = trx_rf_lock(obj, 0); + break; + default: + granted = 1; + break; + } + + if (!granted && rc == 0) + /* in progress, will send ack/nack after completion */ + return 0; + + mo->procedure_pending = 0; + + break; + default: + /* blindly accept all state changes */ + granted = 1; + break; + } + + if (granted) { + mo->nm_state.administrative = adm_state; + return oml_mo_statechg_ack(mo); + } else + return oml_mo_statechg_nack(mo, NM_NACK_REQ_NOT_GRANT); + } int bts_model_rsl_chan_act(struct gsm_lchan *lchan, struct tlv_parsed *tp) { |