1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <sys/errno.h>
7 #include "emulate.h"
8 
9 #include "dump-vdr.h"		// debugging transponder.
10 #include "dump-xine.h"		// debugging transponder.
11 #include "dvbscan.h"		// debugging transponder.
12 #include "tools.h"		// hexdump
13 
14 #define Hz   1
15 #define kHz (1000 * Hz)
16 #define MHz (1000 * kHz)
17 
18 //#define EM_INFO(msg...) info(msg)
19 #define EM_INFO(msg...)
20 
21 /* this struct stores the contents (DVB SI data) of an section buffer,
22  * alltogether with the current tuning state of the dvb device.
23  */
24 typedef struct {
25   /*----------------------------*/
26 	void *prev;
27 	void *next;
28 	uint32_t index;
29   /*----------------------------*/
30 	uint16_t pid;
31 	uint16_t table_id;
32 	uint16_t table_id_ext;
33 	uint16_t original_network_id;
34 	uint16_t network_id;
35 	uint16_t transport_stream_id;
36 	uint16_t service_id;
37 	uint16_t len;
38 	struct transponder t;
39 	unsigned char buf[SECTION_BUF_SIZE];
40 } sidata_t;
41 
42  /*
43   * list of DVB SI data and list of running demux filters.
44   */
45 cList __em_buf1, *em_runningfilters = &__em_buf1;
46 cList __em_buf2, *em_sidata = &__em_buf2;
47 
48  /*
49   * drivers DVB API.
50   * NOTE:
51   *   - API defaults to 5.3
52   *   - if not overwritten from log -> bug.
53   */
54 struct {
55 	unsigned major;
56 	unsigned minor;
57 } em_api = {
58 5, 3};
59 
60  /*
61   * The emulated DVB device.
62   * NOTE:
63   *   - state is set by em_setproperty and returned by em_getproperty
64   *   - not to be exposed outside this file.
65   */
66 static struct {
67 	unsigned w_scan_version;
68 	uint32_t w_scan_flags;
69 	fe_delivery_system_t delsys;
70 	uint32_t frequency;
71 	uint32_t bandwidth_hz;
72 	uint32_t symbolrate;
73 	uint8_t stream_id;
74 	fe_spectral_inversion_t inversion;
75 	fe_modulation_t modulation;
76 	fe_code_rate_t fec;
77 	fe_pilot_t pilot;
78 	fe_rolloff_t rolloff;
79 	fe_transmit_mode_t transmission;
80 	fe_guard_interval_t guard;
81 	fe_hierarchy_t hierarchy;
82 	fe_polarization_t polarization;
83 	struct dvb_frontend_info fe_info;
84 	fe_delivery_system_t delsystems[32];
85 	uint8_t ndelsystems;
86 	scantype_t scantype;
87 	bool T2_delsys_bug;
88 	bool highband;
89 	uint32_t lnb_low;
90 	uint32_t lnb_high;
91 } em_device;
92 
93 #define EM_OLD_DELSYSLIST (((uint32_t)1) << 1)
94 #define EM_OLD_APIDISP    (((uint32_t)1) << 2)
95 #define EM_HEXDUMP_BUG    (((uint32_t)1) << 3)
96 #define EM_OLD_SI_HEADER  (((uint32_t)1) << 4)
97 
98 /*
99  * forward declarations.
100  */
101 static int parse_logfile(const char *log);
102 
103 // Declare parse_xyz in scan.h? Hmm..
104 extern void parse_pat(const unsigned char *buf, uint16_t section_length,
105 		      uint16_t transport_stream_id, uint32_t flags);
106 extern void parse_pmt(const unsigned char *buf, uint16_t section_length,
107 		      uint16_t service_id);
108 extern void parse_nit(const unsigned char *buf, uint16_t section_length,
109 		      uint8_t table_id, uint16_t network_id,
110 		      uint32_t section_flags);
111 extern void parse_sdt(const unsigned char *buf, uint16_t section_length,
112 		      uint16_t transport_stream_id);
113 extern void parse_psip_vct(const unsigned char *buf, uint16_t section_length,
114 			   uint8_t table_id, uint16_t transport_stream_id);
115 
116  /*
117   * initializes emulated dvb device and fills in data by parsing logfile.
118   */
em_init(const char * log)119 void em_init(const char *log)
120 {
121 	NewList(em_runningfilters, "em_runningfilters");
122 	NewList(em_sidata, "em_sidata");
123 	memset(&em_device, 0, sizeof(em_device));
124 	parse_logfile(log);
125 }
126 
127  /*
128   * let 'frontend_fd' be any non-negative int to pass validity checks.
129   */
em_open(int * frontend_fd)130 void em_open(int *frontend_fd)
131 {
132 	*frontend_fd = 1;
133 }
134 
135  /*
136   * replaces FE_GET_INFO ioctl.
137   */
em_info(struct dvb_frontend_info * fe_info)138 void em_info(struct dvb_frontend_info *fe_info)
139 {
140 	memcpy(fe_info, &em_device.fe_info, sizeof(struct dvb_frontend_info));
141 }
142 
143  /*
144   * replaces DTV_API_VERSION ioctl.
145   */
em_dvbapi(uint16_t * flags)146 void em_dvbapi(uint16_t * flags)
147 {
148 	*flags = (em_api.major << 8) | em_api.minor;
149 }
150 
151  /*
152   * replaces FE_SET_PROPERTY ioctl.
153   */
em_setproperty(struct dtv_properties * cmdseq)154 int em_setproperty(struct dtv_properties *cmdseq)
155 {
156 	uint8_t i;
157 	for (i = 0; i < cmdseq->num; i++) {
158 		switch (cmdseq->props[i].cmd) {
159 		case DTV_DELIVERY_SYSTEM:
160 			em_device.delsys = cmdseq->props[i].u.data;
161 			break;
162 		case DTV_FREQUENCY:
163 			em_device.frequency = cmdseq->props[i].u.data;
164 			break;
165 		case DTV_INVERSION:
166 			em_device.inversion = cmdseq->props[i].u.data;
167 			break;
168 		case DTV_MODULATION:
169 			em_device.modulation = cmdseq->props[i].u.data;
170 			break;
171 		case DTV_SYMBOL_RATE:
172 			em_device.symbolrate = cmdseq->props[i].u.data;
173 			break;
174 		case DTV_INNER_FEC:
175 			em_device.fec = cmdseq->props[i].u.data;
176 			break;
177 		case DTV_PILOT:
178 			em_device.pilot = cmdseq->props[i].u.data;
179 			break;
180 		case DTV_ROLLOFF:
181 			em_device.rolloff = cmdseq->props[i].u.data;
182 			break;
183 		case DTV_STREAM_ID:
184 			em_device.stream_id = cmdseq->props[i].u.data;
185 			break;
186 		case DTV_BANDWIDTH_HZ:
187 			em_device.bandwidth_hz = cmdseq->props[i].u.data;
188 			break;
189 		case DTV_CODE_RATE_HP:
190 			em_device.fec = cmdseq->props[i].u.data;
191 			break;
192 		case DTV_TRANSMISSION_MODE:
193 			em_device.transmission = cmdseq->props[i].u.data;
194 			break;
195 		case DTV_GUARD_INTERVAL:
196 			em_device.guard = cmdseq->props[i].u.data;
197 			break;
198 		case DTV_HIERARCHY:
199 			em_device.hierarchy = cmdseq->props[i].u.data;
200 			break;
201 		case DTV_CLEAR:
202 			break;	// what to do with clear?
203 		default:;
204 		}
205 	}
206 	return 0;		// no err.
207 }
208 
209  /*
210   * replaces FE_GET_PROPERTY ioctl.
211   */
em_getproperty(struct dtv_properties * cmdseq)212 int em_getproperty(struct dtv_properties *cmdseq)
213 {
214 	uint8_t i;
215 	int j, k;
216 	for (i = 0; i < cmdseq->num; i++) {
217 		switch (cmdseq->props[i].cmd) {
218 		case DTV_DELIVERY_SYSTEM:
219 			cmdseq->props[i].u.data = em_device.delsys;
220 			break;
221 		case DTV_FREQUENCY:
222 			cmdseq->props[i].u.data = em_device.frequency;
223 			break;
224 		case DTV_INVERSION:
225 			cmdseq->props[i].u.data = em_device.inversion;
226 			break;
227 		case DTV_MODULATION:
228 			cmdseq->props[i].u.data = em_device.modulation;
229 			break;
230 		case DTV_SYMBOL_RATE:
231 			cmdseq->props[i].u.data = em_device.symbolrate;
232 			break;
233 		case DTV_INNER_FEC:
234 			cmdseq->props[i].u.data = em_device.fec;
235 			break;
236 		case DTV_PILOT:
237 			cmdseq->props[i].u.data = em_device.pilot;
238 			break;
239 		case DTV_ROLLOFF:
240 			cmdseq->props[i].u.data = em_device.rolloff;
241 			break;
242 		case DTV_STREAM_ID:
243 			cmdseq->props[i].u.data = em_device.stream_id;
244 			break;
245 		case DTV_BANDWIDTH_HZ:
246 			cmdseq->props[i].u.data = em_device.bandwidth_hz;
247 			break;
248 		case DTV_CODE_RATE_HP:
249 			cmdseq->props[i].u.data = em_device.fec;
250 			break;
251 		case DTV_TRANSMISSION_MODE:
252 			cmdseq->props[i].u.data = em_device.transmission;
253 			break;
254 		case DTV_GUARD_INTERVAL:
255 			cmdseq->props[i].u.data = em_device.guard;
256 			break;
257 		case DTV_HIERARCHY:
258 			cmdseq->props[i].u.data = em_device.hierarchy;
259 			break;
260 		case DTV_ENUM_DELSYS:
261 			cmdseq->props[i].u.buffer.len = em_device.ndelsystems;
262 			for (j = 0, k = em_device.ndelsystems - 1;
263 			     j < em_device.ndelsystems; j++, k--)
264 				cmdseq->props[i].u.buffer.data[k] =
265 				    em_device.delsystems[j];
266 			break;
267 		default:;
268 		}
269 	}
270 	return 0;		// no err.
271 }
272 
em_lnb(int high_band,uint32_t high_val,uint32_t low_val)273 void em_lnb(int high_band, uint32_t high_val, uint32_t low_val)
274 {
275 	em_device.highband = high_band;
276 	em_device.lnb_low = low_val;
277 	em_device.lnb_high = high_val;
278 }
279 
em_polarization(uint8_t p)280 void em_polarization(uint8_t p)
281 {
282 	em_device.polarization = p & 0x3;
283 }
284 
285 /*
286  * INTERNAL USE ONLY. DONT EXPOSE THIS FUNC OUTSIDE THIS FILE.
287  */
has_lock(fe_delivery_system_t em_delsys,struct transponder * t)288 static int has_lock(fe_delivery_system_t em_delsys, struct transponder *t)
289 {
290 	uint32_t tp_if = 0;
291 
292 	switch (em_delsys) {
293 	case SYS_DVBT:
294 	case SYS_DVBT2:
295 		if (t->frequency != em_device.frequency)
296 			return 0;
297 		EM_INFO("%s: f=%u B%uC%dD0M%dT%dG%dY%dS%d\n"
298 			"          f=%u B%dC%dD0M%dT%dG%dY%dS%d\n",
299 			__FUNCTION__,
300 			freq_scale(em_device.frequency, 1e-3),
301 			freq_scale(em_device.bandwidth_hz, 1e-6), em_device.fec,
302 			em_device.modulation, em_device.transmission,
303 			em_device.guard, em_device.hierarchy,
304 			em_device.delsys == SYS_DVBT2, freq_scale(t->frequency,
305 								  1e-3),
306 			freq_scale(t->bandwidth, 1e-6), t->coderate,
307 			t->modulation, t->transmission, t->guard, t->hierarchy,
308 			t->delsys == SYS_DVBT2);
309 		if (t->bandwidth != em_device.bandwidth_hz)
310 			return 0;
311 		if ((t->coderate != em_device.fec) && (t->coderate != FEC_AUTO))
312 			return 0;
313 		if ((t->modulation != em_device.modulation)
314 		    && (t->modulation != QAM_AUTO))
315 			return 0;
316 		if ((t->transmission != em_device.transmission)
317 		    && (t->transmission != TRANSMISSION_MODE_AUTO))
318 			return 0;
319 		if ((t->guard != em_device.guard)
320 		    && (t->guard != GUARD_INTERVAL_AUTO))
321 			return 0;
322 		if ((t->hierarchy != em_device.hierarchy)
323 		    && (t->hierarchy != HIERARCHY_AUTO))
324 			return 0;
325 		if (!em_device.T2_delsys_bug) {
326 			// any dvb driver here, except CXD2820R
327 			if (t->delsys != em_device.delsys)
328 				return 0;
329 		} else {
330 			// CXD2820R only: driver silently changes delsys.
331 			em_device.delsys = t->delsys;
332 		}
333 		return 0x1F;
334 		break;
335 	case SYS_DVBC_ANNEX_A:
336 	case SYS_DVBC_ANNEX_C:
337 		if (t->frequency != em_device.frequency)
338 			return 0;
339 		if ((t->delsys != SYS_DVBC_ANNEX_A)
340 		    && (t->delsys != SYS_DVBC_ANNEX_C))
341 			return 0;
342 		if ((t->modulation != em_device.modulation)
343 		    && (em_device.modulation != QAM_AUTO))
344 			return 0;
345 		if (t->symbolrate != em_device.symbolrate)
346 			return 0;
347 		return 0x1F;
348 		break;
349 	case SYS_DVBS2:
350 		if ((t->rolloff != em_device.rolloff)
351 		    && (em_device.rolloff != ROLLOFF_35)
352 		    && (em_device.rolloff != ROLLOFF_AUTO)) {
353 			EM_INFO("wrong rolloff: %d != %d\n", t->rolloff,
354 				em_device.rolloff);
355 			return 0;
356 		}
357 		if ((t->pilot != em_device.pilot)
358 		    && (em_device.pilot != PILOT_AUTO)) {
359 			EM_INFO("wrong pilot: %d != %d\n", t->pilot,
360 				em_device.pilot);
361 			return 0;
362 		}
363 		/* fall trough. */
364 	case SYS_DVBS:
365 		if (em_device.highband)
366 			tp_if = abs(t->frequency - em_device.lnb_high);
367 		else
368 			tp_if = abs(t->frequency - em_device.lnb_low);
369 
370 		if (abs(tp_if - em_device.frequency) > 2000) {
371 			EM_INFO
372 			    ("t->frequency = %u: tp_if = %u <-> em_device.frequency = %u\n",
373 			     t->frequency, tp_if, em_device.frequency);
374 			return 0;
375 		}
376 		if (t->delsys != em_device.delsys) {
377 			EM_INFO("wrong delsys\n");
378 			return 0;
379 		}
380 		if (t->polarization != em_device.polarization) {
381 			EM_INFO("wrong polarization\n");
382 			return 0;
383 		}
384 		if ((t->coderate != em_device.fec)
385 		    && (em_device.fec != FEC_AUTO)) {
386 			EM_INFO("wrong coderate\n");
387 			return 0;
388 		}
389 		if (t->symbolrate != em_device.symbolrate) {
390 			EM_INFO("wrong symbolrate\n");
391 			return 0;
392 		}
393 		if (t->modulation != em_device.modulation) {
394 			EM_INFO("wrong modulation\n");
395 			return 0;
396 		}
397 		return 0x1F;
398 		break;
399 	case SYS_ATSC:
400 		if (t->frequency != em_device.frequency)
401 			return 0;
402 		if (t->delsys != em_device.delsys)
403 			return 0;
404 		if (t->modulation != em_device.modulation)
405 			return 0;
406 		return 0x1F;
407 		break;
408 	default:
409 		fatal("unsupported del sys.\n");
410 	}
411 	return 0;
412 }
413 
414 /*
415  * replaces FE_READ_STATUS ioctl.
416  */
em_status(fe_status_t * status)417 int em_status(fe_status_t * status)
418 {
419 	sidata_t *s;
420 
421 	*status = 0;
422 	for (s = em_sidata->first; s; s = s->next) {
423 		//char b[256];
424 		//print_transponder(b, &s->t);
425 		//info("%s: try %s (current: %d lo %d highband=%d)\n",__FUNCTION__,b, em_device.frequency, em_device.highband?em_device.lnb_high:em_device.lnb_low, em_device.highband);
426 		if (has_lock(em_device.delsys, &s->t)) {
427 			*status = 0x1F;	// sync && lock.
428 			break;
429 		}
430 	}
431 	return 0;
432 }
433 
434 /*----------------------------------------------------------------------------------------------------------------------
435  * DEMUX related.
436  *---------------------------------------------------------------------------------------------------------------------*/
437 
table_name(uint16_t id)438 static const char *table_name(uint16_t id)
439 {
440 	switch (id) {
441 	case TABLE_PAT:
442 		return "PAT";
443 	case TABLE_PMT:
444 		return "PMT";
445 	case TABLE_NIT_ACT:
446 		return "NIT(ACT)";
447 	case TABLE_NIT_OTH:
448 		return "NIT(OTH)";
449 	case TABLE_SDT_ACT:
450 		return "SDT(ACT)";
451 	case TABLE_SDT_OTH:
452 		return "SDT(OTH)";
453 	case TABLE_VCT_TERR:
454 		return "VCT(TERR)";
455 	case TABLE_VCT_CABLE:
456 		return "VCT(CABLE)";
457 	default:
458 		return "???";
459 	}
460 }
461 
em_addfilter(struct section_buf * s)462 void em_addfilter(struct section_buf *s)
463 {
464 	EM_INFO("%s: %s pid=%d\n", __FUNCTION__, table_name(s->table_id),
465 		s->pid);
466 	AddItem(em_runningfilters, s);
467 }
468 
em_readfilters(int * result)469 void em_readfilters(int *result)
470 {
471 	sidata_t *sidata;
472 	struct section_buf *filter;
473 	int maxiter = 10000;
474 
475 	while ((filter = em_runningfilters->first)) {
476 		bool data_found = false;
477 		if (!maxiter--)
478 			fatal("%s: max iterations.\n", __FUNCTION__);
479 		for (sidata = em_sidata->first; sidata; sidata = sidata->next) {
480 			if (filter->table_id != sidata->table_id) {
481 				// info("(filter->table_id = %d != table_id = %d), table_id_ext = %d, pid = %d\n", filter->table_id, sidata->table_id, sidata->table_id_ext, sidata->pid);
482 				continue;
483 			}
484 			EM_INFO
485 			    ("f=%-6d: searching %-10s: table_id_ext = %d, pid = %d\n",
486 			     freq_scale(em_device.frequency, 1e-3),
487 			     table_name(filter->table_id), filter->table_id_ext,
488 			     filter->pid);
489 
490 			if (!has_lock(em_device.delsys, &sidata->t)) {
491 				EM_INFO(" -> no lock @ %d\n",
492 					freq_scale(sidata->t.frequency, 1e-3));
493 				continue;
494 			}
495 
496 			if ((filter->pid != sidata->pid)
497 			    && (filter->table_id == TABLE_PMT)) {
498 				EM_INFO(" -> wrong pid %d\n", sidata->pid);
499 				continue;
500 			}
501 
502 			if ((filter->table_id_ext != sidata->table_id_ext)
503 			    && (filter->table_id_ext > -1)) {
504 				EM_INFO(" -> wrong table_id_ext = %d\n",
505 					sidata->table_id_ext);
506 				continue;
507 			}
508 			EM_INFO(" -> OK.\n");
509 			data_found = true;
510 
511 			switch (filter->table_id) {
512 			case TABLE_PAT:
513 				parse_pat(sidata->buf, sidata->len,
514 					  sidata->transport_stream_id,
515 					  filter->flags);
516 				break;
517 			case TABLE_NIT_ACT:
518 			case TABLE_NIT_OTH:
519 				parse_nit(sidata->buf, sidata->len,
520 					  filter->table_id, sidata->network_id,
521 					  filter->flags);
522 				break;
523 			case TABLE_PMT:
524 				verbose
525 				    ("PMT %d (0x%04x) for service %d (0x%04x)\n",
526 				     sidata->pid, sidata->pid,
527 				     sidata->service_id, sidata->service_id);
528 				parse_pmt(sidata->buf, sidata->len,
529 					  sidata->service_id);
530 				break;
531 			case TABLE_SDT_ACT:
532 			case TABLE_SDT_OTH:
533 				verbose
534 				    ("SDT(%s TS, transport_stream_id %d (0x%04x) )\n",
535 				     filter->table_id ==
536 				     0x42 ? "actual" : "other",
537 				     sidata->transport_stream_id,
538 				     sidata->transport_stream_id);
539 				parse_sdt(sidata->buf, sidata->len,
540 					  sidata->transport_stream_id);
541 				break;
542 			case TABLE_VCT_TERR:
543 			case TABLE_VCT_CABLE:
544 				verbose
545 				    ("ATSC VCT, table_id %d, table_id_ext %d\n",
546 				     sidata->table_id, sidata->table_id_ext);
547 				parse_psip_vct(sidata->buf, sidata->len,
548 					       filter->table_id,
549 					       sidata->table_id_ext);
550 				break;
551 			default:
552 				fatal("%s %d: unhandled table_id %d\n",
553 				      __FUNCTION__, __LINE__, filter->table_id);
554 			}
555 			//if (filter->run_once) /* probably i would have to check version nums here. */
556 			//   break;
557 		}
558 
559 		if (!data_found) {
560 			const char *intro = "        Info: no data from ";
561 			// timeout waiting for data.
562 			switch (filter->table_id) {
563 			case TABLE_PAT:
564 			case TABLE_PMT:
565 			case TABLE_NIT_ACT:
566 			case TABLE_NIT_OTH:
567 			case TABLE_SDT_ACT:
568 			case TABLE_SDT_OTH:
569 			case TABLE_VCT_TERR:
570 			case TABLE_VCT_CABLE:
571 				info("%s%s after %lld seconds\n", intro,
572 				     table_name(filter->table_id),
573 				     (long long)filter->timeout);
574 				break;
575 			default:
576 				info("%spid %u after %lld seconds\n", intro,
577 				     filter->pid, (long long)filter->timeout);
578 			}
579 			*result = 0;
580 		}
581 		UnlinkItem(em_runningfilters, filter,
582 			   filter->flags & SECTION_FLAG_FREE ? true : false);
583 	}
584 	*result = 1;
585 	return;
586 }
587 
parse_tp(const char * str)588 static int parse_tp(const char *str)
589 {
590 	uint32_t args[8];
591 	char mbuf[64], fecbuf[5], robuf[5];
592 	char c;
593 	char *p = strchr(str, '(');
594 	if (p && *p)
595 		*p = 0;		// cut '(ONID:NID:SID)'
596 
597 	switch (em_device.scantype) {
598 	case SCAN_TERRESTRIAL:
599 		p = strchr(str, 'P');
600 		if (p) {
601 			em_device.delsys = SYS_DVBT2;
602 			sscanf(p + 1, "%u", &args[0]);
603 			em_device.stream_id = args[0];
604 		} else {
605 			em_device.delsys = SYS_DVBT;
606 			em_device.stream_id = 0;
607 		}
608 		sscanf(str, "%8s f = %6d kHz I%uB%uC%uD%uT%uG%uY%u",
609 		       mbuf, &args[0], &args[1], &args[2], &args[3], &args[4],
610 		       &args[5], &args[6], &args[7]);
611 
612 		if (strncmp(mbuf, "QPSK", 4) == 0)
613 			em_device.modulation = QPSK;
614 		else if (strncmp(mbuf, "QAM_16", 6) == 0)
615 			em_device.modulation = QAM_16;
616 		else if (strncmp(mbuf, "QAM_64", 6) == 0)
617 			em_device.modulation = QAM_64;
618 		else if (strncmp(mbuf, "QAM_256", 7) == 0)
619 			em_device.modulation = QAM_256;
620 		else
621 			em_device.modulation = QAM_AUTO;
622 		em_device.frequency = 1000 * args[0];
623 		switch (args[1]) {
624 		case 0:
625 			em_device.inversion = INVERSION_OFF;
626 			break;
627 		case 1:
628 			em_device.inversion = INVERSION_ON;
629 			break;
630 		default:
631 			em_device.inversion = INVERSION_AUTO;
632 		}
633 		switch (args[2]) {
634 		case 5 ... 10:
635 			em_device.bandwidth_hz = args[2] * MHz;
636 			break;
637 		case 1712:
638 			em_device.bandwidth_hz = args[2] * kHz;
639 			break;
640 		default:
641 			em_device.bandwidth_hz = 8 * MHz;
642 		}
643 		switch (args[3]) {
644 		case 0:
645 			em_device.fec = FEC_NONE;
646 			break;
647 		case 12:
648 			em_device.fec = FEC_1_2;
649 			break;
650 		case 23:
651 			em_device.fec = FEC_2_3;
652 			break;
653 		case 34:
654 			em_device.fec = FEC_3_4;
655 			break;
656 		case 45:
657 			em_device.fec = FEC_4_5;
658 			break;
659 		case 56:
660 			em_device.fec = FEC_5_6;
661 			break;
662 		case 67:
663 			em_device.fec = FEC_6_7;
664 			break;
665 		case 78:
666 			em_device.fec = FEC_7_8;
667 			break;
668 		case 89:
669 			em_device.fec = FEC_8_9;
670 			break;
671 		case 35:
672 			em_device.fec = FEC_3_5;
673 			break;
674 		case 910:
675 			em_device.fec = FEC_9_10;
676 			break;
677 		default:
678 			em_device.fec = FEC_AUTO;
679 			break;
680 		}
681 		switch (args[5]) {
682 		case 2:
683 			em_device.transmission = TRANSMISSION_MODE_2K;
684 			break;
685 		case 8:
686 			em_device.transmission = TRANSMISSION_MODE_8K;
687 			break;
688 		case 4:
689 			em_device.transmission = TRANSMISSION_MODE_4K;
690 			break;
691 		case 1:
692 			em_device.transmission = TRANSMISSION_MODE_1K;
693 			break;
694 		case 16:
695 			em_device.transmission = TRANSMISSION_MODE_16K;
696 			break;
697 		case 32:
698 			em_device.transmission = TRANSMISSION_MODE_32K;
699 			break;
700 		default:
701 			em_device.transmission = TRANSMISSION_MODE_AUTO;
702 			break;
703 		}
704 		switch (args[6]) {
705 		case 32:
706 			em_device.guard = GUARD_INTERVAL_1_32;
707 			break;
708 		case 16:
709 			em_device.guard = GUARD_INTERVAL_1_16;
710 			break;
711 		case 8:
712 			em_device.guard = GUARD_INTERVAL_1_8;
713 			break;
714 		case 4:
715 			em_device.guard = GUARD_INTERVAL_1_4;
716 			break;
717 		case 128:
718 			em_device.guard = GUARD_INTERVAL_1_128;
719 			break;
720 		case 19128:
721 			em_device.guard = GUARD_INTERVAL_19_128;
722 			break;
723 		case 19256:
724 			em_device.guard = GUARD_INTERVAL_19_256;
725 			break;
726 		default:
727 			em_device.guard = GUARD_INTERVAL_AUTO;
728 			break;
729 		}
730 		switch (args[7]) {
731 		case 0:
732 			em_device.hierarchy = HIERARCHY_NONE;
733 			break;
734 		case 1:
735 			em_device.hierarchy = HIERARCHY_1;
736 			break;
737 		case 2:
738 			em_device.hierarchy = HIERARCHY_2;
739 			break;
740 		case 4:
741 			em_device.hierarchy = HIERARCHY_4;
742 			break;
743 		default:
744 			em_device.hierarchy = HIERARCHY_AUTO;
745 			break;
746 		}
747 		if (em_device.delsys == SYS_DVBT2)
748 			sprintf(mbuf, "P%d", em_device.stream_id);
749 		else
750 			mbuf[0] = 0;
751 		//EM_INFO("%s: '%-55s' -> %-8s f = %6d kHz I%sB%sC%sD%sT%sG%sY%s%s\n", \
752 		//    __FUNCTION__, str,                                               \
753 		//    xine_modulation_name(em_device.modulation),                      \
754 		//    freq_scale(em_device.frequency, 1e-3),                           \
755 		//    vdr_inversion_name(em_device.inversion),                         \
756 		//    vdr_bandwidth_name(em_device.bandwidth_hz),                      \
757 		//    vdr_fec_name(em_device.fec),                                     \
758 		//    vdr_fec_name(FEC_NONE),                                          \
759 		//    vdr_transmission_mode_name(em_device.transmission),              \
760 		//    vdr_guard_name(em_device.guard),                                 \
761 		//    vdr_hierarchy_name(em_device.hierarchy),                         \
762 		//    mbuf);
763 		break;
764 	case SCAN_TERRCABLE_ATSC:
765 		sscanf(str, "%8s f=%u kHz ", mbuf, &args[0]);
766 		if (strncmp(mbuf, "QAM64", 5) == 0)
767 			em_device.modulation = QAM_64;
768 		else if (strncmp(mbuf, "QAM256", 6) == 0)
769 			em_device.modulation = QAM_256;
770 		else if (strncmp(mbuf, "8VSB", 4) == 0)
771 			em_device.modulation = VSB_8;
772 		else if (strncmp(mbuf, "16VSB", 5) == 0)
773 			em_device.modulation = VSB_16;
774 		else
775 			em_device.modulation = QAM_AUTO;
776 		em_device.frequency = 1000 * args[0];
777 		//EM_INFO("%s: '%-55s' -> %-8s f=%d kHz\n",  \
778 		//    __FUNCTION__, str,                     \
779 		//    atsc_mod_to_txt(em_device.modulation), \
780 		//    freq_scale(em_device.frequency, 1e-3));
781 		break;
782 	case SCAN_CABLE:
783 		sscanf(str, "%8s f = %u kHz S%uC%u  ", mbuf, &args[0], &args[1],
784 		       &args[2]);
785 		if (strncmp(mbuf, "QAM_16", 6) == 0)
786 			em_device.modulation = QAM_16;
787 		else if (strncmp(mbuf, "QAM_32", 6) == 0)
788 			em_device.modulation = QAM_32;
789 		else if (strncmp(mbuf, "QAM_64", 6) == 0)
790 			em_device.modulation = QAM_64;
791 		else if (strncmp(mbuf, "QAM_128", 7) == 0)
792 			em_device.modulation = QAM_128;
793 		else if (strncmp(mbuf, "QAM_256", 7) == 0)
794 			em_device.modulation = QAM_256;
795 		else
796 			em_device.modulation = QAM_AUTO;
797 		em_device.frequency = 1000 * args[0];
798 		em_device.symbolrate = 1000 * args[1];
799 		em_device.fec = FEC_NONE;
800 		//EM_INFO("%s: '%-55s' -> %-8s f = %d kHz S%dC%s\n", \
801 		//    __FUNCTION__, str,                             \
802 		//    xine_modulation_name(em_device.modulation),    \
803 		//    freq_scale(em_device.frequency, 1e-3),         \
804 		//    freq_scale(em_device.symbol_rate, 1e-3),         \
805 		//    vdr_fec_name(FEC_NONE));
806 		break;
807 	case SCAN_SATELLITE:
808 		em_device.delsys = SYS_DVBS;
809 		em_device.rolloff = ROLLOFF_AUTO;
810 		em_device.pilot = PILOT_AUTO;
811 		if (strlen(str) > 2)
812 			if (str[1] == '2')
813 				em_device.delsys = SYS_DVBS2;
814 		p = strchr(str, 'f');
815 		if (!p || !*p)
816 			return 0;
817 		sscanf(p, "f = %u kHz %c SR = %5d %4s 0,%s %5s ", &args[0], &c,
818 		       &args[1], fecbuf, robuf, mbuf);
819 		em_device.frequency = 1000 * args[0];
820 		if (c == 'V')
821 			em_device.polarization = POLARIZATION_VERTICAL;
822 		else if (c == 'R')
823 			em_device.polarization = POLARIZATION_CIRCULAR_RIGHT;
824 		else if (c == 'L')
825 			em_device.polarization = POLARIZATION_CIRCULAR_LEFT;
826 		else
827 			em_device.polarization = POLARIZATION_HORIZONTAL;
828 		em_device.symbolrate = 1000 * args[1];
829 		if (strncmp(fecbuf, "NONE", 4) == 0)
830 			em_device.fec = FEC_NONE;
831 		else if (strncmp(fecbuf, "1/2", 3) == 0)
832 			em_device.fec = FEC_1_2;
833 		else if (strncmp(fecbuf, "2/3", 3) == 0)
834 			em_device.fec = FEC_2_3;
835 		else if (strncmp(fecbuf, "3/4", 3) == 0)
836 			em_device.fec = FEC_3_4;
837 		else if (strncmp(fecbuf, "4/5", 3) == 0)
838 			em_device.fec = FEC_4_5;
839 		else if (strncmp(fecbuf, "5/6", 3) == 0)
840 			em_device.fec = FEC_5_6;
841 		else if (strncmp(fecbuf, "6/7", 3) == 0)
842 			em_device.fec = FEC_6_7;
843 		else if (strncmp(fecbuf, "7/8", 3) == 0)
844 			em_device.fec = FEC_7_8;
845 		else if (strncmp(fecbuf, "8/9", 3) == 0)
846 			em_device.fec = FEC_8_9;
847 		else if (strncmp(fecbuf, "3/5", 3) == 0)
848 			em_device.fec = FEC_3_5;
849 		else if (strncmp(fecbuf, "9/10", 4) == 0)
850 			em_device.fec = FEC_9_10;
851 		else if (strncmp(fecbuf, "AUTO", 4) == 0)
852 			em_device.fec = FEC_AUTO;
853 		else
854 			em_device.fec = FEC_AUTO;
855 		if (strncmp(robuf, "35", 2) == 0)
856 			em_device.rolloff = ROLLOFF_35;
857 		else if (strncmp(robuf, "25", 2) == 0)
858 			em_device.rolloff = ROLLOFF_25;
859 		else if (strncmp(robuf, "20", 2) == 0)
860 			em_device.rolloff = ROLLOFF_20;
861 		else if (strncmp(robuf, "AUTO", 4) == 0)
862 			em_device.rolloff = ROLLOFF_35;
863 		else
864 			em_device.rolloff = ROLLOFF_35;
865 		if (strncmp(mbuf, "QPSK", 4) == 0)
866 			em_device.modulation = QPSK;
867 		else if (strncmp(mbuf, "8PSK", 4) == 0)
868 			em_device.modulation = PSK_8;
869 		else if (strncmp(mbuf, "16APSK", 6) == 0)
870 			em_device.modulation = APSK_16;
871 		else if (strncmp(mbuf, "32APSK", 6) == 0)
872 			em_device.modulation = APSK_32;
873 		else
874 			em_device.modulation = QPSK;
875 		EM_INFO
876 		    ("%s: '%-55s' -> %-2s f = %d kHz %s SR = %5d %4s 0,%s %5s\n",
877 		     __FUNCTION__, str,
878 		     sat_delivery_system_to_txt(em_device.delsys),
879 		     freq_scale(em_device.frequency, 1e-3),
880 		     sat_pol_to_txt(em_device.polarization),
881 		     freq_scale(em_device.symbolrate, 1e-3),
882 		     sat_fec_to_txt(em_device.fec),
883 		     sat_rolloff_to_txt(em_device.rolloff),
884 		     sat_mod_to_txt(em_device.modulation));
885 		break;
886 	default:
887 		fatal("could not find scan type for '%s'\n", str);
888 	}
889 	return 1;		//success.
890 }
891 
parse_intro(uint16_t table_id,const char * str,uint16_t * i1,uint16_t * i2)892 static void parse_intro(uint16_t table_id, const char *str, uint16_t * i1,
893 			uint16_t * i2)
894 {
895 	unsigned tmp;
896 	switch (table_id) {
897 	case TABLE_PAT:
898 		sscanf(str, "PAT (xxxx:xxxx:%hu)", i1);
899 		break;
900 	case TABLE_NIT_ACT:
901 		sscanf(str, "NIT(act): (xxxx:%hu:xxxx)", i1);
902 		break;
903 	case TABLE_NIT_OTH:
904 		sscanf(str, "NIT(oth): (xxxx:%hu:xxxx)", i1);
905 		break;
906 	case TABLE_SDT_ACT:
907 		sscanf(str, "SDT(actual TS, transport_stream_id %hu ", i1);
908 		break;
909 	case TABLE_SDT_OTH:
910 		sscanf(str, "SDT(other TS, transport_stream_id %hu ", i1);
911 		break;
912 	case TABLE_PMT:
913 		sscanf(str, "PMT %hu (0x%04x) for service %hu ", i1, &tmp, i2);
914 		break;
915 	default:;
916 	}
917 	//EM_INFO("table_id = %x -> %d %d\n", table_id, *i1, i2?*i2:-1);
918 }
919 
parse_logfile(const char * log)920 static int parse_logfile(const char *log)
921 {
922 	FILE *logfile = NULL;
923 	char *line = (char *)calloc(1, 256);
924 	char *p;
925 	int pid = 0, table_id = -1, len = 0, line_no = 0;
926 	uint16_t original_network_id = 0, network_id = 0, transport_stream_id =
927 	    0;
928 	uint16_t service_id = 0, pmt_pid = 0;
929 	int dev_props = 0;
930 	sidata_t *sidata = NULL;
931 	bool delsys_list = false;
932 	em_device.scantype = SCAN_UNDEFINED;
933 	em_device.w_scan_version = em_device.w_scan_flags = 0;	// logging w_scan's version.
934 
935 	if (!log || !*log) {
936 		free(line);
937 		error("could not open logfile: invalid file name.\n");
938 		return 0;	// err
939 	}
940 
941 	logfile = fopen(log, "r");
942 	if (!logfile) {
943 		free(line);
944 		fatal("cannot open '%s': error %d %s\n", log, errno,
945 		      strerror(errno));
946 		return 0;	// err
947 	}
948 
949 	while (fgets(line, 256, logfile) != NULL) {
950 		bool is_tp = false;
951 		line_no++;
952 
953 		// --- get logging w_scan's version -------------------------------------------------------------------------------
954 		if (!em_device.w_scan_version) {
955 			sscanf(line,
956 			       "w_scan version %u (compiled for DVB API 5.xx)",
957 			       &em_device.w_scan_version);
958 			EM_INFO("detected w_scan version %u\n",
959 				em_device.w_scan_version);
960 			if (em_device.w_scan_version
961 			    && (em_device.w_scan_version < 20140614)) {
962 				EM_INFO("using flag EM_OLD_DELSYSLIST\n");
963 				em_device.w_scan_flags |= EM_OLD_DELSYSLIST;
964 			}
965 			if (em_device.w_scan_version
966 			    && (em_device.w_scan_version < 20140529)) {
967 				EM_INFO("using flag EM_OLD_SI_HEADER\n");
968 				em_device.w_scan_flags |= EM_OLD_SI_HEADER;
969 			}
970 			if (em_device.w_scan_version
971 			    && (em_device.w_scan_version < 20140423)) {
972 				EM_INFO("using flag EM_OLD_APIDISP\n");
973 				em_device.w_scan_flags |= EM_OLD_APIDISP;
974 				EM_INFO("using flag EM_OLD_APIDISP\n");
975 				em_device.w_scan_flags |= EM_HEXDUMP_BUG;
976 			}
977 			continue;
978 		}
979 		// --- end logging w_scan's version -------------------------------------------------------------------------------
980 
981 		// --- get scan type ----------------------------------------------------------------------------------------------
982 		if (em_device.scantype == SCAN_UNDEFINED) {
983 			if (strstr(line, "scan type")) {
984 				if (strstr(line, "CABLE"))
985 					em_device.scantype = SCAN_CABLE;
986 				else if (strstr(line, "SATELLITE"))
987 					em_device.scantype = SCAN_SATELLITE;
988 				else if (strstr(line, "TERRCABLE_ATSC"))
989 					em_device.scantype =
990 					    SCAN_TERRCABLE_ATSC;
991 				else if (strstr(line, "TERRESTRIAL"))
992 					em_device.scantype = SCAN_TERRESTRIAL;
993 				else
994 					fatal
995 					    ("cannot read scan type from '%s'\n",
996 					     line);
997 			}
998 			continue;	// anything else is meaningless until this is known.
999 		}
1000 		// --- end scan type ----------------------------------------------------------------------------------------------
1001 
1002 		// --- get the properties of dvb device ---------------------------------------------------------------------------
1003 		if (dev_props < 2) {
1004 			float fmin, fmax;
1005 			if (strstr
1006 			    (line,
1007 			     "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_"))
1008 			{
1009 				dev_props = 2;
1010 				continue;
1011 			}
1012 			if (strstr
1013 			    (line,
1014 			     "-_-_-_-_ Getting frontend capabilities-_-_-_-_"))
1015 			{
1016 				dev_props = 1;
1017 				continue;
1018 			}
1019 			if (dev_props != 1)
1020 				continue;
1021 
1022 			// used DVB API
1023 			if (strstr(line, "Using DVB API ")) {
1024 				if (em_device.w_scan_flags & EM_OLD_APIDISP) {
1025 					sscanf(line, "Using DVB API %x.%x",
1026 					       &em_api.major, &em_api.minor);
1027 				} else {
1028 					sscanf(line, "Using DVB API %u.%u",
1029 					       &em_api.major, &em_api.minor);
1030 				}
1031 				continue;
1032 			}
1033 			// capabilities: frontend name
1034 			if ((p = strstr(line, "frontend "))
1035 			    && strstr(line, " supports")) {
1036 				char *pEnd;
1037 				p += 10;
1038 				pEnd = strchr(p, 39);
1039 				*pEnd = 0;
1040 				strncpy(&em_device.fe_info.name[0], p, 128);
1041 				em_device.T2_delsys_bug =
1042 				    strstr(em_device.fe_info.name,
1043 					   "CXD2820R") != NULL;
1044 				continue;
1045 			}
1046 			// all other capabilities.
1047 			if (em_device.scantype == SCAN_TERRESTRIAL) {
1048 				if (strstr(line, "DVB-T2"))
1049 					em_device.fe_info.caps |=
1050 					    FE_CAN_2G_MODULATION;
1051 				if (strstr(line, "INVERSION_AUTO")
1052 				    && (strstr(line, "not supported") == NULL))
1053 					em_device.fe_info.caps |=
1054 					    FE_CAN_INVERSION_AUTO;
1055 				if (strstr(line, "QAM_AUTO")
1056 				    && (strstr(line, "not supported") == NULL))
1057 					em_device.fe_info.caps |=
1058 					    FE_CAN_QAM_AUTO;
1059 				if (strstr(line, "TRANSMISSION_MODE_AUTO")
1060 				    && (strstr(line, "not supported") == NULL))
1061 					em_device.fe_info.caps |=
1062 					    FE_CAN_TRANSMISSION_MODE_AUTO;
1063 				if (strstr(line, "GUARD_INTERVAL_AUTO")
1064 				    && (strstr(line, "not supported") == NULL))
1065 					em_device.fe_info.caps |=
1066 					    FE_CAN_GUARD_INTERVAL_AUTO;
1067 				if (strstr(line, "HIERARCHY_AUTO")
1068 				    && (strstr(line, "not supported") == NULL))
1069 					em_device.fe_info.caps |=
1070 					    FE_CAN_HIERARCHY_AUTO;
1071 				if (strstr(line, "FEC_AUTO")
1072 				    && (strstr(line, "not supported") == NULL))
1073 					em_device.fe_info.caps |=
1074 					    FE_CAN_FEC_AUTO;
1075 				if (sscanf
1076 				    (line, "FREQ (%fMHz ... %fMHz)", &fmin,
1077 				     &fmax) == 2) {
1078 					em_device.fe_info.frequency_min =
1079 					    (0.5 + fmin * MHz);
1080 					em_device.fe_info.frequency_max =
1081 					    (0.5 + fmax * MHz);
1082 				}
1083 				continue;
1084 			} else if (em_device.scantype == SCAN_CABLE) {
1085 				if (strstr(line, "DVB-C2"))
1086 					em_device.fe_info.caps |=
1087 					    FE_CAN_2G_MODULATION;
1088 				if (strstr(line, "INVERSION_AUTO")
1089 				    && (strstr(line, "not supported") == NULL))
1090 					em_device.fe_info.caps |=
1091 					    FE_CAN_INVERSION_AUTO;
1092 				if (strstr(line, "QAM_AUTO")
1093 				    && (strstr(line, "not supported") == NULL))
1094 					em_device.fe_info.caps |=
1095 					    FE_CAN_QAM_AUTO;
1096 				if (strstr(line, "FEC_AUTO")
1097 				    && (strstr(line, "not supported") == NULL))
1098 					em_device.fe_info.caps |=
1099 					    FE_CAN_FEC_AUTO;
1100 				if (sscanf
1101 				    (line, "FREQ (%fMHz ... %fMHz)", &fmin,
1102 				     &fmax) == 2) {
1103 					em_device.fe_info.frequency_min =
1104 					    (0.5 + fmin * MHz);
1105 					em_device.fe_info.frequency_max =
1106 					    (0.5 + fmax * MHz);
1107 				}
1108 				if (sscanf
1109 				    (line, "SRATE (%fMSym/s ... %fMSym/s)",
1110 				     &fmin, &fmax) == 2) {
1111 					em_device.fe_info.symbol_rate_min =
1112 					    (0.5 + fmin * MHz);
1113 					em_device.fe_info.symbol_rate_max =
1114 					    (0.5 + fmax * MHz);
1115 				}
1116 				continue;
1117 			} else if (em_device.scantype == SCAN_TERRCABLE_ATSC) {
1118 				if (strstr(line, "INVERSION_AUTO")
1119 				    && (strstr(line, "not supported") == NULL))
1120 					em_device.fe_info.caps |=
1121 					    FE_CAN_INVERSION_AUTO;
1122 				if (strstr(line, "8VSB"))
1123 					em_device.fe_info.caps |= FE_CAN_8VSB;
1124 				if (strstr(line, "16VSB"))
1125 					em_device.fe_info.caps |= FE_CAN_16VSB;
1126 				if (strstr(line, "QAM_64"))
1127 					em_device.fe_info.caps |= FE_CAN_QAM_64;
1128 				if (strstr(line, "QAM_256"))
1129 					em_device.fe_info.caps |=
1130 					    FE_CAN_QAM_256;
1131 				if (sscanf
1132 				    (line, "FREQ (%fMHz ... %fMHz)", &fmin,
1133 				     &fmax) == 2) {
1134 					em_device.fe_info.frequency_min =
1135 					    (0.5 + fmin * MHz);
1136 					em_device.fe_info.frequency_max =
1137 					    (0.5 + fmax * MHz);
1138 				}
1139 				continue;
1140 			} else if (em_device.scantype == SCAN_SATELLITE) {
1141 				if (strstr(line, "QAM_AUTO")
1142 				    && (strstr(line, "not supported") == NULL))
1143 					em_device.fe_info.caps |=
1144 					    FE_CAN_QAM_AUTO;
1145 				if (strstr(line, "DVB-S2")
1146 				    && (strstr(line, "not supported") == NULL))
1147 					em_device.fe_info.caps |=
1148 					    FE_CAN_2G_MODULATION;
1149 				if (strstr(line, "DVB-S")
1150 				    && (strstr(line, "not supported") == NULL))
1151 					em_device.fe_info.caps |= FE_CAN_QPSK;
1152 				if (sscanf
1153 				    (line, "FREQ (%fGHz ... %fGHz)", &fmin,
1154 				     &fmax) == 2) {
1155 					em_device.fe_info.frequency_min =
1156 					    (0.5 + fmin * MHz);
1157 					em_device.fe_info.frequency_max =
1158 					    (0.5 + fmax * MHz);
1159 				}
1160 				if (sscanf
1161 				    (line, "SRATE (%fMSym/s ... %fMSym/s)",
1162 				     &fmin, &fmax) == 2) {
1163 					em_device.fe_info.symbol_rate_min =
1164 					    (0.5 + fmin * MHz);
1165 					em_device.fe_info.symbol_rate_max =
1166 					    (0.5 + fmax * MHz);
1167 				}
1168 				continue;
1169 			} else
1170 				fatal
1171 				    ("unsupported frontend type, cannot parse '%s'\n",
1172 				     line);
1173 		}
1174 
1175 		if (em_device.w_scan_flags & EM_OLD_DELSYSLIST) {
1176 			EM_INFO("%d: lookup oldstyle delsys hex array\n",
1177 				line_no);
1178 			if (strstr(line, "=====================") == NULL) {
1179 				info("skip line %d: '%s'\n", line_no, line);
1180 			} else {
1181 				int len = 0;
1182 				unsigned tmp, args[16];
1183 				//EM_INFO("lookup oldstyle delsys hex array: started\n");
1184 
1185 				while (fgets(line, 256, logfile) != NULL) {
1186 					EM_INFO("checking line '%s'", line);
1187 					line_no++;
1188 					if (strstr
1189 					    (line,
1190 					     "	======================"))
1191 						continue;
1192 					if (!len) {
1193 						sscanf(line, "	len = %d",
1194 						       &len);
1195 						continue;
1196 					}
1197 					if (len) {
1198 						int i;
1199 						int nitems = sscanf(line,
1200 								    "	0x%X: %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X :",
1201 								    &tmp,
1202 								    &args[0],
1203 								    &args[1],
1204 								    &args[2],
1205 								    &args[3],
1206 								    &args[4],
1207 								    &args[5],
1208 								    &args[6],
1209 								    &args[7],
1210 								    &args[8],
1211 								    &args[9],
1212 								    &args[10],
1213 								    &args[11],
1214 								    &args[12],
1215 								    &args[13],
1216 								    &args[14],
1217 								    &args[15]);
1218 						EM_INFO("nitems = %d\n",
1219 							nitems);
1220 						if (!nitems)
1221 							continue;
1222 						for (i = 0; i < len; i++)
1223 							em_device.delsystems
1224 							    [em_device.ndelsystems++]
1225 							    =
1226 							    (fe_delivery_system_t)
1227 							    args[i];
1228 						//for(i=0; i<em_device.ndelsystems; i++)
1229 						//   info("delsys %d\n", em_device.delsystems[i]);
1230 						break;
1231 					}
1232 				}
1233 				em_device.w_scan_flags &= ~EM_OLD_DELSYSLIST;
1234 			}
1235 			continue;
1236 		}
1237 		if ((p = strstr(line, "   check ")) != NULL) {
1238 			delsys_list = true;
1239 			continue;
1240 		}
1241 		if (delsys_list) {
1242 			const char *dname[] = {
1243 				"UNDEFINED", "DVB-C ann.A", "DVB-C ann.B",
1244 				"DVB-T", "DSS", "DVB-S", "DVB-S2", "DVB-H",
1245 				"ISDB-T", "ISDB-S",
1246 				"ISDB-C", "ATSC", "ATSC/MH", "DTMB", "CMMB",
1247 				"DAB", "DVB-T2", "TURBO-FEC", "DVB-C ann.C"
1248 			};
1249 			uint8_t i = 0;
1250 			bool delsys = false;
1251 			p = strchr(line, '\n');
1252 			if (p)
1253 				*p = 0;
1254 			p = line;
1255 			while (p && isspace(*p))
1256 				p++;
1257 
1258 			for (i = 0; i < sizeof(dname) / sizeof(dname[0]); i++) {
1259 				//EM_INFO("'%s' = '%s'?\n",p,dname[i]);
1260 				if (strncmp(p, dname[i], strlen(p)) == 0) {
1261 					em_device.delsystems[em_device.
1262 							     ndelsystems++]
1263 					    = (fe_delivery_system_t) i;
1264 					delsys = true;
1265 					break;
1266 				}
1267 			}
1268 			if (delsys)
1269 				continue;
1270 			else
1271 				delsys_list = false;
1272 		}
1273 
1274 		if (dev_props != 2)
1275 			continue;	// continue only after frontend reading.
1276 		// --- end of dvb device ------------------------------------------------------------------------------------------
1277 
1278 		// --- we tuned to a new transponder. all si data belongs to this new tp ------------------------------------------
1279 		if (strncmp(line, "        signal ok:	", 19) == 0)
1280 			is_tp = true;	// '        signal ok:        <FOOBAR>'
1281 		if (strncmp(line, "tune to: ", 9) == 0)
1282 			is_tp = true;	// 'tune to: <FOOBAR>'
1283 		if (strncmp(line, "signal ok:", 10) == 0) {
1284 			if (fgets(line, 256, logfile) != NULL) {
1285 				*line = ':';
1286 			}
1287 			line_no++;
1288 			is_tp = true;
1289 		}
1290 		if (is_tp) {
1291 			char *p = strchr(line, ':');
1292 			p++;
1293 			while (isspace(*p))
1294 				p++;
1295 			parse_tp(p);
1296 			table_id = -1;
1297 			continue;
1298 		}
1299 		// --- end of tp reading ------------------------------------------------------------------------------------------
1300 
1301 		// --- we got data from demux. first: intro with table_id_ext -----------------------------------------------------
1302 		if (strstr(line, "no data from"))
1303 			continue;
1304 		if ((p = strstr(line, "PAT (xxxx:xxxx:")) != NULL) {
1305 			table_id = TABLE_PAT;
1306 			parse_intro(table_id, p, &transport_stream_id, 0);
1307 			pid = PID_PAT;
1308 			continue;
1309 		}
1310 		if ((p = strstr(line, "NIT(act): (xxxx:")) != NULL) {
1311 			table_id = TABLE_NIT_ACT;
1312 			parse_intro(table_id, p, &network_id, 0);
1313 			pid = PID_NIT_ST;
1314 			continue;
1315 		}
1316 		if ((p = strstr(line, "NIT(oth): (xxxx:")) != NULL) {
1317 			table_id = TABLE_NIT_OTH;
1318 			parse_intro(table_id, p, &network_id, 0);
1319 			pid = PID_NIT_ST;
1320 			continue;
1321 		}
1322 		if ((p = strstr(line, "SDT(act")) != NULL) {
1323 			table_id = TABLE_SDT_ACT;
1324 			parse_intro(table_id, p, &transport_stream_id, 0);
1325 			pid = PID_SDT_BAT_ST;
1326 			continue;
1327 		}
1328 		if ((p = strstr(line, "SDT(oth")) != NULL) {
1329 			table_id = TABLE_SDT_OTH;
1330 			parse_intro(table_id, p, &transport_stream_id, 0);
1331 			pid = PID_SDT_BAT_ST;
1332 			continue;
1333 		}
1334 		if ((p = strstr(line, "PMT ")) != NULL) {
1335 			table_id = TABLE_PMT;
1336 			parse_intro(table_id, p, &pmt_pid, &service_id);
1337 			pid = pmt_pid;
1338 			continue;
1339 		}
1340 
1341 		if ((em_device.w_scan_flags & EM_OLD_SI_HEADER)
1342 		    && !strncmp(line, "parse_section", 13)) {
1343 			unsigned args[9];
1344 			int nargs, tmp;
1345 //                            parse_section:1376: pid 0x10 tid 0x40 table_id_ext 0x0056, 2/3 (version 16)
1346 //                            parse_section:1376: pid 17 (0x11), tid 66 (0x42), table_id_ext 30 (0x001e), section_number 0, last_section_number 0, version 3\n"
1347 			nargs = sscanf(line, "parse_section:%d: pid %x tid %x table_id_ext %x, %i/%i (version %i)",	//",
1348 				       &tmp, &args[0], &args[1], &args[2], &args[3], &args[4], &args[5]);	//);
1349 			if (nargs != 7)
1350 				nargs =
1351 				    sscanf(line,
1352 					   "parse_section:%d: pid %d (%x), tid %d (%x), table_id_ext %d (%x), section_number %i, last_section_number %i, version %i\n",
1353 					   &tmp, &args[0], &args[1], &args[2],
1354 					   &args[3], &args[4], &args[5],
1355 					   &args[6], &args[7], &args[8]);
1356 			//if (nargs) info("found %d args---------\n", nargs);
1357 			if ((nargs == 7) || (nargs == 10)) {
1358 				EM_INFO("found table. nargs = %d\n", nargs);
1359 				table_id =
1360 				    (nargs == 7) ? (int)args[1] : (nargs ==
1361 								   10) ? (int)
1362 				    args[2] : table_id;
1363 				switch (table_id) {
1364 				case TABLE_PAT:
1365 					transport_stream_id =
1366 					    (nargs ==
1367 					     7) ? (int)args[2] : (nargs ==
1368 								  10) ? (int)
1369 					    args[4] : transport_stream_id;
1370 					break;
1371 				case TABLE_NIT_ACT:
1372 				case TABLE_NIT_OTH:
1373 					network_id =
1374 					    (nargs ==
1375 					     7) ? (int)args[2] : (nargs ==
1376 								  10) ? (int)
1377 					    args[4] : network_id;
1378 					break;
1379 				case TABLE_SDT_ACT:
1380 				case TABLE_SDT_OTH:
1381 					transport_stream_id =
1382 					    (nargs ==
1383 					     7) ? (int)args[2] : (nargs ==
1384 								  10) ? (int)
1385 					    args[4] : transport_stream_id;
1386 					break;
1387 				case TABLE_PMT:
1388 					pmt_pid = ((nargs == 7)
1389 						   || (nargs ==
1390 						       10)) ? (int)args[0] :
1391 					    pmt_pid;
1392 					service_id =
1393 					    (nargs ==
1394 					     7) ? (int)args[2] : (nargs ==
1395 								  10) ? (int)
1396 					    args[4] : service_id;
1397 					break;
1398 				default:
1399 					info("invalid table id %d\n", table_id);
1400 				}
1401 				if (fgets(line, 256, logfile) != NULL) {
1402 					EM_INFO("next: %s\n", line);
1403 				}
1404 				line_no++;	//"NIT (act"
1405 				if (fgets(line, 256, logfile) != NULL) {
1406 					EM_INFO("next: %s\n", line);
1407 				}
1408 				line_no++;	//"       ===================== parse_"
1409 				if (fgets(line, 256, logfile) != NULL) {
1410 					EM_INFO("next: %s\n", line);
1411 				}
1412 				line_no++;	//"       len = "
1413 			}
1414 		}
1415 
1416 		if (strstr
1417 		    (line,
1418 		     "========================================================================"))
1419 		{
1420 			table_id = -1;
1421 			continue;
1422 		}
1423 		if (table_id < 0)
1424 			continue;	// we found something, which we cannot assign to any table.
1425 
1426 		if (strstr(line, "	len = ")) {
1427 			sscanf(line, "	len = %d", &len);
1428 			if (len > 0) {
1429 				sidata =
1430 				    (sidata_t *) calloc(1, sizeof(sidata_t));
1431 				sidata->t.frequency = em_device.frequency;
1432 				sidata->t.inversion = em_device.inversion;
1433 				switch (em_device.delsys) {
1434 				case SYS_DVBT:
1435 				case SYS_DVBT2:
1436 					sidata->t.type = SCAN_TERRESTRIAL;
1437 					sidata->t.bandwidth =
1438 					    em_device.bandwidth_hz;
1439 					sidata->t.coderate = em_device.fec;
1440 					sidata->t.coderate_LP = FEC_AUTO;
1441 					sidata->t.modulation =
1442 					    em_device.modulation;
1443 					sidata->t.transmission =
1444 					    em_device.transmission;
1445 					sidata->t.guard = em_device.guard;
1446 					sidata->t.hierarchy =
1447 					    em_device.hierarchy;
1448 					sidata->t.delsys = em_device.delsys;
1449 					break;
1450 				case SYS_DVBC_ANNEX_A:
1451 				case SYS_DVBC_ANNEX_C:
1452 					sidata->t.type = SCAN_CABLE;
1453 					sidata->t.delsys = em_device.delsys;
1454 					sidata->t.modulation =
1455 					    em_device.modulation;
1456 					sidata->t.symbolrate =
1457 					    em_device.symbolrate;
1458 					break;
1459 				case SYS_DVBS:
1460 				case SYS_DVBS2:
1461 					sidata->t.type = SCAN_SATELLITE;
1462 					sidata->t.rolloff = em_device.rolloff;
1463 					sidata->t.pilot = em_device.pilot;
1464 					sidata->t.delsys = em_device.delsys;
1465 					sidata->t.polarization =
1466 					    em_device.polarization;
1467 					sidata->t.coderate = em_device.fec;
1468 					sidata->t.symbolrate =
1469 					    em_device.symbolrate;
1470 					sidata->t.modulation =
1471 					    em_device.modulation;
1472 					break;
1473 				case SYS_ATSC:
1474 					sidata->t.type = SCAN_TERRCABLE_ATSC;
1475 				default:
1476 					fatal("unsupported del sys.\n");
1477 				}
1478 				sidata->pid = pid;
1479 				sidata->table_id = table_id;
1480 				sidata->original_network_id =
1481 				    original_network_id;
1482 				sidata->network_id = network_id;
1483 				sidata->transport_stream_id =
1484 				    transport_stream_id;
1485 				sidata->service_id = service_id;
1486 				switch (table_id) {
1487 				case TABLE_PAT:
1488 					sidata->table_id_ext =
1489 					    transport_stream_id;
1490 					break;
1491 				case TABLE_PMT:
1492 					sidata->table_id_ext = service_id;
1493 					sidata->pid = pmt_pid;
1494 					break;
1495 				case TABLE_NIT_ACT:
1496 				case TABLE_NIT_OTH:
1497 					sidata->table_id_ext = network_id;
1498 					break;
1499 				case TABLE_SDT_ACT:
1500 				case TABLE_SDT_OTH:
1501 					sidata->table_id_ext =
1502 					    transport_stream_id;
1503 					break;
1504 				default:
1505 					info("%s: no table id.\n",
1506 					     __FUNCTION__);
1507 				}
1508 				//EM_INFO("line %-5d: new sidata: table_id = %-8s, table_id_ext = %u, pid = %u (%u:%u:%u)\n", \
1509 				//     line_no,                                                                               \
1510 				//     sidata->table_id == TABLE_PAT    ?"PAT":                                               \
1511 				//     sidata->table_id == TABLE_NIT_ACT?"NIT(act)":                                          \
1512 				//     sidata->table_id == TABLE_NIT_OTH?"NIT(oth)":                                          \
1513 				//     sidata->table_id == TABLE_SDT_ACT?"SDT(act)":                                          \
1514 				//     sidata->table_id == TABLE_SDT_OTH?"SDT(oth)":                                          \
1515 				//     sidata->table_id == TABLE_PMT    ?"PMT":"---ERROR---" ,                                \
1516 				//     sidata->table_id_ext, sidata->pid,                                                     \
1517 				//     sidata->original_network_id, sidata->network_id, sidata->transport_stream_id);
1518 			}
1519 			continue;
1520 		}
1521 		if (strstr(line, "=== parse"))
1522 			continue;
1523 
1524 		if (!sidata)
1525 			fatal("%d: sidata invalid for table_id 0x%02x\n",
1526 			      line_no, table_id);
1527 		if (strlen(line) > 8) {
1528 			if ((p = strstr(line, "	0x")) != NULL) {
1529 				unsigned tmp, args[16];
1530 				int nitems = 0, i;
1531 				if (len > 0) {
1532 					p = strchr(line, '\n');
1533 					if (p)
1534 						*p = 0;
1535 
1536 					nitems =
1537 					    sscanf(line,
1538 						   "	0x%X: %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X :",
1539 						   &tmp, &args[0], &args[1],
1540 						   &args[2], &args[3], &args[4],
1541 						   &args[5], &args[6], &args[7],
1542 						   &args[8], &args[9],
1543 						   &args[10], &args[11],
1544 						   &args[12], &args[13],
1545 						   &args[14], &args[15]);
1546 					len -= (nitems - 1);
1547 					//EM_INFO("%d: '%-80s' (%d bytes left)\n", line_no, line, len);
1548 
1549 					for (i = 0; i < nitems - 1; i++)
1550 						sidata->buf[sidata->len++] =
1551 						    args[i];
1552 					if (len < 1) {
1553 						//info("line %d\n", line_no);
1554 						//switch(table_id) {
1555 						//   case TABLE_PAT:
1556 						//      info("PAT (xxxx:xxxx:%u)\n", transport_stream_id);
1557 						//      break;
1558 						//   case TABLE_NIT_ACT:
1559 						//   case TABLE_NIT_OTH:
1560 						//      info("%s: (xxxx:%u:xxxx)\n", table_id == 0x40?"NIT(act)":"NIT(oth)", network_id);
1561 						//      break;
1562 						//   case TABLE_SDT_ACT:
1563 						//   case TABLE_SDT_OTH:
1564 						//      info("SDT(%s TS, transport_stream_id %d (0x%04x) )\n", table_id == 0x42 ? "actual":"other",
1565 						//          transport_stream_id, transport_stream_id);
1566 						//      break;
1567 						//   case TABLE_PMT:
1568 						//      info("PMT %d (0x%04x) for service %d (0x%04x)\n", pid, pid, service_id, service_id);
1569 						//      break;
1570 						//   default:
1571 						//      info("??? unknown table_id %d\n", table_id);
1572 						//   }
1573 						if (em_device.
1574 						    w_scan_flags &
1575 						    EM_HEXDUMP_BUG) {
1576 							// each sections hexdump misses two bytes, because of bug in older versions. :(
1577 							// those are really lost in logfile && not recoverable.
1578 							sidata->buf[sidata->
1579 								    len++] = 0;
1580 							sidata->buf[sidata->
1581 								    len++] = 0;
1582 						}
1583 						//hexdump("sidata", &sidata->buf[0], sidata->len);
1584 						AddItem(em_sidata, sidata);
1585 						sidata = NULL;
1586 					}
1587 
1588 				}
1589 			}
1590 		}
1591 	}
1592 	fclose(logfile);
1593 	free(line);
1594 	return 1;
1595 }
1596