blob: db3318b8d06cef2de41061d0431b23685ee1eb92 [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 Khassrafa212ca22015-07-12 21:19:35 +020093 current.channel_type = "GPRS - Temporary Block Flow TBF";
Roman Khassraf5bd14f22015-06-24 17:59:13 +020094 }
95
96 /*
97 msg_elements[5], msg_elements[6] are octets 3 and 4 in specs
98
99 3 bits training sequence (we dont process this for the moment)
100 1 bit hopping channel H
101
102 if H = 0:
103 2 bit spare
104 2 bit high part of single channel arfcn
105
106 8 bit low part of single channel arfcn
107
108 if H = 1:
109 4 bit high part of MAIO
110
111 2 bit low part of MAIO
112 6bit HSN
113 */
Roman Khassrafa212ca22015-07-12 21:19:35 +0200114 current.hopping = (msg_elements[5] >> 4) & 1;
115 if (current.hopping)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200116 {
117 uint8_t maio = (msg_elements[5] & 0xf) << 2;
118 maio |= (msg_elements[6] >> 6);
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200119 current.maio = maio;
Roman Khassrafa212ca22015-07-12 21:19:35 +0200120 current.hsn = (msg_elements[6] & 0x3f);
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200121 }
122 else
123 {
124 uint16_t arfcn = (msg_elements[5] & 3) << 8;
125 arfcn |= msg_elements[6];
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200126 current.arfcn = arfcn;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200127 }
128
Roman Khassrafa212ca22015-07-12 21:19:35 +0200129 // TODO: add option where request reference is set as ID,
130 // so we get only one immediate assignment per reference
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200131 /*
132 msg_elements[7 - 9], octets 5 - 7 in specs : request reference, maybe later
133
134 msg_elements[10]: timing advance
135 */
Roman Khassrafa212ca22015-07-12 21:19:35 +0200136 current.timing_advance = msg_elements[10];
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200137
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200138 /*
Roman Khassrafa212ca22015-07-12 21:19:35 +0200139 msg_elements[11 - 20]: mobile allocation, flexible length, see 10.5.2.21
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200140 */
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200141 uint8_t mobile_allocation_len = msg_elements[11];
142 if (mobile_allocation_len > 0)
143 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200144 std::string ma;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200145 for (int i=0; i<mobile_allocation_len; i++)
146 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200147 for (int j=0; j<8; j++)
148 {
Roman Khassrafa212ca22015-07-12 21:19:35 +0200149 ma.push_back('0' + ((msg_elements[12 + i] >> (7-j)) & 0x1));
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200150 }
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200151 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200152 current.mobile_allocation = ma;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200153 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200154
155 d_assignment_map[current.frame_nr] = current;
Roman Khassrafa212ca22015-07-12 21:19:35 +0200156
157 if (d_print_immediate_assignments)
158 {
159 std::cout << "\n------------------------------------------------\n" << std::endl;
160 std::cout << "FrameNr: " << (unsigned)current.frame_nr << std::endl;
161 std::cout << "Channel type: " << current.channel_type << std::endl;
162 std::cout << "Timeslot: " << (unsigned)current.timeslot << std::endl;
163 // Dont print subchannel if mode == 1 or if the assigned channel is TCH/F
164 if (mode == 0 && channeltype >= 2)
165 {
166 std::cout << "Subchannel: " << (unsigned)current.subchannel << std::endl;
167 }
168 std::cout << "Hopping: " << (unsigned)current.hopping << std::endl;
169 if (current.hopping)
170 {
171 std::cout << "MAIO: " << (unsigned)current.maio << std::endl;
172 std::cout << "HSN: " << (unsigned)current.hsn << std::endl;
173 std::cout << "Mobile Allocation: " << current.mobile_allocation << std::endl;
174 }
175 else
176 {
177 std::cout << "ARFCN: " << (unsigned)current.arfcn << std::endl;
178 }
179 std::cout << "Timing Advance: " << (unsigned)current.timing_advance << std::endl;
180 }
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200181 }
182 }
183
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200184 std::vector<int> extract_immediate_assignment_impl::get_frame_numbers()
185 {
186 std::vector<int> fnrs;
187 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
188 {
189 fnrs.push_back(i.second.frame_nr);
190 }
191 return fnrs;
192 }
193
194 std::vector<std::string> extract_immediate_assignment_impl::get_channel_types()
195 {
196 std::vector<std::string> types;
197 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
198 {
199 types.push_back(i.second.channel_type);
200 }
201 return types;
202 }
203
204 std::vector<int> extract_immediate_assignment_impl::get_timeslots()
205 {
206 std::vector<int> timeslots;
207 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
208 {
209 timeslots.push_back(i.second.timeslot);
210 }
211 return timeslots;
212 }
213
214 std::vector<int> extract_immediate_assignment_impl::get_subchannels()
215 {
216 std::vector<int> subchannels;
217 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
218 {
219 subchannels.push_back(i.second.subchannel);
220 }
221 return subchannels;
222 }
223
224 std::vector<int> extract_immediate_assignment_impl::get_hopping()
225 {
226 std::vector<int> hopping;
227 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
228 {
229 hopping.push_back(i.second.hopping);
230 }
231 return hopping;
232 }
233
234 std::vector<int> extract_immediate_assignment_impl::get_maios()
235 {
236 std::vector<int> maios;
237 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
238 {
239 maios.push_back(i.second.maio);
240 }
241 return maios;
242 }
243
244 std::vector<int> extract_immediate_assignment_impl::get_hsns()
245 {
246 std::vector<int> hsns;
247 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
248 {
249 hsns.push_back(i.second.hsn);
250 }
251 return hsns;
252 }
253
254 std::vector<int> extract_immediate_assignment_impl::get_arfcns()
255 {
256 std::vector<int> arfcns;
257 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
258 {
259 arfcns.push_back(i.second.arfcn);
260 }
261 return arfcns;
262 }
263
264 std::vector<int> extract_immediate_assignment_impl::get_timing_advances()
265 {
266 std::vector<int> tas;
267 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
268 {
269 tas.push_back(i.second.timing_advance);
270 }
271 return tas;
272 }
273
274 std::vector<std::string> extract_immediate_assignment_impl::get_mobile_allocations()
275 {
276 std::vector<std::string> mobile_allocations;
277 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
278 {
279 mobile_allocations.push_back(i.second.mobile_allocation);
280 }
281 return mobile_allocations;
282 }
283
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200284 extract_immediate_assignment::sptr
Roman Khassrafa212ca22015-07-12 21:19:35 +0200285 extract_immediate_assignment::make(bool print_immediate_assignments)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200286 {
287 return gnuradio::get_initial_sptr
Roman Khassrafa212ca22015-07-12 21:19:35 +0200288 (new extract_immediate_assignment_impl(print_immediate_assignments));
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200289 }
290
291 /*
292 * The private constructor
293 */
Roman Khassrafa212ca22015-07-12 21:19:35 +0200294 extract_immediate_assignment_impl::extract_immediate_assignment_impl(bool print_immediate_assignments)
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200295 : gr::block("extract_immediate_assignment",
296 gr::io_signature::make(0, 0, 0),
297 gr::io_signature::make(0, 0, 0))
298 {
Roman Khassrafa212ca22015-07-12 21:19:35 +0200299 d_print_immediate_assignments = print_immediate_assignments;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200300 message_port_register_in(pmt::mp("msgs"));
301 set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_immediate_assignment_impl::process_message, this, _1));
302 }
303
304 /*
305 * Our virtual destructor.
306 */
307 extract_immediate_assignment_impl::~extract_immediate_assignment_impl()
308 {
309 }
310 } /* namespace gsm */
311} /* namespace gr */
312