<p>Neels Hofmeyr has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/9669">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">move RSL and RR related functions to abis_rsl.[hc]<br><br>It doesn't make sense to spread them all over the place, and introduces odd<br>dependencies from utility programs or regression test linkages.<br><br>This is a cosmetic patch preparing for lchan activation refactoring.<br><br>Change-Id: Ie8ee334145bf7bc3a601d395ea7ab9b2009b61c7<br>---<br>M include/osmocom/bsc/abis_rsl.h<br>M include/osmocom/bsc/bsc_api.h<br>M include/osmocom/bsc/gsm_04_08_utils.h<br>M src/osmo-bsc/abis_rsl.c<br>M src/osmo-bsc/bsc_api.c<br>M src/osmo-bsc/gsm_04_08_utils.c<br>6 files changed, 594 insertions(+), 593 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/69/9669/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/abis_rsl.h b/include/osmocom/bsc/abis_rsl.h</span><br><span>index 2fe8c38..c04c61a 100644</span><br><span>--- a/include/osmocom/bsc/abis_rsl.h</span><br><span>+++ b/include/osmocom/bsc/abis_rsl.h</span><br><span>@@ -110,5 +110,20 @@</span><br><span> int dyn_ts_switchover_start(struct gsm_bts_trx_ts *ts,</span><br><span> enum gsm_phys_chan_config to_pchan);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *gsm48_create_rr_status(uint8_t cause);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_tx_rr_status(struct gsm_subscriber_connection *conn, uint8_t cause);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);</span><br><span style="color: hsl(120, 100%, 40%);">+int send_siemens_mrpci(struct gsm_lchan *lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *classmark2_lv);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_rx_rr_modif_ack(struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rr_release(struct gsm_lchan *lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t power_command, uint8_t ho_ref);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_command);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif /* RSL_MT_H */</span><br><span> </span><br><span>diff --git a/include/osmocom/bsc/bsc_api.h b/include/osmocom/bsc/bsc_api.h</span><br><span>index a90268b..9e2b44e 100644</span><br><span>--- a/include/osmocom/bsc/bsc_api.h</span><br><span>+++ b/include/osmocom/bsc/bsc_api.h</span><br><span>@@ -28,5 +28,4 @@</span><br><span> unsigned int mi_len, uint8_t *mi, int chan_type);</span><br><span> int gsm0808_clear(struct gsm_subscriber_connection *conn);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);</span><br><span> #endif</span><br><span>diff --git a/include/osmocom/bsc/gsm_04_08_utils.h b/include/osmocom/bsc/gsm_04_08_utils.h</span><br><span>index 4349a37..207ed38 100644</span><br><span>--- a/include/osmocom/bsc/gsm_04_08_utils.h</span><br><span>+++ b/include/osmocom/bsc/gsm_04_08_utils.h</span><br><span>@@ -3,20 +3,11 @@</span><br><span> void gsm_net_update_ctype(struct gsm_network *network);</span><br><span> enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *network, uint8_t ra);</span><br><span> int get_reason_by_chreq(uint8_t ra, int neci);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_rr_release(struct gsm_lchan *lchan);</span><br><span style="color: hsl(0, 100%, 40%);">-int send_siemens_mrpci(struct gsm_lchan *lchan,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *classmark2_lv);</span><br><span> int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn,</span><br><span> struct msgb *msg, struct bsc_subscr *bsub);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);</span><br><span> void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,</span><br><span> const struct gsm_lchan *lchan);</span><br><span> int gsm48_multirate_config(uint8_t *lv, const struct amr_multirate_conf *mr, const struct amr_mode *modes);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t power_command, uint8_t ho_ref);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_command);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_rx_rr_modif_ack(struct msgb *msg);</span><br><span> int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg);</span><br><span> int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);</span><br><span> int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,</span><br><span>@@ -28,9 +19,6 @@</span><br><span> char *mi_string, uint8_t *mi_type);</span><br><span> struct msgb *gsm48_create_loc_upd_rej(uint8_t cause);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct msgb *gsm48_create_rr_status(uint8_t cause);</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_tx_rr_status(struct gsm_subscriber_connection *conn, uint8_t cause);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #define GSM48_ALLOC_SIZE 2048</span><br><span> #define GSM48_ALLOC_HEADROOM 256</span><br><span> </span><br><span>diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c</span><br><span>index ab3658d..b6741a8 100644</span><br><span>--- a/src/osmo-bsc/abis_rsl.c</span><br><span>+++ b/src/osmo-bsc/abis_rsl.c</span><br><span>@@ -3032,3 +3032,582 @@</span><br><span> dyn_ts_init(ts);</span><br><span> return true;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_classmark_chg(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t cm2_len, cm3_len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *cm2, *cm3 = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "CLASSMARK CHANGE ");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* classmark 2 */</span><br><span style="color: hsl(120, 100%, 40%);">+ cm2_len = gh->data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ cm2 = &gh->data[1];</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (payload_len > cm2_len + 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* we must have a classmark3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (gh->data[cm2_len+1] != 0x20) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGPC(DRR, "ERR CM3 TAG\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cm2_len > 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGPC(DRR, "CM2 too long!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cm3_len = gh->data[cm2_len+2];</span><br><span style="color: hsl(120, 100%, 40%);">+ cm3 = &gh->data[cm2_len+3];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cm3_len > 14) {</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_cm_update(conn, cm2, cm2_len, cm3, cm3_len);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Chapter 9.1.16 Handover complete */</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_rr_ho_compl(struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lchan_signal_data sig;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "HANDOVER COMPLETE cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sig.lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ sig.mr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: release old channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+ gscon_dtap_cache_flush(msg->lchan->conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Chapter 9.1.17 Handover Failure */</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_rr_ho_fail(struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lchan_signal_data sig;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Log on both RR and HO categories: it is an RR message, but is still quite important when</span><br><span style="color: hsl(120, 100%, 40%);">+ * filtering on HO. */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DHO, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sig.lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ sig.mr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: release allocated new channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+ gscon_dtap_cache_flush(msg->lchan->conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_ass_compl(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ enum gsm48_rr_cause cause;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Expecting gsm48_hdr + cause value */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msgb_l3len(msg) != sizeof(*gh) + 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "RR Assignment Complete: length invalid: %u, expected %zu\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_l3len(msg), sizeof(*gh) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cause = gh->data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT COMPLETE cause = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ rr_cause_name(cause));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn->ho) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lchan_signal_data sig = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .lchan = msg->lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_COMPL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: release old channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+ gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn->secondary_lchan != msg->lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "RR Assignment Complete does not match conn's secondary lchan.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan_release(conn->lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(120, 100%, 40%);">+ conn->lchan = conn->secondary_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ conn->secondary_lchan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+ gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (is_ipaccess_bts(conn_get_bts(conn)) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)</span><br><span style="color: hsl(120, 100%, 40%);">+ rsl_ipacc_crcx(conn->lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_assign_compl(conn, cause);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void handle_ass_fail(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *rr_failure;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn->ho) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lchan_signal_data sig;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT FAILED cause = %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sig.lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ sig.mr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_FAIL, &sig);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: release allocated new channel */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+ gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn->lchan != msg->lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DMSC, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Assignment failure should occur on primary lchan.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* stop the timer and release it */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (conn->secondary_lchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(120, 100%, 40%);">+ conn->secondary_lchan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send pending messages, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+ gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msgb_l3len(msg) - sizeof(*gh) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(conn->lchan, DMSC, LOGL_ERROR, "assignment failure unhandled: %zu\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_l3len(msg) - sizeof(*gh));</span><br><span style="color: hsl(120, 100%, 40%);">+ rr_failure = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ rr_failure = &gh->data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_assign_fail(conn, GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, rr_failure);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dispatch_dtap(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t link_id, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t pdisc;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t msg_type;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msgb_l3len(msg) < sizeof(*gh)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DMSC, LOGL_ERROR, "(%s) Message too short for a GSM48 header.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_subscr_name(conn->bsub));</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ pdisc = gsm48_hdr_pdisc(gh);</span><br><span style="color: hsl(120, 100%, 40%);">+ msg_type = gsm48_hdr_msg_type(gh);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* the idea is to handle all RR messages here, and only hand</span><br><span style="color: hsl(120, 100%, 40%);">+ * MM/CC/SMS-CP/LCS up to the MSC. Some messages like PAGING</span><br><span style="color: hsl(120, 100%, 40%);">+ * RESPONSE or CM SERVICE REQUEST will not be covered here, as</span><br><span style="color: hsl(120, 100%, 40%);">+ * they are only possible in the first L3 message of each L2</span><br><span style="color: hsl(120, 100%, 40%);">+ * channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()</span><br><span style="color: hsl(120, 100%, 40%);">+ * will call api->compl_l3() for it */</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (pdisc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_PDISC_RR:</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_GPRS_SUSP_REQ:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "%s\n", gsm48_rr_msg_name(GSM48_MT_RR_GPRS_SUSP_REQ));</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_STATUS:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+ "%s (cause: %s)\n", gsm48_rr_msg_name(GSM48_MT_RR_STATUS),</span><br><span style="color: hsl(120, 100%, 40%);">+ rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_MEAS_REP:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* This shouldn't actually end up here, as RSL treats</span><br><span style="color: hsl(120, 100%, 40%);">+ * L3 Info of 08.58 MEASUREMENT REPORT different by calling</span><br><span style="color: hsl(120, 100%, 40%);">+ * directly into gsm48_parse_meas_rep */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DMEAS, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+ "DIRECT GSM48 MEASUREMENT REPORT ?!?\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_HANDO_COMPL:</span><br><span style="color: hsl(120, 100%, 40%);">+ handle_rr_ho_compl(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_HANDO_FAIL:</span><br><span style="color: hsl(120, 100%, 40%);">+ handle_rr_ho_fail(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_CIPH_M_COMPL:</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_cipher_mode_compl(conn, msg, conn->lchan->encr.alg_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_ASS_COMPL:</span><br><span style="color: hsl(120, 100%, 40%);">+ handle_ass_compl(conn, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_ASS_FAIL:</span><br><span style="color: hsl(120, 100%, 40%);">+ handle_ass_fail(conn, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = gsm48_rx_rr_modif_ack(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_assign_fail(conn, GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_assign_compl(conn, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_CLSM_CHG:</span><br><span style="color: hsl(120, 100%, 40%);">+ handle_classmark_chg(conn, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_MT_RR_APP_INFO:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Passing RR APP INFO to MSC, not quite</span><br><span style="color: hsl(120, 100%, 40%);">+ * according to spec */</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_dtap(conn, link_id, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Drop unknown RR message */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Dropping %s 04.08 RR message\n", gsm48_rr_msg_name(msg_type));</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_dtap(conn, link_id, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief RSL has received a DATA INDICATION with L3 from MS */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan = msg->lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lchan->state != LCHAN_S_ACTIVE) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPLCHAN(msg->lchan, DRSL, LOGL_INFO, "Got data in non active state, discarding.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lchan->conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* if we already have a connection, forward via DTAP to</span><br><span style="color: hsl(120, 100%, 40%);">+ * MSC */</span><br><span style="color: hsl(120, 100%, 40%);">+ dispatch_dtap(lchan->conn, link_id, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* allocate a new connection */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = BSC_API_CONN_POL_REJECT;</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->conn = bsc_subscr_con_allocate(msg->lchan->ts->trx->bts->network);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!lchan->conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan_release(lchan, 1, RSL_REL_NORMAL);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->conn->lchan = lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* fwd via bsc_api to send COMPLETE L3 INFO to MSC */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = bsc_compl_l3(lchan->conn, msg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != BSC_API_CONN_POL_ACCEPT) {</span><br><span style="color: hsl(120, 100%, 40%);">+ //osmo_fsm_inst_dispatch(lchan->conn->fi, FIXME, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 9.1.29 RR Status */</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *gsm48_create_rr_status(uint8_t cause)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = gsm48_msgb_alloc_name("GSM 04.08 RR STATUS");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!msg)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->msg_type = GSM48_MT_RR_STATUS;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->data[0] = cause;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return msg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 9.1.29 RR Status */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_tx_rr_status(struct gsm_subscriber_connection *conn, uint8_t cause)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = gsm48_create_rr_status(cause);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!msg)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ gscon_submit_rsl_dtap(conn, msg, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int send_siemens_mrpci(struct gsm_lchan *lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *classmark2_lv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct rsl_mrpci mrpci;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (classmark2_lv[0] < 2)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mrpci.power_class = classmark2_lv[1] & 0x7;</span><br><span style="color: hsl(120, 100%, 40%);">+ mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);</span><br><span style="color: hsl(120, 100%, 40%);">+ mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rsl_siemens_mrpci(lchan, &mrpci);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_rx_rr_modif_ack(struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_chan_mode_modify *mod =</span><br><span style="color: hsl(120, 100%, 40%);">+ (struct gsm48_chan_mode_modify *) gh->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mod->mode != msg->lchan->tch_mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRR, LOGL_ERROR, "CHANNEL MODE change failed. Wanted: %d Got: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan->tch_mode, mod->mode);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* update the channel type */</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (mod->mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_SIGN:</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_SPEECH_V1:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_SPEECH_EFR:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_SPEECH_AMR:</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_DATA_14k5:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_DATA_12k0:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_DATA_6k0:</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM48_CMODE_DATA_3k6:</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan->rsl_cmode = RSL_CMOD_SPD_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We've successfully modified the MS side of the channel,</span><br><span style="color: hsl(120, 100%, 40%);">+ * now go on to modify the BTS side of the channel */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = rsl_chan_mode_modify_req(msg->lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: we not only need to do this after mode modify, but</span><br><span style="color: hsl(120, 100%, 40%);">+ * also after channel activation */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && mod->mode != GSM48_CMODE_SIGN)</span><br><span style="color: hsl(120, 100%, 40%);">+ rsl_ipacc_crcx(msg->lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int gsm48_sendmsg(struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msg->lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->dst = msg->lchan->ts->trx->rsl_link;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->l3h = msg->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ return rsl_data_request(msg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 7.1.7 and 9.1.7: RR CHANnel RELease */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rr_release(struct gsm_lchan *lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 RR REL");</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *cause;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan = lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->msg_type = GSM48_MT_RR_CHAN_REL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cause = msgb_put(msg, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ cause[0] = GSM48_RR_CAUSE_NORMAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->nr, lchan->type);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Send actual release request to MS */</span><br><span style="color: hsl(120, 100%, 40%);">+ return gsm48_sendmsg(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Chapter 9.1.9: Ciphering Mode Command */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CIPH");</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ciph_mod_set;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan = lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DRR, "TX CIPHERING MODE CMD\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lchan->encr.alg_id <= RSL_ENC_ALG_A5(0))</span><br><span style="color: hsl(120, 100%, 40%);">+ ciph_mod_set = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ ciph_mod_set = (lchan->encr.alg_id-2)<<1 | 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->msg_type = GSM48_MT_RR_CIPH_M_CMD;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->data[0] = (want_imeisv & 0x1) << 4 | (ciph_mod_set & 0xf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return rsl_encryption_cmd(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void gsm48_cell_desc(struct gsm48_cell_desc *cd,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct gsm_bts *bts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ cd->ncc = (bts->bsic >> 3 & 0x7);</span><br><span style="color: hsl(120, 100%, 40%);">+ cd->bcc = (bts->bsic & 0x7);</span><br><span style="color: hsl(120, 100%, 40%);">+ cd->arfcn_hi = bts->c0->arfcn >> 8;</span><br><span style="color: hsl(120, 100%, 40%);">+ cd->arfcn_lo = bts->c0->arfcn & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define GSM48_HOCMD_CCHDESC_LEN 16</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Chapter 9.1.15: Handover Command */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t power_command, uint8_t ho_ref)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 HO CMD");</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_ho_cmd *ho =</span><br><span style="color: hsl(120, 100%, 40%);">+ (struct gsm48_ho_cmd *) msgb_put(msg, sizeof(*ho));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan = old_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->msg_type = GSM48_MT_RR_HANDO_CMD;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* mandatory bits */</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm48_cell_desc(&ho->cell_desc, new_lchan->ts->trx->bts);</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm48_lchan2chan_desc(&ho->chan_desc, new_lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+ ho->ho_ref = ho_ref;</span><br><span style="color: hsl(120, 100%, 40%);">+ ho->power_command = power_command;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (new_lchan->ts->hopping.enabled) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_bts *bts = new_lchan->ts->trx->bts;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_system_information_type_1 *si1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t *cur;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ si1 = GSM_BTS_SI(bts, SYSINFO_TYPE_1);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Copy the Cell Chan Desc (ARFCNS in this cell) */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_put_u8(msg, GSM48_IE_CELL_CH_DESC);</span><br><span style="color: hsl(120, 100%, 40%);">+ cur = msgb_put(msg, GSM48_HOCMD_CCHDESC_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(cur, si1->cell_channel_description,</span><br><span style="color: hsl(120, 100%, 40%);">+ GSM48_HOCMD_CCHDESC_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Copy the Mobile Allocation */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_tlv_put(msg, GSM48_IE_MA_BEFORE,</span><br><span style="color: hsl(120, 100%, 40%);">+ new_lchan->ts->hopping.ma_len,</span><br><span style="color: hsl(120, 100%, 40%);">+ new_lchan->ts->hopping.ma_data);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: optional bits for type of synchronization? */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_tv_put(msg, GSM48_IE_CHANMODE_1, new_lchan->tch_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* in case of multi rate we need to attach a config */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (new_lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_tlv_put(msg, GSM48_IE_MUL_RATE_CFG, new_lchan->mr_ms_lv[0],</span><br><span style="color: hsl(120, 100%, 40%);">+ new_lchan->mr_ms_lv + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return gsm48_sendmsg(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void mr_config_for_ms(struct gsm_lchan *lchan, struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_tlv_put(msg, GSM48_IE_MUL_RATE_CFG, lchan->mr_ms_lv[0],</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->mr_ms_lv + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Chapter 9.1.2: Assignment Command */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_command)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ASS CMD");</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_ass_cmd *ass =</span><br><span style="color: hsl(120, 100%, 40%);">+ (struct gsm48_ass_cmd *) msgb_put(msg, sizeof(*ass));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DRR, "-> ASSIGNMENT COMMAND tch_mode=0x%02x\n", lchan->tch_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan = dest_lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->msg_type = GSM48_MT_RR_ASS_CMD;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * fill the channel information element, this code</span><br><span style="color: hsl(120, 100%, 40%);">+ * should probably be shared with rsl_rx_chan_rqd(),</span><br><span style="color: hsl(120, 100%, 40%);">+ * gsm48_lchan_modify(). But beware that 10.5.2.5</span><br><span style="color: hsl(120, 100%, 40%);">+ * 10.5.2.5.a have slightly different semantic for</span><br><span style="color: hsl(120, 100%, 40%);">+ * the chan_desc. But as long as multi-slot configurations</span><br><span style="color: hsl(120, 100%, 40%);">+ * are not used we seem to be fine.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm48_lchan2chan_desc(&ass->chan_desc, lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+ ass->power_command = power_command;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* optional: cell channel description */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_tv_put(msg, GSM48_IE_CHANMODE_1, lchan->tch_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* mobile allocation in case of hopping */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lchan->ts->hopping.enabled) {</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_tlv_put(msg, GSM48_IE_MA_BEFORE, lchan->ts->hopping.ma_len,</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->ts->hopping.ma_data);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* in case of multi rate we need to attach a config */</span><br><span style="color: hsl(120, 100%, 40%);">+ mr_config_for_ms(lchan, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return gsm48_sendmsg(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 9.1.5 Channel mode modify: Modify the mode on the MS side */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD");</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm48_chan_mode_modify *cmm =</span><br><span style="color: hsl(120, 100%, 40%);">+ (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->tch_mode = mode;</span><br><span style="color: hsl(120, 100%, 40%);">+ msg->lchan = lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(120, 100%, 40%);">+ gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* fill the channel information element, this code</span><br><span style="color: hsl(120, 100%, 40%);">+ * should probably be shared with rsl_rx_chan_rqd() */</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm48_lchan2chan_desc(&cmm->chan_desc, lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+ cmm->mode = mode;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* in case of multi rate we need to attach a config */</span><br><span style="color: hsl(120, 100%, 40%);">+ mr_config_for_ms(lchan, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return gsm48_sendmsg(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/osmo-bsc/bsc_api.c b/src/osmo-bsc/bsc_api.c</span><br><span>index 2c799e3..eed475b 100644</span><br><span>--- a/src/osmo-bsc/bsc_api.c</span><br><span>+++ b/src/osmo-bsc/bsc_api.c</span><br><span>@@ -195,312 +195,6 @@</span><br><span> return rsl_paging_cmd(bts, page_group, mi_len, mi, chan_type, false);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_ass_compl(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- enum gsm48_rr_cause cause;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Expecting gsm48_hdr + cause value */</span><br><span style="color: hsl(0, 100%, 40%);">- if (msgb_l3len(msg) != sizeof(*gh) + 1) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "RR Assignment Complete: length invalid: %u, expected %zu\n",</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_l3len(msg), sizeof(*gh) + 1);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cause = gh->data[0];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT COMPLETE cause = %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- rr_cause_name(cause));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (conn->ho) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct lchan_signal_data sig = {</span><br><span style="color: hsl(0, 100%, 40%);">- .lchan = msg->lchan,</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_COMPL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: release old channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">- gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (conn->secondary_lchan != msg->lchan) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "RR Assignment Complete does not match conn's secondary lchan.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lchan_release(conn->lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(0, 100%, 40%);">- conn->lchan = conn->secondary_lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- conn->secondary_lchan = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">- gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (is_ipaccess_bts(conn_get_bts(conn)) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)</span><br><span style="color: hsl(0, 100%, 40%);">- rsl_ipacc_crcx(conn->lchan);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_assign_compl(conn, cause);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_ass_fail(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *rr_failure;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (conn->ho) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct lchan_signal_data sig;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "ASSIGNMENT FAILED cause = %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- sig.lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- sig.mr = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_signal_dispatch(SS_LCHAN, S_LCHAN_ASSIGNMENT_FAIL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: release allocated new channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">- gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (conn->lchan != msg->lchan) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DMSC, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "Assignment failure should occur on primary lchan.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop the timer and release it */</span><br><span style="color: hsl(0, 100%, 40%);">- if (conn->secondary_lchan) {</span><br><span style="color: hsl(0, 100%, 40%);">- lchan_release(conn->secondary_lchan, 0, RSL_REL_LOCAL_END);</span><br><span style="color: hsl(0, 100%, 40%);">- conn->secondary_lchan = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">- gscon_dtap_cache_flush(conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- if (msgb_l3len(msg) - sizeof(*gh) != 1) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(conn->lchan, DMSC, LOGL_ERROR, "assignment failure unhandled: %zu\n",</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_l3len(msg) - sizeof(*gh));</span><br><span style="color: hsl(0, 100%, 40%);">- rr_failure = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- rr_failure = &gh->data[0];</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_assign_fail(conn, GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, rr_failure);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_classmark_chg(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t cm2_len, cm3_len = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *cm2, *cm3 = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG, "CLASSMARK CHANGE ");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* classmark 2 */</span><br><span style="color: hsl(0, 100%, 40%);">- cm2_len = gh->data[0];</span><br><span style="color: hsl(0, 100%, 40%);">- cm2 = &gh->data[1];</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (payload_len > cm2_len + 1) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* we must have a classmark3 */</span><br><span style="color: hsl(0, 100%, 40%);">- if (gh->data[cm2_len+1] != 0x20) {</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGPC(DRR, "ERR CM3 TAG\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (cm2_len > 3) {</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGPC(DRR, "CM2 too long!\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cm3_len = gh->data[cm2_len+2];</span><br><span style="color: hsl(0, 100%, 40%);">- cm3 = &gh->data[cm2_len+3];</span><br><span style="color: hsl(0, 100%, 40%);">- if (cm3_len > 14) {</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_cm_update(conn, cm2, cm2_len, cm3, cm3_len);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Chapter 9.1.16 Handover complete */</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_rr_ho_compl(struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct lchan_signal_data sig;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "HANDOVER COMPLETE cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- sig.lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- sig.mr = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: release old channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">- gscon_dtap_cache_flush(msg->lchan->conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Chapter 9.1.17 Handover Failure */</span><br><span style="color: hsl(0, 100%, 40%);">-static void handle_rr_ho_fail(struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct lchan_signal_data sig;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Log on both RR and HO categories: it is an RR message, but is still quite important when</span><br><span style="color: hsl(0, 100%, 40%);">- * filtering on HO. */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DHO, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "HANDOVER FAILED cause = %s\n", rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- sig.lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- sig.mr = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: release allocated new channel */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* send pending messages, if any */</span><br><span style="color: hsl(0, 100%, 40%);">- gscon_dtap_cache_flush(msg->lchan->conn, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void dispatch_dtap(struct gsm_subscriber_connection *conn,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t link_id, struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t pdisc;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t msg_type;</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (msgb_l3len(msg) < sizeof(*gh)) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DMSC, LOGL_ERROR, "(%s) Message too short for a GSM48 header.\n",</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_subscr_name(conn->bsub));</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- pdisc = gsm48_hdr_pdisc(gh);</span><br><span style="color: hsl(0, 100%, 40%);">- msg_type = gsm48_hdr_msg_type(gh);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* the idea is to handle all RR messages here, and only hand</span><br><span style="color: hsl(0, 100%, 40%);">- * MM/CC/SMS-CP/LCS up to the MSC. Some messages like PAGING</span><br><span style="color: hsl(0, 100%, 40%);">- * RESPONSE or CM SERVICE REQUEST will not be covered here, as</span><br><span style="color: hsl(0, 100%, 40%);">- * they are only possible in the first L3 message of each L2</span><br><span style="color: hsl(0, 100%, 40%);">- * channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()</span><br><span style="color: hsl(0, 100%, 40%);">- * will call api->compl_l3() for it */</span><br><span style="color: hsl(0, 100%, 40%);">- switch (pdisc) {</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_PDISC_RR:</span><br><span style="color: hsl(0, 100%, 40%);">- switch (msg_type) {</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_GPRS_SUSP_REQ:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- "%s\n", gsm48_rr_msg_name(GSM48_MT_RR_GPRS_SUSP_REQ));</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_STATUS:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">- "%s (cause: %s)\n", gsm48_rr_msg_name(GSM48_MT_RR_STATUS),</span><br><span style="color: hsl(0, 100%, 40%);">- rr_cause_name(gh->data[0]));</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_MEAS_REP:</span><br><span style="color: hsl(0, 100%, 40%);">- /* This shouldn't actually end up here, as RSL treats</span><br><span style="color: hsl(0, 100%, 40%);">- * L3 Info of 08.58 MEASUREMENT REPORT different by calling</span><br><span style="color: hsl(0, 100%, 40%);">- * directly into gsm48_parse_meas_rep */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DMEAS, LOGL_ERROR,</span><br><span style="color: hsl(0, 100%, 40%);">- "DIRECT GSM48 MEASUREMENT REPORT ?!?\n");</span><br><span style="color: hsl(0, 100%, 40%);">- gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_HANDO_COMPL:</span><br><span style="color: hsl(0, 100%, 40%);">- handle_rr_ho_compl(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_HANDO_FAIL:</span><br><span style="color: hsl(0, 100%, 40%);">- handle_rr_ho_fail(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_CIPH_M_COMPL:</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_cipher_mode_compl(conn, msg, conn->lchan->encr.alg_id);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_ASS_COMPL:</span><br><span style="color: hsl(0, 100%, 40%);">- handle_ass_compl(conn, msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_ASS_FAIL:</span><br><span style="color: hsl(0, 100%, 40%);">- handle_ass_fail(conn, msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:</span><br><span style="color: hsl(0, 100%, 40%);">- rc = gsm48_rx_rr_modif_ack(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc < 0)</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_assign_fail(conn, GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_assign_compl(conn, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_CLSM_CHG:</span><br><span style="color: hsl(0, 100%, 40%);">- handle_classmark_chg(conn, msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_MT_RR_APP_INFO:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Passing RR APP INFO to MSC, not quite</span><br><span style="color: hsl(0, 100%, 40%);">- * according to spec */</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_dtap(conn, link_id, msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- /* Drop unknown RR message */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRR, LOGL_NOTICE,</span><br><span style="color: hsl(0, 100%, 40%);">- "Dropping %s 04.08 RR message\n", gsm48_rr_msg_name(msg_type));</span><br><span style="color: hsl(0, 100%, 40%);">- gsm48_tx_rr_status(conn, GSM48_RR_CAUSE_MSG_TYPE_N);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- bsc_dtap(conn, link_id, msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief RSL has received a DATA INDICATION with L3 from MS */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm_lchan *lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lchan = msg->lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- if (lchan->state != LCHAN_S_ACTIVE) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPLCHAN(msg->lchan, DRSL, LOGL_INFO, "Got data in non active state, discarding.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (lchan->conn) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* if we already have a connection, forward via DTAP to</span><br><span style="color: hsl(0, 100%, 40%);">- * MSC */</span><br><span style="color: hsl(0, 100%, 40%);">- dispatch_dtap(lchan->conn, link_id, msg);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- /* allocate a new connection */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = BSC_API_CONN_POL_REJECT;</span><br><span style="color: hsl(0, 100%, 40%);">- lchan->conn = bsc_subscr_con_allocate(msg->lchan->ts->trx->bts->network);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!lchan->conn) {</span><br><span style="color: hsl(0, 100%, 40%);">- lchan_release(lchan, 1, RSL_REL_NORMAL);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- lchan->conn->lchan = lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* fwd via bsc_api to send COMPLETE L3 INFO to MSC */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = bsc_compl_l3(lchan->conn, msg, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc != BSC_API_CONN_POL_ACCEPT) {</span><br><span style="color: hsl(0, 100%, 40%);">- //osmo_fsm_inst_dispatch(lchan->conn->fi, FIXME, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! \brief We received a GSM 08.08 CIPHER MODE from the MSC */</span><br><span> int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,</span><br><span> const uint8_t *key, int len, int include_imeisv)</span><br><span>diff --git a/src/osmo-bsc/gsm_04_08_utils.c b/src/osmo-bsc/gsm_04_08_utils.c</span><br><span>index c548500..c52239f 100644</span><br><span>--- a/src/osmo-bsc/gsm_04_08_utils.c</span><br><span>+++ b/src/osmo-bsc/gsm_04_08_utils.c</span><br><span>@@ -41,15 +41,6 @@</span><br><span> * or should OpenBSC always act as RTP relay/proxy in between (0) ? */</span><br><span> int ipacc_rtp_direct = 1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int gsm48_sendmsg(struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (msg->lchan)</span><br><span style="color: hsl(0, 100%, 40%);">- msg->dst = msg->lchan->ts->trx->rsl_link;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msg->l3h = msg->data;</span><br><span style="color: hsl(0, 100%, 40%);">- return rsl_data_request(msg, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* Section 9.1.8 / Table 9.9 */</span><br><span> struct chreq {</span><br><span> uint8_t val;</span><br><span>@@ -225,83 +216,6 @@</span><br><span> return GSM_CHREQ_REASON_OTHER;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void mr_config_for_ms(struct gsm_lchan *lchan, struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_tlv_put(msg, GSM48_IE_MUL_RATE_CFG, lchan->mr_ms_lv[0],</span><br><span style="color: hsl(0, 100%, 40%);">- lchan->mr_ms_lv + 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* 7.1.7 and 9.1.7: RR CHANnel RELease */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_rr_release(struct gsm_lchan *lchan)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 RR REL");</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *cause;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan = lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->msg_type = GSM48_MT_RR_CHAN_REL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cause = msgb_put(msg, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- cause[0] = GSM48_RR_CAUSE_NORMAL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- lchan->nr, lchan->type);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Send actual release request to MS */</span><br><span style="color: hsl(0, 100%, 40%);">- return gsm48_sendmsg(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int send_siemens_mrpci(struct gsm_lchan *lchan,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *classmark2_lv)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct rsl_mrpci mrpci;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (classmark2_lv[0] < 2)</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- mrpci.power_class = classmark2_lv[1] & 0x7;</span><br><span style="color: hsl(0, 100%, 40%);">- mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1);</span><br><span style="color: hsl(0, 100%, 40%);">- mrpci.vbs_capable = classmark2_lv[2] & (1 <<2);</span><br><span style="color: hsl(0, 100%, 40%);">- mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return rsl_siemens_mrpci(lchan, &mrpci);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Chapter 9.1.9: Ciphering Mode Command */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CIPH");</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t ciph_mod_set;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan = lchan;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DRR, "TX CIPHERING MODE CMD\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (lchan->encr.alg_id <= RSL_ENC_ALG_A5(0))</span><br><span style="color: hsl(0, 100%, 40%);">- ciph_mod_set = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- ciph_mod_set = (lchan->encr.alg_id-2)<<1 | 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);</span><br><span style="color: hsl(0, 100%, 40%);">- gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->msg_type = GSM48_MT_RR_CIPH_M_CMD;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->data[0] = (want_imeisv & 0x1) << 4 | (ciph_mod_set & 0xf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return rsl_encryption_cmd(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void gsm48_cell_desc(struct gsm48_cell_desc *cd,</span><br><span style="color: hsl(0, 100%, 40%);">- const struct gsm_bts *bts)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- cd->ncc = (bts->bsic >> 3 & 0x7);</span><br><span style="color: hsl(0, 100%, 40%);">- cd->bcc = (bts->bsic & 0x7);</span><br><span style="color: hsl(0, 100%, 40%);">- cd->arfcn_hi = bts->c0->arfcn >> 8;</span><br><span style="color: hsl(0, 100%, 40%);">- cd->arfcn_lo = bts->c0->arfcn & 0xff;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! \brief Encode a TS 04.08 multirate config LV according to 10.5.2.21aa</span><br><span> * \param[out] lv caller-allocated buffer of 7 bytes. First octet is IS length</span><br><span> * \param[in] mr multi-rate configuration to encode</span><br><span>@@ -347,166 +261,6 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define GSM48_HOCMD_CCHDESC_LEN 16</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Chapter 9.1.15: Handover Command */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t power_command, uint8_t ho_ref)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 HO CMD");</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_ho_cmd *ho =</span><br><span style="color: hsl(0, 100%, 40%);">- (struct gsm48_ho_cmd *) msgb_put(msg, sizeof(*ho));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan = old_lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->msg_type = GSM48_MT_RR_HANDO_CMD;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* mandatory bits */</span><br><span style="color: hsl(0, 100%, 40%);">- gsm48_cell_desc(&ho->cell_desc, new_lchan->ts->trx->bts);</span><br><span style="color: hsl(0, 100%, 40%);">- gsm48_lchan2chan_desc(&ho->chan_desc, new_lchan);</span><br><span style="color: hsl(0, 100%, 40%);">- ho->ho_ref = ho_ref;</span><br><span style="color: hsl(0, 100%, 40%);">- ho->power_command = power_command;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (new_lchan->ts->hopping.enabled) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm_bts *bts = new_lchan->ts->trx->bts;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_system_information_type_1 *si1;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t *cur;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- si1 = GSM_BTS_SI(bts, SYSINFO_TYPE_1);</span><br><span style="color: hsl(0, 100%, 40%);">- /* Copy the Cell Chan Desc (ARFCNS in this cell) */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_put_u8(msg, GSM48_IE_CELL_CH_DESC);</span><br><span style="color: hsl(0, 100%, 40%);">- cur = msgb_put(msg, GSM48_HOCMD_CCHDESC_LEN);</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(cur, si1->cell_channel_description,</span><br><span style="color: hsl(0, 100%, 40%);">- GSM48_HOCMD_CCHDESC_LEN);</span><br><span style="color: hsl(0, 100%, 40%);">- /* Copy the Mobile Allocation */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_tlv_put(msg, GSM48_IE_MA_BEFORE,</span><br><span style="color: hsl(0, 100%, 40%);">- new_lchan->ts->hopping.ma_len,</span><br><span style="color: hsl(0, 100%, 40%);">- new_lchan->ts->hopping.ma_data);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: optional bits for type of synchronization? */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_tv_put(msg, GSM48_IE_CHANMODE_1, new_lchan->tch_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* in case of multi rate we need to attach a config */</span><br><span style="color: hsl(0, 100%, 40%);">- if (new_lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_tlv_put(msg, GSM48_IE_MUL_RATE_CFG, new_lchan->mr_ms_lv[0],</span><br><span style="color: hsl(0, 100%, 40%);">- new_lchan->mr_ms_lv + 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return gsm48_sendmsg(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Chapter 9.1.2: Assignment Command */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_command)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ASS CMD");</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_ass_cmd *ass =</span><br><span style="color: hsl(0, 100%, 40%);">- (struct gsm48_ass_cmd *) msgb_put(msg, sizeof(*ass));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DRR, "-> ASSIGNMENT COMMAND tch_mode=0x%02x\n", lchan->tch_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan = dest_lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->msg_type = GSM48_MT_RR_ASS_CMD;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /*</span><br><span style="color: hsl(0, 100%, 40%);">- * fill the channel information element, this code</span><br><span style="color: hsl(0, 100%, 40%);">- * should probably be shared with rsl_rx_chan_rqd(),</span><br><span style="color: hsl(0, 100%, 40%);">- * gsm48_lchan_modify(). But beware that 10.5.2.5</span><br><span style="color: hsl(0, 100%, 40%);">- * 10.5.2.5.a have slightly different semantic for</span><br><span style="color: hsl(0, 100%, 40%);">- * the chan_desc. But as long as multi-slot configurations</span><br><span style="color: hsl(0, 100%, 40%);">- * are not used we seem to be fine.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- gsm48_lchan2chan_desc(&ass->chan_desc, lchan);</span><br><span style="color: hsl(0, 100%, 40%);">- ass->power_command = power_command;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* optional: cell channel description */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_tv_put(msg, GSM48_IE_CHANMODE_1, lchan->tch_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* mobile allocation in case of hopping */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lchan->ts->hopping.enabled) {</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_tlv_put(msg, GSM48_IE_MA_BEFORE, lchan->ts->hopping.ma_len,</span><br><span style="color: hsl(0, 100%, 40%);">- lchan->ts->hopping.ma_data);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* in case of multi rate we need to attach a config */</span><br><span style="color: hsl(0, 100%, 40%);">- mr_config_for_ms(lchan, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return gsm48_sendmsg(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* 9.1.5 Channel mode modify: Modify the mode on the MS side */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD");</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_chan_mode_modify *cmm =</span><br><span style="color: hsl(0, 100%, 40%);">- (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lchan->tch_mode = mode;</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan = lchan;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* fill the channel information element, this code</span><br><span style="color: hsl(0, 100%, 40%);">- * should probably be shared with rsl_rx_chan_rqd() */</span><br><span style="color: hsl(0, 100%, 40%);">- gsm48_lchan2chan_desc(&cmm->chan_desc, lchan);</span><br><span style="color: hsl(0, 100%, 40%);">- cmm->mode = mode;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* in case of multi rate we need to attach a config */</span><br><span style="color: hsl(0, 100%, 40%);">- mr_config_for_ms(lchan, msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return gsm48_sendmsg(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_rx_rr_modif_ack(struct msgb *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int rc;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_chan_mode_modify *mod =</span><br><span style="color: hsl(0, 100%, 40%);">- (struct gsm48_chan_mode_modify *) gh->data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (mod->mode != msg->lchan->tch_mode) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DRR, LOGL_ERROR, "CHANNEL MODE change failed. Wanted: %d Got: %d\n",</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan->tch_mode, mod->mode);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* update the channel type */</span><br><span style="color: hsl(0, 100%, 40%);">- switch (mod->mode) {</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_SIGN:</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_SPEECH_V1:</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_SPEECH_EFR:</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_SPEECH_AMR:</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_DATA_14k5:</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_DATA_12k0:</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_DATA_6k0:</span><br><span style="color: hsl(0, 100%, 40%);">- case GSM48_CMODE_DATA_3k6:</span><br><span style="color: hsl(0, 100%, 40%);">- msg->lchan->rsl_cmode = RSL_CMOD_SPD_DATA;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* We've successfully modified the MS side of the channel,</span><br><span style="color: hsl(0, 100%, 40%);">- * now go on to modify the BTS side of the channel */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = rsl_chan_mode_modify_req(msg->lchan);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* FIXME: we not only need to do this after mode modify, but</span><br><span style="color: hsl(0, 100%, 40%);">- * also after channel activation */</span><br><span style="color: hsl(0, 100%, 40%);">- if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && mod->mode != GSM48_CMODE_SIGN)</span><br><span style="color: hsl(0, 100%, 40%);">- rsl_ipacc_crcx(msg->lchan);</span><br><span style="color: hsl(0, 100%, 40%);">- return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)</span><br><span> {</span><br><span> struct gsm48_hdr *gh = msgb_l3(msg);</span><br><span>@@ -622,34 +376,6 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* 9.1.29 RR Status */</span><br><span style="color: hsl(0, 100%, 40%);">-struct msgb *gsm48_create_rr_status(uint8_t cause)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gsm48_hdr *gh;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msg = gsm48_msgb_alloc_name("GSM 04.08 RR STATUS");</span><br><span style="color: hsl(0, 100%, 40%);">- if (!msg)</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);</span><br><span style="color: hsl(0, 100%, 40%);">- gh->proto_discr = GSM48_PDISC_RR;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->msg_type = GSM48_MT_RR_STATUS;</span><br><span style="color: hsl(0, 100%, 40%);">- gh->data[0] = cause;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return msg;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* 9.1.29 RR Status */</span><br><span style="color: hsl(0, 100%, 40%);">-int gsm48_tx_rr_status(struct gsm_subscriber_connection *conn, uint8_t cause)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct msgb *msg = gsm48_create_rr_status(cause);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!msg)</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- gscon_submit_rsl_dtap(conn, msg, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value)</span><br><span> {</span><br><span> struct msgb *msg;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/9669">change 9669</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/9669"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ie8ee334145bf7bc3a601d395ea7ab9b2009b61c7 </div>
<div style="display:none"> Gerrit-Change-Number: 9669 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>