Use the app_info->name instead of the hostname
[osmocom-bb.git] / src / rsl.c
index 6ba1375..3bfeffb 100644 (file)
--- a/src/rsl.c
+++ b/src/rsl.c
@@ -1,7 +1,7 @@
 /* GSM Radio Signalling Link messages on the A-bis interface 
  * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
 
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
  *
  * All Rights Reserved
  *
  *
  */
 
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+
 #include <osmocore/tlv.h>
 #include <osmocore/rsl.h>
 
+#define RSL_ALLOC_SIZE         200
+#define RSL_ALLOC_HEADROOM     56
+
 void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type)
 {
        dh->c.msg_discr = ABIS_RSL_MDISC_RLL;
@@ -32,6 +39,13 @@ void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type)
        dh->ie_link_id = RSL_IE_LINK_IDENT;
 }
 
+void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type)
+{
+       ch->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN;
+       ch->c.msg_type = msg_type;
+       ch->ie_chan = RSL_IE_CHAN_NR;
+}
+
 const struct tlv_definition rsl_att_tlvdef = {
        .def = {
                [RSL_IE_CHAN_NR]                = { TLV_TYPE_TV },
@@ -139,42 +153,104 @@ uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot)
        return ret;
 }
 
-/* FIXME: convert to value_string */
-static const char *rsl_err_vals[0xff] = {
-       [RSL_ERR_RADIO_IF_FAIL] =       "Radio Interface Failure",
-       [RSL_ERR_RADIO_LINK_FAIL] =     "Radio Link Failure",
-       [RSL_ERR_HANDOVER_ACC_FAIL] =   "Handover Access Failure",
-       [RSL_ERR_TALKER_ACC_FAIL] =     "Talker Access Failure",
-       [RSL_ERR_OM_INTERVENTION] =     "O&M Intervention",
-       [RSL_ERR_NORMAL_UNSPEC] =       "Normal event, unspecified",
-       [RSL_ERR_T_MSRFPCI_EXP] =       "Siemens: T_MSRFPCI Expired",
-       [RSL_ERR_EQUIPMENT_FAIL] =      "Equipment Failure",
-       [RSL_ERR_RR_UNAVAIL] =          "Radio Resource not available",
-       [RSL_ERR_TERR_CH_FAIL] =        "Terrestrial Channel Failure",
-       [RSL_ERR_CCCH_OVERLOAD] =       "CCCH Overload",
-       [RSL_ERR_ACCH_OVERLOAD] =       "ACCH Overload",
-       [RSL_ERR_PROCESSOR_OVERLOAD] =  "Processor Overload",
-       [RSL_ERR_RES_UNAVAIL] =         "Resource not available, unspecified",
-       [RSL_ERR_TRANSC_UNAVAIL] =      "Transcoding not available",
-       [RSL_ERR_SERV_OPT_UNAVAIL] =    "Service or Option not available",
-       [RSL_ERR_ENCR_UNIMPL] =         "Encryption algorithm not implemented",
-       [RSL_ERR_SERV_OPT_UNIMPL] =     "Service or Option not implemented",
-       [RSL_ERR_RCH_ALR_ACTV_ALLOC] =  "Radio channel already activated",
-       [RSL_ERR_INVALID_MESSAGE] =     "Invalid Message, unspecified",
-       [RSL_ERR_MSG_DISCR] =           "Message Discriminator Error",
-       [RSL_ERR_MSG_TYPE] =            "Message Type Error",
-       [RSL_ERR_MSG_SEQ] =             "Message Sequence Error",
-       [RSL_ERR_IE_ERROR] =            "General IE error",
-       [RSL_ERR_MAND_IE_ERROR] =       "Mandatory IE error",
-       [RSL_ERR_OPT_IE_ERROR] =        "Optional IE error",
-       [RSL_ERR_IE_NONEXIST] =         "IE non-existent",
-       [RSL_ERR_IE_LENGTH] =           "IE length error",
-       [RSL_ERR_IE_CONTENT] =          "IE content error",
-       [RSL_ERR_PROTO] =               "Protocol error, unspecified",
-       [RSL_ERR_INTERWORKING] =        "Interworking error, unspecified",
+int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot)
+{
+       *timeslot = chan_nr & 0x7;
+
+       if ((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs) {
+               *type = RSL_CHAN_Bm_ACCHs;
+               *subch = 0;
+       } else if ((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs) {
+               *type = RSL_CHAN_Lm_ACCHs;
+               *subch = (chan_nr >> 3) & 0x1;
+       } else if ((chan_nr & 0xe0) == RSL_CHAN_SDCCH4_ACCH) {
+               *type = RSL_CHAN_SDCCH4_ACCH;
+               *subch = (chan_nr >> 3) & 0x3;
+       } else if ((chan_nr & 0xc0) == RSL_CHAN_SDCCH8_ACCH) {
+               *type = RSL_CHAN_SDCCH8_ACCH;
+               *subch = (chan_nr >> 3) & 0x7;
+       } else if ((chan_nr & 0xf8) == RSL_CHAN_BCCH) {
+               *type = RSL_CHAN_BCCH;
+               *subch = 0;
+       } else if ((chan_nr & 0xf8) == RSL_CHAN_RACH) {
+               *type = RSL_CHAN_RACH;
+               *subch = 0;
+       } else if ((chan_nr & 0xf8) == RSL_CHAN_PCH_AGCH) {
+               *type = RSL_CHAN_PCH_AGCH;
+               *subch = 0;
+       } else
+               return -EINVAL;
+
+       return 0;
+}
+
+const char *rsl_chan_nr_str(uint8_t chan_nr)
+{
+       static char str[20];
+       int ts = chan_nr & 7;
+       uint8_t cbits = chan_nr >> 3;
+
+       if (cbits == 0x01)
+               sprintf(str, "TCH/F on TS%d", ts);
+       else if ((cbits & 0x1e) == 0x02)
+               sprintf(str, "TCH/H(%u) on TS%d", cbits & 0x01, ts);
+       else if ((cbits & 0x1c) == 0x04)
+               sprintf(str, "SDCCH/4(%u) on TS%d", cbits & 0x03, ts);
+       else if ((cbits & 0x18) == 0x08)
+               sprintf(str, "SDCCH/8(%u) on TS%d", cbits & 0x07, ts);
+       else if (cbits == 0x10)
+               sprintf(str, "BCCH on TS%d", ts);
+       else if (cbits == 0x11)
+               sprintf(str, "RACH on TS%d", ts);
+       else if (cbits == 0x12)
+               sprintf(str, "PCH/AGCH on TS%d", ts);
+       else
+               sprintf(str, "UNKNOWN on TS%d", ts);
+
+        return str;
+}
+
+static const struct value_string rsl_err_vals[] = {
+       { RSL_ERR_RADIO_IF_FAIL,        "Radio Interface Failure" },
+       { RSL_ERR_RADIO_LINK_FAIL,      "Radio Link Failure" },
+       { RSL_ERR_HANDOVER_ACC_FAIL,    "Handover Access Failure" },
+       { RSL_ERR_TALKER_ACC_FAIL,      "Talker Access Failure" },
+       { RSL_ERR_OM_INTERVENTION,      "O&M Intervention" },
+       { RSL_ERR_NORMAL_UNSPEC,        "Normal event, unspecified" },
+       { RSL_ERR_T_MSRFPCI_EXP,        "Siemens: T_MSRFPCI Expired" },
+       { RSL_ERR_EQUIPMENT_FAIL,       "Equipment Failure" },
+       { RSL_ERR_RR_UNAVAIL,           "Radio Resource not available" },
+       { RSL_ERR_TERR_CH_FAIL,         "Terrestrial Channel Failure" },
+       { RSL_ERR_CCCH_OVERLOAD,        "CCCH Overload" },
+       { RSL_ERR_ACCH_OVERLOAD,        "ACCH Overload" },
+       { RSL_ERR_PROCESSOR_OVERLOAD,   "Processor Overload" },
+       { RSL_ERR_RES_UNAVAIL,          "Resource not available, unspecified" },
+       { RSL_ERR_TRANSC_UNAVAIL,       "Transcoding not available" },
+       { RSL_ERR_SERV_OPT_UNAVAIL,     "Service or Option not available" },
+       { RSL_ERR_ENCR_UNIMPL,          "Encryption algorithm not implemented" },
+       { RSL_ERR_SERV_OPT_UNIMPL,      "Service or Option not implemented" },
+       { RSL_ERR_RCH_ALR_ACTV_ALLOC,   "Radio channel already activated" },
+       { RSL_ERR_INVALID_MESSAGE,      "Invalid Message, unspecified" },
+       { RSL_ERR_MSG_DISCR,            "Message Discriminator Error" },
+       { RSL_ERR_MSG_TYPE,             "Message Type Error" },
+       { RSL_ERR_MSG_SEQ,              "Message Sequence Error" },
+       { RSL_ERR_IE_ERROR,             "General IE error" },
+       { RSL_ERR_MAND_IE_ERROR,        "Mandatory IE error" },
+       { RSL_ERR_OPT_IE_ERROR,         "Optional IE error" },
+       { RSL_ERR_IE_NONEXIST,          "IE non-existent" },
+       { RSL_ERR_IE_LENGTH,            "IE length error" },
+       { RSL_ERR_IE_CONTENT,           "IE content error" },
+       { RSL_ERR_PROTO,                "Protocol error, unspecified" },
+       { RSL_ERR_INTERWORKING,         "Interworking error, unspecified" },
+       { 0,                            NULL }
 };
 
-const struct value_string rsl_rlm_cause_strs[] = {
+const char *rsl_err_name(uint8_t err)
+{
+       return get_value_string(rsl_err_vals, err);
+}
+
+static const struct value_string rsl_rlm_cause_strs[] = {
        { RLL_CAUSE_T200_EXPIRED,       "Timer T200 expired (N200+1) times" },
        { RLL_CAUSE_REEST_REQ,          "Re-establishment request" },
        { RLL_CAUSE_UNSOL_UA_RESP,      "Unsolicited UA response" },
@@ -192,12 +268,9 @@ const struct value_string rsl_rlm_cause_strs[] = {
        { 0,                            NULL },
 };
 
-const char *rsl_err_name(uint8_t err)
+const char *rsl_rlm_cause_name(uint8_t err)
 {
-       if (rsl_err_vals[err])
-               return rsl_err_vals[err];
-       else
-               return "unknown";
+       return get_value_string(rsl_rlm_cause_strs, err);
 }
 
 /* Section 3.3.2.3 TS 05.02. I think this looks like a table */
@@ -238,37 +311,47 @@ int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf)
        }
 }
 
-/* Push a RSL RLL header with L3_INFO IE */
-int rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type,
-                   uint8_t chan_nr, uint8_t link_id)
+/* Push a RSL RLL header */
+void rsl_rll_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
+                     uint8_t link_id, int transparent)
 {
-       uint8_t l3_len = msg->tail - (uint8_t *)msgb_l3(msg);
        struct abis_rsl_rll_hdr *rh;
 
-       /* construct a RSLms RLL message (DATA INDICATION, UNIT DATA
-        * INDICATION) and send it off via RSLms */
-
-       /* Push the L3 IE tag and lengh */
-       msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
-
-       /* Then push the RSL header */
        rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh));
        rsl_init_rll_hdr(rh, msg_type);
-       rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
+       if (transparent)
+               rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
        rh->chan_nr = chan_nr;
        rh->link_id = link_id;
 
        /* set the l2 header pointer */
        msg->l2h = (uint8_t *)rh;
+}
 
-       return 0;
+/* Push a RSL RLL header with L3_INFO IE */
+void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
+                    uint8_t link_id, int transparent)
+{
+       uint8_t l3_len = msg->tail - (uint8_t *)msgb_l3(msg);
+
+       /* construct a RSLms RLL message (DATA INDICATION, UNIT DATA
+        * INDICATION) and send it off via RSLms */
+
+       /* Push the L3 IE tag and lengh */
+       msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
+
+       /* Then push the RSL header */
+       rsl_rll_push_hdr(msg, msg_type, chan_nr, link_id, transparent);
 }
 
 struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
-                           uint8_t link_id)
+                           uint8_t link_id, int transparent)
 {
        struct abis_rsl_rll_hdr *rh;
-       struct msgb *msg = msgb_alloc(sizeof(*rh), "rsl_rll_simple");
+       struct msgb *msg;
+
+       msg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM,
+                                 RSL_ALLOC_HEADROOM, "rsl_rll_simple");
 
        if (!msg)
                return NULL;
@@ -276,7 +359,8 @@ struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
        /* put the RSL header */
        rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
        rsl_init_rll_hdr(rh, msg_type);
-       rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
+       if (transparent)
+               rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
        rh->chan_nr = chan_nr;
        rh->link_id = link_id;