1 /*
2 * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
3 * Copyright (c) 2013 - Andre Roth <neolynx@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation version 2.1 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18 */
19
20 /******************************************************************************
21 * Parse DVB tables
22 * According with:
23 * ETSI EN 301 192 V1.5.1 (2009-11)
24 * ISO/IEC 13818-1:2007
25 * ETSI EN 300 468 V1.11.1 (2010-04)
26 *****************************************************************************/
27
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/ioctl.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <stdlib.h>
38 #include <sys/time.h>
39
40 #include "dvb-fe-priv.h"
41 #include <libdvbv5/dvb-scan.h>
42 #include <libdvbv5/dvb-frontend.h>
43 #include <libdvbv5/descriptors.h>
44 #include <libdvbv5/crc32.h>
45 #include <libdvbv5/dvb-file.h>
46 #include <libdvbv5/dvb-scan.h>
47 #include <libdvbv5/dvb-log.h>
48 #include <libdvbv5/dvb-demux.h>
49 #include <libdvbv5/descriptors.h>
50 #include <libdvbv5/header.h>
51 #include <libdvbv5/pat.h>
52 #include <libdvbv5/pmt.h>
53 #include <libdvbv5/nit.h>
54 #include <libdvbv5/sdt.h>
55 #include <libdvbv5/vct.h>
56 #include <libdvbv5/desc_extension.h>
57 #include <libdvbv5/desc_cable_delivery.h>
58 #include <libdvbv5/desc_isdbt_delivery.h>
59 #include <libdvbv5/desc_partial_reception.h>
60 #include <libdvbv5/desc_terrestrial_delivery.h>
61 #include <libdvbv5/desc_t2_delivery.h>
62 #include <libdvbv5/desc_sat.h>
63
64 #include <config.h>
65
66 #ifdef ENABLE_NLS
67 # include <stdio.h>
68 # include <libintl.h>
69 # define _(string) dgettext(LIBDVBV5_DOMAIN, string)
70
71 #else
72 # define _(string) string
73 #endif
74
75 # define N_(string) string
76
dvb_poll(struct dvb_v5_fe_parms_priv * parms,int fd,unsigned int seconds)77 static int dvb_poll(struct dvb_v5_fe_parms_priv *parms, int fd, unsigned int seconds)
78 {
79 fd_set set;
80 struct timeval timeout;
81 int ret;
82
83 /* Initialize the file descriptor set. */
84 FD_ZERO (&set);
85 FD_SET (fd, &set);
86
87 /* Initialize the timeout data structure. */
88 timeout.tv_sec = seconds;
89 timeout.tv_usec = 0;
90
91 /* `select' logfuncreturns 0 if timeout, 1 if input available, -1 if error. */
92 do ret = select (FD_SETSIZE, &set, NULL, NULL, &timeout);
93 while (!parms->p.abort && ret == -1 && errno == EINTR);
94
95 return ret;
96 }
97
dvb_read_section(struct dvb_v5_fe_parms * parms,int dmx_fd,unsigned char tid,uint16_t pid,void ** table,unsigned timeout)98 int dvb_read_section(struct dvb_v5_fe_parms *parms, int dmx_fd,
99 unsigned char tid, uint16_t pid, void **table,
100 unsigned timeout)
101 {
102 return dvb_read_section_with_id(parms, dmx_fd, tid, pid, -1, table, timeout);
103 }
104
105 /*
106 * The code below was inspired on Linux Kernel's bitmask implementation
107 */
108
109 #define BITS_PER_LONG (8 * sizeof(long))
110 #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
111 #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
112 #define BITS_TO_LONGS(nr) ((nr +BITS_PER_LONG - 1) / BITS_PER_LONG)
113
set_bit(int nr,unsigned long * addr)114 static void set_bit(int nr, unsigned long *addr)
115 {
116 unsigned long mask = BIT_MASK(nr);
117 unsigned long *p = addr + BIT_WORD(nr);
118
119 *p |= mask;
120 }
121
test_bit(int nr,unsigned long * addr)122 static int test_bit(int nr, unsigned long *addr)
123 {
124 unsigned long mask = BIT_MASK(nr);
125 unsigned long *p = addr + BIT_WORD(nr);
126
127 return (*p & mask) ? -1 : 0;
128 }
129
is_all_bits_set(int nr,unsigned long * addr)130 static int is_all_bits_set(int nr, unsigned long *addr)
131 {
132 unsigned long mask = BIT_MASK(nr + 1) - 1;
133
134 return (*addr == mask);
135 }
136
137
138 struct dvb_table_filter_ext_priv {
139 int last_section;
140 unsigned long is_read_bits[BITS_TO_LONGS(256)];
141
142 /* section gaps and multiple ts_id handling */
143 int ext_id;
144 int first_section;
145 int done;
146 };
147
148 struct dvb_table_filter_priv {
149 int num_extensions;
150 struct dvb_table_filter_ext_priv *extensions;
151 };
152
dvb_parse_section_alloc(struct dvb_v5_fe_parms_priv * parms,struct dvb_table_filter * sect)153 static int dvb_parse_section_alloc(struct dvb_v5_fe_parms_priv *parms,
154 struct dvb_table_filter *sect)
155 {
156 struct dvb_table_filter_priv *priv;
157
158 if (!sect->table) {
159 dvb_logerr(_("%s: table memory pointer not filled"),
160 __func__);
161 return -4;
162 }
163 *sect->table = NULL;
164 priv = calloc(sizeof(struct dvb_table_filter_priv), 1);
165 if (!priv) {
166 dvb_logerr(_("%s: out of memory"), __func__);
167 return -1;
168 }
169 sect->priv = priv;
170
171 return 0;
172 }
173
dvb_table_filter_free(struct dvb_table_filter * sect)174 void dvb_table_filter_free(struct dvb_table_filter *sect)
175 {
176 struct dvb_table_filter_priv *priv = sect->priv;
177
178 if (priv) {
179 free (priv->extensions);
180 free(priv);
181 sect->priv = NULL;
182 }
183 }
184
dvb_parse_section(struct dvb_v5_fe_parms_priv * parms,struct dvb_table_filter * sect,const uint8_t * buf,ssize_t buf_length)185 static int dvb_parse_section(struct dvb_v5_fe_parms_priv *parms,
186 struct dvb_table_filter *sect,
187 const uint8_t *buf, ssize_t buf_length)
188 {
189 struct dvb_table_header h;
190 struct dvb_table_filter_priv *priv;
191 struct dvb_table_filter_ext_priv *ext;
192 unsigned char tid;
193 int i = 0, new = 0;
194
195 memcpy(&h, buf, sizeof(struct dvb_table_header));
196 dvb_table_header_init(&h);
197
198 if (parms->p.verbose)
199 dvb_log(_("%s: received table 0x%02x, extension ID 0x%04x, section %d/%d"),
200 __func__, h.table_id, h.id, h.section_id, h.last_section);
201
202 if (sect->tid != h.table_id) {
203 dvb_logdbg(_("%s: couldn't match ID %d at the active section filters"),
204 __func__, h.table_id);
205 return -1;
206 }
207 priv = sect->priv;
208 ext = priv->extensions;
209 tid = h.table_id;
210
211 if (!ext) {
212 ext = calloc(sizeof(struct dvb_table_filter_ext_priv), 1);
213 if (!ext) {
214 dvb_logerr(_("%s: out of memory"), __func__);
215 return -1;
216 }
217 ext->ext_id = h.id;
218 ext->first_section = h.section_id;
219 ext->last_section = h.last_section;
220 priv->extensions = ext;
221 priv->num_extensions = 1;
222 new = 1;
223 } else {
224 /* search for an specific TS ID */
225 if (sect->ts_id != -1) {
226 if (h.id != sect->ts_id)
227 return 0;
228 }
229
230 for (i = 0; i < priv->num_extensions; i++, ext++) {
231 if (ext->ext_id == h.id)
232 break;
233 }
234 if (i == priv->num_extensions) {
235 priv->num_extensions++;
236 priv->extensions = realloc(priv->extensions, sizeof(struct dvb_table_filter_ext_priv) * (priv->num_extensions));
237 ext = priv->extensions;
238 if (!ext) {
239 dvb_logerr(_("%s: out of memory"), __func__);
240 return -1;
241 }
242 ext += i;
243 memset(ext, 0, sizeof(struct dvb_table_filter_ext_priv));
244 ext->ext_id = h.id;
245 ext->first_section = h.section_id;
246 ext->last_section = h.last_section;
247 new = 1;
248 }
249 }
250
251 if (!new) { /* Check if the table was already parsed, but not on first pass */
252 if(ext->done) {
253 if (parms->p.verbose)
254 dvb_log(_("%s: extension already done, ignoring: 0x%04x"), __func__, ext->ext_id);
255 return 0;
256 }
257
258 if (!sect->allow_section_gaps && sect->ts_id == -1) {
259 if (test_bit(h.section_id, ext->is_read_bits))
260 return 0;
261 } else if (ext->ext_id == h.id && ext->first_section == h.section_id) {
262 /* tables like EIT can increment sections by gaps > 1.
263 * in this case, reading is done when a already read
264 * table is reached.
265 */
266 if (parms->p.verbose)
267 dvb_log(_("%s: section repeated on table 0x%02x, extension ID 0x%04x, section %d/%d: done"),
268 __func__, h.table_id, ext->ext_id, h.section_id, h.last_section);
269
270 ext->done = 1;
271
272 goto ret;
273 }
274 }
275
276 /* handle the sections */
277 if (!sect->allow_section_gaps && sect->ts_id == -1)
278 set_bit(h.section_id, ext->is_read_bits);
279
280 if (dvb_table_initializers[tid])
281 dvb_table_initializers[tid](&parms->p, buf,
282 buf_length - DVB_CRC_SIZE,
283 sect->table);
284 else
285 dvb_logerr(_("%s: no initializer for table %d"),
286 __func__, tid);
287
288 if (!sect->allow_section_gaps && sect->ts_id == -1 &&
289 is_all_bits_set(ext->last_section, ext->is_read_bits)) {
290 if (parms->p.verbose)
291 dvb_log(_("%s: table 0x%02x, extension ID 0x%04x: done"),
292 __func__, h.table_id, h.id);
293 ext->done = 1;
294 }
295
296 if (!ext->done)
297 return 0;
298
299 ret:
300 /* Check if all extensions are done */
301 for (ext = priv->extensions, i = 0; i < priv->num_extensions; i++, ext++) {
302 if (!ext->done) {
303 if (parms->p.verbose)
304 dvb_log(_("%s: extension not completed yet: 0x%04x"),
305 __func__, ext->ext_id);
306 return 0;
307 }
308 }
309
310 /* Section was fully parsed */
311 return 1;
312 }
313
dvb_read_sections(struct dvb_v5_fe_parms * __p,int dmx_fd,struct dvb_table_filter * sect,unsigned timeout)314 int dvb_read_sections(struct dvb_v5_fe_parms *__p, int dmx_fd,
315 struct dvb_table_filter *sect,
316 unsigned timeout)
317 {
318 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
319 int ret;
320 uint8_t *buf = NULL;
321 uint8_t mask = 0xff;
322
323 ret = dvb_parse_section_alloc(parms, sect);
324 if (ret < 0)
325 return ret;
326
327 if (dvb_set_section_filter(dmx_fd, sect->pid, 1,
328 §->tid, &mask, NULL,
329 DMX_IMMEDIATE_START | DMX_CHECK_CRC)) {
330 dvb_dmx_stop(dmx_fd);
331 return -1;
332 }
333 if (parms->p.verbose)
334 dvb_log(_("%s: waiting for table ID 0x%02x, program ID 0x%02x"),
335 __func__, sect->tid, sect->pid);
336
337 buf = calloc(DVB_MAX_PAYLOAD_PACKET_SIZE, 1);
338 if (!buf) {
339 dvb_logerr(_("%s: out of memory"), __func__);
340 dvb_dmx_stop(dmx_fd);
341 dvb_table_filter_free(sect);
342 return -1;
343 }
344
345
346 do {
347 int available;
348 uint32_t crc;
349 ssize_t buf_length = 0;
350
351 do {
352 available = dvb_poll(parms, dmx_fd, timeout);
353 } while (available < 0 && errno == EOVERFLOW);
354
355 if (parms->p.abort) {
356 ret = 0;
357 break;
358 }
359 if (available <= 0) {
360 dvb_logerr(_("%s: no data read on section filter"), __func__);
361 ret = -1;
362 break;
363 }
364 buf_length = read(dmx_fd, buf, DVB_MAX_PAYLOAD_PACKET_SIZE);
365
366 if (!buf_length) {
367 dvb_logerr(_("%s: buf returned an empty buffer"), __func__);
368 ret = -1;
369 break;
370 }
371 if (buf_length < 0) {
372 dvb_perror(_("dvb_read_section: read error"));
373 ret = -2;
374 break;
375 }
376
377 crc = dvb_crc32(buf, buf_length, 0xFFFFFFFF);
378 if (crc != 0) {
379 dvb_logerr(_("%s: crc error"), __func__);
380 ret = -3;
381 break;
382 }
383
384 ret = dvb_parse_section(parms, sect, buf, buf_length);
385 } while (!ret);
386 free(buf);
387 dvb_dmx_stop(dmx_fd);
388 dvb_table_filter_free(sect);
389
390 if (ret > 0)
391 ret = 0;
392
393 return ret;
394 }
395
dvb_read_section_with_id(struct dvb_v5_fe_parms * parms,int dmx_fd,unsigned char tid,uint16_t pid,int ts_id,void ** table,unsigned timeout)396 int dvb_read_section_with_id(struct dvb_v5_fe_parms *parms, int dmx_fd,
397 unsigned char tid, uint16_t pid,
398 int ts_id,
399 void **table, unsigned timeout)
400 {
401 struct dvb_table_filter tab;
402
403 tab.tid = tid;
404 tab.pid = pid;
405 tab.ts_id = ts_id;
406 tab.table = table;
407 tab.allow_section_gaps = 0;
408
409 return dvb_read_sections(parms, dmx_fd, &tab, timeout);
410 }
411
dvb_scan_alloc_handler_table(uint32_t delivery_system)412 struct dvb_v5_descriptors *dvb_scan_alloc_handler_table(uint32_t delivery_system)
413 {
414 struct dvb_v5_descriptors *dvb_scan_handler;
415
416 dvb_scan_handler = calloc(sizeof(*dvb_scan_handler), 1);
417 if (!dvb_scan_handler)
418 return NULL;
419
420 dvb_scan_handler->delivery_system = delivery_system;
421
422 return dvb_scan_handler;
423 }
424
dvb_scan_free_handler_table(struct dvb_v5_descriptors * dvb_scan_handler)425 void dvb_scan_free_handler_table(struct dvb_v5_descriptors *dvb_scan_handler)
426 {
427 int i;
428
429 if (!dvb_scan_handler)
430 return;
431
432 if (dvb_scan_handler->pat)
433 dvb_table_pat_free(dvb_scan_handler->pat);
434 if (dvb_scan_handler->vct)
435 atsc_table_vct_free(dvb_scan_handler->vct);
436 if (dvb_scan_handler->nit)
437 dvb_table_nit_free(dvb_scan_handler->nit);
438 if (dvb_scan_handler->sdt)
439 dvb_table_sdt_free(dvb_scan_handler->sdt);
440 if (dvb_scan_handler->program) {
441 for (i = 0; i < dvb_scan_handler->num_program; i++)
442 if (dvb_scan_handler->program[i].pmt)
443 dvb_table_pmt_free(dvb_scan_handler->program[i].pmt);
444 free(dvb_scan_handler->program);
445 }
446
447 free(dvb_scan_handler);
448 }
449
dvb_get_ts_tables(struct dvb_v5_fe_parms * __p,int dmx_fd,uint32_t delivery_system,unsigned other_nit,unsigned timeout_multiply)450 struct dvb_v5_descriptors *dvb_get_ts_tables(struct dvb_v5_fe_parms *__p,
451 int dmx_fd,
452 uint32_t delivery_system,
453 unsigned other_nit,
454 unsigned timeout_multiply)
455 {
456 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
457 int rc;
458 unsigned pat_pmt_time, sdt_time, nit_time, vct_time;
459 int atsc_filter = 0;
460 unsigned num_pmt = 0;
461
462 struct dvb_v5_descriptors *dvb_scan_handler;
463
464 dvb_scan_handler = dvb_scan_alloc_handler_table(delivery_system);
465 if (!dvb_scan_handler)
466 return NULL;
467
468 if (!timeout_multiply)
469 timeout_multiply = 1;
470
471 /* Get standard timeouts for each table */
472 switch(delivery_system) {
473 case SYS_DVBC_ANNEX_A:
474 case SYS_DVBC_ANNEX_C:
475 case SYS_DVBS:
476 case SYS_DVBS2:
477 case SYS_TURBO:
478 pat_pmt_time = 1;
479 sdt_time = 2;
480 nit_time = 10;
481 break;
482 case SYS_DVBT:
483 case SYS_DVBT2:
484 pat_pmt_time = 1;
485 sdt_time = 2;
486 nit_time = 12;
487 break;
488 case SYS_ISDBT:
489 pat_pmt_time = 1;
490 sdt_time = 2;
491 nit_time = 12;
492 break;
493 case SYS_ATSC:
494 atsc_filter = ATSC_TABLE_TVCT;
495 pat_pmt_time = 2;
496 vct_time = 2;
497 sdt_time = 5;
498 nit_time = 5;
499 break;
500 case SYS_DVBC_ANNEX_B:
501 atsc_filter = ATSC_TABLE_CVCT;
502 pat_pmt_time = 2;
503 vct_time = 2;
504 sdt_time = 5;
505 nit_time = 5;
506 break;
507 default:
508 pat_pmt_time = 1;
509 sdt_time = 2;
510 nit_time = 10;
511 break;
512 };
513
514 /* PAT table */
515 rc = dvb_read_section(&parms->p, dmx_fd,
516 DVB_TABLE_PAT, DVB_TABLE_PAT_PID,
517 (void **)&dvb_scan_handler->pat,
518 pat_pmt_time * timeout_multiply);
519 if (parms->p.abort)
520 return dvb_scan_handler;
521 if (rc < 0) {
522 dvb_logerr(_("error while waiting for PAT table"));
523 dvb_scan_free_handler_table(dvb_scan_handler);
524 return NULL;
525 }
526 if (parms->p.verbose)
527 dvb_table_pat_print(&parms->p, dvb_scan_handler->pat);
528
529 /* ATSC-specific VCT table */
530 if (atsc_filter) {
531 rc = dvb_read_section(&parms->p, dmx_fd,
532 atsc_filter, ATSC_TABLE_VCT_PID,
533 (void **)&dvb_scan_handler->vct,
534 vct_time * timeout_multiply);
535 if (parms->p.abort)
536 return dvb_scan_handler;
537 if (rc < 0)
538 dvb_logerr(_("error while waiting for VCT table"));
539 else if (parms->p.verbose)
540 atsc_table_vct_print(&parms->p, dvb_scan_handler->vct);
541 }
542
543 /* PMT tables */
544 dvb_scan_handler->program = calloc(dvb_scan_handler->pat->programs,
545 sizeof(*dvb_scan_handler->program));
546
547 dvb_pat_program_foreach(program, dvb_scan_handler->pat) {
548 dvb_scan_handler->program[num_pmt].pat_pgm = program;
549
550 if (!program->service_id) {
551 if (parms->p.verbose)
552 dvb_log(_("Program #%d is network PID: 0x%04x"),
553 num_pmt, program->pid);
554 num_pmt++;
555 continue;
556 }
557 if (parms->p.verbose)
558 dvb_log(_("Program #%d ID 0x%04x, service ID 0x%04x"),
559 num_pmt, program->pid, program->service_id);
560 rc = dvb_read_section(&parms->p, dmx_fd,
561 DVB_TABLE_PMT, program->pid,
562 (void **)&dvb_scan_handler->program[num_pmt].pmt,
563 pat_pmt_time * timeout_multiply);
564 if (parms->p.abort) {
565 dvb_scan_handler->num_program = num_pmt + 1;
566 return dvb_scan_handler;
567 }
568 if (rc < 0) {
569 dvb_logerr(_("error while reading the PMT table for service 0x%04x"),
570 program->service_id);
571 dvb_scan_handler->program[num_pmt].pmt = NULL;
572 } else {
573 if (parms->p.verbose)
574 dvb_table_pmt_print(&parms->p,
575 dvb_scan_handler->program[num_pmt].pmt);
576 }
577 num_pmt++;
578 }
579 dvb_scan_handler->num_program = num_pmt;
580
581 /* NIT table */
582 rc = dvb_read_section(&parms->p, dmx_fd,
583 DVB_TABLE_NIT, DVB_TABLE_NIT_PID,
584 (void **)&dvb_scan_handler->nit,
585 nit_time * timeout_multiply);
586 if (parms->p.abort)
587 return dvb_scan_handler;
588 if (rc < 0)
589 dvb_logerr(_("error while reading the NIT table"));
590 else if (parms->p.verbose)
591 dvb_table_nit_print(&parms->p, dvb_scan_handler->nit);
592
593 /* SDT table */
594 if (!dvb_scan_handler->vct || other_nit) {
595 rc = dvb_read_section(&parms->p, dmx_fd,
596 DVB_TABLE_SDT, DVB_TABLE_SDT_PID,
597 (void **)&dvb_scan_handler->sdt,
598 sdt_time * timeout_multiply);
599 if (parms->p.abort)
600 return dvb_scan_handler;
601 if (rc < 0)
602 dvb_logerr(_("error while reading the SDT table"));
603 else if (parms->p.verbose)
604 dvb_table_sdt_print(&parms->p, dvb_scan_handler->sdt);
605 }
606
607 /* NIT/SDT other tables */
608 if (other_nit) {
609 if (parms->p.verbose)
610 dvb_log(_("Parsing other NIT/SDT"));
611 rc = dvb_read_section(&parms->p, dmx_fd,
612 DVB_TABLE_NIT2, DVB_TABLE_NIT_PID,
613 (void **)&dvb_scan_handler->nit,
614 nit_time * timeout_multiply);
615 if (parms->p.abort)
616 return dvb_scan_handler;
617 if (rc < 0)
618 dvb_logerr(_("error while reading the NIT table"));
619 else if (parms->p.verbose)
620 dvb_table_nit_print(&parms->p, dvb_scan_handler->nit);
621
622 rc = dvb_read_section(&parms->p, dmx_fd,
623 DVB_TABLE_SDT2, DVB_TABLE_SDT_PID,
624 (void **)&dvb_scan_handler->sdt,
625 sdt_time * timeout_multiply);
626 if (parms->p.abort)
627 return dvb_scan_handler;
628 if (rc < 0)
629 dvb_logerr(_("error while reading the SDT table"));
630 else if (parms->p.verbose)
631 dvb_table_sdt_print(&parms->p, dvb_scan_handler->sdt);
632 }
633
634 return dvb_scan_handler;
635 }
636
dvb_scan_transponder(struct dvb_v5_fe_parms * __p,struct dvb_entry * entry,int dmx_fd,check_frontend_t * check_frontend,void * args,unsigned other_nit,unsigned timeout_multiply)637 struct dvb_v5_descriptors *dvb_scan_transponder(struct dvb_v5_fe_parms *__p,
638 struct dvb_entry *entry,
639 int dmx_fd,
640 check_frontend_t *check_frontend,
641 void *args,
642 unsigned other_nit,
643 unsigned timeout_multiply)
644 {
645 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
646 struct dvb_v5_descriptors *dvb_scan_handler = NULL;
647 uint32_t freq, delsys = SYS_UNDEFINED;
648 int i, rc;
649
650 /* First of all, set the delivery system */
651 dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys);
652 dvb_set_compat_delivery_system(&parms->p, delsys);
653
654 /* Copy data into parms */
655 for (i = 0; i < entry->n_props; i++) {
656 uint32_t data = entry->props[i].u.data;
657
658 /* Don't change the delivery system */
659 if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM)
660 continue;
661
662 dvb_fe_store_parm(&parms->p, entry->props[i].cmd, data);
663
664 if (parms->p.current_sys == SYS_ATSC &&
665 entry->props[i].cmd == DTV_MODULATION) {
666 if (data != VSB_8 && data != VSB_16)
667 dvb_fe_store_parm(&parms->p,
668 DTV_DELIVERY_SYSTEM,
669 SYS_DVBC_ANNEX_B);
670 }
671 }
672
673 rc = dvb_fe_set_parms(&parms->p);
674 if (rc < 0) {
675 dvb_perror(_("dvb_fe_set_parms failed"));
676 return NULL;
677 }
678
679 /* As the DVB core emulates it, better to always use auto */
680 dvb_fe_store_parm(&parms->p, DTV_INVERSION, INVERSION_AUTO);
681
682 dvb_fe_retrieve_parm(&parms->p, DTV_FREQUENCY, &freq);
683 if (parms->p.verbose)
684 dvb_fe_prt_parms(&parms->p);
685
686 rc = check_frontend(args, &parms->p);
687 if (rc < 0)
688 return NULL;
689
690 dvb_scan_handler = dvb_get_ts_tables(&parms->p, dmx_fd,
691 parms->p.current_sys,
692 other_nit,
693 timeout_multiply);
694
695 return dvb_scan_handler;
696 }
697
dvb_estimate_freq_shift(struct dvb_v5_fe_parms * __p)698 int dvb_estimate_freq_shift(struct dvb_v5_fe_parms *__p)
699 {
700 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
701 uint32_t shift = 0, bw = 0, min_bw = 0, symbol_rate, ro;
702 int rolloff = 0;
703 int divisor = 100;
704
705 /* Need to handle only cable/satellite and ATSC standards */
706 switch (parms->p.current_sys) {
707 case SYS_DVBC_ANNEX_A:
708 case SYS_DVBC_ANNEX_C:
709 rolloff = 115;
710 break;
711 case SYS_DVBS:
712 divisor = 100000;
713 rolloff = 135;
714 break;
715 case SYS_DVBS2:
716 case SYS_DSS:
717 case SYS_TURBO:
718 divisor = 100000;
719 dvb_fe_retrieve_parm(&parms->p, DTV_ROLLOFF, &ro);
720 switch (ro) {
721 case ROLLOFF_20:
722 rolloff = 120;
723 break;
724 case ROLLOFF_25:
725 rolloff = 125;
726 break;
727 default:
728 case ROLLOFF_AUTO:
729 case ROLLOFF_35:
730 rolloff = 135;
731 break;
732 }
733 break;
734 case SYS_ATSC:
735 case SYS_DVBC_ANNEX_B:
736 bw = 6000000;
737 break;
738 case SYS_ISDBS:
739 /* since ISDBS uses fixed symbol_rate & rolloff,
740 * those parameters are not mandatory in channel config file.
741 */
742 bw = 28860 * 135 / 100;
743 break;
744 case SYS_DVBT2:
745 min_bw = 1700000;
746 break;
747 case SYS_ISDBT:
748 case SYS_DVBT:
749 case SYS_DTMB:
750 /* FIXME: does it also apply for DTMB? */
751 min_bw = 6000000;
752 break;
753 default:
754 break;
755 }
756 if (rolloff) {
757 /*
758 * This is not 100% correct for DVB-S2, as there is a bw
759 * guard interval there but it should be enough for the
760 * purposes of estimating a max frequency shift here.
761 */
762 dvb_fe_retrieve_parm(&parms->p, DTV_SYMBOL_RATE, &symbol_rate);
763 bw = (symbol_rate * rolloff) / divisor;
764 }
765 if (!bw)
766 dvb_fe_retrieve_parm(&parms->p, DTV_BANDWIDTH_HZ, &bw);
767 if (!bw)
768 bw = min_bw;
769 if (!bw)
770 dvb_log(_("Cannot calc frequency shift. " \
771 "Either bandwidth/symbol-rate is unavailable (yet)."));
772 /*
773 * If the max frequency shift between two frequencies is below
774 * than the used bandwidth / 8, it should be the same channel.
775 */
776 shift = bw / 8;
777
778 return shift;
779 }
780
dvb_new_freq_is_needed(struct dvb_entry * entry,struct dvb_entry * last_entry,uint32_t freq,enum dvb_sat_polarization pol,int shift)781 int dvb_new_freq_is_needed(struct dvb_entry *entry, struct dvb_entry *last_entry,
782 uint32_t freq, enum dvb_sat_polarization pol, int shift)
783 {
784 return dvb_new_entry_is_needed(entry, last_entry, freq, shift,
785 pol, NO_STREAM_ID_FILTER);
786 }
787
dvb_scan_add_entry(struct dvb_v5_fe_parms * __p,struct dvb_entry * first_entry,struct dvb_entry * entry,uint32_t freq,uint32_t shift,enum dvb_sat_polarization pol)788 struct dvb_entry *dvb_scan_add_entry(struct dvb_v5_fe_parms *__p,
789 struct dvb_entry *first_entry,
790 struct dvb_entry *entry,
791 uint32_t freq, uint32_t shift,
792 enum dvb_sat_polarization pol)
793 {
794 return dvb_scan_add_entry_ex(__p, first_entry, entry, freq, shift,
795 pol, NO_STREAM_ID_FILTER);
796 }
797
dvb_new_entry_is_needed(struct dvb_entry * entry,struct dvb_entry * last_entry,uint32_t freq,int shift,enum dvb_sat_polarization pol,uint32_t stream_id)798 int dvb_new_entry_is_needed(struct dvb_entry *entry,
799 struct dvb_entry *last_entry,
800 uint32_t freq, int shift,
801 enum dvb_sat_polarization pol, uint32_t stream_id)
802 {
803 for (; entry != last_entry; entry = entry->next) {
804 int i;
805
806 for (i = 0; i < entry->n_props; i++) {
807 uint32_t data = entry->props[i].u.data;
808
809 if (entry->props[i].cmd == DTV_FREQUENCY) {
810 if (freq < data - shift || freq > data + shift)
811 break;
812 }
813 if (pol != POLARIZATION_OFF
814 && entry->props[i].cmd == DTV_POLARIZATION) {
815 if (data != pol)
816 break;
817 }
818 /* NO_STREAM_ID_FILTER: stream_id is not used.
819 * 0: unspecified/auto. libdvbv5 default value.
820 */
821 if (stream_id != NO_STREAM_ID_FILTER && stream_id != 0
822 && entry->props[i].cmd == DTV_STREAM_ID) {
823 if (data != stream_id)
824 break;
825 }
826 }
827 if (i == entry->n_props && entry->n_props > 0)
828 return 0;
829 }
830
831 return 1;
832 }
833
dvb_scan_add_entry_ex(struct dvb_v5_fe_parms * __p,struct dvb_entry * first_entry,struct dvb_entry * entry,uint32_t freq,uint32_t shift,enum dvb_sat_polarization pol,uint32_t stream_id)834 struct dvb_entry *dvb_scan_add_entry_ex(struct dvb_v5_fe_parms *__p,
835 struct dvb_entry *first_entry,
836 struct dvb_entry *entry,
837 uint32_t freq, uint32_t shift,
838 enum dvb_sat_polarization pol,
839 uint32_t stream_id)
840 {
841 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
842 struct dvb_entry *new_entry;
843 int i, n = 2;
844
845 if (!dvb_new_entry_is_needed(first_entry, NULL, freq, shift, pol,
846 stream_id))
847 return NULL;
848
849 /* Clone the current entry into a new entry */
850 new_entry = calloc(sizeof(*new_entry), 1);
851 if (!new_entry) {
852 dvb_perror(_("not enough memory for a new scanning frequency/TS"));
853 return NULL;
854 }
855
856 /*
857 * We can't just copy the entire entry struct, as some strings
858 * like lnb, channel, vchannel will be freed multiple times.
859 * So, copy the props and the Satellite parameters only.
860 */
861 memcpy(new_entry->props, entry->props, sizeof(entry->props));
862 new_entry->n_props = entry->n_props;
863 new_entry->sat_number = entry->sat_number;
864 new_entry->freq_bpf = entry->freq_bpf;
865 new_entry->diseqc_wait = entry->diseqc_wait;
866 if (entry->lnb)
867 new_entry->lnb = strdup(entry->lnb);
868
869 /*
870 * The frequency should change to the new one. Seek for it and
871 * replace its value to the desired one.
872 */
873 for (i = 0; i < new_entry->n_props; i++) {
874 if (new_entry->props[i].cmd == DTV_FREQUENCY) {
875 new_entry->props[i].u.data = freq;
876 /* Navigate to the end of the entry list */
877 while (entry->next) {
878 entry = entry->next;
879 n++;
880 }
881 dvb_log(_("New transponder/channel found: #%d: %d"),
882 n, freq);
883 entry->next = new_entry;
884 new_entry->next = NULL;
885 return new_entry;
886 }
887 }
888
889 /* This should never happen */
890 dvb_logerr(_("BUG: Couldn't add %d to the scan frequency list."), freq);
891 free(new_entry);
892
893 return NULL;
894 }
895
896 struct update_transponders {
897 struct dvb_v5_fe_parms *parms;
898 struct dvb_v5_descriptors *dvb_scan_handler;
899 struct dvb_entry *first_entry;
900 struct dvb_entry *entry;
901 uint32_t update;
902 enum dvb_sat_polarization pol;
903 uint32_t shift;
904 };
905
add_update_nit_dvbc(struct dvb_table_nit * nit,struct dvb_table_nit_transport * tran,struct dvb_desc * desc,void * priv)906 static void add_update_nit_dvbc(struct dvb_table_nit *nit,
907 struct dvb_table_nit_transport *tran,
908 struct dvb_desc *desc,
909 void *priv)
910 {
911 struct update_transponders *tr = priv;
912 struct dvb_entry *new;
913 struct dvb_desc_cable_delivery *d = (void *)desc;
914
915 if (tr->update) {
916 uint32_t freq;
917 dvb_fe_retrieve_parm(tr->parms, DTV_FREQUENCY, &freq);
918
919 if (freq != d->frequency)
920 return;
921 new = tr->entry;
922 } else {
923 new = dvb_scan_add_entry(tr->parms, tr->first_entry, tr->entry,
924 d->frequency, tr->shift, tr->pol);
925 if (!new)
926 return;
927 }
928
929 /* Set NIT props for the transponder */
930 dvb_store_entry_prop(new, DTV_MODULATION,
931 dvbc_modulation_table[d->modulation]);
932 dvb_store_entry_prop(new, DTV_SYMBOL_RATE, d->symbol_rate);
933 dvb_store_entry_prop(new, DTV_INNER_FEC, dvbc_fec_table[d->fec_inner]);
934
935 }
936
add_update_nit_isdbt(struct dvb_table_nit * nit,struct dvb_table_nit_transport * tran,struct dvb_desc * desc,void * priv)937 static void add_update_nit_isdbt(struct dvb_table_nit *nit,
938 struct dvb_table_nit_transport *tran,
939 struct dvb_desc *desc,
940 void *priv)
941 {
942 struct update_transponders *tr = priv;
943 struct dvb_entry *new;
944 struct isdbt_desc_terrestrial_delivery_system *d = (void *)desc;
945 int i;
946
947 if (tr->update) {
948 uint32_t mode = isdbt_mode[d->transmission_mode];
949 uint32_t guard = isdbt_interval[d->guard_interval];
950
951 dvb_store_entry_prop(tr->entry, DTV_TRANSMISSION_MODE, mode);
952 dvb_store_entry_prop(tr->entry, DTV_GUARD_INTERVAL, guard);
953 return;
954 }
955
956 for (i = 0; i < d->num_freqs; i++) {
957 new = dvb_scan_add_entry(tr->parms, tr->first_entry, tr->entry,
958 d->frequency[i], tr->shift, tr->pol);
959 if (!new)
960 return;
961 }
962 }
963
add_update_nit_1seg(struct dvb_table_nit * nit,struct dvb_table_nit_transport * tran,struct dvb_desc * desc,void * priv)964 static void add_update_nit_1seg(struct dvb_table_nit *nit,
965 struct dvb_table_nit_transport *tran,
966 struct dvb_desc *desc,
967 void *priv)
968 {
969 struct update_transponders *tr = priv;
970 struct isdb_desc_partial_reception *d = (void *)desc;
971 size_t len;
972 int i;
973
974 if (!tr->update)
975 return;
976
977 len = d->length / sizeof(*d->partial_reception);
978
979 for (i = 0; i < len; i++) {
980 if (tr->entry->service_id == d->partial_reception[i].service_id) {
981 dvb_store_entry_prop(tr->entry,
982 DTV_ISDBT_PARTIAL_RECEPTION, 1);
983 return;
984 }
985 }
986 dvb_store_entry_prop(tr->entry, DTV_ISDBT_PARTIAL_RECEPTION, 0);
987 }
988
add_update_nit_dvbt2(struct dvb_table_nit * nit,struct dvb_table_nit_transport * tran,struct dvb_desc * desc,void * priv)989 static void add_update_nit_dvbt2(struct dvb_table_nit *nit,
990 struct dvb_table_nit_transport *tran,
991 struct dvb_desc *desc,
992 void *priv)
993 {
994 struct update_transponders *tr = priv;
995 struct dvb_entry *new;
996 struct dvb_extension_descriptor *d = (void *)desc;
997 struct dvb_desc_t2_delivery *t2 = (void *)d->descriptor;
998 int i;
999
1000 if (d->extension_code != T2_delivery_system_descriptor)
1001 return;
1002
1003 if (tr->update) {
1004 uint32_t freq;
1005 dvb_fe_retrieve_parm(tr->parms, DTV_FREQUENCY, &freq);
1006
1007 if (tr->entry->service_id != t2->system_id)
1008 return;
1009
1010 dvb_store_entry_prop(tr->entry, DTV_DELIVERY_SYSTEM,
1011 SYS_DVBT2);
1012 dvb_store_entry_prop(tr->entry, DTV_STREAM_ID,
1013 t2->plp_id);
1014
1015 if (d->length -1 <= 4)
1016 return;
1017
1018 dvb_store_entry_prop(tr->entry, DTV_BANDWIDTH_HZ,
1019 dvbt2_bw[t2->bandwidth]);
1020 dvb_store_entry_prop(tr->entry, DTV_GUARD_INTERVAL,
1021 dvbt2_interval[t2->guard_interval]);
1022 dvb_store_entry_prop(tr->entry, DTV_TRANSMISSION_MODE,
1023 dvbt2_transmission_mode[t2->transmission_mode]);
1024
1025 return;
1026 }
1027
1028 if (d->length -1 <= 4)
1029 return;
1030
1031 for (i = 0; i < t2->frequency_loop_length; i++) {
1032 new = dvb_scan_add_entry_ex(tr->parms,
1033 tr->first_entry, tr->entry,
1034 t2->centre_frequency[i] * 10,
1035 tr->shift, tr->pol, t2->plp_id);
1036 if (!new)
1037 continue;
1038
1039 dvb_store_entry_prop(new, DTV_DELIVERY_SYSTEM,
1040 SYS_DVBT2);
1041 dvb_store_entry_prop(new, DTV_STREAM_ID,
1042 t2->plp_id);
1043 dvb_store_entry_prop(new, DTV_BANDWIDTH_HZ,
1044 dvbt2_bw[t2->bandwidth]);
1045 dvb_store_entry_prop(new, DTV_GUARD_INTERVAL,
1046 dvbt2_interval[t2->guard_interval]);
1047 dvb_store_entry_prop(new, DTV_TRANSMISSION_MODE,
1048 dvbt2_transmission_mode[t2->transmission_mode]);
1049 }
1050 }
1051
add_update_nit_dvbt(struct dvb_table_nit * nit,struct dvb_table_nit_transport * tran,struct dvb_desc * desc,void * priv)1052 static void add_update_nit_dvbt(struct dvb_table_nit *nit,
1053 struct dvb_table_nit_transport *tran,
1054 struct dvb_desc *desc,
1055 void *priv)
1056 {
1057 struct update_transponders *tr = priv;
1058 struct dvb_entry *new;
1059 struct dvb_desc_terrestrial_delivery *d = (void *)desc;
1060
1061 if (tr->update)
1062 return;
1063
1064 new = dvb_scan_add_entry(tr->parms, tr->first_entry, tr->entry,
1065 d->centre_frequency * 10, tr->shift, tr->pol);
1066 if (!new)
1067 return;
1068
1069 /* Set NIT DVB-T props for the transponder */
1070 dvb_store_entry_prop(new, DTV_MODULATION,
1071 dvbt_modulation[d->constellation]);
1072 dvb_store_entry_prop(new, DTV_BANDWIDTH_HZ,
1073 dvbt_bw[d->bandwidth]);
1074 dvb_store_entry_prop(new, DTV_CODE_RATE_HP,
1075 dvbt_code_rate[d->code_rate_hp_stream]);
1076 dvb_store_entry_prop(new, DTV_CODE_RATE_LP,
1077 dvbt_code_rate[d->code_rate_lp_stream]);
1078 dvb_store_entry_prop(new, DTV_GUARD_INTERVAL,
1079 dvbt_interval[d->guard_interval]);
1080 dvb_store_entry_prop(new, DTV_TRANSMISSION_MODE,
1081 dvbt_transmission_mode[d->transmission_mode]);
1082 dvb_store_entry_prop(new, DTV_HIERARCHY,
1083 dvbt_hierarchy[d->hierarchy_information]);
1084 }
1085
add_update_nit_dvbs(struct dvb_table_nit * nit,struct dvb_table_nit_transport * tran,struct dvb_desc * desc,void * priv)1086 static void add_update_nit_dvbs(struct dvb_table_nit *nit,
1087 struct dvb_table_nit_transport *tran,
1088 struct dvb_desc *desc,
1089 void *priv)
1090 {
1091 struct update_transponders *tr = priv;
1092 struct dvb_entry *new;
1093 struct dvb_desc_sat *d = (void *)desc;
1094
1095 if (tr->update) {
1096 uint32_t freq;
1097
1098 dvb_fe_retrieve_parm(tr->parms, DTV_FREQUENCY, &freq);
1099 if (freq != d->frequency)
1100 return;
1101 new = tr->entry;
1102 } else {
1103 new = dvb_scan_add_entry(tr->parms, tr->first_entry, tr->entry,
1104 d->frequency, tr->shift, tr->pol);
1105 if (!new)
1106 return;
1107 }
1108
1109 /* Set NIT DVB-S props for the transponder */
1110
1111 dvb_store_entry_prop(new, DTV_MODULATION,
1112 dvbs_modulation[d->modulation_system]);
1113 dvb_store_entry_prop(new, DTV_POLARIZATION,
1114 dvbs_polarization[d->polarization]);
1115 dvb_store_entry_prop(new, DTV_SYMBOL_RATE,
1116 d->symbol_rate);
1117 dvb_store_entry_prop(new, DTV_INNER_FEC,
1118 dvbs_dvbc_dvbs_freq_inner[d->fec]);
1119 dvb_store_entry_prop(new, DTV_ROLLOFF,
1120 dvbs_rolloff[d->roll_off]);
1121 if (d->roll_off != 0)
1122 dvb_store_entry_prop(new, DTV_DELIVERY_SYSTEM,
1123 SYS_DVBS2);
1124 }
1125
add_update_nit_isdbs(struct dvb_table_nit * nit,struct dvb_table_nit_transport * tran,struct dvb_desc * desc,void * priv)1126 static void add_update_nit_isdbs(struct dvb_table_nit *nit,
1127 struct dvb_table_nit_transport *tran,
1128 struct dvb_desc *desc,
1129 void *priv)
1130 {
1131 struct update_transponders *tr = priv;
1132 struct dvb_entry *new;
1133 /* FIXME:
1134 * use the ISDB-S specific satellite delsys descriptor structure,
1135 * instead of overloading to the EN300-468's one, dvb_desc_sat.
1136 * The following members are incompatible:
1137 * {.modulation_type, .modulation_system, .roll_off, .fec}
1138 */
1139 struct dvb_desc_sat *d = (void *)desc;
1140 uint32_t ts_id;
1141
1142 if (tr->update)
1143 return;
1144
1145 ts_id = tran->transport_id;
1146 new = dvb_scan_add_entry_ex(tr->parms, tr->first_entry, tr->entry,
1147 d->frequency, tr->shift, tr->pol, ts_id);
1148 if (!new)
1149 return;
1150
1151 /* Set (optional) ISDB-S props for the transponder */
1152 /* FIXME: fill in other props like DTV_MODULATION, DTV_INNER_FEC.
1153 * This requires extending the enum definitions in DVBv5 API
1154 * to include the ISDB-S/T specific modulation/fec values,
1155 * such as "BPSK" and "look TMCC".
1156 * Since even "AUTO" is not defined, skip setting them now.
1157 */
1158 dvb_store_entry_prop(new, DTV_POLARIZATION,
1159 dvbs_polarization[d->polarization]);
1160 dvb_store_entry_prop(new, DTV_SYMBOL_RATE,
1161 d->symbol_rate);
1162 }
1163
1164
__dvb_add_update_transponders(struct dvb_v5_fe_parms_priv * parms,struct dvb_v5_descriptors * dvb_scan_handler,struct dvb_entry * first_entry,struct dvb_entry * entry,uint32_t update)1165 static void __dvb_add_update_transponders(struct dvb_v5_fe_parms_priv *parms,
1166 struct dvb_v5_descriptors *dvb_scan_handler,
1167 struct dvb_entry *first_entry,
1168 struct dvb_entry *entry,
1169 uint32_t update)
1170 {
1171 struct update_transponders tr = {
1172 .parms = &parms->p,
1173 .dvb_scan_handler = dvb_scan_handler,
1174 .first_entry = first_entry,
1175 .entry = entry,
1176 .update = update,
1177 .pol = POLARIZATION_OFF,
1178 };
1179
1180 if (!dvb_scan_handler->nit)
1181 return;
1182
1183 tr.shift = dvb_estimate_freq_shift(&parms->p);
1184
1185 switch (parms->p.current_sys) {
1186 case SYS_DVBC_ANNEX_A:
1187 case SYS_DVBC_ANNEX_C:
1188 dvb_table_nit_descriptor_handler(
1189 &parms->p, dvb_scan_handler->nit,
1190 cable_delivery_system_descriptor,
1191 NULL, add_update_nit_dvbc, &tr);
1192 return;
1193 case SYS_ISDBT:
1194 dvb_table_nit_descriptor_handler(
1195 &parms->p, dvb_scan_handler->nit,
1196 partial_reception_descriptor,
1197 NULL, add_update_nit_1seg, &tr);
1198 dvb_table_nit_descriptor_handler(&parms->p,
1199 dvb_scan_handler->nit,
1200 ISDBT_delivery_system_descriptor,
1201 NULL, add_update_nit_isdbt, &tr);
1202 return;
1203 case SYS_DVBT:
1204 case SYS_DVBT2:
1205 case SYS_DTMB: /* FIXME: are DTMB nit tables equal to DVB-T? */
1206 dvb_table_nit_descriptor_handler(
1207 &parms->p, dvb_scan_handler->nit,
1208 extension_descriptor,
1209 NULL, add_update_nit_dvbt2, &tr);
1210
1211 dvb_table_nit_descriptor_handler(
1212 &parms->p, dvb_scan_handler->nit,
1213 terrestrial_delivery_system_descriptor,
1214 NULL, add_update_nit_dvbt, &tr);
1215 return;
1216 case SYS_DVBS:
1217 case SYS_DVBS2:
1218 dvb_table_nit_descriptor_handler(
1219 &parms->p, dvb_scan_handler->nit,
1220 satellite_delivery_system_descriptor,
1221 NULL, add_update_nit_dvbs, &tr);
1222 return;
1223 case SYS_ISDBS:
1224 /* see the FIXME: in add_update_nit_isdbs() */
1225 dvb_table_nit_descriptor_handler(
1226 &parms->p, dvb_scan_handler->nit,
1227 satellite_delivery_system_descriptor,
1228 NULL, add_update_nit_isdbs, &tr);
1229 return;
1230
1231 default:
1232 dvb_log(_("Transponders detection not implemented for this standard yet."));
1233 return;
1234 }
1235 }
1236
dvb_add_scaned_transponders(struct dvb_v5_fe_parms * __p,struct dvb_v5_descriptors * dvb_scan_handler,struct dvb_entry * first_entry,struct dvb_entry * entry)1237 void dvb_add_scaned_transponders(struct dvb_v5_fe_parms *__p,
1238 struct dvb_v5_descriptors *dvb_scan_handler,
1239 struct dvb_entry *first_entry,
1240 struct dvb_entry *entry)
1241 {
1242 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
1243
1244 return __dvb_add_update_transponders(parms, dvb_scan_handler,
1245 first_entry, entry, 0);
1246 }
1247
dvb_update_transponders(struct dvb_v5_fe_parms * __p,struct dvb_v5_descriptors * dvb_scan_handler,struct dvb_entry * first_entry,struct dvb_entry * entry)1248 void dvb_update_transponders(struct dvb_v5_fe_parms *__p,
1249 struct dvb_v5_descriptors *dvb_scan_handler,
1250 struct dvb_entry *first_entry,
1251 struct dvb_entry *entry)
1252 {
1253 struct dvb_v5_fe_parms_priv *parms = (void *)__p;
1254
1255 return __dvb_add_update_transponders(parms, dvb_scan_handler,
1256 first_entry, entry, 1);
1257 }
1258