/* -*- c++ -*- */ /* * @file * @author (C) 2015 by Roman Khassraf * @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 "extract_immediate_assignment_impl.h" namespace gr { namespace gsm { boost::mutex extract_immediate_assignment_mutex; void extract_immediate_assignment_impl::process_message(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)); uint32_t frame_nr = be32toh(header->frame_number); if(msg_elements[2]==0x3f) { immediate_assignment current; current.frame_nr = frame_nr; /* channel description, see table 10.23 in GSM 04.08 msg_elements[4], octet 2 in specs 5 bits channel type ignored in TBF 00001 TCH/F 0001T TCH/H, subchannel/TDMA offset T 001TT SDCCH/4, subchannel/TDMA offset TT 01TTT SDCCH/8, subchannel/TDMA offset TTT 3 bits timeslot number TN */ current.timeslot = (msg_elements[4] & 7); uint8_t channeltype = (msg_elements[4] >> 3); uint8_t mode = msg_elements[3] & (1 << 4); if (mode == 0) { if (channeltype >= 8) { current.channel_type = "SDCCH/8"; current.subchannel = (channeltype & 7); } else if (channeltype >= 4 && channeltype <= 7) { current.channel_type = "SDCCH/4"; current.subchannel = (channeltype & 3); } else if (channeltype >= 2 && channeltype <= 3) { current.channel_type = "TCH/H"; current.subchannel = (channeltype & 1); } else { current.channel_type = "TCH/F"; } } else { // We return if ignore_gprs is set true if (d_ignore_gprs) { return; } current.channel_type = "GPRS - Temporary Block Flow TBF"; } /* msg_elements[5], msg_elements[6] are octets 3 and 4 in specs 3 bits training sequence (we dont process this for the moment) 1 bit hopping channel H if H = 0: 2 bit spare 2 bit high part of single channel arfcn 8 bit low part of single channel arfcn if H = 1: 4 bit high part of MAIO 2 bit low part of MAIO 6bit HSN */ current.hopping = (msg_elements[5] >> 4) & 1; if (current.hopping) { uint8_t maio = (msg_elements[5] & 0xf) << 2; maio |= (msg_elements[6] >> 6); current.maio = maio; current.hsn = (msg_elements[6] & 0x3f); } else { uint16_t arfcn = (msg_elements[5] & 3) << 8; arfcn |= msg_elements[6]; current.arfcn = arfcn; } /* msg_elements[7 - 9], octets 5 - 7 in specs, see 10.5.2.30 request reference, maybe later */ uint8_t random_access_info = msg_elements[7]; uint8_t rr_t1 = (msg_elements[8] >> 3); uint8_t rr_t2 = (msg_elements[9] & 0x1F); uint8_t rr_t3 = (msg_elements[8] & 0x7) << 3; rr_t3 |= (msg_elements[9] >> 5); uint32_t request_fnr = 51*((rr_t3-rr_t2) % 26) + rr_t3 + (51*26*rr_t1); // we will use random_access_info and request_fnr together as request_reference in the map, // if unique_references is set true uint32_t request_ref = (random_access_info << 0x16); request_ref |= request_fnr; /* msg_elements[10]: timing advance */ current.timing_advance = msg_elements[10]; /* msg_elements[11 - 20]: mobile allocation, flexible length, see 10.5.2.21 */ uint8_t mobile_allocation_len = msg_elements[11]; if (mobile_allocation_len > 0) { std::string ma; for (int i=0; i> (7-j)) & 0x1)); } } current.mobile_allocation = ma; } bool is_duplicate = false; if (d_unique_references) { if (d_assignment_map.find(request_ref) != d_assignment_map.end()) { is_duplicate = true; } else { d_assignment_map[request_ref] = current; } } else { d_assignment_map[current.frame_nr] = current; } if (d_print_immediate_assignments && !is_duplicate) { std::cout << "\n------------------------------------------------\n" << std::endl; std::cout << "FrameNr: " << (unsigned)current.frame_nr << std::endl; std::cout << "Channel type: " << current.channel_type << std::endl; std::cout << "Timeslot: " << (unsigned)current.timeslot << std::endl; // Dont print subchannel if mode == 1 or if the assigned channel is TCH/F if (mode == 0 && channeltype >= 2) { std::cout << "Subchannel: " << (unsigned)current.subchannel << std::endl; } std::cout << "Hopping: " << (unsigned)current.hopping << std::endl; if (current.hopping) { std::cout << "MAIO: " << (unsigned)current.maio << std::endl; std::cout << "HSN: " << (unsigned)current.hsn << std::endl; std::cout << "Mobile Allocation: " << current.mobile_allocation << std::endl; } else { std::cout << "ARFCN: " << (unsigned)current.arfcn << std::endl; } std::cout << "Timing Advance: " << (unsigned)current.timing_advance << std::endl; } } } std::vector extract_immediate_assignment_impl::get_frame_numbers() { std::vector fnrs; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { fnrs.push_back(i.second.frame_nr); } return fnrs; } std::vector extract_immediate_assignment_impl::get_channel_types() { std::vector types; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { types.push_back(i.second.channel_type); } return types; } std::vector extract_immediate_assignment_impl::get_timeslots() { std::vector timeslots; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { timeslots.push_back(i.second.timeslot); } return timeslots; } std::vector extract_immediate_assignment_impl::get_subchannels() { std::vector subchannels; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { subchannels.push_back(i.second.subchannel); } return subchannels; } std::vector extract_immediate_assignment_impl::get_hopping() { std::vector hopping; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { hopping.push_back(i.second.hopping); } return hopping; } std::vector extract_immediate_assignment_impl::get_maios() { std::vector maios; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { maios.push_back(i.second.maio); } return maios; } std::vector extract_immediate_assignment_impl::get_hsns() { std::vector hsns; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { hsns.push_back(i.second.hsn); } return hsns; } std::vector extract_immediate_assignment_impl::get_arfcns() { std::vector arfcns; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { arfcns.push_back(i.second.arfcn); } return arfcns; } std::vector extract_immediate_assignment_impl::get_timing_advances() { std::vector tas; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { tas.push_back(i.second.timing_advance); } return tas; } std::vector extract_immediate_assignment_impl::get_mobile_allocations() { std::vector mobile_allocations; BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map) { mobile_allocations.push_back(i.second.mobile_allocation); } return mobile_allocations; } extract_immediate_assignment::sptr extract_immediate_assignment::make(bool print_immediate_assignments, bool ignore_gprs, bool unique_references) { return gnuradio::get_initial_sptr (new extract_immediate_assignment_impl(print_immediate_assignments, ignore_gprs, unique_references)); } /* * The private constructor */ extract_immediate_assignment_impl::extract_immediate_assignment_impl(bool print_immediate_assignments, bool ignore_gprs, bool unique_references) : gr::block("extract_immediate_assignment", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) { d_print_immediate_assignments = print_immediate_assignments; d_ignore_gprs = ignore_gprs; d_unique_references = unique_references; message_port_register_in(pmt::mp("msgs")); set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_immediate_assignment_impl::process_message, this, _1)); } /* * Our virtual destructor. */ extract_immediate_assignment_impl::~extract_immediate_assignment_impl() { } } /* namespace gsm */ } /* namespace gr */