blob: e3bce374ea775d37876ecc055fa29ce31df5de96 [file] [log] [blame]
Roman Khassraf5bd14f22015-06-24 17:59:13 +02001/* -*- c++ -*- */
2/*
3 * @file
4 * @author Roman Khassraf <rkhassraf@gmail.com>
5 * @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>
29#include <unistd.h>
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020030#include <map>
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020031#include <endian.h>
32#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 Khassrafa212ca22015-07-12 21:19:35 +0200134 // TODO: add option where request reference is set as ID,
135 // so we get only one immediate assignment per reference
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200136 /*
137 msg_elements[7 - 9], octets 5 - 7 in specs : request reference, maybe later
138
139 msg_elements[10]: timing advance
140 */
Roman Khassrafa212ca22015-07-12 21:19:35 +0200141 current.timing_advance = msg_elements[10];
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200142
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200143 /*
Roman Khassrafa212ca22015-07-12 21:19:35 +0200144 msg_elements[11 - 20]: mobile allocation, flexible length, see 10.5.2.21
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200145 */
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200146 uint8_t mobile_allocation_len = msg_elements[11];
147 if (mobile_allocation_len > 0)
148 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200149 std::string ma;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200150 for (int i=0; i<mobile_allocation_len; i++)
151 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200152 for (int j=0; j<8; j++)
153 {
Roman Khassrafa212ca22015-07-12 21:19:35 +0200154 ma.push_back('0' + ((msg_elements[12 + i] >> (7-j)) & 0x1));
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200155 }
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200156 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200157 current.mobile_allocation = ma;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200158 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200159
160 d_assignment_map[current.frame_nr] = current;
Roman Khassrafa212ca22015-07-12 21:19:35 +0200161
162 if (d_print_immediate_assignments)
163 {
164 std::cout << "\n------------------------------------------------\n" << std::endl;
165 std::cout << "FrameNr: " << (unsigned)current.frame_nr << std::endl;
166 std::cout << "Channel type: " << current.channel_type << std::endl;
167 std::cout << "Timeslot: " << (unsigned)current.timeslot << std::endl;
168 // Dont print subchannel if mode == 1 or if the assigned channel is TCH/F
169 if (mode == 0 && channeltype >= 2)
170 {
171 std::cout << "Subchannel: " << (unsigned)current.subchannel << std::endl;
172 }
173 std::cout << "Hopping: " << (unsigned)current.hopping << std::endl;
174 if (current.hopping)
175 {
176 std::cout << "MAIO: " << (unsigned)current.maio << std::endl;
177 std::cout << "HSN: " << (unsigned)current.hsn << std::endl;
178 std::cout << "Mobile Allocation: " << current.mobile_allocation << std::endl;
179 }
180 else
181 {
182 std::cout << "ARFCN: " << (unsigned)current.arfcn << std::endl;
183 }
184 std::cout << "Timing Advance: " << (unsigned)current.timing_advance << std::endl;
185 }
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200186 }
187 }
188
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200189 std::vector<int> extract_immediate_assignment_impl::get_frame_numbers()
190 {
191 std::vector<int> fnrs;
192 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
193 {
194 fnrs.push_back(i.second.frame_nr);
195 }
196 return fnrs;
197 }
198
199 std::vector<std::string> extract_immediate_assignment_impl::get_channel_types()
200 {
201 std::vector<std::string> types;
202 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
203 {
204 types.push_back(i.second.channel_type);
205 }
206 return types;
207 }
208
209 std::vector<int> extract_immediate_assignment_impl::get_timeslots()
210 {
211 std::vector<int> timeslots;
212 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
213 {
214 timeslots.push_back(i.second.timeslot);
215 }
216 return timeslots;
217 }
218
219 std::vector<int> extract_immediate_assignment_impl::get_subchannels()
220 {
221 std::vector<int> subchannels;
222 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
223 {
224 subchannels.push_back(i.second.subchannel);
225 }
226 return subchannels;
227 }
228
229 std::vector<int> extract_immediate_assignment_impl::get_hopping()
230 {
231 std::vector<int> hopping;
232 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
233 {
234 hopping.push_back(i.second.hopping);
235 }
236 return hopping;
237 }
238
239 std::vector<int> extract_immediate_assignment_impl::get_maios()
240 {
241 std::vector<int> maios;
242 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
243 {
244 maios.push_back(i.second.maio);
245 }
246 return maios;
247 }
248
249 std::vector<int> extract_immediate_assignment_impl::get_hsns()
250 {
251 std::vector<int> hsns;
252 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
253 {
254 hsns.push_back(i.second.hsn);
255 }
256 return hsns;
257 }
258
259 std::vector<int> extract_immediate_assignment_impl::get_arfcns()
260 {
261 std::vector<int> arfcns;
262 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
263 {
264 arfcns.push_back(i.second.arfcn);
265 }
266 return arfcns;
267 }
268
269 std::vector<int> extract_immediate_assignment_impl::get_timing_advances()
270 {
271 std::vector<int> tas;
272 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
273 {
274 tas.push_back(i.second.timing_advance);
275 }
276 return tas;
277 }
278
279 std::vector<std::string> extract_immediate_assignment_impl::get_mobile_allocations()
280 {
281 std::vector<std::string> mobile_allocations;
282 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
283 {
284 mobile_allocations.push_back(i.second.mobile_allocation);
285 }
286 return mobile_allocations;
287 }
288
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200289 extract_immediate_assignment::sptr
Roman Khassraf2b5ca482015-07-13 10:28:17 +0200290 extract_immediate_assignment::make(bool print_immediate_assignments, bool ignore_gprs)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200291 {
292 return gnuradio::get_initial_sptr
Roman Khassraf2b5ca482015-07-13 10:28:17 +0200293 (new extract_immediate_assignment_impl(print_immediate_assignments, ignore_gprs));
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200294 }
295
296 /*
297 * The private constructor
298 */
Roman Khassraf2b5ca482015-07-13 10:28:17 +0200299 extract_immediate_assignment_impl::extract_immediate_assignment_impl(bool print_immediate_assignments, bool ignore_gprs)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200300 : gr::block("extract_immediate_assignment",
301 gr::io_signature::make(0, 0, 0),
302 gr::io_signature::make(0, 0, 0))
303 {
Roman Khassrafa212ca22015-07-12 21:19:35 +0200304 d_print_immediate_assignments = print_immediate_assignments;
Roman Khassraf2b5ca482015-07-13 10:28:17 +0200305 d_ignore_gprs = ignore_gprs;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200306 message_port_register_in(pmt::mp("msgs"));
307 set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_immediate_assignment_impl::process_message, this, _1));
308 }
309
310 /*
311 * Our virtual destructor.
312 */
313 extract_immediate_assignment_impl::~extract_immediate_assignment_impl()
314 {
315 }
316 } /* namespace gsm */
317} /* namespace gr */
318