/* -*- c++ -*- */ /* * @file * @author (C) 2014 by Piotr Krysik * @section LICENSE * * Gr-gsm is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * Gr-gsm is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with gr-gsm; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include //#include #include #include #include #include #include #include extern "C" { #include } #include "extract_system_info_impl.h" namespace gr { namespace gsm { boost::mutex extract_mutex; void extract_system_info_impl::process_bursts(pmt::pmt_t msg) { pmt::pmt_t burst_plus_header_blob = pmt::cdr(msg); gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(burst_plus_header_blob); chan_info info; info.id = be16toh(header->arfcn); info.pwr_db = header->signal_dbm; boost::mutex::scoped_lock lock(extract_mutex); if(d_c0_channels.find(info.id) != d_c0_channels.end()){ d_c0_channels[info.id].copy_nonzero_elements(info); } else { d_c0_channels[info.id] = info; } } void extract_system_info_impl::process_sysinfo(pmt::pmt_t msg){ pmt::pmt_t message_plus_header_blob = pmt::cdr(msg); uint8_t * message_plus_header = (uint8_t *)pmt::blob_data(message_plus_header_blob); gsmtap_hdr * header = (gsmtap_hdr *)message_plus_header; uint8_t * msg_elements = (uint8_t *)(message_plus_header+sizeof(gsmtap_hdr)); struct gsm_sysinfo_freq freq[1024]; if(msg_elements[2]==0x1b){ chan_info info; info.id = be16toh(header->arfcn); //take arfcn info.pwr_db = header->signal_dbm; info.cell_id = (msg_elements[3]<<8)+msg_elements[4]; //take cell id info.lac = (msg_elements[8]<<8)+msg_elements[9]; //take lac info.mcc = ((msg_elements[5] & 0xF) * 100) + (((msg_elements[5] & 0xF0) >> 4) * 10) + ((msg_elements[6] & 0xF)); // take mcc info.mnc = (msg_elements[7] & 0xF) * 10 + (msg_elements[7]>>4); //take mnc if (((msg_elements[6] & 0xF0) >> 4) < 10) // we have a 3 digit mnc, see figure 10.5.3 of 3GPP TS 24.008 { info.mnc *= 10; info.mnc += (msg_elements[6] & 0xF0) >> 4; } info.ccch_conf = (msg_elements[10] & 0x7); // ccch_conf boost::mutex::scoped_lock lock(extract_mutex); if(d_c0_channels.find(info.id) != d_c0_channels.end()){ d_c0_channels[info.id].copy_nonzero_elements(info); } else { d_c0_channels[info.id] = info; } } else if(msg_elements[2]==0x1c){ chan_info info; info.id = be16toh(header->arfcn); //take arfcn info.pwr_db = header->signal_dbm; info.lac = (msg_elements[6]<<8)+msg_elements[7]; //take lac info.mcc = ((msg_elements[3] & 0xF) * 100) + (((msg_elements[3] & 0xF0) >> 4) * 10) + ((msg_elements[4] & 0xF)); // take mcc info.mnc = (msg_elements[5] & 0xF) * 10 + (msg_elements[5]>>4); //take mnc if (((msg_elements[4] & 0xF0) >> 4) < 10) // we have a 3 digit mnc, see figure 10.5.3 of 3GPP TS 24.008 { info.mnc *= 10; info.mnc += (msg_elements[4] & 0xF0) >> 4; } boost::mutex::scoped_lock lock(extract_mutex); if(d_c0_channels.find(info.id) != d_c0_channels.end()){ d_c0_channels[info.id].copy_nonzero_elements(info); } else { d_c0_channels[info.id] = info; } } else if(msg_elements[2]==0x1a){ //System Information Type 2 memset(freq, 0, sizeof(freq)); chan_info info; info.id = be16toh(header->arfcn); //take arfcn info.pwr_db = header->signal_dbm; boost::mutex::scoped_lock lock(extract_mutex); //read neighbour cells gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0xce, 0x01); if(d_c0_channels.find(info.id) != d_c0_channels.end()){ d_c0_channels[info.id].copy_nonzero_elements(info); } else { d_c0_channels[info.id] = info; } for(int arfcn=0; arfcnarfcn); //take arfcn info.pwr_db = header->signal_dbm; boost::mutex::scoped_lock lock(extract_mutex); //read neighbour cells gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0xce, 0x01); if(d_c0_channels.find(info.id) != d_c0_channels.end()){ d_c0_channels[info.id].copy_nonzero_elements(info); } else { d_c0_channels[info.id] = info; } for(int arfcn=0; arfcnarfcn); //take arfcn info.pwr_db = header->signal_dbm; boost::mutex::scoped_lock lock(extract_mutex); //read neighbour cells gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0x8e, 0x01); if(d_c0_channels.find(info.id) != d_c0_channels.end()){ d_c0_channels[info.id].copy_nonzero_elements(info); } else { d_c0_channels[info.id] = info; } for(int arfcn=0; arfcnarfcn); //take arfcn info.pwr_db = header->signal_dbm; boost::mutex::scoped_lock lock(extract_mutex); //read cell arfcn's gsm48_decode_freq_list(freq, &msg_elements[3], 16, 0x8e, 0x01); if(d_c0_channels.find(info.id) != d_c0_channels.end()){ d_c0_channels[info.id].copy_nonzero_elements(info); } else { d_c0_channels[info.id] = info; } for(int arfcn=0; arfcn extract_system_info_impl::get_chans() { std::vector chans_ids; BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){ chans_ids.push_back(i.second.id); } return chans_ids; } std::vector extract_system_info_impl::get_lac() { std::vector lacs; BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){ lacs.push_back(i.second.lac); } return lacs; } std::vector extract_system_info_impl::get_mcc() { std::vector mccs; BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){ mccs.push_back(i.second.mcc); } return mccs; } std::vector extract_system_info_impl::get_mnc() { std::vector mncs; BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){ mncs.push_back(i.second.mnc); } return mncs; } std::vector extract_system_info_impl::get_cell_id() { std::vector cell_ids; BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){ cell_ids.push_back(i.second.cell_id); } return cell_ids; } std::vector extract_system_info_impl::get_pwrs() { std::vector pwrs; BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){ pwrs.push_back(i.second.pwr_db); } return pwrs; } std::vector extract_system_info_impl::get_ccch_conf() { std::vector ccch_confs; BOOST_FOREACH(chan_info_map::value_type &i, d_c0_channels){ ccch_confs.push_back(i.second.ccch_conf); } return ccch_confs; } std::vector extract_system_info_impl::get_neighbours(int chan_id) { std::vector neighbour_cells; BOOST_FOREACH(int n, d_c0_channels[chan_id].neighbour_cells){ neighbour_cells.push_back(n); } return neighbour_cells; } std::vector extract_system_info_impl::get_cell_arfcns(int chan_id) { std::vector cell_arfcns; BOOST_FOREACH(int n, d_c0_channels[chan_id].cell_arfcns){ cell_arfcns.push_back(n); } return cell_arfcns; } void extract_system_info_impl::reset() { d_c0_channels.clear(); if(!empty_p(pmt::mp("bursts"))){ // delete_head_blocking(pmt::mp("bursts")); } if(!empty_p(pmt::mp("msgs"))){ // delete_head_blocking(pmt::mp("msgs")); } } extract_system_info::sptr extract_system_info::make() { return gnuradio::get_initial_sptr (new extract_system_info_impl()); } /* * The private constructor */ extract_system_info_impl::extract_system_info_impl() : gr::block("extract_system_info", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)), after_reset(false) { message_port_register_in(pmt::mp("bursts")); set_msg_handler(pmt::mp("bursts"), boost::bind(&extract_system_info_impl::process_bursts, this, _1)); message_port_register_in(pmt::mp("msgs")); set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_system_info_impl::process_sysinfo, this, _1)); } /* * Our virtual destructor. */ extract_system_info_impl::~extract_system_info_impl() { } } /* namespace gsm */ } /* namespace gr */