blob: 0129d2f5bad2ad0ee06de264fee683d5795f8bcd [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>
30#include <set>
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020031#include <map>
Roman Khassraf5bd14f22015-06-24 17:59:13 +020032#include <iterator>
33#include <algorithm>
34#include <iostream>
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020035#include <endian.h>
36#include <boost/foreach.hpp>
Roman Khassraf5bd14f22015-06-24 17:59:13 +020037
38#include "extract_immediate_assignment_impl.h"
39
40namespace gr {
41 namespace gsm {
42 boost::mutex extract_immediate_assignment_mutex;
43
44 void extract_immediate_assignment_impl::process_message(pmt::pmt_t msg){
45 pmt::pmt_t message_plus_header_blob = pmt::cdr(msg);
46 uint8_t * message_plus_header = (uint8_t *)pmt::blob_data(message_plus_header_blob);
47 gsmtap_hdr * header = (gsmtap_hdr *)message_plus_header;
48 uint8_t * msg_elements = (uint8_t *)(message_plus_header+sizeof(gsmtap_hdr));
49 uint32_t frame_nr = be32toh(header->frame_number);
50
51 if(msg_elements[2]==0x3f)
52 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020053 immediate_assignment current;
Roman Khassraf5bd14f22015-06-24 17:59:13 +020054 std::cout << "\n------------------------------------------------------------------\n" << std::endl;
Roman Khassraf5bd14f22015-06-24 17:59:13 +020055 std::cout << "FrameNr: " << (unsigned)frame_nr << std::endl;
56
Roman Khassraf95c6f9d2015-07-12 19:02:32 +020057 current.frame_nr = frame_nr;
58
Roman Khassraf5bd14f22015-06-24 17:59:13 +020059 uint8_t mode = msg_elements[3] & (1 << 4);
60
61 /*
62 channel description, see table 10.23 in GSM 04.08
63
64 msg_elements[4], octet 2 in specs
65
66 5 bits channel type
67 ignored in TBF
68 00001 TCH/F
69 0001T TCH/H, subchannel/TDMA offset T
70 001TT SDCCH/4, subchannel/TDMA offset TT
71 01TTT SDCCH/8, subchannel/TDMA offset TTT
72 3 bits timeslot number TN
73 */
74 uint8_t channeltype = (msg_elements[4] >> 3);
75 uint8_t timeslot = (msg_elements[4] & 7);
76 uint8_t subchannel;
77 std::string channel_type;
78
79 std::cout << "Timeslot: " << (unsigned)timeslot << std::endl;
80
81 if (mode == 0)
82 {
83 if (channeltype >= 8)
84 {
85 channel_type = "SDCCH/8";
86 subchannel = (channeltype & 7);
87 }
88 else if (channeltype >= 4 && channeltype <= 7)
89 {
90 channel_type = "SDCCH/4";
91 subchannel = (channeltype & 3);
92 }
93 else if (channeltype >= 2 && channeltype <= 3)
94 {
95 channel_type = "TCH/H";
96 subchannel = (channeltype & 1);
97 }
98 else
99 {
100 channel_type = "TCH/F";
101 subchannel = 0;
102 }
103
104 std::cout << "Channel type: " << channel_type << std::endl;
105 std::cout << "Subchannel: " << (unsigned)subchannel << std::endl;
106 }
107 else
108 {
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200109 channel_type = "GPRS - Temporary Block Flow TBF";
110 subchannel = 0;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200111 std::cout << "Channel type: " << "GPRS - Temporary Block Flow TBF" << std::endl;
112 }
113
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200114 current.channel_type = channel_type;
115 current.timeslot = timeslot;
116 current.subchannel = subchannel;
117
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200118 /*
119 msg_elements[5], msg_elements[6] are octets 3 and 4 in specs
120
121 3 bits training sequence (we dont process this for the moment)
122 1 bit hopping channel H
123
124 if H = 0:
125 2 bit spare
126 2 bit high part of single channel arfcn
127
128 8 bit low part of single channel arfcn
129
130 if H = 1:
131 4 bit high part of MAIO
132
133 2 bit low part of MAIO
134 6bit HSN
135 */
136 uint8_t hopping = (msg_elements[5] >> 4) & 1;
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200137 current.hopping = hopping;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200138
139 std::cout << "Hopping: " << (unsigned)hopping << std::endl;
140
141 if (hopping)
142 {
143 uint8_t maio = (msg_elements[5] & 0xf) << 2;
144 maio |= (msg_elements[6] >> 6);
145
146 uint8_t hsn = (msg_elements[6] & 0x3f);
147
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200148 current.maio = maio;
149 current.hsn = hsn;
150
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200151 std::cout << "MAIO: " << (unsigned)maio << std::endl;
152 std::cout << "HSN: " << (unsigned)hsn << std::endl;
153 }
154 else
155 {
156 uint16_t arfcn = (msg_elements[5] & 3) << 8;
157 arfcn |= msg_elements[6];
158
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200159 current.arfcn = arfcn;
160
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200161 std::cout << "ARFCN: " << (unsigned)arfcn << std::endl;
162 }
163
164 // request reference as ID in set, so we get only one immediate assignment per reference
165 /*
166 msg_elements[7 - 9], octets 5 - 7 in specs : request reference, maybe later
167
168 msg_elements[10]: timing advance
169 */
170 uint8_t timing_advance = msg_elements[10];
171 std::cout << "TA: " << (unsigned)timing_advance << std::endl;
172
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200173 current.timing_advance = timing_advance;
174
175
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200176 /*
177 msg_elements[11] - 20: mobile allocation, flexible length, see 10.5.2.21
178 */
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200179 uint8_t mobile_allocation_len = msg_elements[11];
180 if (mobile_allocation_len > 0)
181 {
182 uint8_t mobile_allocation[mobile_allocation_len];
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200183 std::string ma;
184
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200185 for (int i=0; i<mobile_allocation_len; i++)
186 {
187 mobile_allocation[i] = msg_elements[12 + i];
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200188
189 for (int j=0; j<8; j++)
190 {
191 ma.push_back('0' + ((mobile_allocation[i] >> (7-j)) & 0x1));
192 }
193
194// std::cout << "MA: " << (unsigned)mobile_allocation[i] << std::endl;
195 std::cout << "MA: " << ma << std::endl;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200196 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200197
198 current.mobile_allocation = ma;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200199 }
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200200
201 d_assignment_map[current.frame_nr] = current;
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200202 }
203 }
204
Roman Khassraf95c6f9d2015-07-12 19:02:32 +0200205 std::vector<int> extract_immediate_assignment_impl::get_frame_numbers()
206 {
207 std::vector<int> fnrs;
208 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
209 {
210 fnrs.push_back(i.second.frame_nr);
211 }
212 return fnrs;
213 }
214
215 std::vector<std::string> extract_immediate_assignment_impl::get_channel_types()
216 {
217 std::vector<std::string> types;
218 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
219 {
220 types.push_back(i.second.channel_type);
221 }
222 return types;
223 }
224
225 std::vector<int> extract_immediate_assignment_impl::get_timeslots()
226 {
227 std::vector<int> timeslots;
228 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
229 {
230 timeslots.push_back(i.second.timeslot);
231 }
232 return timeslots;
233 }
234
235 std::vector<int> extract_immediate_assignment_impl::get_subchannels()
236 {
237 std::vector<int> subchannels;
238 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
239 {
240 subchannels.push_back(i.second.subchannel);
241 }
242 return subchannels;
243 }
244
245 std::vector<int> extract_immediate_assignment_impl::get_hopping()
246 {
247 std::vector<int> hopping;
248 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
249 {
250 hopping.push_back(i.second.hopping);
251 }
252 return hopping;
253 }
254
255 std::vector<int> extract_immediate_assignment_impl::get_maios()
256 {
257 std::vector<int> maios;
258 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
259 {
260 maios.push_back(i.second.maio);
261 }
262 return maios;
263 }
264
265 std::vector<int> extract_immediate_assignment_impl::get_hsns()
266 {
267 std::vector<int> hsns;
268 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
269 {
270 hsns.push_back(i.second.hsn);
271 }
272 return hsns;
273 }
274
275 std::vector<int> extract_immediate_assignment_impl::get_arfcns()
276 {
277 std::vector<int> arfcns;
278 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
279 {
280 arfcns.push_back(i.second.arfcn);
281 }
282 return arfcns;
283 }
284
285 std::vector<int> extract_immediate_assignment_impl::get_timing_advances()
286 {
287 std::vector<int> tas;
288 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
289 {
290 tas.push_back(i.second.timing_advance);
291 }
292 return tas;
293 }
294
295 std::vector<std::string> extract_immediate_assignment_impl::get_mobile_allocations()
296 {
297 std::vector<std::string> mobile_allocations;
298 BOOST_FOREACH(immediate_assignment_map::value_type &i, d_assignment_map)
299 {
300 mobile_allocations.push_back(i.second.mobile_allocation);
301 }
302 return mobile_allocations;
303 }
304
Roman Khassraf5bd14f22015-06-24 17:59:13 +0200305 extract_immediate_assignment::sptr
306 extract_immediate_assignment::make()
307 {
308 return gnuradio::get_initial_sptr
309 (new extract_immediate_assignment_impl());
310 }
311
312 /*
313 * The private constructor
314 */
315 extract_immediate_assignment_impl::extract_immediate_assignment_impl()
316 : gr::block("extract_immediate_assignment",
317 gr::io_signature::make(0, 0, 0),
318 gr::io_signature::make(0, 0, 0))
319 {
320 message_port_register_in(pmt::mp("msgs"));
321 set_msg_handler(pmt::mp("msgs"), boost::bind(&extract_immediate_assignment_impl::process_message, this, _1));
322 }
323
324 /*
325 * Our virtual destructor.
326 */
327 extract_immediate_assignment_impl::~extract_immediate_assignment_impl()
328 {
329 }
330 } /* namespace gsm */
331} /* namespace gr */
332