summaryrefslogtreecommitdiffstats
path: root/src/host/layer23/src/mobile/app_mobile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/host/layer23/src/mobile/app_mobile.c')
-rw-r--r--src/host/layer23/src/mobile/app_mobile.c301
1 files changed, 162 insertions, 139 deletions
diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c
index f0f118b6..477c4fa5 100644
--- a/src/host/layer23/src/mobile/app_mobile.c
+++ b/src/host/layer23/src/mobile/app_mobile.c
@@ -16,32 +16,35 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <errno.h>
#include <signal.h>
#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/ms.h>
#include <osmocom/bb/common/l1l2_interface.h>
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/gps.h>
+#include <osmocom/bb/common/sap_interface.h>
+#include <osmocom/bb/common/sim.h>
+#include <osmocom/bb/common/l23_app.h>
+
#include <osmocom/bb/mobile/gsm48_rr.h>
#include <osmocom/bb/mobile/gsm480_ss.h>
+#include <osmocom/bb/mobile/gsm48_mm.h>
+#include <osmocom/bb/mobile/gsm48_cc.h>
+#include <osmocom/bb/mobile/gsm44068_gcc_bcc.h>
#include <osmocom/bb/mobile/gsm411_sms.h>
+#include <osmocom/bb/mobile/gsm322.h>
#include <osmocom/bb/mobile/vty.h>
#include <osmocom/bb/mobile/app_mobile.h>
#include <osmocom/bb/mobile/mncc.h>
-#include <osmocom/bb/mobile/voice.h>
+#include <osmocom/bb/mobile/tch.h>
#include <osmocom/bb/mobile/primitives.h>
-#include <osmocom/bb/common/sap_interface.h>
-#include <osmocom/vty/ports.h>
-#include <osmocom/vty/logging.h>
+#include <osmocom/vty/vty.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/core/msgb.h>
@@ -51,14 +54,16 @@
#include <l1ctl_proto.h>
+#include "config.h"
+
extern void *l23_ctx;
extern struct llist_head ms_list;
-extern int vty_reading;
-int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg);
+int mncc_recv_internal(struct osmocom_ms *ms, int msg_type, void *arg);
+int mncc_recv_external(struct osmocom_ms *ms, int msg_type, void *arg);
int mncc_recv_dummy(struct osmocom_ms *ms, int msg_type, void *arg);
-int (*mncc_recv_app)(struct osmocom_ms *ms, int, void *);
-static int quit;
+static int _quit;
+extern int quit; /* l23 main */
/* handle ms instance */
int mobile_work(struct osmocom_ms *ms)
@@ -82,12 +87,54 @@ int mobile_work(struct osmocom_ms *ms)
return work;
}
-/* run ms instance, if layer1 is available */
-int mobile_signal_cb(unsigned int subsys, unsigned int signal,
+/* SIM becomes ATTACHED/DETACHED, or answers a request */
+static int mobile_l23_subscr_signal_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
+ struct msgb *nmsg;
+ struct gsm48_mm_event *nmme;
+ struct osmocom_ms *ms;
+ struct osmobb_l23_subscr_sim_auth_resp_sig_data *sim_auth_resp;
+
+ OSMO_ASSERT(subsys == SS_L23_SUBSCR);
+
+ switch (signal) {
+ case S_L23_SUBSCR_SIM_ATTACHED:
+ ms = signal_data;
+ nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_REG_REQ);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm48_mmr_downmsg(ms, nmsg);
+ break;
+ case S_L23_SUBSCR_SIM_DETACHED:
+ ms = signal_data;
+ nmsg = gsm48_mmr_msgb_alloc(GSM48_MMR_NREG_REQ);
+ if (!nmsg)
+ return 0;
+ gsm48_mmr_downmsg(ms, nmsg);
+ break;
+ case S_L23_SUBSCR_SIM_AUTH_RESP:
+ sim_auth_resp = signal_data;
+ ms = sim_auth_resp->ms;
+ nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_AUTH_RESPONSE);
+ if (!nmsg)
+ return 0;
+ nmme = (struct gsm48_mm_event *) nmsg->data;
+ memcpy(nmme->sres, sim_auth_resp->sres, 4);
+ gsm48_mmevent_msg(ms, nmsg);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+
+ return 0;
+}
+
+/* run ms instance, if layer1 is available */
+static int mobile_signal_cb(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
struct osmocom_ms *ms;
- struct gsm_settings *set;
struct msgb *nmsg;
if (subsys != SS_L1CTL)
@@ -96,11 +143,10 @@ int mobile_signal_cb(unsigned int subsys, unsigned int signal,
switch (signal) {
case S_L1CTL_RESET:
ms = signal_data;
- set = &ms->settings;
/* waiting for reset after shutdown */
if (ms->shutdown == MS_SHUTDOWN_WAIT_RESET) {
- LOGP(DMOB, LOGL_NOTICE, "MS '%s' has been resetted\n", ms->name);
+ LOGP(DMOB, LOGL_NOTICE, "MS '%s' has been reset\n", ms->name);
ms->shutdown = MS_SHUTDOWN_COMPL;
break;
}
@@ -108,21 +154,10 @@ int mobile_signal_cb(unsigned int subsys, unsigned int signal,
if (ms->started)
break;
- /* insert test card, if enabled */
- switch (set->sim_type) {
- case GSM_SIM_TYPE_L1PHY:
- /* trigger sim card reader process */
- gsm_subscr_simcard(ms);
- break;
- case GSM_SIM_TYPE_TEST:
- gsm_subscr_testcard(ms, set->test_rplmn_mcc,
- set->test_rplmn_mnc, set->test_lac,
- set->test_tmsi, set->test_imsi_attached);
- break;
- case GSM_SIM_TYPE_SAP:
- gsm_subscr_sapcard(ms);
- break;
- default:
+ if (ms->settings.sim_type != GSM_SIM_TYPE_NONE) {
+ /* insert sim card */
+ gsm_subscr_insert(ms);
+ } else {
/* no SIM, trigger PLMN selection process */
nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON);
if (!nmsg)
@@ -167,6 +202,7 @@ int mobile_exit(struct osmocom_ms *ms, int force)
gsm48_cc_exit(ms);
gsm480_ss_exit(ms);
gsm411_sms_exit(ms);
+ gsm44068_gcc_exit(ms);
gsm_sim_exit(ms);
lapdm_channel_exit(&ms->lapdm_channel);
@@ -176,8 +212,8 @@ int mobile_exit(struct osmocom_ms *ms, int force)
} else {
mobile_set_shutdown(ms, MS_SHUTDOWN_COMPL); /* being down */
}
- vty_notify(ms, NULL);
- vty_notify(ms, "Power off!\n");
+ l23_vty_ms_notify(ms, NULL);
+ l23_vty_ms_notify(ms, "Power off!\n");
LOGP(DMOB, LOGL_NOTICE, "Power off! (MS %s)\n", ms->name);
return 0;
@@ -190,26 +226,27 @@ static int mobile_init(struct osmocom_ms *ms)
gsm_settings_arfcn(ms);
- lapdm_channel_init(&ms->lapdm_channel, LAPDM_MODE_MS);
- ms->lapdm_channel.lapdm_dcch.datalink[DL_SAPI3].dl.t200_sec =
- T200_DCCH_SHARED;
- ms->lapdm_channel.lapdm_dcch.datalink[DL_SAPI3].dl.t200_usec = 0;
- ms->lapdm_channel.lapdm_acch.datalink[DL_SAPI3].dl.t200_sec =
- T200_ACCH;
- ms->lapdm_channel.lapdm_acch.datalink[DL_SAPI3].dl.t200_usec = 0;
+ const int t200_ms_dcch[_NR_DL_SAPI] = {
+ [DL_SAPI0] = 1000,
+ [DL_SAPI3] = 1000 * T200_DCCH_SHARED
+ };
+ const int t200_ms_acch[_NR_DL_SAPI] = {
+ [DL_SAPI0] = 2000,
+ [DL_SAPI3] = 1000 * T200_ACCH
+ };
+
+ lapdm_channel_init3(&ms->lapdm_channel, LAPDM_MODE_MS,
+ t200_ms_dcch, t200_ms_acch,
+ GSM_LCHAN_SDCCH, NULL);
+ lapdm_channel_set_flags(&ms->lapdm_channel, LAPDM_ENT_F_DROP_2ND_REJ);
lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms);
- /* init SAP client before SIM card starts up */
- sap_init(ms);
-
- /* SAP response call-back */
- ms->sap_entity.sap_rsp_cb = &gsm_subscr_sap_rsp_cb;
-
gsm_sim_init(ms);
gsm48_cc_init(ms);
gsm480_ss_init(ms);
gsm411_sms_init(ms);
- gsm_voice_init(ms);
+ gsm44068_gcc_init(ms);
+ tch_init(ms);
gsm_subscr_init(ms);
gsm48_rr_init(ms);
gsm48_mm_init(ms);
@@ -236,6 +273,24 @@ static int mobile_init(struct osmocom_ms *ms)
"default IMEI.\n***\n");
}
+ switch (ms->settings.mncc_handler) {
+ case MNCC_HANDLER_INTERNAL:
+ LOGP(DMOB, LOGL_INFO, "Using the built-in MNCC-handler for MS '%s'\n", ms->name);
+ ms->mncc_entity.mncc_recv = &mncc_recv_internal;
+ break;
+ case MNCC_HANDLER_EXTERNAL:
+ LOGP(DMOB, LOGL_INFO, "Using external MNCC-handler (socket '%s') for MS '%s'\n",
+ ms->settings.mncc_socket_path, ms->name);
+ ms->mncc_entity.mncc_recv = &mncc_recv_external;
+ ms->mncc_entity.sock_state = mncc_sock_init(ms, ms->settings.mncc_socket_path);
+ break;
+ case MNCC_HANDLER_DUMMY:
+ default:
+ LOGP(DMOB, LOGL_INFO, "Using dummy MNCC-handler (no call support) "
+ "for MS '%s'\n", ms->name);
+ ms->mncc_entity.mncc_recv = &mncc_recv_dummy;
+ }
+
l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
LOGP(DMOB, LOGL_NOTICE, "Mobile '%s' initialized, please start phone now!\n", ms->name);
return 0;
@@ -255,7 +310,7 @@ int mobile_start(struct osmocom_ms *ms, char **other_name)
if (!strcmp(ms->settings.layer2_socket_path,
tmp->settings.layer2_socket_path)) {
LOGP(DMOB, LOGL_ERROR, "Cannot start MS '%s', because MS '%s' "
- "use the same layer2-socket.\nPlease shutdown "
+ "is using the same layer2-socket.\nPlease shutdown "
"MS '%s' first.\n", ms->name, tmp->name, tmp->name);
*other_name = tmp->name;
return -1;
@@ -263,11 +318,19 @@ int mobile_start(struct osmocom_ms *ms, char **other_name)
if (!strcmp(ms->settings.sap_socket_path,
tmp->settings.sap_socket_path)) {
LOGP(DMOB, LOGL_ERROR, "Cannot start MS '%s', because MS '%s' "
- "use the same sap-socket.\nPlease shutdown "
+ "is using the same sap-socket.\nPlease shutdown "
"MS '%s' first.\n", ms->name, tmp->name, tmp->name);
*other_name = tmp->name;
return -2;
}
+ if (!strcmp(ms->settings.mncc_socket_path,
+ tmp->settings.mncc_socket_path)) {
+ LOGP(DMOB, LOGL_ERROR, "Cannot start MS '%s', because MS '%s' "
+ "is using the same mncc-socket.\nPlease shutdown "
+ "MS '%s' first.\n", ms->name, tmp->name, tmp->name);
+ *other_name = tmp->name;
+ return -3;
+ }
}
rc = mobile_init(ms);
@@ -290,40 +353,14 @@ int mobile_stop(struct osmocom_ms *ms, int force)
struct osmocom_ms *mobile_new(char *name)
{
static struct osmocom_ms *ms;
- char *mncc_name;
- ms = talloc_zero(l23_ctx, struct osmocom_ms);
+ ms = osmocom_ms_alloc(l23_ctx, name);
if (!ms) {
LOGP(DMOB, LOGL_ERROR, "Failed to allocate MS: %s\n", name);
return NULL;
}
- talloc_set_name(ms, "ms_%s", name);
- ms->name = talloc_strdup(ms, name);
- ms->l2_wq.bfd.fd = -1;
- ms->sap_wq.bfd.fd = -1;
-
- /* Register a new MS */
- llist_add_tail(&ms->entity, &ms_list);
-
- gsm_support_init(ms);
- gsm_settings_init(ms);
-
mobile_set_shutdown(ms, MS_SHUTDOWN_COMPL);
-
- if (mncc_recv_app) {
- mncc_name = talloc_asprintf(ms, "/tmp/ms_mncc_%s", ms->name);
-
- ms->mncc_entity.mncc_recv = mncc_recv_app;
- ms->mncc_entity.sock_state = mncc_sock_init(ms, mncc_name);
-
- talloc_free(mncc_name);
- } else if (ms->settings.ch_cap == GSM_CAP_SDCCH)
- ms->mncc_entity.mncc_recv = mncc_recv_dummy;
- else
- ms->mncc_entity.mncc_recv = mncc_recv_mobile;
-
-
return ms;
}
@@ -334,7 +371,7 @@ int mobile_delete(struct osmocom_ms *ms, int force)
ms->deleting = true;
- if (mncc_recv_app) {
+ if (ms->settings.mncc_handler == MNCC_HANDLER_EXTERNAL) {
mncc_sock_exit(ms->mncc_entity.sock_state);
ms->mncc_entity.sock_state = NULL;
}
@@ -349,8 +386,8 @@ int mobile_delete(struct osmocom_ms *ms, int force)
}
/* handle global shutdown */
-int global_signal_cb(unsigned int subsys, unsigned int signal,
- void *handler_data, void *signal_data)
+static int global_signal_cb(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
{
struct osmocom_ms *ms, *ms2;
@@ -361,20 +398,20 @@ int global_signal_cb(unsigned int subsys, unsigned int signal,
case S_GLOBAL_SHUTDOWN:
/* force to exit, if signalled */
if (signal_data && *((uint8_t *)signal_data))
- quit = 1;
+ _quit = 1;
llist_for_each_entry_safe(ms, ms2, &ms_list, entity)
- mobile_delete(ms, quit);
+ mobile_delete(ms, _quit);
/* quit, after all MS processes are gone */
- quit = 1;
+ _quit = 1;
break;
}
return 0;
}
/* global work handler */
-int l23_app_work(int *_quit)
+static int _mobile_app_work(void)
{
struct osmocom_ms *ms, *ms2;
int work = 0;
@@ -387,14 +424,9 @@ int l23_app_work(int *_quit)
layer2_close(ms);
ms->l2_wq.bfd.fd = -1;
}
-
- if (ms->sap_wq.bfd.fd > -1) {
- sap_close(ms);
- ms->sap_wq.bfd.fd = -1;
- }
-
if (ms->deleting) {
gsm_settings_exit(ms);
+ script_lua_close(ms);
llist_del(&ms->entity);
talloc_free(ms);
work = 1;
@@ -403,70 +435,27 @@ int l23_app_work(int *_quit)
}
/* return, if a shutdown was scheduled (quit = 1) */
- *_quit = quit;
+ quit = _quit;
return work;
}
/* global exit */
-int l23_app_exit(void)
+static int _mobile_app_exit(void)
{
+ osmo_signal_unregister_handler(SS_L23_SUBSCR, &mobile_l23_subscr_signal_cb, NULL);
osmo_signal_unregister_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
osmo_signal_unregister_handler(SS_L1CTL, &mobile_signal_cb, NULL);
osmo_signal_unregister_handler(SS_GLOBAL, &global_signal_cb, NULL);
osmo_gps_close();
- telnet_exit();
-
return 0;
}
-static struct vty_app_info vty_info = {
- .name = "OsmocomBB",
- .version = PACKAGE_VERSION,
- .go_parent_cb = ms_vty_go_parent,
-};
-/* global init */
-int l23_app_init(int (*mncc_recv)(struct osmocom_ms *ms, int, void *),
- const char *config_file)
+static int _mobile_app_start(void)
{
- struct telnet_connection dummy_conn;
- int rc = 0;
-
- mncc_recv_app = mncc_recv;
-
- osmo_gps_init();
-
- vty_info.tall_ctx = l23_ctx;
- vty_init(&vty_info);
- logging_vty_add_cmds();
- ms_vty_init();
- dummy_conn.priv = NULL;
- vty_reading = 1;
- if (config_file != NULL) {
- rc = vty_read_config_file(config_file, &dummy_conn);
- if (rc < 0) {
- LOGP(DMOB, LOGL_FATAL, "Failed to parse the configuration "
- "file '%s'\n", config_file);
- LOGP(DMOB, LOGL_FATAL, "Please make sure the file "
- "'%s' exists, or use an example from "
- "'doc/examples/mobile/'\n", config_file);
- return rc;
- }
- LOGP(DMOB, LOGL_INFO, "Using configuration from '%s'\n", config_file);
- }
- vty_reading = 0;
- rc = telnet_init_default(l23_ctx, NULL, OSMO_VTY_PORT_BB);
- if (rc < 0) {
- LOGP(DMOB, LOGL_FATAL, "Cannot init VTY on %s port %u: %s\n",
- vty_get_bind_addr(), OSMO_VTY_PORT_BB, strerror(errno));
- return rc;
- }
-
- osmo_signal_register_handler(SS_GLOBAL, &global_signal_cb, NULL);
- osmo_signal_register_handler(SS_L1CTL, &mobile_signal_cb, NULL);
- osmo_signal_register_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
+ int rc;
if (llist_empty(&ms_list)) {
struct osmocom_ms *ms;
@@ -481,11 +470,45 @@ int l23_app_init(int (*mncc_recv)(struct osmocom_ms *ms, int, void *),
return rc;
}
- quit = 0;
+ _quit = 0;
+
+ return 0;
+}
+
+/* global init */
+int l23_app_init(void)
+{
+ l23_app_start = _mobile_app_start;
+ l23_app_work = _mobile_app_work;
+ l23_app_exit = _mobile_app_exit;
+ osmo_gps_init();
+
+ osmo_signal_register_handler(SS_GLOBAL, &global_signal_cb, NULL);
+ osmo_signal_register_handler(SS_L1CTL, &mobile_signal_cb, NULL);
+ osmo_signal_register_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
+ osmo_signal_register_handler(SS_L23_SUBSCR, &mobile_l23_subscr_signal_cb, NULL);
return 0;
}
+static int _mobile_vty_init(void)
+{
+ return ms_vty_init();
+}
+
+static struct vty_app_info _mobile_vty_info = {
+ .name = "OsmocomBB(mobile)",
+ .version = PACKAGE_VERSION,
+};
+
+const struct l23_app_info l23_app_info = {
+ .copyright = "Copyright (C) 2010-2015 Andreas Eversberg, Sylvain Munaut, Holger Freyther, Harald Welte\n",
+ .contribution = "Contributions by Alex Badea, Pablo Neira, Steve Markgraf and others\n",
+ .opt_supported = L23_OPT_TAP | L23_OPT_VTY | L23_OPT_DBG,
+ .vty_info = &_mobile_vty_info,
+ .vty_init = _mobile_vty_init,
+};
+
void mobile_set_started(struct osmocom_ms *ms, bool state)
{
ms->started = state;