[gsm48] Add generation of ASSIGNMENT COMMAND to the 0408 utils

Add code to generate an assignment command for a given lchan. It
is expected that the lchan is modified already and the mode will
be picked up from their. Currently only the mandantory items
are supported.
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 8c944e6..ae13581 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -59,6 +59,15 @@
 	GSM48_CMODE_DATA_3k6	= 0x23,
 };
 
+/* Chapter 9.1.2 */
+struct gsm48_ass_cmd {
+	/* Semantic is from 10.5.2.5a */
+	struct gsm48_chan_desc chan_desc;
+	u_int8_t power_command;
+	u_int8_t data[0];
+} __attribute__((packed));
+
+
 /* Chapter 9.1.18 */
 struct gsm48_imm_ass {
 	u_int8_t l2_plen;
@@ -727,6 +736,7 @@
 int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
 int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
 			   u_int8_t apdu_len, const u_int8_t *apdu);
+int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_class);
 
 int bsc_upqueue(struct gsm_network *net);
 
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 6b328bb..a4764f5 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -239,6 +239,7 @@
 	return lchan;
 }
 
+/* See Table 10.5.25 of GSM04.08 */
 u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
 {
 	struct gsm_bts_trx_ts *ts = lchan->ts;
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index ef9e59c..358212f 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -482,3 +482,35 @@
 	return rsl_encryption_cmd(msg);
 }
 
+/* Chapter 9.1.2: Assignment Command */
+int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
+{
+	struct msgb *msg = gsm48_msgb_alloc();
+	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+	struct gsm48_ass_cmd *ass =
+		(struct gsm48_ass_cmd *) msgb_put(msg, sizeof(*ass));
+	u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
+
+	DEBUGP(DRR, "-> ASSIGNMENT COMMAND tch_mode=0x%02x\n", lchan->tch_mode);
+
+	msg->lchan = lchan;
+	gh->proto_discr = GSM48_PDISC_RR;
+	gh->msg_type = GSM48_MT_RR_ASS_CMD;
+
+	/*
+	 * fill the channel information element, this code
+	 * should probably be shared with rsl_rx_chan_rqd(),
+	 * gsm48_tx_chan_mode_modify. But beware that 10.5.2.5
+	 * 10.5.2.5.a have slightly different semantic for
+	 * the chan_desc. But as long as multi-slot configurations
+	 * are not used we seem to be fine.
+	 */
+	ass->chan_desc.chan_nr = lchan2chan_nr(lchan);
+	ass->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
+	ass->chan_desc.h0.h = 0;
+	ass->chan_desc.h0.arfcn_high = arfcn >> 8;
+	ass->chan_desc.h0.arfcn_low = arfcn & 0xff;
+	ass->power_command = power_command;
+
+	return gsm48_sendmsg(msg, NULL);
+}