blob: 3fef7d3e922913b4e467ac42b3887977c51d3589 [file] [log] [blame]
piotrdda22272014-08-04 11:31:54 +02001/* -*- c++ -*- */
ptrkrysik529895b2014-12-02 18:07:38 +01002/*
3 * @file
Piotr Krysika6268a52017-08-23 16:02:19 +02004 * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
ptrkrysik529895b2014-12-02 18:07:38 +01005 * @section LICENSE
6 *
7 * Gr-gsm is free software; you can redistribute it and/or modify
piotrdda22272014-08-04 11:31:54 +02008 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
ptrkrysik529895b2014-12-02 18:07:38 +010011 *
12 * Gr-gsm is distributed in the hope that it will be useful,
piotrdda22272014-08-04 11:31:54 +020013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
ptrkrysik529895b2014-12-02 18:07:38 +010016 *
piotrdda22272014-08-04 11:31:54 +020017 * You should have received a copy of the GNU General Public License
ptrkrysik529895b2014-12-02 18:07:38 +010018 * along with gr-gsm; see the file COPYING. If not, write to
piotrdda22272014-08-04 11:31:54 +020019 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <gnuradio/io_signature.h>
ptrkrysik3be74a72014-12-13 10:11:00 +010028#include <grgsm/gsmtap.h>
Piotr Krysikeb81b032018-02-27 08:46:17 +010029//#include <unistd.h>
ptrkrysike9539c12015-07-06 08:34:22 +020030#include <map>
piotrdda22272014-08-04 11:31:54 +020031#include <iterator>
32#include <algorithm>
piotrdda22272014-08-04 11:31:54 +020033#include <iostream>
David Holm41b63f22015-08-22 16:52:42 +020034#include <grgsm/endian.h>
ptrkrysike9539c12015-07-06 08:34:22 +020035#include <boost/foreach.hpp>
ptrkrysik09405382015-08-02 22:02:52 +020036extern "C" {
37 #include <osmocom/gsm/gsm48_ie.h>
38}
39
piotrdda22272014-08-04 11:31:54 +020040
ptrkrysik402c1fa2014-12-03 22:09:29 +010041#include "extract_system_info_impl.h"
42
piotrdda22272014-08-04 11:31:54 +020043namespace gr {
44 namespace gsm {
45 boost::mutex extract_mutex;
46 void extract_system_info_impl::process_bursts(pmt::pmt_t msg)
47 {
ptrkrysika31a4812014-12-15 09:10:01 +010048 pmt::pmt_t burst_plus_header_blob = pmt::cdr(msg);
49 gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(burst_plus_header_blob);
piotrdda22272014-08-04 11:31:54 +020050
piotrdda22272014-08-04 11:31:54 +020051 chan_info info;
ptrkrysike9539c12015-07-06 08:34:22 +020052 info.id = be16toh(header->arfcn);
piotrdda22272014-08-04 11:31:54 +020053 info.pwr_db = header->signal_dbm;
piotrdda22272014-08-04 11:31:54 +020054
55 boost::mutex::scoped_lock lock(extract_mutex);
ptrkrysike9539c12015-07-06 08:34:22 +020056
57 if(d_c0_channels.find(info.id) != d_c0_channels.end()){
58 d_c0_channels[info.id].copy_nonzero_elements(info);
59 } else {
60 d_c0_channels[info.id] = info;
61 }
piotrdda22272014-08-04 11:31:54 +020062 }
63
64 void extract_system_info_impl::process_sysinfo(pmt::pmt_t msg){
ptrkrysika31a4812014-12-15 09:10:01 +010065 pmt::pmt_t message_plus_header_blob = pmt::cdr(msg);
66 uint8_t * message_plus_header = (uint8_t *)pmt::blob_data(message_plus_header_blob);
67 gsmtap_hdr * header = (gsmtap_hdr *)message_plus_header;
68 uint8_t * msg_elements = (uint8_t *)(message_plus_header+sizeof(gsmtap_hdr));
ptrkrysik09405382015-08-02 22:02:52 +020069 struct gsm_sysinfo_freq freq[1024];
piotrdda22272014-08-04 11:31:54 +020070
71 if(msg_elements[2]==0x1b){
piotrdda22272014-08-04 11:31:54 +020072 chan_info info;
ptrkrysike9539c12015-07-06 08:34:22 +020073 info.id = be16toh(header->arfcn); //take arfcn
piotrdda22272014-08-04 11:31:54 +020074 info.pwr_db = header->signal_dbm;
ptrkrysika31a4812014-12-15 09:10:01 +010075 info.cell_id = (msg_elements[3]<<8)+msg_elements[4]; //take cell id
76 info.lac = (msg_elements[8]<<8)+msg_elements[9]; //take lac
Roman Khassrafa1dd7ee2015-09-26 17:20:49 +020077 info.mcc = ((msg_elements[5] & 0xF) * 100) + (((msg_elements[5] & 0xF0) >> 4) * 10) + ((msg_elements[6] & 0xF)); // take mcc
78 info.mnc = (msg_elements[7] & 0xF) * 10 + (msg_elements[7]>>4); //take mnc
Roman Khassrafddd096e2016-11-28 21:57:19 +010079 if (((msg_elements[6] & 0xF0) >> 4) < 10) // we have a 3 digit mnc, see figure 10.5.3 of 3GPP TS 24.008
80 {
81 info.mnc *= 10;
82 info.mnc += (msg_elements[6] & 0xF0) >> 4;
83 }
84
Roman Khassraf9f4feb52015-09-26 18:44:56 +020085 info.ccch_conf = (msg_elements[10] & 0x7); // ccch_conf
86
piotrdda22272014-08-04 11:31:54 +020087 boost::mutex::scoped_lock lock(extract_mutex);
ptrkrysike9539c12015-07-06 08:34:22 +020088 if(d_c0_channels.find(info.id) != d_c0_channels.end()){
89 d_c0_channels[info.id].copy_nonzero_elements(info);
90 } else {
91 d_c0_channels[info.id] = info;
piotrdda22272014-08-04 11:31:54 +020092 }
piotrdda22272014-08-04 11:31:54 +020093 }
94 else if(msg_elements[2]==0x1c){
piotrdda22272014-08-04 11:31:54 +020095 chan_info info;
ptrkrysike9539c12015-07-06 08:34:22 +020096 info.id = be16toh(header->arfcn); //take arfcn
piotrdda22272014-08-04 11:31:54 +020097 info.pwr_db = header->signal_dbm;
ptrkrysike9539c12015-07-06 08:34:22 +020098 info.lac = (msg_elements[6]<<8)+msg_elements[7]; //take lac
Piotr Krysik34935e92015-11-22 08:07:02 +010099 info.mcc = ((msg_elements[3] & 0xF) * 100) + (((msg_elements[3] & 0xF0) >> 4) * 10) + ((msg_elements[4] & 0xF)); // take mcc
Roman Khassrafa1dd7ee2015-09-26 17:20:49 +0200100 info.mnc = (msg_elements[5] & 0xF) * 10 + (msg_elements[5]>>4); //take mnc
Roman Khassrafddd096e2016-11-28 21:57:19 +0100101 if (((msg_elements[4] & 0xF0) >> 4) < 10) // we have a 3 digit mnc, see figure 10.5.3 of 3GPP TS 24.008
102 {
103 info.mnc *= 10;
104 info.mnc += (msg_elements[4] & 0xF0) >> 4;
105 }
Roman Khassrafa1dd7ee2015-09-26 17:20:49 +0200106
piotrdda22272014-08-04 11:31:54 +0200107 boost::mutex::scoped_lock lock(extract_mutex);
ptrkrysike9539c12015-07-06 08:34:22 +0200108 if(d_c0_channels.find(info.id) != d_c0_channels.end()){
109 d_c0_channels[info.id].copy_nonzero_elements(info);
110 } else {
111 d_c0_channels[info.id] = info;
piotrdda22272014-08-04 11:31:54 +0200112 }
ptrkrysik09405382015-08-02 22:02:52 +0200113 }
114 else if(msg_elements[2]==0x1a){ //System Information Type 2
115 memset(freq, 0, sizeof(freq));
ptrkrysike9539c12015-07-06 08:34:22 +0200116 chan_info info;
117 info.id = be16toh(header->arfcn); //take arfcn
118 info.pwr_db = header->signal_dbm;
119 boost::mutex::scoped_lock lock(extract_mutex);
120 //read neighbour cells
ptrkrysik09405382015-08-02 22:02:52 +0200121 gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0xce, 0x01);
ptrkrysik09405382015-08-02 22:02:52 +0200122
123 if(d_c0_channels.find(info.id) != d_c0_channels.end()){
124 d_c0_channels[info.id].copy_nonzero_elements(info);
125 } else {
126 d_c0_channels[info.id] = info;
127 }
ptrkrysik5e376742015-08-06 10:02:04 +0200128
129 for(int arfcn=0; arfcn<sizeof(freq); arfcn++){
130 if(freq[arfcn].mask==0x01){
131 d_c0_channels[info.id].neighbour_cells.insert(arfcn);
132 }
133 }
ptrkrysik09405382015-08-02 22:02:52 +0200134 }
135 else if(msg_elements[2]==0x02){ //System Information Type 2bis
136 memset(freq, 0, sizeof(freq));
137 chan_info info;
138 info.id = be16toh(header->arfcn); //take arfcn
139 info.pwr_db = header->signal_dbm;
140 boost::mutex::scoped_lock lock(extract_mutex);
141 //read neighbour cells
142 gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0xce, 0x01);
ptrkrysik09405382015-08-02 22:02:52 +0200143 if(d_c0_channels.find(info.id) != d_c0_channels.end()){
144 d_c0_channels[info.id].copy_nonzero_elements(info);
145 } else {
146 d_c0_channels[info.id] = info;
147 }
ptrkrysik5e376742015-08-06 10:02:04 +0200148
149 for(int arfcn=0; arfcn<sizeof(freq); arfcn++){
150 if(freq[arfcn].mask==0x01){
151 d_c0_channels[info.id].neighbour_cells.insert(arfcn);
152 }
153 }
ptrkrysik09405382015-08-02 22:02:52 +0200154 }
155 else if(msg_elements[2]==0x03){ //System Information Type 2ter
156 memset(freq, 0, sizeof(freq));
157 chan_info info;
158 info.id = be16toh(header->arfcn); //take arfcn
159 info.pwr_db = header->signal_dbm;
160 boost::mutex::scoped_lock lock(extract_mutex);
161 //read neighbour cells
162 gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0x8e, 0x01);
ptrkrysike9539c12015-07-06 08:34:22 +0200163 if(d_c0_channels.find(info.id) != d_c0_channels.end()){
164 d_c0_channels[info.id].copy_nonzero_elements(info);
165 } else {
166 d_c0_channels[info.id] = info;
167 }
ptrkrysik5e376742015-08-06 10:02:04 +0200168
169 for(int arfcn=0; arfcn<sizeof(freq); arfcn++){
170 if(freq[arfcn].mask==0x01){
171 d_c0_channels[info.id].neighbour_cells.insert(arfcn);
172 }
173 }
piotrdda22272014-08-04 11:31:54 +0200174 }
Roman Khassraf74efd102015-09-27 10:49:23 +0200175 else if(msg_elements[2]==0x19)
176 { //System Information Type 1
177 memset(freq, 0, sizeof(freq));
178 chan_info info;
179 info.id = be16toh(header->arfcn); //take arfcn
180 info.pwr_db = header->signal_dbm;
181 boost::mutex::scoped_lock lock(extract_mutex);
182 //read cell arfcn's
Piotr Krysikb31689d2017-06-11 20:30:56 +0200183 gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0x8e, 0x01);
Roman Khassraf74efd102015-09-27 10:49:23 +0200184 if(d_c0_channels.find(info.id) != d_c0_channels.end()){
185 d_c0_channels[info.id].copy_nonzero_elements(info);
186 } else {
187 d_c0_channels[info.id] = info;
188 }
189
190 for(int arfcn=0; arfcn<sizeof(freq); arfcn++){
191 if(freq[arfcn].mask==0x01){
192 d_c0_channels[info.id].cell_arfcns.insert(arfcn);
193 }
194 }
195 }
piotrdda22272014-08-04 11:31:54 +0200196 }
197
piotrdda22272014-08-04 11:31:54 +0200198 std::vector<int> extract_system_info_impl::get_chans()
199 {
ptrkrysike9539c12015-07-06 08:34:22 +0200200 std::vector<int> chans_ids;
201 BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){
202 chans_ids.push_back(i.second.id);
piotrdda22272014-08-04 11:31:54 +0200203 }
piotrdda22272014-08-04 11:31:54 +0200204 return chans_ids;
205 }
206
207 std::vector<int> extract_system_info_impl::get_lac()
208 {
ptrkrysike9539c12015-07-06 08:34:22 +0200209 std::vector<int> lacs;
210 BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){
211 lacs.push_back(i.second.lac);
piotrdda22272014-08-04 11:31:54 +0200212 }
ptrkrysike9539c12015-07-06 08:34:22 +0200213 return lacs;
piotrdda22272014-08-04 11:31:54 +0200214 }
ptrkrysike9539c12015-07-06 08:34:22 +0200215
Roman Khassrafa1dd7ee2015-09-26 17:20:49 +0200216 std::vector<int> extract_system_info_impl::get_mcc()
217 {
218 std::vector<int> mccs;
219 BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){
220 mccs.push_back(i.second.mcc);
221 }
222 return mccs;
223 }
224
piotrdda22272014-08-04 11:31:54 +0200225 std::vector<int> extract_system_info_impl::get_mnc()
226 {
ptrkrysike9539c12015-07-06 08:34:22 +0200227 std::vector<int> mncs;
228 BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){
229 mncs.push_back(i.second.mnc);
piotrdda22272014-08-04 11:31:54 +0200230 }
ptrkrysike9539c12015-07-06 08:34:22 +0200231 return mncs;
piotrdda22272014-08-04 11:31:54 +0200232 }
ptrkrysike9539c12015-07-06 08:34:22 +0200233
piotrdda22272014-08-04 11:31:54 +0200234 std::vector<int> extract_system_info_impl::get_cell_id()
235 {
ptrkrysike9539c12015-07-06 08:34:22 +0200236 std::vector<int> cell_ids;
237 BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){
238 cell_ids.push_back(i.second.cell_id);
piotrdda22272014-08-04 11:31:54 +0200239 }
ptrkrysike9539c12015-07-06 08:34:22 +0200240 return cell_ids;
piotrdda22272014-08-04 11:31:54 +0200241 }
242
243 std::vector<int> extract_system_info_impl::get_pwrs()
244 {
ptrkrysike9539c12015-07-06 08:34:22 +0200245 std::vector<int> pwrs;
246 BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){
247 pwrs.push_back(i.second.pwr_db);
piotrdda22272014-08-04 11:31:54 +0200248 }
piotrdda22272014-08-04 11:31:54 +0200249 return pwrs;
250 }
Roman Khassrafa1dd7ee2015-09-26 17:20:49 +0200251
Roman Khassraf9f4feb52015-09-26 18:44:56 +0200252 std::vector<int> extract_system_info_impl::get_ccch_conf()
253 {
254 std::vector<int> ccch_confs;
255 BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){
256 ccch_confs.push_back(i.second.ccch_conf);
257 }
258 return ccch_confs;
259 }
260
ptrkrysike9539c12015-07-06 08:34:22 +0200261 std::vector<int> extract_system_info_impl::get_neighbours(int chan_id)
262 {
263 std::vector<int> neighbour_cells;
264 BOOST_FOREACH(int n, d_c0_channels[chan_id].neighbour_cells){
265 neighbour_cells.push_back(n);
266 }
267 return neighbour_cells;
268 }
Roman Khassraf74efd102015-09-27 10:49:23 +0200269
270 std::vector<int> extract_system_info_impl::get_cell_arfcns(int chan_id)
271 {
272 std::vector<int> cell_arfcns;
273 BOOST_FOREACH(int n, d_c0_channels[chan_id].cell_arfcns){
274 cell_arfcns.push_back(n);
275 }
276 return cell_arfcns;
277 }
piotrdda22272014-08-04 11:31:54 +0200278
279 void extract_system_info_impl::reset()
280 {
ptrkrysike9539c12015-07-06 08:34:22 +0200281 d_c0_channels.clear();
piotrdda22272014-08-04 11:31:54 +0200282 if(!empty_p(pmt::mp("bursts"))){
Piotr Krysikd01e2222016-08-18 18:58:46 +0200283// delete_head_blocking(pmt::mp("bursts"));
piotrdda22272014-08-04 11:31:54 +0200284 }
ptrkrysike9539c12015-07-06 08:34:22 +0200285 if(!empty_p(pmt::mp("msgs"))){
Piotr Krysikd01e2222016-08-18 18:58:46 +0200286// delete_head_blocking(pmt::mp("msgs"));
ptrkrysike9539c12015-07-06 08:34:22 +0200287 }
piotrdda22272014-08-04 11:31:54 +0200288 }
289
290 extract_system_info::sptr
291 extract_system_info::make()
292 {
293 return gnuradio::get_initial_sptr
294 (new extract_system_info_impl());
295 }
296
297 /*
298 * The private constructor
299 */
300 extract_system_info_impl::extract_system_info_impl()
301 : gr::block("extract_system_info",
302 gr::io_signature::make(0, 0, 0),
303 gr::io_signature::make(0, 0, 0)),
304 after_reset(false)
305 {
306 message_port_register_in(pmt::mp("bursts"));
Vadim Yanitskiya1169202021-05-03 19:00:43 +0200307 set_msg_handler(pmt::mp("bursts"), boost::bind(&extract_system_info_impl::process_bursts, this, boost::placeholders::_1));
piotrdda22272014-08-04 11:31:54 +0200308 message_port_register_in(pmt::mp("msgs"));
Vadim Yanitskiya1169202021-05-03 19:00:43 +0200309 set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_system_info_impl::process_sysinfo, this, boost::placeholders::_1));
piotrdda22272014-08-04 11:31:54 +0200310 }
311
312 /*
313 * Our virtual destructor.
314 */
315 extract_system_info_impl::~extract_system_info_impl()
316 {
317 }
318
319
320 } /* namespace gsm */
321} /* namespace gr */
322