blob: 63afa20d016b83e4343df02eae658215643501b9 [file] [log] [blame]
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +08001/*
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +01002 * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
3 * (C) 2010-2013 by On-Waves
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +08004 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01007 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +08009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010014 * GNU Affero General Public License for more details.
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080015 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080018 *
19 */
20
21#include <openbsc/osmo_bsc_grace.h>
22#include <openbsc/osmo_bsc_rf.h>
Neels Hofmeyra42855f2017-02-23 21:49:55 +010023#include <openbsc/bsc_msc_data.h>
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080024#include <openbsc/gsm_04_80.h>
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010025#include <openbsc/bsc_subscriber.h>
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010026#include <openbsc/paging.h>
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080027#include <openbsc/signal.h>
28
Holger Hans Peter Freyther3d119f12012-08-30 16:43:28 +020029int bsc_grace_allow_new_connection(struct gsm_network *network, struct gsm_bts *bts)
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080030{
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010031 if (bts->excl_from_rf_lock)
Holger Hans Peter Freyther3d119f12012-08-30 16:43:28 +020032 return 1;
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +020033 return network->bsc_data->rf_ctrl->policy == S_RF_ON;
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080034}
35
Holger Hans Peter Freyther067ce6d2015-04-01 18:19:45 +020036
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010037static int normal_paging(struct bsc_subscr *subscr, int chan_needed,
38 struct bsc_msc_data *msc)
Holger Hans Peter Freyther067ce6d2015-04-01 18:19:45 +020039{
Holger Hans Peter Freyther40407832015-04-01 18:28:04 +020040 /* we can't page by lac.. we need to page everything */
41 if (msc->core_lac != -1) {
42 struct gsm_bts *bts;
43
44 llist_for_each_entry(bts, &msc->network->bts_list, list)
45 paging_request_bts(bts, subscr, chan_needed, NULL, msc);
46
47 return 0;
48 }
49
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010050 return paging_request(msc->network, subscr, chan_needed, NULL, msc);
Holger Hans Peter Freyther067ce6d2015-04-01 18:19:45 +020051}
52
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010053static int locked_paging(struct bsc_subscr *subscr, int chan_needed,
54 struct bsc_msc_data *msc)
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010055{
56 struct gsm_bts *bts = NULL;
57
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010058 /*
59 * Check if there is any BTS that is on for the given lac. Start
60 * with NULL and iterate through all bts.
61 */
Holger Hans Peter Freyther40407832015-04-01 18:28:04 +020062 llist_for_each_entry(bts, &msc->network->bts_list, list) {
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010063 /*
64 * continue if the BTS is not excluded from the lock
65 */
66 if (!bts->excl_from_rf_lock)
67 continue;
68
Holger Hans Peter Freyther40407832015-04-01 18:28:04 +020069 /* in case of no lac patching is in place, check the BTS */
70 if (msc->core_lac == -1 && subscr->lac != bts->location_area_code)
71 continue;
72
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010073 /*
74 * now page on this bts
75 */
76 paging_request_bts(bts, subscr, chan_needed, NULL, msc);
Holger Hans Peter Freyther40407832015-04-01 18:28:04 +020077 };
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010078
79 /* All bts are either off or in the grace period */
80 return 0;
Holger Hans Peter Freyther067ce6d2015-04-01 18:19:45 +020081}
82
83/**
84 * Try to not page if everything the cell is not on.
85 */
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010086int bsc_grace_paging_request(enum signal_rf rf_policy,
87 struct bsc_subscr *subscr,
88 int chan_needed,
89 struct bsc_msc_data *msc)
Holger Hans Peter Freyther067ce6d2015-04-01 18:19:45 +020090{
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010091 if (rf_policy == S_RF_ON)
Holger Hans Peter Freyther067ce6d2015-04-01 18:19:45 +020092 return normal_paging(subscr, chan_needed, msc);
93 return locked_paging(subscr, chan_needed, msc);
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010094}
95
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080096static int handle_sub(struct gsm_lchan *lchan, const char *text)
97{
98 struct gsm_subscriber_connection *conn;
99
100 /* only send it to TCH */
101 if (lchan->type != GSM_LCHAN_TCH_H && lchan->type != GSM_LCHAN_TCH_F)
102 return -1;
103
104 /* only send on the primary channel */
105 conn = lchan->conn;
106 if (!conn)
107 return -1;
108
109 if (conn->lchan != lchan)
110 return -1;
111
112 /* only when active */
113 if (lchan->state != LCHAN_S_ACTIVE)
114 return -1;
115
Neels Hofmeyr43273c62016-05-10 12:50:31 +0200116 bsc_send_ussd_notify(conn, 0, text);
117 bsc_send_ussd_release_complete(conn);
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +0800118
119 return 0;
120}
121
122/*
123 * The place to handle the grace mode. Right now we will send
124 * USSD messages to the subscriber, in the future we might start
125 * a timer to have different modes for the grace period.
126 */
127static int handle_grace(struct gsm_network *network)
128{
129 int ts_nr, lchan_nr;
130 struct gsm_bts *bts;
131 struct gsm_bts_trx *trx;
132
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200133 if (!network->bsc_data->mid_call_txt)
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +0800134 return 0;
135
136 llist_for_each_entry(bts, &network->bts_list, list) {
137 llist_for_each_entry(trx, &bts->trx_list, list) {
138 for (ts_nr = 0; ts_nr < TRX_NR_TS; ++ts_nr) {
139 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
140 for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; ++lchan_nr) {
141 handle_sub(&ts->lchan[lchan_nr],
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200142 network->bsc_data->mid_call_txt);
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +0800143 }
144 }
145 }
146 }
147 return 0;
148}
149
150static int handle_rf_signal(unsigned int subsys, unsigned int signal,
151 void *handler_data, void *signal_data)
152{
153 struct rf_signal_data *sig;
154
155 if (subsys != SS_RF)
156 return -1;
157
158 sig = signal_data;
159
160 if (signal == S_RF_GRACE)
161 handle_grace(sig->net);
162
163 return 0;
164}
165
166static __attribute__((constructor)) void on_dso_load_grace(void)
167{
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200168 osmo_signal_register_handler(SS_RF, handle_rf_signal, NULL);
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +0800169}