X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Fhost%2Flayer23%2Fsrc%2Fmobile%2Fapp_mobile.c;h=164f3edb11371e4579691e0c7d7ecd718c425dc6;hb=cc10636f91dbd514ffe712325e10b7c1509678f3;hp=293d1355aa8bca41280c1a4958db900ada639fd4;hpb=6f2b172780195e0af780ecd0a4fff0fac9b8438b;p=osmocom-bb.git diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c index 293d135..164f3ed 100644 --- a/src/host/layer23/src/mobile/app_mobile.c +++ b/src/host/layer23/src/mobile/app_mobile.c @@ -30,18 +30,30 @@ #include #include #include +#include #include #include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include + +#include + +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_dummy(struct osmocom_ms *ms, int msg_type, void *arg); -extern int (*l23_app_exit) (struct osmocom_ms *ms, int force); +int (*mncc_recv_app)(struct osmocom_ms *ms, int, void *); +static int quit; +/* handle ms instance */ int mobile_work(struct osmocom_ms *ms) { int work = 0, w; @@ -63,6 +75,7 @@ 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, void *handler_data, void *signal_data) { @@ -89,7 +102,8 @@ int mobile_signal_cb(unsigned int subsys, unsigned int signal, break; case GSM_SIM_TYPE_TEST: gsm_subscr_testcard(ms, set->test_rplmn_mcc, - set->test_rplmn_mnc); + set->test_rplmn_mnc, set->test_lac, + set->test_tmsi); break; default: /* no SIM, trigger PLMN selection process */ @@ -108,6 +122,7 @@ int mobile_signal_cb(unsigned int subsys, unsigned int signal, return 0; } +/* power-off ms instance */ int mobile_exit(struct osmocom_ms *ms, int force) { struct gsm48_mmlayer *mm = &ms->mmlayer; @@ -130,8 +145,7 @@ int mobile_exit(struct osmocom_ms *ms, int force) gsm_subscr_exit(ms); gsm48_cc_exit(ms); gsm_sim_exit(ms); - lapdm_exit(&ms->l2_entity.lapdm_acch); - lapdm_exit(&ms->l2_entity.lapdm_dcch); + lapdm_channel_exit(&ms->lapdm_channel); ms->shutdown = 2; /* being down */ vty_notify(ms, NULL); @@ -141,12 +155,16 @@ int mobile_exit(struct osmocom_ms *ms, int force) return 0; } -int l23_app_init(struct osmocom_ms *ms) +/* power-on ms instance */ +int mobile_init(struct osmocom_ms *ms) { int rc; - lapdm_init(&ms->l2_entity.lapdm_dcch, ms); - lapdm_init(&ms->l2_entity.lapdm_acch, ms); + gsm_settings_arfcn(ms); + + lapdm_channel_init(&ms->lapdm_channel, LAPDM_MODE_MS); + lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms); + gsm_sim_init(ms); gsm48_cc_init(ms); gsm_subscr_init(ms); @@ -159,7 +177,7 @@ int l23_app_init(struct osmocom_ms *ms) if (rc < 0) { fprintf(stderr, "Failed during layer2_open()\n"); ms->l2_wq.bfd.fd = -1; - l23_app_exit(ms, 1); + mobile_exit(ms, 1); return rc; } @@ -168,12 +186,14 @@ int l23_app_init(struct osmocom_ms *ms) if (rc < 0) { fprintf(stderr, "Failed during sap_open(), no SIM reader\n"); ms->sap_wq.bfd.fd = -1; - l23_app_exit(ms, 1); + mobile_exit(ms, 1); return rc; } #endif - if (ms->settings.ch_cap == GSM_CAP_SDCCH) + if (mncc_recv_app) + ms->cclayer.mncc_recv = mncc_recv_app; + else if (ms->settings.ch_cap == GSM_CAP_SDCCH) ms->cclayer.mncc_recv = mncc_recv_dummy; else ms->cclayer.mncc_recv = mncc_recv_mobile; @@ -183,8 +203,204 @@ int l23_app_init(struct osmocom_ms *ms) ms->shutdown = 0; ms->started = 0; + if (!strcmp(ms->settings.imei, "000000000000000")) { + printf("***\nWarning: Mobile '%s' has default IMEI: %s\n", + ms->name, ms->settings.imei); + printf("This could relate your identitiy to other users with " + "default IMEI.\n***\n"); + } + l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL); printf("Mobile '%s' initialized, please start phone now!\n", ms->name); return 0; } +/* create ms instance */ +struct osmocom_ms *mobile_new(char *name) +{ + static struct osmocom_ms *ms; + + ms = talloc_zero(l23_ctx, struct osmocom_ms); + if (!ms) { + fprintf(stderr, "Failed to allocate MS\n"); + exit(1); + } + llist_add_tail(&ms->entity, &ms_list); + + strcpy(ms->name, name); + + ms->l2_wq.bfd.fd = -1; + ms->sap_wq.bfd.fd = -1; + + gsm_support_init(ms); + gsm_settings_init(ms); + + ms->shutdown = 2; /* being down */ + + if (mncc_recv_app) { + struct msgb *msg; + + msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC"); + if (msg) { + struct gsm_mncc *mncc = (struct gsm_mncc *)msg->data; + + mncc->msg_type = MS_NEW; + mncc_recv_app(ms, mncc->msg_type, mncc); + } + ms->cclayer.mncc_recv = mncc_recv_app; + } else + ms->cclayer.mncc_recv = mncc_recv_dummy; + + return ms; +} + +/* destroy ms instance */ +int mobile_delete(struct osmocom_ms *ms, int force) +{ + int rc; + + ms->deleting = 1; + + if (ms->shutdown == 0 || (ms->shutdown == 1 && force)) { + rc = mobile_exit(ms, force); + if (rc < 0) + return rc; + } + + if (mncc_recv_app) { + struct msgb *msg; + + msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC"); + if (msg) { + struct gsm_mncc *mncc = (struct gsm_mncc *)msg->data; + + mncc->msg_type = MS_DELETE; + mncc_recv_app(ms, mncc->msg_type, mncc); + } + } + + return 0; +} + +/* handle global shutdown */ +int global_signal_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct osmocom_ms *ms, *ms2; + + if (subsys != SS_GLOBAL) + return 0; + + switch (signal) { + case S_GLOBAL_SHUTDOWN: + llist_for_each_entry_safe(ms, ms2, &ms_list, entity) + mobile_delete(ms, quit); + + /* if second signal is received, force to exit */ + quit = 1; + break; + } + return 0; +} + +/* global work handler */ +int l23_app_work(int *_quit) +{ + struct osmocom_ms *ms, *ms2; + int work = 0; + + llist_for_each_entry_safe(ms, ms2, &ms_list, entity) { + if (ms->shutdown != 2) + work |= mobile_work(ms); + if (ms->shutdown == 2) { + if (ms->l2_wq.bfd.fd > -1) { + 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); + llist_del(&ms->entity); + talloc_free(ms); + work = 1; + } + } + } + + /* return, if a shutdown was scheduled (quit = 1) */ + *_quit = quit; + return work; +} + +/* global exit */ +int l23_app_exit(void) +{ + 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(); + + 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, uint16_t vty_port) +{ + struct telnet_connection dummy_conn; + int rc = 0; + + mncc_recv_app = mncc_recv; + + osmo_gps_init(); + + vty_init(&vty_info); + 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) { + fprintf(stderr, "Failed to parse the config file:" + " '%s'\n", config_file); + fprintf(stderr, "Please check or create config file" + " using: 'touch %s'\n", config_file); + return rc; + } + } + vty_reading = 0; + telnet_init(l23_ctx, NULL, vty_port); + if (rc < 0) + return rc; + printf("VTY available on port %u.\n", vty_port); + + 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); + + if (llist_empty(&ms_list)) { + struct osmocom_ms *ms; + + printf("No Mobile Station defined, creating: MS '1'\n"); + ms = mobile_new("1"); + if (ms) + mobile_init(ms); + } + + quit = 0; + + return 0; +} +