Merge commit '7f6615a37df0dadbe86fdfc980e0a8a15013a80e'
[osmocom-bb.git] / src / host / layer23 / src / mobile / app_mobile.c
1 /* "Application" code of the layer2/3 stack */
2
3 /* (C) 2010 by Holger Hans Peter Freyther
4  * (C) 2010 by Harald Welte <laforge@gnumonks.org>
5  * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
6  *
7  * All Rights Reserved
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  */
24
25 #include <errno.h>
26 #include <signal.h>
27
28 #include <osmocom/bb/common/osmocom_data.h>
29 #include <osmocom/bb/common/l1l2_interface.h>
30 #include <osmocom/bb/common/l1ctl.h>
31 #include <osmocom/bb/common/lapdm.h>
32 #include <osmocom/bb/common/logging.h>
33 #include <osmocom/bb/mobile/gsm48_rr.h>
34 #include <osmocom/bb/mobile/vty.h>
35 #include <osmocom/vty/telnet_interface.h>
36
37 #include <osmocore/msgb.h>
38 #include <osmocore/talloc.h>
39 #include <osmocore/select.h>
40
41 int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg);
42 int mncc_recv_dummy(struct osmocom_ms *ms, int msg_type, void *arg);
43 extern int (*l23_app_exit) (struct osmocom_ms *ms, int force);
44
45 int mobile_work(struct osmocom_ms *ms)
46 {
47         int work = 0, w;
48
49         do {
50                 w = 0;
51                 w |= gsm48_rsl_dequeue(ms);
52                 w |= gsm48_rr_dequeue(ms);
53                 w |= gsm48_mmxx_dequeue(ms);
54                 w |= gsm48_mmr_dequeue(ms);
55                 w |= gsm48_mmevent_dequeue(ms);
56                 w |= gsm322_plmn_dequeue(ms);
57                 w |= gsm322_cs_dequeue(ms);
58                 w |= gsm_sim_job_dequeue(ms);
59                 w |= mncc_dequeue(ms);
60                 if (w)
61                         work = 1;
62         } while (w);
63         return work;
64 }
65
66 int mobile_signal_cb(unsigned int subsys, unsigned int signal,
67                      void *handler_data, void *signal_data)
68 {
69         struct osmocom_ms *ms;
70         struct gsm_settings *set;
71         struct msgb *nmsg;
72
73         if (subsys != SS_L1CTL)
74                 return 0;
75
76         switch (signal) {
77         case S_L1CTL_RESET:
78                 ms = signal_data;
79                 set = &ms->settings;
80
81                 if (ms->started)
82                         break;
83
84                 /* insert test card, if enabled */
85                 switch (set->sim_type) {
86                 case GSM_SIM_TYPE_READER:
87                         /* trigger sim card reader process */
88                         gsm_subscr_simcard(ms);
89                         break;
90                 case GSM_SIM_TYPE_TEST:
91                         gsm_subscr_testcard(ms, set->test_rplmn_mcc,
92                                                 set->test_rplmn_mnc);
93                         break;
94                 default:
95                         /* no SIM, trigger PLMN selection process */
96                         nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON);
97                         if (!nmsg)
98                                 return -ENOMEM;
99                         gsm322_plmn_sendmsg(ms, nmsg);
100                         nmsg = gsm322_msgb_alloc(GSM322_EVENT_SWITCH_ON);
101                         if (!nmsg)
102                                 return -ENOMEM;
103                         gsm322_cs_sendmsg(ms, nmsg);
104                 }
105
106                 ms->started = 1;
107         }
108         return 0;
109 }
110
111 int mobile_exit(struct osmocom_ms *ms, int force)
112 {
113         struct gsm48_mmlayer *mm = &ms->mmlayer;
114
115         if (!force && ms->started) {
116                 struct msgb *nmsg;
117
118                 ms->shutdown = 1; /* going down */
119                 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_IMSI_DETACH);
120                 if (!nmsg)
121                         return -ENOMEM;
122                 gsm48_mmevent_msg(mm->ms, nmsg);
123
124                 return -EBUSY;
125         }
126
127         gsm322_exit(ms);
128         gsm48_mm_exit(ms);
129         gsm48_rr_exit(ms);
130         gsm_subscr_exit(ms);
131         gsm48_cc_exit(ms);
132         gsm_sim_exit(ms);
133         lapdm_exit(&ms->l2_entity.lapdm_acch);
134         lapdm_exit(&ms->l2_entity.lapdm_dcch);
135
136         ms->shutdown = 2; /* being down */
137         vty_notify(ms, NULL);
138         vty_notify(ms, "Power off!\n");
139         printf("Power off! (MS %s)\n", ms->name);
140
141         return 0;
142 }
143
144 int l23_app_init(struct osmocom_ms *ms)
145 {
146         int rc;
147
148         lapdm_init(&ms->l2_entity.lapdm_dcch, ms);
149         lapdm_init(&ms->l2_entity.lapdm_acch, ms);
150         gsm_sim_init(ms);
151         gsm48_cc_init(ms);
152         gsm_subscr_init(ms);
153         gsm48_rr_init(ms);
154         gsm48_mm_init(ms);
155         INIT_LLIST_HEAD(&ms->trans_list);
156         gsm322_init(ms);
157
158         rc = layer2_open(ms, ms->settings.layer2_socket_path);
159         if (rc < 0) {
160                 fprintf(stderr, "Failed during layer2_open()\n");
161                 ms->l2_wq.bfd.fd = -1;
162                 l23_app_exit(ms, 1);
163                 return rc;
164         }
165
166 #if 0
167         rc = sap_open(ms, ms->settings.sap_socket_path);
168         if (rc < 0) {
169                 fprintf(stderr, "Failed during sap_open(), no SIM reader\n");
170                 ms->sap_wq.bfd.fd = -1;
171                 l23_app_exit(ms, 1);
172                 return rc;
173         }
174 #endif
175
176         if (ms->settings.ch_cap == GSM_CAP_SDCCH)
177                 ms->cclayer.mncc_recv = mncc_recv_dummy;
178         else
179                 ms->cclayer.mncc_recv = mncc_recv_mobile;
180
181         gsm_random_imei(&ms->settings);
182
183         ms->shutdown = 0;
184         ms->started = 0;
185
186         l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
187         printf("Mobile '%s' initialized, please start phone now!\n", ms->name);
188         return 0;
189 }
190