X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Fhost%2Flayer23%2Fsrc%2Fmobile%2Fapp_mobile.c;h=164f3edb11371e4579691e0c7d7ecd718c425dc6;hb=cc10636f91dbd514ffe712325e10b7c1509678f3;hp=53e26bc13c1225217496c87631815f601f2728cd;hpb=de21ca4aaf999b15caca686b217708111117789b;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 53e26bc..164f3ed 100644 --- a/src/host/layer23/src/mobile/app_mobile.c +++ b/src/host/layer23/src/mobile/app_mobile.c @@ -24,32 +24,36 @@ #include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include -extern struct log_target *stderr_target; -static const char *config_file = "/etc/osmocom/osmocom.cfg"; -extern void *l23_ctx; -extern unsigned short vty_port; +#include -static int started = 0; +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); +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 +67,7 @@ int mobile_work(struct osmocom_ms *ms) w |= gsm48_mmevent_dequeue(ms); w |= gsm322_plmn_dequeue(ms); w |= gsm322_cs_dequeue(ms); + w |= gsm_sim_job_dequeue(ms); w |= mncc_dequeue(ms); if (w) work = 1; @@ -70,7 +75,8 @@ int mobile_work(struct osmocom_ms *ms) return work; } -static int signal_cb(unsigned int subsys, unsigned int signal, +/* run ms instance, if layer1 is available */ +int mobile_signal_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { struct osmocom_ms *ms; @@ -82,36 +88,49 @@ static int signal_cb(unsigned int subsys, unsigned int signal, switch (signal) { case S_L1CTL_RESET: - if (started) - break; - started = 1; ms = signal_data; set = &ms->settings; + + if (ms->started) + break; + /* insert test card, if enabled */ - if (set->simtype == GSM_SIM_TYPE_TEST) + switch (set->sim_type) { + case GSM_SIM_TYPE_READER: + /* 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); - /* start PLMN + cell selection process */ - nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON); - if (!nmsg) - return -ENOMEM; - gsm322_plmn_sendmsg(ms, nmsg); - nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON); - if (!nmsg) - return -ENOMEM; - gsm322_cs_sendmsg(ms, nmsg); + set->test_rplmn_mnc, set->test_lac, + set->test_tmsi); + break; + default: + /* no SIM, trigger PLMN selection process */ + nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON); + if (!nmsg) + return -ENOMEM; + gsm322_plmn_sendmsg(ms, nmsg); + nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON); + if (!nmsg) + return -ENOMEM; + gsm322_cs_sendmsg(ms, nmsg); + } + + ms->started = 1; } return 0; } -int mobile_exit(struct osmocom_ms *ms) +/* power-off ms instance */ +int mobile_exit(struct osmocom_ms *ms, int force) { struct gsm48_mmlayer *mm = &ms->mmlayer; - if (!mm->power_off && started) { + if (!force && ms->started) { struct msgb *nmsg; - mm->power_off = 1; + ms->shutdown = 1; /* going down */ nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_IMSI_DETACH); if (!nmsg) return -ENOMEM; @@ -120,73 +139,268 @@ int mobile_exit(struct osmocom_ms *ms) return -EBUSY; } - /* in case there is a lockup during exit */ - signal(SIGINT, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGPIPE, SIG_DFL); - - unregister_signal_handler(SS_L1CTL, &signal_cb, NULL); gsm322_exit(ms); gsm48_mm_exit(ms); gsm48_rr_exit(ms); gsm_subscr_exit(ms); gsm48_cc_exit(ms); + gsm_sim_exit(ms); + lapdm_channel_exit(&ms->lapdm_channel); - printf("Power off!\n"); + ms->shutdown = 2; /* being down */ + vty_notify(ms, NULL); + vty_notify(ms, "Power off!\n"); + printf("Power off! (MS %s)\n", ms->name); return 0; } -static struct vty_app_info vty_info = { - .name = "OsmocomBB", - .version = PACKAGE_VERSION, - .go_parent_cb = ms_vty_go_parent, -}; - -int l23_app_init(struct osmocom_ms *ms) +/* power-on ms instance */ +int mobile_init(struct osmocom_ms *ms) { int rc; - struct telnet_connection dummy_conn; -// log_parse_category_mask(stderr_target, "DRSL:DLAPDM:DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG:DSUM"); - log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG:DSUM"); + gsm_settings_arfcn(ms); - srand(time(NULL)); + lapdm_channel_init(&ms->lapdm_channel, LAPDM_MODE_MS); + lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms); - gsm_settings_init(ms); + gsm_sim_init(ms); gsm48_cc_init(ms); - gsm_support_init(ms); gsm_subscr_init(ms); gsm48_rr_init(ms); gsm48_mm_init(ms); INIT_LLIST_HEAD(&ms->trans_list); - ms->cclayer.mncc_recv = mncc_recv_mobile; gsm322_init(ms); - l23_app_work = mobile_work; - register_signal_handler(SS_L1CTL, &signal_cb, NULL); - l23_app_exit = mobile_exit; + rc = layer2_open(ms, ms->settings.layer2_socket_path); + if (rc < 0) { + fprintf(stderr, "Failed during layer2_open()\n"); + ms->l2_wq.bfd.fd = -1; + mobile_exit(ms, 1); + return rc; + } + +#if 0 + rc = sap_open(ms, ms->settings.sap_socket_path); + if (rc < 0) { + fprintf(stderr, "Failed during sap_open(), no SIM reader\n"); + ms->sap_wq.bfd.fd = -1; + mobile_exit(ms, 1); + return rc; + } +#endif + + 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; + + gsm_random_imei(&ms->settings); + + 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; - 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 = 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); - gsm_random_imei(&ms->settings); + 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; - printf("Mobile initialized, please start phone now!\n"); return 0; }