[gsm] Make LCR work with current Osmocom-BB.
authorAndreas Eversberg <jolly@eversberg.eu>
Sat, 26 Feb 2011 16:49:21 +0000 (16:49 +0000)
committerAndreas Eversberg <jolly@eversberg.eu>
Sat, 26 Feb 2011 16:49:21 +0000 (16:49 +0000)
Osmocom-BB is still developed, and this only works with the jolly/voice
branch. Audio is not yet transmitted, so it is not quite usefull yet.

default/interface.conf
gsm.cpp
gsm.h
gsm_bs.h
gsm_ms.cpp
gsm_ms.h
interface.c
interface.h
mISDN.cpp
main.c

index 4c80fed..004df59 100644 (file)
 # of LCR. The actual interface is defined in gsm.conf.
 # You may add 'extern' to make this interface the external line by default.
 #[GSM]
 # of LCR. The actual interface is defined in gsm.conf.
 # You may add 'extern' to make this interface the external line by default.
 #[GSM]
-#gsm-ms 1 /tmp/osmocom_l2
+#gsm-ms 1
 #layer1hold no
 #layer2hold no
 #tones no
 #layer1hold no
 #layer2hold no
 #tones no
diff --git a/gsm.cpp b/gsm.cpp
index 07746f7..119f0f5 100644 (file)
--- a/gsm.cpp
+++ b/gsm.cpp
@@ -199,14 +199,16 @@ struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
 }
 int send_and_free_mncc(void *instance, unsigned int msg_type, void *data)
 {
 }
 int send_and_free_mncc(void *instance, unsigned int msg_type, void *data)
 {
-       int ret;
+       int ret = 0;
 
 
+       if (instance) {
 #ifdef WITH_GSM_BS
 #ifdef WITH_GSM_BS
-       ret = mncc_send((struct gsm_network *)instance, msg_type, data);
+               ret = mncc_send((struct gsm_network *)instance, msg_type, data);
 #endif
 #ifdef WITH_GSM_MS
 #endif
 #ifdef WITH_GSM_MS
-       ret = mncc_send((struct osmocom_ms *)instance, msg_type, data);
+               ret = mncc_send((struct osmocom_ms *)instance, msg_type, data);
 #endif
 #endif
+       }
        free(data);
 
        return ret;
        free(data);
 
        return ret;
diff --git a/gsm.h b/gsm.h
index 4bfad78..c12baa0 100644 (file)
--- a/gsm.h
+++ b/gsm.h
@@ -75,6 +75,3 @@ int gsm_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_exit(int rc);
 int gsm_init(void);
 
 int gsm_exit(int rc);
 int gsm_init(void);
 
-extern "C" {
-int mncc_send(struct gsm_network *instance, int msg_type, void *data);
-};
index fd56efe..8a55213 100644 (file)
--- a/gsm_bs.h
+++ b/gsm_bs.h
@@ -25,3 +25,7 @@ int handle_gsm_bs(void);
 int gsm_bs_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_bs_exit(int rc);
 int gsm_bs_init(void);
 int gsm_bs_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_bs_exit(int rc);
 int gsm_bs_init(void);
+
+extern "C" {
+int mncc_send(struct gsm_network *instance, int msg_type, void *data);
+};
index 551fcad..481a4ac 100644 (file)
 #endif
 extern "C" {
 #include <getopt.h>
 #endif
 extern "C" {
 #include <getopt.h>
+#include <arpa/inet.h>
 
 #include <osmocore/select.h>
 #include <osmocore/talloc.h>
 
 #include <osmocore/select.h>
 #include <osmocore/talloc.h>
+#include <osmocore/gsmtap_util.h>
 
 #include <osmocom/bb/common/osmocom_data.h>
 #include <osmocom/bb/common/logging.h>
 #include <osmocom/bb/common/l1l2_interface.h>
 
 #include <osmocom/bb/common/osmocom_data.h>
 #include <osmocom/bb/common/logging.h>
 #include <osmocom/bb/common/l1l2_interface.h>
-#include <osmocom/bb/common/l23_app.h>
+#include <osmocom/bb/mobile/app_mobile.h>
 }
 
 }
 
-const char *openbsc_copyright = "";
+static const char *config_file = "/etc/osmocom/osmocom.cfg";
 short vty_port = 4247;
 
 struct llist_head ms_list;
 struct log_target *stderr_target;
 void *l23_ctx = NULL;
 short vty_port = 4247;
 
 struct llist_head ms_list;
 struct log_target *stderr_target;
 void *l23_ctx = NULL;
-int (*l23_app_work) (struct osmocom_ms *ms) = NULL;
-int (*l23_app_exit) (struct osmocom_ms *ms) = NULL;
 
 static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index);
 
 
 static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index);
 
@@ -54,9 +54,6 @@ Pgsm_ms::Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct p
                }
        }
 
                }
        }
 
-       if (!p_m_g_instance)
-               FATAL("MS name %s does not exists. Please fix!");
-
        p_m_g_dtmf_state = DTMF_ST_IDLE;
        p_m_g_dtmf_index = 0;
        p_m_g_dtmf[0] = '\0';
        p_m_g_dtmf_state = DTMF_ST_IDLE;
        p_m_g_dtmf_index = 0;
        p_m_g_dtmf[0] = '\0';
@@ -391,7 +388,31 @@ static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg)
        struct mISDNport *mISDNport;
 
        /* Special messages */
        struct mISDNport *mISDNport;
 
        /* Special messages */
-       if (msg_type) {
+       switch (msg_type) {
+       case MS_NEW:
+               PDEBUG(DEBUG_GSM, "MS %s comes available\n", ms->name);
+               return 0;
+       case MS_DELETE:
+               PDEBUG(DEBUG_GSM, "MS %s is removed\n", ms->name);
+               port = port_first;
+               while(port) {
+                       if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
+                               pgsm_ms = (class Pgsm_ms *)port;
+                               if (pgsm_ms->p_m_g_instance == ms) {
+                                       struct lcr_msg *message;
+
+                                       pgsm_ms->p_m_g_instance = 0;
+                                       message = message_create(pgsm_ms->p_serial, ACTIVE_EPOINT(pgsm_ms->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
+                                       message->param.disconnectinfo.cause = 27;
+                                       message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+                                       message_put(message);
+                                       pgsm_ms->new_state(PORT_STATE_RELEASE);
+                                       trigger_work(&pgsm_ms->p_m_g_delete);
+                               }
+                       }
+                       port = port->next;
+               }
+               return 0;
        }
 
        /* find callref */
        }
 
        /* find callref */
@@ -508,6 +529,20 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
        memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
 
        memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
 
+       /* no instance */
+       if (!p_m_g_instance) {
+               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+               add_trace("failure", NULL, "MS %s instance is unavailable", p_m_mISDNport->ifport->gsm_ms_name);
+               end_trace();
+               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+               message->param.disconnectinfo.cause = 27;
+               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+               message_put(message);
+               new_state(PORT_STATE_RELEASE);
+               trigger_work(&p_m_g_delete);
+               return;
+       }
+       
        /* no number */
        if (!p_dialinginfo.id[0]) {
                gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
        /* no number */
        if (!p_dialinginfo.id[0]) {
                gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
@@ -782,6 +817,7 @@ int Pgsm_ms::message_epoint(unsigned int epoint_id, int message_id, union parame
 
 int gsm_ms_exit(int rc)
 {
 
 int gsm_ms_exit(int rc)
 {
+       l23_app_exit();
 
        return(rc);
 }
 
        return(rc);
 }
@@ -796,50 +832,40 @@ int gsm_ms_init(void)
 
        l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
 
 
        l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
 
-       return 0;
-}
-
-/* add a new GSM mobile instance */
-int gsm_ms_new(const char *name, const char *socket_path)
-{
-       struct osmocom_ms *ms = NULL;
-       int rc;
-
-       PDEBUG(DEBUG_GSM, "GSM: creating new instance '%s' on '%s'\n", name, socket_path);
+       log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
+       log_set_log_level(stderr_target, LOGL_INFO);
 
 
-       ms = talloc_zero(l23_ctx, struct osmocom_ms);
-       if (!ms) {
-               FATAL("Failed to allocate MS\n");
+#if 0
+       if (gsmtap_ip) {
+               rc = gsmtap_init(gsmtap_ip);
+               if (rc < 0) {
+                       fprintf(stderr, "Failed during gsmtap_init()\n");
+                       exit(1);
+               }
        }
        }
-       /* must add here, because other init processes may search in the list */
-       llist_add_tail(&ms->entity, &ms_list);
-
-
-       SPRINT(ms->name, name);
+#endif
 
 
-       rc = layer2_open(ms, socket_path);
-       if (rc < 0) {
-               FATAL("Failed during layer2_open()\n");
-       }
+       l23_app_init(message_ms, config_file, vty_port);
 
 
-       lapdm_init(&ms->l2_entity.lapdm_dcch, ms);
-       lapdm_init(&ms->l2_entity.lapdm_acch, ms);
+       return 0;
+}
 
 
-       rc = l23_app_init(ms);
-       if (rc < 0) {
-               FATAL("Failed to init layer23\n");
-       }
-       ms->mncc_entity.mncc_recv = message_ms;
+/* add a new GSM mobile instance */
+int gsm_ms_new(const char *name)
+{
+       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is up\n", name);
 
        return 0;
 }
 
 int gsm_ms_delete(const char *name)
 {
 
        return 0;
 }
 
 int gsm_ms_delete(const char *name)
 {
-       struct osmocom_ms *ms = NULL;
+       struct osmocom_ms *ms;
        int found = 0;
        int found = 0;
+       class Port *port;
+       class Pgsm_ms *pgsm_ms = NULL;
 
 
-       PDEBUG(DEBUG_GSM, "GSM: destroying instance '%s'\n", name);
+       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is down\n", name);
 
        llist_for_each_entry(ms, &ms_list, entity) {
                if (!strcmp(ms->name, name)) {
 
        llist_for_each_entry(ms, &ms_list, entity) {
                if (!strcmp(ms->name, name)) {
@@ -848,15 +874,29 @@ int gsm_ms_delete(const char *name)
                }
        }
 
                }
        }
 
-       if (!found) {
-               FATAL("Failed delete layer23, instance '%s' not found\n", name);
-       }
-
-       l23_app_exit(ms);
-       lapdm_exit(&ms->l2_entity.lapdm_dcch);
-       lapdm_exit(&ms->l2_entity.lapdm_acch);
+       if (!found)
+               return 0;
 
 
-       llist_del(&ms->entity);
+       port = port_first;
+       while(port) {
+               if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
+                       pgsm_ms = (class Pgsm_ms *)port;
+                       if (pgsm_ms->p_m_g_instance == ms && pgsm_ms->p_m_g_callref) {
+                               struct gsm_mncc *rej;
+
+                               rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_m_g_callref);
+                               rej->fields |= MNCC_F_CAUSE;
+                               rej->cause.coding = 3;
+                               rej->cause.location = 1;
+                               rej->cause.value = 27;
+                               gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
+                               add_trace("cause", "coding", "%d", rej->cause.coding);
+                               add_trace("cause", "location", "%d", rej->cause.location);
+                               add_trace("cause", "value", "%d", rej->cause.value);
+                               end_trace();
+                       }
+               }
+       }
 
        return 0;
 }
 
        return 0;
 }
@@ -864,18 +904,17 @@ int gsm_ms_delete(const char *name)
 /*
  * handles bsc select function within LCR's main loop
  */
 /*
  * handles bsc select function within LCR's main loop
  */
-int handle_gsm_ms(void)
+int handle_gsm_ms(int *_quit)
 {
 {
-       struct osmocom_ms *ms = NULL;
-       int work = 0;
-
-       llist_for_each_entry(ms, &ms_list, entity) {
-               if (l23_app_work(ms))
-                       work = 1;
-//             debug_reset_context();
-               if (bsc_select_main(1)) /* polling */
-                       work = 1;
-       }
+       int work = 0, quit = 0;
+
+       if (l23_app_work(&quit))
+               work = 1;
+       if (quit && llist_empty(&ms_list))
+               *_quit = 1;
+//     debug_reset_context();
+       if (bsc_select_main(1)) /* polling */
+               work = 1;
 
        return work;
 }
 
        return work;
 }
index 3e9794f..822f0a6 100644 (file)
--- a/gsm_ms.h
+++ b/gsm_ms.h
@@ -23,10 +23,10 @@ class Pgsm_ms : public Pgsm
        int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
 };
 
        int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
 };
 
-int handle_gsm_ms(void);
+int handle_gsm_ms(int *quit);
 int gsm_ms_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_ms_exit(int rc);
 int gsm_ms_init(void);
 int gsm_ms_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_ms_exit(int rc);
 int gsm_ms_init(void);
-int gsm_ms_new(const char *name, const char *socket_path);
+int gsm_ms_new(const char *name);
 int gsm_ms_delete(const char *name);
 
 int gsm_ms_delete(const char *name);
 
index 4b894cf..4e432af 100644 (file)
@@ -961,21 +961,15 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c
                return(-1);
        }
        SCPY(ifport->gsm_ms_name, element);
                return(-1);
        }
        SCPY(ifport->gsm_ms_name, element);
-       element = strsep(&value, " ");
-       if (!element || !element[0]) {
-               SPRINT(interface_error, "Error in %s (line %d): Missing socket name after MS name.\n", filename, line);
-               return(-1);
-       }
-       SCPY(ifport->gsm_ms_socket, element);
 
 
-       /* check if socket is used multiple times */
+       /* check if name is used multiple times */
        searchif = interface_newlist;
        while(searchif) {
                searchifport = searchif->ifport;
                while(searchifport) {
                        if (searchifport != ifport 
        searchif = interface_newlist;
        while(searchif) {
                searchifport = searchif->ifport;
                while(searchifport) {
                        if (searchifport != ifport 
-                        && !strcmp(searchifport->gsm_ms_socket, ifport->gsm_ms_socket)) {
-                               SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given socket '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_socket);
+                        && !strcmp(searchifport->gsm_ms_name, ifport->gsm_ms_name)) {
+                               SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_name);
                                return(-1);
                        }
                        searchifport = searchifport->next;
                                return(-1);
                        }
                        searchifport = searchifport->next;
@@ -1589,7 +1583,7 @@ void load_port(struct interface_port *ifport)
                mISDNport_static(mISDNport);
 #ifdef WITH_GSM_MS
                if (ifport->gsm_ms)
                mISDNport_static(mISDNport);
 #ifdef WITH_GSM_MS
                if (ifport->gsm_ms)
-                       gsm_ms_new(ifport->gsm_ms_name, ifport->gsm_ms_socket);
+                       gsm_ms_new(ifport->gsm_ms_name);
 #endif
        } else {
                ifport->block = 2; /* not available */
 #endif
        } else {
                ifport->block = 2; /* not available */
index eea6915..f271080 100644 (file)
@@ -57,8 +57,6 @@ struct interface_port {
 #ifdef WITH_GSM_MS
        int                     gsm_ms; /* interface is an GSM MS interface */
        char                    gsm_ms_name[32]; /* name of ms */
 #ifdef WITH_GSM_MS
        int                     gsm_ms; /* interface is an GSM MS interface */
        char                    gsm_ms_name[32]; /* name of ms */
-       char                    gsm_ms_socket[128]; /* layer1 socket name */
-       char                    gsm_ms_service; /* see GSM_SERVICE_* */
 #endif
        unsigned int            ss5; /* set, if SS5 signalling enabled, also holds feature bits */
        int                     remote; /* interface is a remote app interface */
 #endif
        unsigned int            ss5; /* set, if SS5 signalling enabled, also holds feature bits */
        int                     remote; /* interface is a remote app interface */
index 087963c..50746ec 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -1367,7 +1367,11 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
                if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL) {
                        chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
                        add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
                if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL) {
                        chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
                        add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
+                       if (!p_m_dtmf)
+                               add_trace("info", NULL, "DTMF is disabled");
                        end_trace();
                        end_trace();
+                       if (!p_m_dtmf)
+                               return;
                        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
                        message->param.dtmf = cont & DTMF_TONE_MASK;
                        PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
                        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
                        message->param.dtmf = cont & DTMF_TONE_MASK;
                        PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
diff --git a/main.c b/main.c
index b9e836c..1aa2d8b 100644 (file)
--- a/main.c
+++ b/main.c
 
 #include "main.h"
 #include "config.h"
 
 #include "main.h"
 #include "config.h"
+#ifdef WITH_GSM_MS
+extern "C" {
+#include <osmocore/signal.h>
+}
+#endif
 
 //MESSAGES
 
 
 //MESSAGES
 
@@ -138,11 +143,23 @@ void _printerror(const char *function, int line, const char *fmt, ...)
 void sighandler(int sigset)
 {
        struct sched_param schedp;
 void sighandler(int sigset)
 {
        struct sched_param schedp;
+#ifdef WITH_GSM_MS
+       int wait_ms = 0;
+#endif
 
        if (sigset == SIGHUP)
                return;
        if (sigset == SIGPIPE)
                return;
 
        if (sigset == SIGHUP)
                return;
        if (sigset == SIGPIPE)
                return;
+       fprintf(stderr, "LCR: Signal received: %d\n", sigset);
+       PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset);
+#ifdef WITH_GSM_MS
+       if (!wait_ms) {
+               wait_ms = 1;
+               dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+               return;
+       }
+#endif
        if (!quit) {
                quit = sigset;
                /* set scheduler & priority */
        if (!quit) {
                quit = sigset;
                /* set scheduler & priority */
@@ -151,8 +168,6 @@ void sighandler(int sigset)
                        schedp.sched_priority = 0;
                        sched_setscheduler(0, SCHED_OTHER, &schedp);
                }
                        schedp.sched_priority = 0;
                        sched_setscheduler(0, SCHED_OTHER, &schedp);
                }
-               fprintf(stderr, "LCR: Signal received: %d\n", sigset);
-               PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset);
        }
 }
 
        }
 }
 
@@ -470,7 +485,7 @@ int main(int argc, char *argv[])
                        if (handle_gsm())
                                all_idle = 0;
 #ifdef WITH_GSM_MS
                        if (handle_gsm())
                                all_idle = 0;
 #ifdef WITH_GSM_MS
-                       if (handle_gsm_ms())
+                       if (handle_gsm_ms(&quit))
                                all_idle = 0;
 #endif
                }
                                all_idle = 0;
 #endif
                }