blob: 882ae602e9a8dc1c4b65715f9574e38b9e5f1ccc [file] [log] [blame]
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +08001/*
2 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
3 * (C) 2010 by On-Waves
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
22#include <openbsc/osmo_bsc_grace.h>
23#include <openbsc/osmo_bsc_rf.h>
24#include <openbsc/osmo_msc_data.h>
25#include <openbsc/gsm_04_80.h>
26#include <openbsc/signal.h>
27
28int bsc_grace_allow_new_connection(struct gsm_network *network)
29{
30 if (!network->msc_data->rf_ctl)
31 return 1;
32 return network->msc_data->rf_ctl->policy == S_RF_ON;
33}
34
35static int handle_sub(struct gsm_lchan *lchan, const char *text)
36{
37 struct gsm_subscriber_connection *conn;
38
39 /* only send it to TCH */
40 if (lchan->type != GSM_LCHAN_TCH_H && lchan->type != GSM_LCHAN_TCH_F)
41 return -1;
42
43 /* only send on the primary channel */
44 conn = lchan->conn;
45 if (!conn)
46 return -1;
47
48 if (conn->lchan != lchan)
49 return -1;
50
51 /* only when active */
52 if (lchan->state != LCHAN_S_ACTIVE)
53 return -1;
54
55 gsm0480_send_ussdNotify(conn, 0, text);
56 gsm0480_send_releaseComplete(conn);
57
58 return 0;
59}
60
61/*
62 * The place to handle the grace mode. Right now we will send
63 * USSD messages to the subscriber, in the future we might start
64 * a timer to have different modes for the grace period.
65 */
66static int handle_grace(struct gsm_network *network)
67{
68 int ts_nr, lchan_nr;
69 struct gsm_bts *bts;
70 struct gsm_bts_trx *trx;
71
Holger Hans Peter Freytherbb62b3f2010-11-22 18:30:21 +010072 if (!network->msc_data->mid_call_txt)
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080073 return 0;
74
75 llist_for_each_entry(bts, &network->bts_list, list) {
76 llist_for_each_entry(trx, &bts->trx_list, list) {
77 for (ts_nr = 0; ts_nr < TRX_NR_TS; ++ts_nr) {
78 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
79 for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; ++lchan_nr) {
80 handle_sub(&ts->lchan[lchan_nr],
Holger Hans Peter Freytherbb62b3f2010-11-22 18:30:21 +010081 network->msc_data->mid_call_txt);
Holger Hans Peter Freytherbd76fab2010-09-16 00:20:56 +080082 }
83 }
84 }
85 }
86 return 0;
87}
88
89static int handle_rf_signal(unsigned int subsys, unsigned int signal,
90 void *handler_data, void *signal_data)
91{
92 struct rf_signal_data *sig;
93
94 if (subsys != SS_RF)
95 return -1;
96
97 sig = signal_data;
98
99 if (signal == S_RF_GRACE)
100 handle_grace(sig->net);
101
102 return 0;
103}
104
105static __attribute__((constructor)) void on_dso_load_grace(void)
106{
107 register_signal_handler(SS_RF, handle_rf_signal, NULL);
108}