blob: 341971ef26dfb30259bf5d4d645d4846d43cb9df [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>
23#include <openbsc/osmo_msc_data.h>
24#include <openbsc/gsm_04_80.h>
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010025#include <openbsc/gsm_subscriber.h>
26#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 Freyther8ec49522011-08-15 15:53:00 +020031 if (!network->bsc_data->rf_ctrl)
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080032 return 1;
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010033 if (bts->excl_from_rf_lock)
Holger Hans Peter Freyther3d119f12012-08-30 16:43:28 +020034 return 1;
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +020035 return network->bsc_data->rf_ctrl->policy == S_RF_ON;
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080036}
37
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +010038/**
39 * Try to not page if everything the cell is not on.
40 */
41int bsc_grace_paging_request(struct gsm_subscriber *subscr, int chan_needed,
42 struct osmo_msc_data *msc)
43{
44 struct gsm_bts *bts = NULL;
45
46 if (!subscr->net->bsc_data->rf_ctrl)
47 goto page;
48 if (subscr->net->bsc_data->rf_ctrl->policy == S_RF_ON)
49 goto page;
50
51 /*
52 * Check if there is any BTS that is on for the given lac. Start
53 * with NULL and iterate through all bts.
54 */
55 do {
56 bts = gsm_bts_by_lac(subscr->net, subscr->lac, bts);
57 if (!bts)
58 break;
59
60 /*
61 * continue if the BTS is not excluded from the lock
62 */
63 if (!bts->excl_from_rf_lock)
64 continue;
65
66 /*
67 * now page on this bts
68 */
69 paging_request_bts(bts, subscr, chan_needed, NULL, msc);
70 } while (1);
71
72 /* All bts are either off or in the grace period */
73 return 0;
74page:
75 return paging_request(subscr->net, subscr, chan_needed, NULL, msc);
76}
77
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080078static int handle_sub(struct gsm_lchan *lchan, const char *text)
79{
80 struct gsm_subscriber_connection *conn;
81
82 /* only send it to TCH */
83 if (lchan->type != GSM_LCHAN_TCH_H && lchan->type != GSM_LCHAN_TCH_F)
84 return -1;
85
86 /* only send on the primary channel */
87 conn = lchan->conn;
88 if (!conn)
89 return -1;
90
91 if (conn->lchan != lchan)
92 return -1;
93
94 /* only when active */
95 if (lchan->state != LCHAN_S_ACTIVE)
96 return -1;
97
98 gsm0480_send_ussdNotify(conn, 0, text);
99 gsm0480_send_releaseComplete(conn);
100
101 return 0;
102}
103
104/*
105 * The place to handle the grace mode. Right now we will send
106 * USSD messages to the subscriber, in the future we might start
107 * a timer to have different modes for the grace period.
108 */
109static int handle_grace(struct gsm_network *network)
110{
111 int ts_nr, lchan_nr;
112 struct gsm_bts *bts;
113 struct gsm_bts_trx *trx;
114
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200115 if (!network->bsc_data->mid_call_txt)
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +0800116 return 0;
117
118 llist_for_each_entry(bts, &network->bts_list, list) {
119 llist_for_each_entry(trx, &bts->trx_list, list) {
120 for (ts_nr = 0; ts_nr < TRX_NR_TS; ++ts_nr) {
121 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
122 for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; ++lchan_nr) {
123 handle_sub(&ts->lchan[lchan_nr],
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200124 network->bsc_data->mid_call_txt);
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +0800125 }
126 }
127 }
128 }
129 return 0;
130}
131
132static int handle_rf_signal(unsigned int subsys, unsigned int signal,
133 void *handler_data, void *signal_data)
134{
135 struct rf_signal_data *sig;
136
137 if (subsys != SS_RF)
138 return -1;
139
140 sig = signal_data;
141
142 if (signal == S_RF_GRACE)
143 handle_grace(sig->net);
144
145 return 0;
146}
147
148static __attribute__((constructor)) void on_dso_load_grace(void)
149{
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200150 osmo_signal_register_handler(SS_RF, handle_rf_signal, NULL);
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +0800151}