gsmmap: Dump SYSTEM INFORMATION messages while processing
[osmocom-bb.git] / src / host / gsmmap / gsmmap.c
1 /* Conversion of logged cells to KML file */
2
3 /* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
4  *
5  * All Rights Reserved
6  *
7  * This program 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 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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 along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22 #warning todo bsic
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <math.h>
28 #include <time.h>
29
30 #define GSM_TA_M 553.85
31 #define PI 3.1415926536
32
33 #include <osmocom/bb/common/osmocom_data.h>
34 #include <osmocom/bb/common/networks.h>
35 #include <osmocom/bb/common/logging.h>
36
37 #include "log.h"
38 #include "geo.h"
39 #include "locate.h"
40
41 /*
42  * structure of power and cell infos
43  */
44
45 struct power power;
46 struct sysinfo sysinfo;
47 static struct node_power *node_power_first = NULL;
48 static struct node_power **node_power_last_p = &node_power_first;
49 struct node_mcc *node_mcc_first = NULL;
50 int log_lines = 0, log_debug = 0;
51
52
53 static void nomem(void)
54 {
55         fprintf(stderr, "No mem!\n");
56         exit(-ENOMEM);
57 }
58
59 static void add_power()
60 {
61         struct node_power *node_power;
62
63 //      printf("New Power\n");
64         /* append or insert to list */
65         node_power = calloc(1, sizeof(struct node_power));
66         if (!node_power)
67                 nomem();
68         *node_power_last_p = node_power;
69         node_power_last_p = &node_power->next;
70         memcpy(&node_power->power, &power, sizeof(power));
71 }
72
73 static void print_si(void *priv, const char *fmt, ...)
74 {
75         char buffer[1000];
76         FILE *outfp = (FILE *)priv;
77         va_list args;
78
79         va_start(args, fmt);
80         vsnprintf(buffer, sizeof(buffer) - 1, fmt, args);
81         buffer[sizeof(buffer) - 1] = '\0';
82         va_end(args);
83
84         if (buffer[0])
85                 fprintf(outfp, "%s", buffer);
86 }
87
88 static void add_sysinfo()
89 {
90         struct gsm48_sysinfo s;
91         struct node_mcc *mcc;
92         struct node_mnc *mnc;
93         struct node_lac *lac;
94         struct node_cell *cell;
95         struct node_meas *meas;
96
97         memset(&s, 0, sizeof(s));
98
99         /* decode sysinfo */
100         if (sysinfo.si1[2])
101                 gsm48_decode_sysinfo1(&s,
102                         (struct gsm48_system_information_type_1 *) sysinfo.si1,
103                         23);
104         if (sysinfo.si2[2])
105                 gsm48_decode_sysinfo2(&s,
106                         (struct gsm48_system_information_type_2 *) sysinfo.si2,
107                         23);
108         if (sysinfo.si2bis[2])
109                 gsm48_decode_sysinfo2bis(&s,
110                         (struct gsm48_system_information_type_2bis *)
111                                 sysinfo.si2bis,
112                         23);
113         if (sysinfo.si2ter[2])
114                 gsm48_decode_sysinfo2ter(&s,
115                         (struct gsm48_system_information_type_2ter *)
116                                 sysinfo.si2ter,
117                         23);
118         if (sysinfo.si3[2])
119                 gsm48_decode_sysinfo3(&s,
120                         (struct gsm48_system_information_type_3 *) sysinfo.si3,
121                         23);
122         if (sysinfo.si4[2])
123                 gsm48_decode_sysinfo4(&s,
124                         (struct gsm48_system_information_type_4 *) sysinfo.si4,
125                         23);
126         printf("--------------------------------------------------------------------------\n");
127         gsm48_sysinfo_dump(&s, sysinfo.arfcn, print_si, stdout, NULL);
128         mcc = get_node_mcc(s.mcc);
129         if (!mcc)
130                 nomem();
131         mnc = get_node_mnc(mcc, s.mnc);
132         if (!mnc)
133                 nomem();
134         lac = get_node_lac(mnc, s.lac);
135         if (!lac)
136                 nomem();
137         cell = get_node_cell(lac, s.cell_id);
138         if (!cell)
139                 nomem();
140         meas = add_node_meas(cell);
141         if (!meas)
142                 nomem();
143         if (!cell->content) {
144                 cell->content = 1;
145                 memcpy(&cell->sysinfo, &sysinfo, sizeof(sysinfo));
146                 memcpy(&cell->s, &s, sizeof(s));
147         } else {
148                 if (memcmp(&cell->sysinfo.si1, sysinfo.si1,
149                         sizeof(sysinfo.si1))) {
150 new_sysinfo:
151                         fprintf(stderr, "FIXME: the cell changed sysinfo\n");
152                         return;
153                 }
154                 if (memcmp(&cell->sysinfo.si2, sysinfo.si2,
155                         sizeof(sysinfo.si2)))
156                         goto new_sysinfo;
157                 if (memcmp(&cell->sysinfo.si2bis, sysinfo.si2bis,
158                         sizeof(sysinfo.si2bis)))
159                         goto new_sysinfo;
160                 if (memcmp(&cell->sysinfo.si2ter, sysinfo.si2ter,
161                         sizeof(sysinfo.si2ter)))
162                         goto new_sysinfo;
163                 if (memcmp(&cell->sysinfo.si3, sysinfo.si3,
164                         sizeof(sysinfo.si3)))
165                         goto new_sysinfo;
166                 if (memcmp(&cell->sysinfo.si4, sysinfo.si4,
167                         sizeof(sysinfo.si4)))
168                         goto new_sysinfo;
169         }
170 }
171
172 void kml_header(FILE *outfp, char *name)
173 {
174         /* XML header */
175         fprintf(outfp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
176
177         /* KML open tag */
178         fprintf(outfp, "<kml xmlns=\"http://www.opengis.net/kml/2.2\" "
179                 "xmlns:gx=\"http://www.google.com/kml/ext/2.2\" "
180                 "xmlns:kml=\"http://www.opengis.net/kml/2.2\" "
181                 "xmlns:atom=\"http://www.w3.org/2005/Atom\">\n");
182
183         /* document open tag */
184         fprintf(outfp, "<Document>\n");
185
186         /* pushpin */
187         fprintf(outfp, "\t<Style id=\"sn_placemark_red_pushpin\">\n");
188         fprintf(outfp, "\t\t<IconStyle>\n");
189         fprintf(outfp, "\t\t\t<scale>1.1</scale>\n");
190         fprintf(outfp, "\t\t\t<Icon>\n");
191         fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
192                 "pushpin/red-pushpin.png</href>\n");
193         fprintf(outfp, "\t\t\t</Icon>\n");
194         fprintf(outfp, "\t\t</IconStyle>\n");
195         fprintf(outfp, "\t\t<ListStyle>\n");
196         fprintf(outfp, "\t\t</ListStyle>\n");
197         fprintf(outfp, "\t</Style>\n");
198         fprintf(outfp, "\t<Style id=\"sh_placemark_red_pushpin_highlight\">\n");
199         fprintf(outfp, "\t\t<IconStyle>\n");
200         fprintf(outfp, "\t\t\t<scale>1.3</scale>\n");
201         fprintf(outfp, "\t\t\t<Icon>\n");
202         fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
203                 "pushpin/red-pushpin.png</href>\n");
204         fprintf(outfp, "\t\t\t</Icon>\n");
205         fprintf(outfp, "\t\t</IconStyle>\n");
206         fprintf(outfp, "\t\t<ListStyle>\n");
207         fprintf(outfp, "\t\t</ListStyle>\n");
208         fprintf(outfp, "\t</Style>\n");
209         fprintf(outfp, "\t<StyleMap id=\"msn_placemark_red_pushpin\">\n");
210         fprintf(outfp, "\t\t<Pair>\n");
211         fprintf(outfp, "\t\t\t<key>normal</key>\n");
212         fprintf(outfp, "\t\t\t<styleUrl>#sn_placemark_red_pushpin"
213                 "</styleUrl>\n");
214         fprintf(outfp, "\t\t</Pair>\n");
215         fprintf(outfp, "\t\t<Pair>\n");
216         fprintf(outfp, "\t\t\t<key>highlight</key>\n");
217         fprintf(outfp, "\t\t\t<styleUrl>#sh_placemark_red_pushpin_highlight"
218                 "</styleUrl>\n");
219         fprintf(outfp, "\t\t</Pair>\n");
220         fprintf(outfp, "\t</StyleMap>\n");
221
222         fprintf(outfp, "\t<Style id=\"sn_placemark_grn_pushpin\">\n");
223         fprintf(outfp, "\t\t<IconStyle>\n");
224         fprintf(outfp, "\t\t\t<scale>1.1</scale>\n");
225         fprintf(outfp, "\t\t\t<Icon>\n");
226         fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
227                 "pushpin/grn-pushpin.png</href>\n");
228         fprintf(outfp, "\t\t\t</Icon>\n");
229         fprintf(outfp, "\t\t</IconStyle>\n");
230         fprintf(outfp, "\t\t<ListStyle>\n");
231         fprintf(outfp, "\t\t</ListStyle>\n");
232         fprintf(outfp, "\t</Style>\n");
233         fprintf(outfp, "\t<Style id=\"sh_placemark_grn_pushpin_highlight\">\n");
234         fprintf(outfp, "\t\t<IconStyle>\n");
235         fprintf(outfp, "\t\t\t<scale>1.3</scale>\n");
236         fprintf(outfp, "\t\t\t<Icon>\n");
237         fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
238                 "pushpin/grn-pushpin.png</href>\n");
239         fprintf(outfp, "\t\t\t</Icon>\n");
240         fprintf(outfp, "\t\t</IconStyle>\n");
241         fprintf(outfp, "\t\t<ListStyle>\n");
242         fprintf(outfp, "\t\t</ListStyle>\n");
243         fprintf(outfp, "\t</Style>\n");
244         fprintf(outfp, "\t<StyleMap id=\"msn_placemark_grn_pushpin\">\n");
245         fprintf(outfp, "\t\t<Pair>\n");
246         fprintf(outfp, "\t\t\t<key>normal</key>\n");
247         fprintf(outfp, "\t\t\t<styleUrl>#sn_placemark_grn_pushpin"
248                 "</styleUrl>\n");
249         fprintf(outfp, "\t\t</Pair>\n");
250         fprintf(outfp, "\t\t<Pair>\n");
251         fprintf(outfp, "\t\t\t<key>highlight</key>\n");
252         fprintf(outfp, "\t\t\t<styleUrl>#sh_placemark_grn_pushpin_highlight"
253                 "</styleUrl>\n");
254         fprintf(outfp, "\t\t</Pair>\n");
255         fprintf(outfp, "\t</StyleMap>\n");
256
257         /* circle */
258         fprintf(outfp, "\t<Style id=\"sn_placemark_circle\">\n");
259         fprintf(outfp, "\t\t<IconStyle>\n");
260         fprintf(outfp, "\t\t\t<scale>1.0</scale>\n");
261         fprintf(outfp, "\t\t\t<Icon>\n");
262         fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
263                 "shapes/placemark_circle.png</href>\n");
264         fprintf(outfp, "\t\t\t</Icon>\n");
265         fprintf(outfp, "\t\t</IconStyle>\n");
266         fprintf(outfp, "\t\t<ListStyle>\n");
267         fprintf(outfp, "\t\t</ListStyle>\n");
268         fprintf(outfp, "\t</Style>\n");
269         fprintf(outfp, "\t<Style id=\"sh_placemark_circle_highlight\">\n");
270         fprintf(outfp, "\t\t<IconStyle>\n");
271         fprintf(outfp, "\t\t\t<scale>1.2</scale>\n");
272         fprintf(outfp, "\t\t\t<Icon>\n");
273         fprintf(outfp, "\t\t\t\t<href>http://maps.google.com/mapfiles/kml/"
274                 "shapes/placemark_circle_highlight.png</href>\n");
275         fprintf(outfp, "\t\t\t</Icon>\n");
276         fprintf(outfp, "\t\t</IconStyle>\n");
277         fprintf(outfp, "\t\t<ListStyle>\n");
278         fprintf(outfp, "\t\t</ListStyle>\n");
279         fprintf(outfp, "\t</Style>\n");
280         fprintf(outfp, "\t<StyleMap id=\"msn_placemark_circle\">\n");
281         fprintf(outfp, "\t\t<Pair>\n");
282         fprintf(outfp, "\t\t\t<key>normal</key>\n");
283         fprintf(outfp, "\t\t\t<styleUrl>#sn_placemark_circle</styleUrl>\n");
284         fprintf(outfp, "\t\t</Pair>\n");
285         fprintf(outfp, "\t\t<Pair>\n");
286         fprintf(outfp, "\t\t\t<key>highlight</key>\n");
287         fprintf(outfp, "\t\t\t<styleUrl>#sh_placemark_circle_highlight"
288                 "</styleUrl>\n");
289         fprintf(outfp, "\t\t</Pair>\n");
290         fprintf(outfp, "\t</StyleMap>\n");
291 }
292
293 void kml_footer(FILE *outfp)
294 {
295         /* document close tag */
296         fprintf(outfp, "</Document>\n");
297
298         /* KML close tag */
299         fprintf(outfp, "</kml>\n");
300
301 }
302
303 void kml_meas(FILE *outfp, struct node_meas *meas, int n, uint16_t mcc,
304         uint16_t mnc, uint16_t lac, uint16_t cellid)
305 {
306         struct tm *tm = localtime(&meas->gmt);
307
308         fprintf(outfp, "\t\t\t\t\t<Placemark>\n");
309         fprintf(outfp, "\t\t\t\t\t\t<name>%d: %d</name>\n", n, meas->rxlev);
310         fprintf(outfp, "\t\t\t\t\t\t<description>\n");
311         fprintf(outfp, "MCC=%s MNC=%s\nLAC=%04x CELL-ID=%04x\n(%s %s)\n",
312                 gsm_print_mcc(mcc), gsm_print_mnc(mnc), lac, cellid,
313                 gsm_get_mcc(mcc), gsm_get_mnc(mcc, mnc));
314         fprintf(outfp, "\n%s", asctime(tm));
315         fprintf(outfp, "RX-LEV %d dBm\n", meas->rxlev);
316         if (meas->ta_valid)
317                 fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta,
318                         (int)(GSM_TA_M * meas->ta),
319                         (int)(GSM_TA_M * (meas->ta + 1)));
320         fprintf(outfp, "\t\t\t\t\t\t</description>\n");
321         fprintf(outfp, "\t\t\t\t\t\t<LookAt>\n");
322         fprintf(outfp, "\t\t\t\t\t\t\t<longitude>%.8f</longitude>\n",
323                 meas->longitude);
324         fprintf(outfp, "\t\t\t\t\t\t\t<latitude>%.8f</latitude>\n",
325                 meas->latitude);
326         fprintf(outfp, "\t\t\t\t\t\t\t<altitude>0</altitude>\n");
327         fprintf(outfp, "\t\t\t\t\t\t\t<tilt>0</tilt>\n");
328         fprintf(outfp, "\t\t\t\t\t\t\t<altitudeMode>relativeToGround"
329                 "</altitudeMode>\n");
330         fprintf(outfp, "\t\t\t\t\t\t\t<gx:altitudeMode>relativeToSeaFloor"
331                 "</gx:altitudeMode>\n");
332         fprintf(outfp, "\t\t\t\t\t\t</LookAt>\n");
333         fprintf(outfp, "\t\t\t\t\t\t<styleUrl>#msn_placemark_circle"
334                 "</styleUrl>\n");
335         fprintf(outfp, "\t\t\t\t\t\t<Point>\n");
336         fprintf(outfp, "\t\t\t\t\t\t\t<coordinates>%.8f,%.8f</coordinates>\n",
337                 meas->longitude, meas->latitude);
338         fprintf(outfp, "\t\t\t\t\t\t</Point>\n");
339         fprintf(outfp, "\t\t\t\t\t</Placemark>\n");
340 }
341
342 double debug_long, debug_lat, debug_x_scale;
343 FILE *debug_fp;
344
345 void kml_cell(FILE *outfp, struct node_cell *cell)
346 {
347         struct node_meas *meas;
348         double x, y, z, sum_x = 0, sum_y = 0, sum_z = 0, longitude, latitude;
349         int n, known = 0;
350
351         meas = cell->meas;
352         n = 0;
353         while (meas) {
354                 if (meas->gps_valid && meas->ta_valid) {
355                         geo2space(&x, &y, &z, meas->longitude, meas->latitude);
356                         sum_x += x;
357                         sum_y += y;
358                         sum_z += z;
359                         n++;
360                 }
361                 meas = meas->next;
362         }
363         if (!n)
364                 return;
365         if (n < 3) {
366                 x = sum_x / n;
367                 y = sum_y / n;
368                 z = sum_z / n;
369                 space2geo(&longitude, &latitude, x, y, z);
370         } else {
371                 struct probe *probe_first = NULL, *probe,
372                              **probe_last_p = &probe_first;
373                 double x_scale;
374
375                 /* translate to flat surface */
376                 meas = cell->meas;
377                 x_scale = 1.0 / cos(meas->latitude / 180.0 * PI);
378                 longitude = meas->longitude;
379                 latitude = meas->latitude;
380                 debug_x_scale = x_scale;
381                 debug_long = longitude;
382                 debug_lat = latitude;
383                 debug_fp = outfp;
384                 while (meas) {
385                         if (meas->gps_valid && meas->ta_valid) {
386                                 probe = calloc(1, sizeof(struct probe));
387                                 if (!probe)
388                                         nomem();
389                                 probe->x = (meas->longitude - longitude) /
390                                                 x_scale;
391                                 if (x < -180)
392                                         x += 360;
393                                 else if (x > 180)
394                                         x -= 360;
395                                 probe->y = meas->latitude - latitude;
396                                 probe->dist = GSM_TA_M * (0.5 +
397                                         (double)meas->ta) /
398                                         (EQUATOR_RADIUS * PI / 180.0);
399                                 *probe_last_p = probe;
400                                 probe_last_p = &probe->next;
401                         }
402                         meas = meas->next;
403                 }
404
405                 /* locate */
406                 locate_cell(probe_first, &x, &y);
407
408                 /* translate from flat surface */
409                 longitude += x * x_scale;
410                 if (longitude < 0)
411                         longitude += 360;
412                 else if (longitude >= 360)
413                         longitude -= 360;
414                 latitude += y;
415
416                 /* remove probes */
417                 while (probe_first) {
418                         probe = probe_first;
419                         probe_first = probe->next;
420                         free(probe);
421                 }
422
423                 known = 1;
424         }
425
426         if (!known)
427                 return;
428
429         fprintf(outfp, "\t\t\t\t\t<Placemark>\n");
430         fprintf(outfp, "\t\t\t\t\t\t<name>MCC=%s MNC=%s\nLAC=%04x "
431                 "CELL-ID=%04x\n(%s %s)</name>\n", gsm_print_mcc(cell->s.mcc),
432                 gsm_print_mnc(cell->s.mnc), cell->s.lac, cell->s.cell_id,
433                 gsm_get_mcc(cell->s.mcc),
434                 gsm_get_mnc(cell->s.mcc, cell->s.mnc));
435         fprintf(outfp, "\t\t\t\t\t\t<description>\n");
436         gsm48_sysinfo_dump(&cell->s, cell->sysinfo.arfcn, print_si, outfp,
437                 NULL);
438         fprintf(outfp, "\t\t\t\t\t\t</description>\n");
439         fprintf(outfp, "\t\t\t\t\t\t<LookAt>\n");
440         fprintf(outfp, "\t\t\t\t\t\t\t<longitude>%.8f</longitude>\n",
441                 longitude);
442         fprintf(outfp, "\t\t\t\t\t\t\t<latitude>%.8f</latitude>\n", latitude);
443         fprintf(outfp, "\t\t\t\t\t\t\t<altitude>0</altitude>\n");
444         fprintf(outfp, "\t\t\t\t\t\t\t<tilt>0</tilt>\n");
445         fprintf(outfp, "\t\t\t\t\t\t\t<altitudeMode>relativeToGround"
446                 "</altitudeMode>\n");
447         fprintf(outfp, "\t\t\t\t\t\t\t<gx:altitudeMode>relativeToSeaFloor"
448                 "</gx:altitudeMode>\n");
449         fprintf(outfp, "\t\t\t\t\t\t</LookAt>\n");
450         if (known)
451                 fprintf(outfp, "\t\t\t\t\t\t<styleUrl>#msn_placemark_grn_"
452                         "pushpin</styleUrl>\n");
453         else
454                 fprintf(outfp, "\t\t\t\t\t\t<styleUrl>#msn_placemark_red_"
455                         "pushpin</styleUrl>\n");
456         fprintf(outfp, "\t\t\t\t\t\t<Point>\n");
457         fprintf(outfp, "\t\t\t\t\t\t\t<coordinates>%.8f,%.8f</coordinates>\n",
458                 longitude, latitude);
459         fprintf(outfp, "\t\t\t\t\t\t</Point>\n");
460         fprintf(outfp, "\t\t\t\t\t</Placemark>\n");
461
462         if (!log_lines)
463                 return;
464
465         fprintf(outfp, "\t<Folder>\n");
466         fprintf(outfp, "\t\t<name>Lines</name>\n");
467         fprintf(outfp, "\t\t<open>0</open>\n");
468         fprintf(outfp, "\t\t<visibility>0</visibility>\n");
469
470         geo2space(&x, &y, &z, longitude, latitude);
471         meas = cell->meas;
472         n = 0;
473         while (meas) {
474                 if (meas->gps_valid) {
475                         double mx, my, mz, dist;
476
477                         geo2space(&mx, &my, &mz, meas->longitude,
478                                 meas->latitude);
479                         dist = distinspace(x, y, z, mx, my, mz);
480                         fprintf(outfp, "\t\t<Placemark>\n");
481                         fprintf(outfp, "\t\t\t<name>Range</name>\n");
482                         fprintf(outfp, "\t\t\t<description>\n");
483                         fprintf(outfp, "Distance: %d\n", (int)dist);
484                         fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta,
485                                 (int)(GSM_TA_M * meas->ta),
486                                 (int)(GSM_TA_M * (meas->ta + 1)));
487                         fprintf(outfp, "\t\t\t</description>\n");
488                         fprintf(outfp, "\t\t\t<visibility>0</visibility>\n");
489                         fprintf(outfp, "\t\t\t<LineString>\n");
490                         fprintf(outfp, "\t\t\t\t<tessellate>1</tessellate>\n");
491                         fprintf(outfp, "\t\t\t\t<coordinates>\n");
492                         fprintf(outfp, "%.8f,%.8f\n", longitude, latitude);
493                         fprintf(outfp, "%.8f,%.8f\n", meas->longitude,
494                                 meas->latitude);
495                         fprintf(outfp, "\t\t\t\t</coordinates>\n");
496                         fprintf(outfp, "\t\t\t</LineString>\n");
497                         fprintf(outfp, "\t\t</Placemark>\n");
498                 }
499                 meas = meas->next;
500         }
501         fprintf(outfp, "\t</Folder>\n");
502 }
503
504 struct log_target *stderr_target;
505
506 int main(int argc, char *argv[])
507 {
508         FILE *infp, *outfp;
509         int type, n, i;
510         char *p;
511         struct node_mcc *mcc;
512         struct node_mnc *mnc;
513         struct node_lac *lac;
514         struct node_cell *cell;
515         struct node_meas *meas;
516
517         log_init(&log_info, NULL);
518         stderr_target = log_target_create_stderr();
519         log_add_target(stderr_target);
520         log_set_all_filter(stderr_target, 1);
521         log_parse_category_mask(stderr_target, "Dxxx");
522         log_set_log_level(stderr_target, LOGL_INFO);
523
524         if (argc <= 2) {
525 usage:
526                 fprintf(stderr, "Usage: %s <file.log> <file.kml> "
527                         "[lines] [debug]\n", argv[0]);
528                 fprintf(stderr, "lines: Add lines between cell and "
529                         "Measurement point\n");
530                 fprintf(stderr, "debug: Add debugging of location algorithm.\n"
531                         );
532                 return 0;
533         }
534
535         for (i = 3; i < argc; i++) {
536                 if (!strcmp(argv[i], "lines"))
537                         log_lines = 1;
538                 else if (!strcmp(argv[i], "debug"))
539                         log_debug = 1;
540                 else goto usage;
541         }
542
543         infp = fopen(argv[1], "r");
544         if (!infp) {
545                 fprintf(stderr, "Failed to open '%s' for reading\n", argv[1]);
546                 return -EIO;
547         }
548
549         while ((type = read_log(infp))) {
550                 switch (type) {
551                 case LOG_TYPE_SYSINFO:
552                         add_sysinfo();
553                         break;
554                 case LOG_TYPE_POWER:
555                         add_power();
556                         break;
557                 }
558         }
559
560         fclose(infp);
561
562         if (!strcmp(argv[2], "-"))
563                 outfp = stdout;
564         else
565                 outfp = fopen(argv[2], "w");
566         if (!outfp) {
567                 fprintf(stderr, "Failed to open '%s' for writing\n", argv[2]);
568                 return -EIO;
569         }
570
571         /* document name */
572         p = argv[2];
573         while (strchr(p, '/'))
574                 p = strchr(p, '/') + 1;
575
576         kml_header(outfp, p);
577         mcc = node_mcc_first;
578         while (mcc) {
579           printf("MCC: %02x\n", mcc->mcc);
580          /* folder open */
581           fprintf(outfp, "\t<Folder>\n");
582           fprintf(outfp, "\t\t<name>MCC %s (%s)</name>\n",
583                 gsm_print_mcc(mcc->mcc), gsm_get_mcc(mcc->mcc));
584           fprintf(outfp, "\t\t<open>0</open>\n");
585           mnc = mcc->mnc;
586           while (mnc) {
587             printf(" MNC: %02x\n", mnc->mnc);
588             /* folder open */
589             fprintf(outfp, "\t\t<Folder>\n");
590             fprintf(outfp, "\t\t\t<name>MNC %s (%s)</name>\n",
591                 gsm_print_mnc(mnc->mnc), gsm_get_mnc(mcc->mcc, mnc->mnc));
592             fprintf(outfp, "\t\t\t<open>0</open>\n");
593             lac = mnc->lac;
594             while (lac) {
595               printf("  LAC: %04x\n", lac->lac);
596               /* folder open */
597               fprintf(outfp, "\t\t\t<Folder>\n");
598               fprintf(outfp, "\t\t\t\t<name>LAC %04x</name>\n", lac->lac);
599               fprintf(outfp, "\t\t\t\t<open>0</open>\n");
600               cell = lac->cell;
601               while (cell) {
602                 printf("   CELL: %04x\n", cell->cellid);
603                 fprintf(outfp, "\t\t\t\t<Folder>\n");
604                 fprintf(outfp, "\t\t\t\t\t<name>CELL-ID %04x</name>\n", cell->cellid);
605                 fprintf(outfp, "\t\t\t\t\t<open>0</open>\n");
606                 meas = cell->meas;
607                 n = 0;
608                 while (meas) {
609                         if (meas->ta_valid)
610                                 printf("    TA: %d\n", meas->ta);
611                         if (meas->gps_valid)
612                                 kml_meas(outfp, meas, ++n, mcc->mcc, mnc->mnc,
613                                         lac->lac, cell->cellid);
614                         meas = meas->next;
615                 }
616                 kml_cell(outfp, cell);
617                 /* folder close */
618                 fprintf(outfp, "\t\t\t\t</Folder>\n");
619                 cell = cell->next;
620               }
621               /* folder close */
622               fprintf(outfp, "\t\t\t</Folder>\n");
623               lac = lac->next;
624             }
625             /* folder close */
626             fprintf(outfp, "\t\t</Folder>\n");
627             mnc = mnc->next;
628           }
629           /* folder close */
630           fprintf(outfp, "\t</Folder>\n");
631           mcc = mcc->next;
632         }
633 #if 0
634         FIXME: power
635         /* folder open */
636         fprintf(outfp, "\t<Folder>\n");
637         fprintf(outfp, "\t\t<name>Power</name>\n");
638         fprintf(outfp, "\t\t<open>0</open>\n");
639         power = node_power_first;
640         n = 0;
641         while (power) {
642                 /* folder open */
643                 fprintf(outfp, "\t\t<Folder>\n");
644                 fprintf(outfp, "\t\t\t<name>Power %d</name>\n", ++n);
645                 fprintf(outfp, "\t\t\t<open>0</open>\n");
646                 /* folder close */
647                 fprintf(outfp, "\t\t</Folder>\n");
648                 power = power->next;
649         }
650         /* folder close */
651         fprintf(outfp, "\t</Folder>\n");
652 #endif
653         kml_footer(outfp);
654
655         fclose(outfp);
656
657         return 0;
658 }