blob: a6d1658bcd16a96058fe2ccbc2d05796c6bdc687 [file] [log] [blame]
Roman Khassraf5bd14f22015-06-24 17:59:13 +02001/* -*- c++ -*- */
2/*
3 * @file
Piotr Krysika6268a52017-08-23 16:02:19 +02004 * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
Roman Khassraf5bd14f22015-06-24 17:59:13 +02005 * @section LICENSE
6 *
7 * Gr-gsm is free software; you can redistribute it and/or modify
8 * 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.
11 *
12 * Gr-gsm is distributed in the hope that it will be useful,
13 * 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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with gr-gsm; see the file COPYING. If not, write to
19 * 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>
28#include <grgsm/gsmtap.h>
Piotr Krysikeb81b032018-02-27 08:46:17 +010029//#include <unistd.h>
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020030#include <map>
David Holm41b63f22015-08-22 16:52:42 +020031#include <grgsm/endian.h>
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020032#include <boost/foreach.hpp>
Roman Khassraf5bd14f22015-06-24 17:59:13 +020033
34#include "extract_immediate_assignment_impl.h"
35
36namespace gr {
37 namespace gsm {
38 boost::mutex extract_immediate_assignment_mutex;
39
40 void extract_immediate_assignment_impl::process_message(pmt::pmt_t msg){
41 pmt::pmt_t message_plus_header_blob = pmt::cdr(msg);
42 uint8_t * message_plus_header = (uint8_t *)pmt::blob_data(message_plus_header_blob);
43 gsmtap_hdr * header = (gsmtap_hdr *)message_plus_header;
44 uint8_t * msg_elements = (uint8_t *)(message_plus_header+sizeof(gsmtap_hdr));
45 uint32_t frame_nr = be32toh(header->frame_number);
46
47 if(msg_elements[2]==0x3f)
48 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020049 immediate_assignment current;
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020050 current.frame_nr = frame_nr;
51
Roman Khassraf5bd14f22015-06-24 17:59:13 +020052 /*
53 channel description, see table 10.23 in GSM 04.08
54
55 msg_elements[4], octet 2 in specs
56
57 5 bits channel type
58 ignored in TBF
59 00001 TCH/F
60 0001T TCH/H, subchannel/TDMA offset T
61 001TT SDCCH/4, subchannel/TDMA offset TT
62 01TTT SDCCH/8, subchannel/TDMA offset TTT
63 3 bits timeslot number TN
64 */
Roman Khassrafa212ca22015-07-12 21:19:35 +020065 current.timeslot = (msg_elements[4] & 7);
66
Roman Khassraf5bd14f22015-06-24 17:59:13 +020067 uint8_t channeltype = (msg_elements[4] >> 3);
Roman Khassrafa212ca22015-07-12 21:19:35 +020068 uint8_t mode = msg_elements[3] & (1 << 4);
Roman Khassraf5bd14f22015-06-24 17:59:13 +020069 if (mode == 0)
70 {
71 if (channeltype >= 8)
72 {
Roman Khassrafa212ca22015-07-12 21:19:35 +020073 current.channel_type = "SDCCH/8";
74 current.subchannel = (channeltype & 7);
Roman Khassraf5bd14f22015-06-24 17:59:13 +020075 }
76 else if (channeltype >= 4 && channeltype <= 7)
77 {
Roman Khassrafa212ca22015-07-12 21:19:35 +020078 current.channel_type = "SDCCH/4";
79 current.subchannel = (channeltype & 3);
Roman Khassraf5bd14f22015-06-24 17:59:13 +020080 }
81 else if (channeltype >= 2 && channeltype <= 3)
82 {
Roman Khassrafa212ca22015-07-12 21:19:35 +020083 current.channel_type = "TCH/H";
84 current.subchannel = (channeltype & 1);
Roman Khassraf5bd14f22015-06-24 17:59:13 +020085 }
86 else
87 {
Roman Khassrafa212ca22015-07-12 21:19:35 +020088 current.channel_type = "TCH/F";
Roman Khassraf5bd14f22015-06-24 17:59:13 +020089 }
Roman Khassraf5bd14f22015-06-24 17:59:13 +020090 }
91 else
92 {
Roman Khassraf2b5ca482015-07-13 10:28:17 +020093 // We return if ignore_gprs is set true
94 if (d_ignore_gprs)
95 {
96 return;
97 }
Roman Khassrafa212ca22015-07-12 21:19:35 +020098 current.channel_type = "GPRS - Temporary Block Flow TBF";
Roman Khassraf5bd14f22015-06-24 17:59:13 +020099 }
100
101 /*
102 msg_elements[5], msg_elements[6] are octets 3 and 4 in specs
103
104 3 bits training sequence (we dont process this for the moment)
105 1 bit hopping channel H
106
107 if H = 0:
108 2 bit spare
109 2 bit high part of single channel arfcn
110
111 8 bit low part of single channel arfcn
112
113 if H = 1:
114 4 bit high part of MAIO
115
116 2 bit low part of MAIO
117 6bit HSN
118 */
Roman Khassrafa212ca22015-07-12 21:19:35 +0200119 current.hopping = (msg_elements[5] >> 4) & 1;
120 if (current.hopping)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200121 {
122 uint8_t maio = (msg_elements[5] & 0xf) << 2;
123 maio |= (msg_elements[6] >> 6);
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200124 current.maio = maio;
Roman Khassrafa212ca22015-07-12 21:19:35 +0200125 current.hsn = (msg_elements[6] & 0x3f);
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200126 }
127 else
128 {
129 uint16_t arfcn = (msg_elements[5] & 3) << 8;
130 arfcn |= msg_elements[6];
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200131 current.arfcn = arfcn;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200132 }
133
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200134 /*
Roman Khassraf1669e932015-07-13 11:18:22 +0200135 msg_elements[7 - 9], octets 5 - 7 in specs, see 10.5.2.30 request reference, maybe later
136 */
137 uint8_t random_access_info = msg_elements[7];
138 uint8_t rr_t1 = (msg_elements[8] >> 3);
139 uint8_t rr_t2 = (msg_elements[9] & 0x1F);
140 uint8_t rr_t3 = (msg_elements[8] & 0x7) << 3;
141 rr_t3 |= (msg_elements[9] >> 5);
142 uint32_t request_fnr = 51*((rr_t3-rr_t2) % 26) + rr_t3 + (51*26*rr_t1);
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200143
Roman Khassraf1669e932015-07-13 11:18:22 +0200144 // we will use random_access_info and request_fnr together as request_reference in the map,
145 // if unique_references is set true
146 uint32_t request_ref = (random_access_info << 0x16);
147 request_ref |= request_fnr;
148
149 /*
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200150 msg_elements[10]: timing advance
151 */
Roman Khassrafa212ca22015-07-12 21:19:35 +0200152 current.timing_advance = msg_elements[10];
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200153
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200154 /*
Roman Khassrafa212ca22015-07-12 21:19:35 +0200155 msg_elements[11 - 20]: mobile allocation, flexible length, see 10.5.2.21
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200156 */
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200157 uint8_t mobile_allocation_len = msg_elements[11];
158 if (mobile_allocation_len > 0)
159 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200160 std::string ma;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200161 for (int i=0; i<mobile_allocation_len; i++)
162 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200163 for (int j=0; j<8; j++)
164 {
Roman Khassrafa212ca22015-07-12 21:19:35 +0200165 ma.push_back('0' + ((msg_elements[12 + i] >> (7-j)) & 0x1));
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200166 }
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200167 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200168 current.mobile_allocation = ma;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200169 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200170
Roman Khassraf1669e932015-07-13 11:18:22 +0200171 bool is_duplicate = false;
172 if (d_unique_references)
173 {
174 if (d_assignment_map.find(request_ref) != d_assignment_map.end())
175 {
176 is_duplicate = true;
177 }
178 else
179 {
180 d_assignment_map[request_ref] = current;
181 }
182 }
183 else
184 {
185 d_assignment_map[current.frame_nr] = current;
186 }
Roman Khassrafa212ca22015-07-12 21:19:35 +0200187
Roman Khassraf1669e932015-07-13 11:18:22 +0200188 if (d_print_immediate_assignments && !is_duplicate)
Roman Khassrafa212ca22015-07-12 21:19:35 +0200189 {
190 std::cout << "\n------------------------------------------------\n" << std::endl;
191 std::cout << "FrameNr: " << (unsigned)current.frame_nr << std::endl;
192 std::cout << "Channel type: " << current.channel_type << std::endl;
193 std::cout << "Timeslot: " << (unsigned)current.timeslot << std::endl;
194 // Dont print subchannel if mode == 1 or if the assigned channel is TCH/F
195 if (mode == 0 && channeltype >= 2)
196 {
197 std::cout << "Subchannel: " << (unsigned)current.subchannel << std::endl;
198 }
199 std::cout << "Hopping: " << (unsigned)current.hopping << std::endl;
200 if (current.hopping)
201 {
202 std::cout << "MAIO: " << (unsigned)current.maio << std::endl;
203 std::cout << "HSN: " << (unsigned)current.hsn << std::endl;
204 std::cout << "Mobile Allocation: " << current.mobile_allocation << std::endl;
205 }
206 else
207 {
208 std::cout << "ARFCN: " << (unsigned)current.arfcn << std::endl;
209 }
210 std::cout << "Timing Advance: " << (unsigned)current.timing_advance << std::endl;
211 }
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200212 }
213 }
214
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200215 std::vector<int> extract_immediate_assignment_impl::get_frame_numbers()
216 {
217 std::vector<int> fnrs;
218 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
219 {
220 fnrs.push_back(i.second.frame_nr);
221 }
222 return fnrs;
223 }
224
225 std::vector<std::string> extract_immediate_assignment_impl::get_channel_types()
226 {
227 std::vector<std::string> types;
228 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
229 {
230 types.push_back(i.second.channel_type);
231 }
232 return types;
233 }
234
235 std::vector<int> extract_immediate_assignment_impl::get_timeslots()
236 {
237 std::vector<int> timeslots;
238 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
239 {
240 timeslots.push_back(i.second.timeslot);
241 }
242 return timeslots;
243 }
244
245 std::vector<int> extract_immediate_assignment_impl::get_subchannels()
246 {
247 std::vector<int> subchannels;
248 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
249 {
250 subchannels.push_back(i.second.subchannel);
251 }
252 return subchannels;
253 }
254
255 std::vector<int> extract_immediate_assignment_impl::get_hopping()
256 {
257 std::vector<int> hopping;
258 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
259 {
260 hopping.push_back(i.second.hopping);
261 }
262 return hopping;
263 }
264
265 std::vector<int> extract_immediate_assignment_impl::get_maios()
266 {
267 std::vector<int> maios;
268 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
269 {
270 maios.push_back(i.second.maio);
271 }
272 return maios;
273 }
274
275 std::vector<int> extract_immediate_assignment_impl::get_hsns()
276 {
277 std::vector<int> hsns;
278 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
279 {
280 hsns.push_back(i.second.hsn);
281 }
282 return hsns;
283 }
284
285 std::vector<int> extract_immediate_assignment_impl::get_arfcns()
286 {
287 std::vector<int> arfcns;
288 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
289 {
290 arfcns.push_back(i.second.arfcn);
291 }
292 return arfcns;
293 }
294
295 std::vector<int> extract_immediate_assignment_impl::get_timing_advances()
296 {
297 std::vector<int> tas;
298 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
299 {
300 tas.push_back(i.second.timing_advance);
301 }
302 return tas;
303 }
304
305 std::vector<std::string> extract_immediate_assignment_impl::get_mobile_allocations()
306 {
307 std::vector<std::string> mobile_allocations;
308 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
309 {
310 mobile_allocations.push_back(i.second.mobile_allocation);
311 }
312 return mobile_allocations;
313 }
314
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200315 extract_immediate_assignment::sptr
Roman Khassraf1669e932015-07-13 11:18:22 +0200316 extract_immediate_assignment::make(bool print_immediate_assignments, bool ignore_gprs, bool unique_references)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200317 {
318 return gnuradio::get_initial_sptr
Roman Khassraf1669e932015-07-13 11:18:22 +0200319 (new extract_immediate_assignment_impl(print_immediate_assignments, ignore_gprs, unique_references));
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200320 }
321
322 /*
323 * The private constructor
324 */
Roman Khassraf1669e932015-07-13 11:18:22 +0200325 extract_immediate_assignment_impl::extract_immediate_assignment_impl(bool print_immediate_assignments,
326 bool ignore_gprs, bool unique_references)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200327 : gr::block("extract_immediate_assignment",
328 gr::io_signature::make(0, 0, 0),
329 gr::io_signature::make(0, 0, 0))
330 {
Roman Khassrafa212ca22015-07-12 21:19:35 +0200331 d_print_immediate_assignments = print_immediate_assignments;
Roman Khassraf2b5ca482015-07-13 10:28:17 +0200332 d_ignore_gprs = ignore_gprs;
Roman Khassraf1669e932015-07-13 11:18:22 +0200333 d_unique_references = unique_references;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200334 message_port_register_in(pmt::mp("msgs"));
335 set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_immediate_assignment_impl::process_message, this, _1));
336 }
337
338 /*
339 * Our virtual destructor.
340 */
341 extract_immediate_assignment_impl::~extract_immediate_assignment_impl()
342 {
343 }
344 } /* namespace gsm */
345} /* namespace gr */
346