diff options
Diffstat (limited to 'src/host/layer23/src/mobile/app_mobile.c')
-rw-r--r-- | src/host/layer23/src/mobile/app_mobile.c | 301 |
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; |