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