1 /*
2 * Tvheadend - Linux DVB frontend
3 *
4 * Copyright (C) 2013 Adam Sutton
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "tvheadend.h"
21 #include "linuxdvb_private.h"
22 #include "notify.h"
23 #include "atomic.h"
24 #include "tvhpoll.h"
25 #include "streaming.h"
26
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <assert.h>
33 #include <linux/dvb/dmx.h>
34 #include <linux/dvb/frontend.h>
35
36 #define NOSIGNAL(x) (((x) & FE_HAS_SIGNAL) == 0)
37
38 static void
39 linuxdvb_frontend_monitor ( void *aux );
40 static void *
41 linuxdvb_frontend_input_thread ( void *aux );
42
43 /* **************************************************************************
44 * Class definition
45 * *************************************************************************/
46
47 static void
linuxdvb_frontend_class_changed(idnode_t * in)48 linuxdvb_frontend_class_changed ( idnode_t *in )
49 {
50 linuxdvb_adapter_t *la = ((linuxdvb_frontend_t*)in)->lfe_adapter;
51 linuxdvb_adapter_changed(la);
52 }
53
54 const void *
linuxdvb_frontend_class_active_get(void * obj)55 linuxdvb_frontend_class_active_get ( void *obj )
56 {
57 int *active;
58 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)obj;
59 active = (int *)mpegts_input_class_active_get(obj);
60 if (!(*active) && lfe->lfe_adapter->la_exclusive)
61 *active = lfe->lfe_adapter->la_is_enabled(lfe->lfe_adapter);
62 return active;
63 }
64
65 CLASS_DOC(linuxdvb_frontend)
66 CLASS_DOC(linuxdvb_frontend_dvbs)
67 CLASS_DOC(linuxdvb_frontend_dvbt)
68 CLASS_DOC(linuxdvb_frontend_dvbc)
69
70 const idclass_t linuxdvb_frontend_class =
71 {
72 .ic_super = &mpegts_input_class,
73 .ic_class = "linuxdvb_frontend",
74 .ic_caption = N_("Linux DVB frontend"),
75 .ic_doc = tvh_doc_linuxdvb_frontend_class,
76 .ic_changed = linuxdvb_frontend_class_changed,
77 .ic_properties = (const property_t[]) {
78 {
79 .type = PT_BOOL,
80 .id = "active",
81 .name = N_("Active"),
82 .opts = PO_RDONLY | PO_NOSAVE | PO_NOUI,
83 .get = linuxdvb_frontend_class_active_get,
84 },
85 {
86 .type = PT_STR,
87 .id = "fe_path",
88 .name = N_("Frontend path"),
89 .desc = N_("Path to the frontend used by the device."),
90 .opts = PO_RDONLY | PO_NOSAVE,
91 .off = offsetof(linuxdvb_frontend_t, lfe_fe_path),
92 },
93 {
94 .type = PT_STR,
95 .id = "dvr_path",
96 .name = N_("Input path"),
97 .desc = N_("The input path used by the device."),
98 .opts = PO_RDONLY | PO_NOSAVE,
99 .off = offsetof(linuxdvb_frontend_t, lfe_dvr_path),
100 },
101 {
102 .type = PT_STR,
103 .id = "dmx_path",
104 .name = N_("Demux path"),
105 .desc = N_("The demux path used by the device."),
106 .opts = PO_RDONLY | PO_NOSAVE,
107 .off = offsetof(linuxdvb_frontend_t, lfe_dmx_path),
108 },
109 {
110 .type = PT_INT,
111 .id = "fe_number",
112 .name = N_("Frontend number"),
113 .desc = N_("The frontend number given to the device."),
114 .opts = PO_RDONLY | PO_NOSAVE,
115 .off = offsetof(linuxdvb_frontend_t, lfe_number),
116 },
117 {
118 .type = PT_STR,
119 .id = "sysfs_device",
120 .name = N_("Device path in sysfs"),
121 .desc = N_("The device path in sysfs filesystem (/sys)."),
122 .opts = PO_RDONLY | PO_NOSAVE | PO_MULTILINE,
123 .off = offsetof(linuxdvb_frontend_t, lfe_sysfs),
124 },
125 {
126 .type = PT_INT,
127 .id = "pids_max",
128 .name = N_("Maximum PIDs"),
129 .desc = N_("The limit for the PID filter (driver or hardware)."),
130 .off = offsetof(linuxdvb_frontend_t, lfe_pids_max),
131 .opts = PO_ADVANCED,
132 .def.i = 32
133 },
134 {
135 .type = PT_BOOL,
136 .id = "pids_use_all",
137 .name = N_("Allow all PIDs"),
138 .desc = N_("Allow all PIDs (no filter) when the 'Maximum PIDs' limit is reached."),
139 .off = offsetof(linuxdvb_frontend_t, lfe_pids_use_all),
140 .opts = PO_ADVANCED,
141 .def.i = 1
142 },
143 {
144 .type = PT_BOOL,
145 .id = "powersave",
146 .name = N_("Power save"),
147 .desc = N_("Enable/disable power save mode (if supported by "
148 "the device)."),
149 .off = offsetof(linuxdvb_frontend_t, lfe_powersave),
150 },
151 {
152 .type = PT_U32,
153 .id = "tune_repeats",
154 .name = N_("# tune repeats"),
155 .desc = N_("Number of repeats for the tune requests (default is "
156 "zero - no repeats). Note: this represents the "
157 "number of repeats, not the number of requests - "
158 "so 0 means 'send once: don't repeat', 1 means "
159 "'send twice: send once, then send one repeat',"
160 " etc."),
161 .opts = PO_ADVANCED,
162 .off = offsetof(linuxdvb_frontend_t, lfe_tune_repeats),
163 },
164 {
165 .type = PT_U32,
166 .id = "skip_bytes",
167 .name = N_("Skip initial bytes"),
168 .desc = N_("If set, the first bytes from the MPEG-TS stream "
169 "are discarded. It may be required for some "
170 "drivers or hardware which do not flush the MPEG-TS "
171 "buffers completely after a frequency/parameter change."),
172 .opts = PO_ADVANCED,
173 .off = offsetof(linuxdvb_frontend_t, lfe_skip_bytes),
174 },
175 {
176 .type = PT_U32,
177 .id = "ibuf_size",
178 .name = N_("Input buffer (bytes)"),
179 .desc = N_("The number of bytes to buffer. By default, "
180 "linuxdvb's input buffer is 18800 bytes long. The "
181 "accepted range is 18800-1880000 bytes."),
182 .opts = PO_ADVANCED,
183 .off = offsetof(linuxdvb_frontend_t, lfe_ibuf_size),
184 },
185 {
186 .type = PT_U32,
187 .id = "status_period",
188 .name = N_("Status period (ms)"),
189 .desc = N_("By default, linuxdvb's status read period is "
190 "1000ms (one second). The accepted range is 250ms "
191 "to 8000ms. Note that for some hardware or drivers "
192 "(like USB), the status operations take too much "
193 "time and CPU. In this case, increase the default "
194 "value. For fast hardware, this value might be "
195 "decreased to make the decision of the re-tune "
196 "algorithm based on the signal status faster."),
197 .opts = PO_ADVANCED,
198 .off = offsetof(linuxdvb_frontend_t, lfe_status_period),
199 },
200 {
201 .type = PT_BOOL,
202 .id = "old_status",
203 .name = N_("Force old status"),
204 .desc = N_("Always use the old ioctls to read the linuxdvb "
205 "status (signal strength, SNR, error counters). "
206 "Some drivers are not mature enough to provide the "
207 "correct values using the new v5 linuxdvb API."),
208 .opts = PO_ADVANCED,
209 .off = offsetof(linuxdvb_frontend_t, lfe_old_status),
210 },
211 {}
212 }
213 };
214
215 const idclass_t linuxdvb_frontend_dvbt_class =
216 {
217 .ic_super = &linuxdvb_frontend_class,
218 .ic_class = "linuxdvb_frontend_dvbt",
219 .ic_doc = tvh_doc_linuxdvb_frontend_dvbt_class,
220 .ic_caption = N_("TV Adapters - Linux DVB-T Frontend"),
221 .ic_properties = (const property_t[]){
222 {
223 .type = PT_BOOL,
224 .id = "lna",
225 .name = N_("LNA (low noise amplifier)"),
226 .desc = N_("Enable/disable LNA."),
227 .off = offsetof(linuxdvb_frontend_t, lfe_lna),
228 },
229 {}
230 }
231 };
232
233 static idnode_set_t *
linuxdvb_frontend_dvbs_class_get_childs(idnode_t * self)234 linuxdvb_frontend_dvbs_class_get_childs ( idnode_t *self )
235 {
236 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)self;
237 idnode_set_t *is = idnode_set_create(0);
238 idnode_set_add(is, &lfe->lfe_satconf->ls_id, NULL, NULL);
239 return is;
240 }
241
242 static int
linuxdvb_frontend_dvbs_class_satconf_set(void * self,const void * str)243 linuxdvb_frontend_dvbs_class_satconf_set ( void *self, const void *str )
244 {
245 linuxdvb_frontend_t *lfe = self;
246 htsmsg_t *conf;
247 str = str ?: "";
248 if (lfe->lfe_satconf) {
249 if (!strcmp(str, lfe->lfe_satconf->ls_type))
250 return 0;
251 linuxdvb_satconf_delete(lfe->lfe_satconf, 1);
252 }
253 conf = htsmsg_create_map();
254 htsmsg_add_str(conf, "type", str);
255 lfe->lfe_satconf = linuxdvb_satconf_create(lfe, conf);
256 htsmsg_destroy(conf);
257 return 1;
258 }
259
260 static const void *
linuxdvb_frontend_dvbs_class_satconf_get(void * self)261 linuxdvb_frontend_dvbs_class_satconf_get ( void *self )
262 {
263 linuxdvb_frontend_t *lfe = self;
264 if (lfe->lfe_satconf)
265 prop_ptr = lfe->lfe_satconf->ls_type;
266 else
267 prop_ptr = NULL;
268 return &prop_ptr;
269 }
270
271 static htsmsg_t *
linuxdvb_frontend_dvbs_class_master_enum(void * self,const char * lang)272 linuxdvb_frontend_dvbs_class_master_enum( void * self, const char *lang )
273 {
274 linuxdvb_frontend_t *lfe = self, *lfe2;
275 linuxdvb_adapter_t *la;
276 tvh_hardware_t *th;
277 char ubuf[UUID_HEX_SIZE];
278 htsmsg_t *m = htsmsg_create_list();
279 if (self == NULL) return m;
280 htsmsg_t *e = htsmsg_create_key_val("", N_("This tuner"));
281 htsmsg_add_msg(m, NULL, e);
282 LIST_FOREACH(th, &tvh_hardware, th_link) {
283 if (!idnode_is_instance(&th->th_id, &linuxdvb_adapter_class)) continue;
284 la = (linuxdvb_adapter_t*)th;
285 LIST_FOREACH(lfe2, &la->la_frontends, lfe_link) {
286 if (lfe2 != lfe && lfe2->lfe_type == lfe->lfe_type) {
287 e = htsmsg_create_key_val(idnode_uuid_as_str(&lfe2->ti_id, ubuf), lfe2->mi_name);
288 htsmsg_add_msg(m, NULL, e);
289 }
290 }
291 }
292 return m;
293 }
294
295 const idclass_t linuxdvb_frontend_dvbs_class =
296 {
297 .ic_super = &linuxdvb_frontend_class,
298 .ic_class = "linuxdvb_frontend_dvbs",
299 .ic_doc = tvh_doc_linuxdvb_frontend_dvbs_class,
300 .ic_caption = N_("TV Adapters - Linux DVB-S Frontend (Master)"),
301 .ic_get_childs = linuxdvb_frontend_dvbs_class_get_childs,
302 .ic_properties = (const property_t[]){
303 {
304 .type = PT_STR,
305 .id = "satconf",
306 .name = N_("Satellite config"),
307 .desc = N_("The satellite configuration to use."),
308 .opts = PO_NOSAVE,
309 .set = linuxdvb_frontend_dvbs_class_satconf_set,
310 .get = linuxdvb_frontend_dvbs_class_satconf_get,
311 .list = linuxdvb_satconf_type_list,
312 .def.s = "simple"
313 },
314 {
315 .type = PT_STR,
316 .id = "fe_master",
317 .name = N_("Master tuner"),
318 .desc = N_("The signal from the standard universal LNB can be "
319 "split using a simple coaxial splitter "
320 "(no multiswitch) to several outputs. In this "
321 "case, the position, the polarization and low-high "
322 "band settings must be equal. If you set another "
323 "tuner as master, then this tuner will act as "
324 "a slave and Tvheadend will assure that this tuner "
325 "will not use incompatible parameters (position, "
326 "polarization, lo-hi)."),
327 .list = linuxdvb_frontend_dvbs_class_master_enum,
328 .off = offsetof(linuxdvb_frontend_t, lfe_master),
329 },
330 {
331 .id = "networks",
332 .type = PT_NONE,
333 },
334 {}
335 }
336 };
337
338 const idclass_t linuxdvb_frontend_dvbs_slave_class =
339 {
340 .ic_super = &linuxdvb_frontend_class,
341 .ic_class = "linuxdvb_frontend_dvbs_slave",
342 .ic_doc = tvh_doc_linuxdvb_frontend_dvbs_class,
343 .ic_caption = N_("TV Adapters - Linux DVB-S Slave Frontend"),
344 .ic_properties = (const property_t[]){
345 {
346 .type = PT_STR,
347 .id = "fe_master",
348 .name = N_("Master tuner"),
349 .desc = N_("The signal from the standard universal LNB can be "
350 "split using a simple coaxial splitter "
351 "(no multiswitch) to several outputs. In this "
352 "case, the position, the polarization and low-high "
353 "band settings must be equal. If you set another "
354 "tuner as master, then this tuner will act as "
355 "a slave and tvheadend will assure that this tuner "
356 "will not use incompatible parameters (position, "
357 "polarization, lo-hi)."),
358 .list = linuxdvb_frontend_dvbs_class_master_enum,
359 .off = offsetof(linuxdvb_frontend_t, lfe_master),
360 },
361 {
362 .id = "networks",
363 .type = PT_NONE,
364 },
365 {}
366 }
367 };
368
369 const idclass_t linuxdvb_frontend_dvbc_class =
370 {
371 .ic_super = &linuxdvb_frontend_class,
372 .ic_class = "linuxdvb_frontend_dvbc",
373 .ic_doc = tvh_doc_linuxdvb_frontend_dvbc_class,
374 .ic_caption = N_("TV Adapters - Linux DVB-C Frontend"),
375 .ic_properties = (const property_t[]){
376 {}
377 }
378 };
379
380 const idclass_t linuxdvb_frontend_atsc_t_class =
381 {
382 .ic_super = &linuxdvb_frontend_class,
383 .ic_class = "linuxdvb_frontend_atsc_t",
384 .ic_doc = tvh_doc_linuxdvb_frontend_dvbt_class,
385 .ic_caption = N_("TV Adapters - Linux ATSC-T Frontend"),
386 .ic_properties = (const property_t[]){
387 {}
388 }
389 };
390
391 const idclass_t linuxdvb_frontend_atsc_c_class =
392 {
393 .ic_super = &linuxdvb_frontend_class,
394 .ic_class = "linuxdvb_frontend_atsc_c",
395 .ic_doc = tvh_doc_linuxdvb_frontend_dvbc_class,
396 .ic_caption = N_("TV Adapters - Linux ATSC-C Frontend"),
397 .ic_properties = (const property_t[]){
398 {}
399 }
400 };
401
402 const idclass_t linuxdvb_frontend_isdb_t_class =
403 {
404 .ic_super = &linuxdvb_frontend_class,
405 .ic_class = "linuxdvb_frontend_isdb_t",
406 .ic_doc = tvh_doc_linuxdvb_frontend_dvbt_class,
407 .ic_caption = N_("TV Adapters - Linux ISDB-T Frontend"),
408 .ic_properties = (const property_t[]){
409 {}
410 }
411 };
412
413 const idclass_t linuxdvb_frontend_isdb_c_class =
414 {
415 .ic_super = &linuxdvb_frontend_class,
416 .ic_class = "linuxdvb_frontend_isdb_c",
417 .ic_doc = tvh_doc_linuxdvb_frontend_dvbc_class,
418 .ic_caption = N_("TV Adapters - Linux ISDB-C Frontend"),
419 .ic_properties = (const property_t[]){
420 {}
421 }
422 };
423
424 const idclass_t linuxdvb_frontend_isdb_s_class =
425 {
426 .ic_super = &linuxdvb_frontend_class,
427 .ic_class = "linuxdvb_frontend_isdb_s",
428 .ic_doc = tvh_doc_linuxdvb_frontend_dvbs_class,
429 .ic_caption = N_("TV Adapters - Linux ISDB-S Frontend (Master)"),
430 .ic_properties = (const property_t[]){
431 {}
432 }
433 };
434
435 const idclass_t linuxdvb_frontend_dab_class =
436 {
437 .ic_super = &linuxdvb_frontend_class,
438 .ic_class = "linuxdvb_frontend_dab",
439 .ic_caption = N_("TV Adapters - Linux DAB Frontend"),
440 .ic_properties = (const property_t[]){
441 {}
442 }
443 };
444
445 /* **************************************************************************
446 * Class methods
447 * *************************************************************************/
448
449 static void
linuxdvb_frontend_close_fd(linuxdvb_frontend_t * lfe,const char * name)450 linuxdvb_frontend_close_fd ( linuxdvb_frontend_t *lfe, const char *name )
451 {
452 char buf[256];
453
454 if (lfe->lfe_fe_fd <= 0)
455 return;
456
457 if (name == NULL) {
458 lfe->mi_display_name((mpegts_input_t *)lfe, buf, sizeof(buf));
459 name = buf;
460 }
461
462 tvhtrace(LS_LINUXDVB, "%s - closing FE %s (%d)",
463 name, lfe->lfe_fe_path, lfe->lfe_fe_fd);
464 close(lfe->lfe_fe_fd);
465 lfe->lfe_fe_fd = -1;
466 if (lfe->lfe_satconf)
467 linuxdvb_satconf_reset(lfe->lfe_satconf);
468 }
469
470 static int
linuxdvb_frontend_open_fd(linuxdvb_frontend_t * lfe,const char * name)471 linuxdvb_frontend_open_fd ( linuxdvb_frontend_t *lfe, const char *name )
472 {
473 linuxdvb_frontend_t *lfe2;
474 const char *extra = "";
475
476 if (lfe->lfe_fe_fd > 0)
477 return 0;
478
479 /* Share FD across frontends */
480 if (lfe->lfe_adapter->la_exclusive) {
481 LIST_FOREACH(lfe2, &lfe->lfe_adapter->la_frontends, lfe_link) {
482 if (lfe2->lfe_fe_fd > 0) {
483 lfe->lfe_fe_fd = dup(lfe2->lfe_fe_fd);
484 extra = " (shared)";
485 break;
486 }
487 }
488 }
489
490 if (lfe->lfe_fe_fd <= 0) {
491 lfe->lfe_fe_fd = tvh_open(lfe->lfe_fe_path, O_RDWR | O_NONBLOCK, 0);
492 extra = "";
493 }
494
495 tvhtrace(LS_LINUXDVB, "%s - opening FE %s (%d)%s",
496 name, lfe->lfe_fe_path, lfe->lfe_fe_fd, extra);
497
498 return lfe->lfe_fe_fd <= 0;
499 }
500
501 static void
linuxdvb_frontend_enabled_updated(mpegts_input_t * mi)502 linuxdvb_frontend_enabled_updated ( mpegts_input_t *mi )
503 {
504 char buf[512];
505 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
506
507 mi->mi_display_name(mi, buf, sizeof(buf));
508
509 /* Ensure disabled */
510 if (!mi->mi_enabled) {
511 tvhtrace(LS_LINUXDVB, "%s - disabling tuner", buf);
512 linuxdvb_frontend_close_fd(lfe, buf);
513 mtimer_disarm(&lfe->lfe_monitor_timer);
514
515 /* Ensure FE opened (if not powersave) */
516 } else if (!lfe->lfe_powersave && lfe->lfe_fe_fd <= 0 && lfe->lfe_fe_path) {
517
518 linuxdvb_frontend_open_fd(lfe, buf);
519
520 }
521 }
522
523 static int
linuxdvb_frontend_get_weight(mpegts_input_t * mi,mpegts_mux_t * mm,int flags,int weight)524 linuxdvb_frontend_get_weight ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags, int weight )
525 {
526 int w = 0;
527 linuxdvb_adapter_t *la = ((linuxdvb_frontend_t*)mi)->lfe_adapter;
528 linuxdvb_frontend_t *lfe;
529 if (la->la_exclusive) {
530 LIST_FOREACH(lfe, &la->la_frontends, lfe_link)
531 w = MAX(w, mpegts_input_get_weight((mpegts_input_t*)lfe, mm, flags, weight));
532 } else {
533 w = mpegts_input_get_weight(mi, mm, flags, weight);
534 }
535 return w;
536 }
537
538 static int
linuxdvb_frontend_get_priority(mpegts_input_t * mi,mpegts_mux_t * mm,int flags)539 linuxdvb_frontend_get_priority ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags )
540 {
541 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
542 int r = mpegts_input_get_priority(mi, mm, flags);
543 if (lfe->lfe_satconf)
544 r += linuxdvb_satconf_get_priority(lfe->lfe_satconf, mm);
545 return r;
546 }
547
548 static int
linuxdvb_frontend_get_grace(mpegts_input_t * mi,mpegts_mux_t * mm)549 linuxdvb_frontend_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm )
550 {
551 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
552 int r = 5;
553 if (lfe->lfe_satconf)
554 r = linuxdvb_satconf_get_grace(lfe->lfe_satconf, mm);
555 return r;
556 }
557
558 static int
linuxdvb_frontend_is_enabled(mpegts_input_t * mi,mpegts_mux_t * mm,int flags,int weight)559 linuxdvb_frontend_is_enabled
560 ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags, int weight )
561 {
562 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2;
563 linuxdvb_adapter_t *la;
564 tvh_hardware_t *th;
565 char ubuf[UUID_HEX_SIZE];
566 int w;
567
568 if (lfe->lfe_fe_path == NULL)
569 return MI_IS_ENABLED_NEVER;
570 w = mpegts_input_is_enabled(mi, mm, flags, weight);
571 if (w != MI_IS_ENABLED_OK)
572 return w;
573 if (access(lfe->lfe_fe_path, R_OK | W_OK))
574 return MI_IS_ENABLED_NEVER;
575 if (mm == NULL)
576 return MI_IS_ENABLED_OK;
577 if (lfe->lfe_in_setup)
578 return MI_IS_ENABLED_RETRY;
579 if (lfe->lfe_type != DVB_TYPE_S)
580 goto ok;
581
582 /* check if any "blocking" tuner is running */
583 LIST_FOREACH(th, &tvh_hardware, th_link) {
584 if (!idnode_is_instance(&th->th_id, &linuxdvb_adapter_class)) continue;
585 la = (linuxdvb_adapter_t*)th;
586 LIST_FOREACH(lfe2, &la->la_frontends, lfe_link) {
587 if (lfe2 == lfe) continue;
588 if (lfe2->lfe_type != DVB_TYPE_S) continue;
589 if (lfe->lfe_master && !strcmp(lfe->lfe_master, idnode_uuid_as_str(&lfe2->ti_id, ubuf))) {
590 if (lfe2->lfe_satconf == NULL)
591 return MI_IS_ENABLED_NEVER; /* invalid master */
592 if (lfe2->lfe_refcount <= 0)
593 return MI_IS_ENABLED_RETRY; /* prefer master */
594 if (linuxdvb_satconf_match_mux(lfe2->lfe_satconf, mm))
595 goto ok;
596 return MI_IS_ENABLED_RETRY;
597 }
598 if (lfe2->lfe_master &&
599 !strcmp(lfe2->lfe_master, idnode_uuid_as_str(&lfe->ti_id, ubuf)) &&
600 lfe2->lfe_refcount > 0) {
601 if (lfe->lfe_satconf == NULL)
602 return MI_IS_ENABLED_NEVER;
603 if (linuxdvb_satconf_match_mux(lfe->lfe_satconf, mm))
604 goto ok;
605 return MI_IS_ENABLED_RETRY;
606 }
607 }
608 }
609
610
611 ok:
612 if (lfe->lfe_adapter->la_exclusive) {
613 w = -1;
614 LIST_FOREACH(lfe2, &lfe->lfe_adapter->la_frontends, lfe_link) {
615 if (lfe2 == lfe) continue;
616 w = MAX(w, mpegts_input_get_weight((mpegts_input_t *)lfe2, mm, flags, weight));
617 }
618 if (w >= weight)
619 return MI_IS_ENABLED_RETRY;
620 }
621
622 return MI_IS_ENABLED_OK;
623 }
624
625 static void
linuxdvb_frontend_stop_mux(mpegts_input_t * mi,mpegts_mux_instance_t * mmi)626 linuxdvb_frontend_stop_mux
627 ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
628 {
629 char buf1[256], buf2[256];
630 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2;
631
632 if (lfe->lfe_master)
633 assert(lfe->lfe_type == DVB_TYPE_S);
634
635 mi->mi_display_name(mi, buf1, sizeof(buf1));
636 mpegts_mux_nice_name(mmi->mmi_mux, buf2, sizeof(buf2));
637 tvhdebug(LS_LINUXDVB, "%s - stopping %s", buf1, buf2);
638
639 /* Stop thread */
640 if (lfe->lfe_dvr_pipe.wr > 0) {
641 tvh_write(lfe->lfe_dvr_pipe.wr, "", 1);
642 tvhtrace(LS_LINUXDVB, "%s - waiting for dvr thread", buf1);
643 pthread_join(lfe->lfe_dvr_thread, NULL);
644 tvh_pipe_close(&lfe->lfe_dvr_pipe);
645 tvhdebug(LS_LINUXDVB, "%s - stopped dvr thread", buf1);
646 }
647
648 /* Not locked */
649 lfe->lfe_ready = 0;
650 lfe->lfe_locked = 0;
651 lfe->lfe_status = 0;
652 lfe->lfe_status2 = 0;
653
654 /* Ensure it won't happen immediately */
655 mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, sec2mono(2));
656
657 if (lfe->lfe_satconf && lfe->lfe_refcount == 1)
658 linuxdvb_satconf_post_stop_mux(lfe->lfe_satconf);
659
660 if (lfe->lfe_master) {
661 lfe2 = (linuxdvb_frontend_t *)idnode_find(lfe->lfe_master, &linuxdvb_frontend_class, NULL);
662 if (lfe2->lfe_type != lfe->lfe_type)
663 lfe2 = NULL;
664 if (lfe2) { /* master tuner shutdown procedure */
665 assert(lfe2->lfe_refcount >= 0);
666 if (--lfe2->lfe_refcount == 0) {
667 lfe2->lfe_ready = 0;
668 lfe2->lfe_locked = 0;
669 lfe2->lfe_status = 0;
670 lfe2->lfe_status2 = 0;
671 /* Ensure it won't happen immediately */
672 mtimer_arm_rel(&lfe2->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, sec2mono(2));
673 if (lfe2->lfe_satconf)
674 linuxdvb_satconf_post_stop_mux(lfe2->lfe_satconf);
675 lfe2->lfe_in_setup = 0;
676 lfe2->lfe_freq = 0;
677 }
678 }
679 }
680
681 lfe->lfe_refcount--;
682 lfe->lfe_in_setup = 0;
683 lfe->lfe_freq = 0;
684 mpegts_pid_done(&lfe->lfe_pids);
685 }
686
687 static int
linuxdvb_frontend_warm_mux(mpegts_input_t * mi,mpegts_mux_instance_t * mmi)688 linuxdvb_frontend_warm_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
689 {
690 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2 = NULL;
691 mpegts_mux_instance_t *lmmi = NULL;
692 int r;
693
694 r = mpegts_input_warm_mux(mi, mmi);
695 if (r)
696 return r;
697
698 if (!lfe->lfe_adapter->la_exclusive)
699 return 0;
700
701 /* Stop other active frontend (should be only one) */
702 LIST_FOREACH(lfe2, &lfe->lfe_adapter->la_frontends, lfe_link) {
703 if (lfe2 == lfe) continue;
704 pthread_mutex_lock(&lfe2->mi_output_lock);
705 lmmi = LIST_FIRST(&lfe2->mi_mux_active);
706 pthread_mutex_unlock(&lfe2->mi_output_lock);
707 if (lmmi) {
708 /* Stop */
709 lmmi->mmi_mux->mm_stop(lmmi->mmi_mux, 1, SM_CODE_ABORTED);
710 }
711 linuxdvb_frontend_close_fd(lfe2, NULL);
712 mtimer_disarm(&lfe2->lfe_monitor_timer);
713 }
714 return 0;
715 }
716
717 static int
linuxdvb_frontend_start_mux(mpegts_input_t * mi,mpegts_mux_instance_t * mmi,int weight)718 linuxdvb_frontend_start_mux
719 ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, int weight )
720 {
721 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi, *lfe2;
722 int res, f;
723
724 assert(lfe->lfe_in_setup == 0);
725
726 lfe->lfe_refcount++;
727 lfe->lfe_in_setup = 1;
728 lfe->lfe_ioctls = 0;
729
730 if (lfe->lfe_master) {
731 assert(lfe->lfe_type == DVB_TYPE_S);
732 lfe2 = (linuxdvb_frontend_t *)idnode_find(lfe->lfe_master, &linuxdvb_frontend_class, NULL);
733 if (lfe2 && lfe2->lfe_type != lfe->lfe_type)
734 lfe2 = NULL;
735 res = SM_CODE_TUNING_FAILED;
736 if (lfe2) {
737 f = linuxdvb_satconf_lnb_freq(lfe2->lfe_satconf, mmi);
738 if (f <= 0)
739 goto end;
740 if (lfe2->lfe_refcount++ == 0) {
741 lfe2->lfe_in_setup = 1;
742 lfe2->lfe_ioctls = 0;
743 res = linuxdvb_satconf_start_mux(lfe2->lfe_satconf, mmi, 0);
744 if (res)
745 goto end;
746 }
747 res = linuxdvb_frontend_tune1((linuxdvb_frontend_t*)mi, mmi, f);
748 }
749 goto end;
750 }
751
752 if (lfe->lfe_satconf)
753 res = linuxdvb_satconf_start_mux(lfe->lfe_satconf, mmi, lfe->lfe_refcount > 1);
754 else
755 res = linuxdvb_frontend_tune1((linuxdvb_frontend_t*)mi, mmi, -1);
756
757 end:
758 if (res) {
759 lfe->lfe_in_setup = 0;
760 lfe->lfe_refcount--;
761 }
762 return res;
763 }
764
765 static void
linuxdvb_frontend_update_pids(mpegts_input_t * mi,mpegts_mux_t * mm)766 linuxdvb_frontend_update_pids
767 ( mpegts_input_t *mi, mpegts_mux_t *mm )
768 {
769 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
770 mpegts_pid_t *mp;
771 mpegts_pid_sub_t *mps;
772
773 pthread_mutex_lock(&lfe->lfe_dvr_lock);
774 mpegts_pid_done(&lfe->lfe_pids);
775 RB_FOREACH(mp, &mm->mm_pids, mp_link) {
776 if (mp->mp_pid == MPEGTS_FULLMUX_PID)
777 lfe->lfe_pids.all = 1;
778 else if (mp->mp_pid < MPEGTS_FULLMUX_PID) {
779 RB_FOREACH(mps, &mp->mp_subs, mps_link)
780 mpegts_pid_add(&lfe->lfe_pids, mp->mp_pid, mps->mps_weight);
781 }
782 }
783 pthread_mutex_unlock(&lfe->lfe_dvr_lock);
784
785 if (lfe->lfe_dvr_pipe.wr > 0)
786 tvh_write(lfe->lfe_dvr_pipe.wr, "c", 1);
787 }
788
789 static idnode_set_t *
linuxdvb_frontend_network_list(mpegts_input_t * mi)790 linuxdvb_frontend_network_list ( mpegts_input_t *mi )
791 {
792 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
793
794 tvhtrace(LS_LINUXDVB, "%s: network list for %s",
795 mi->mi_name ?: "", dvb_type2str(lfe->lfe_type));
796
797 return dvb_network_list_by_fe_type(lfe->lfe_type);
798 }
799
800 /* **************************************************************************
801 * Data processing
802 * *************************************************************************/
803
804 static inline int
ioctl_check(linuxdvb_frontend_t * lfe,int bit)805 ioctl_check( linuxdvb_frontend_t *lfe, int bit )
806 {
807 return !(lfe->lfe_ioctls & (1 << bit));
808 }
809
810 static inline void
ioctl_bad(linuxdvb_frontend_t * lfe,int bit)811 ioctl_bad( linuxdvb_frontend_t *lfe, int bit )
812 {
813 lfe->lfe_ioctls |= 1 << bit;
814 }
815
816 static void
linuxdvb_frontend_monitor(void * aux)817 linuxdvb_frontend_monitor ( void *aux )
818 {
819 uint16_t u16;
820 uint32_t u32;
821 char buf[256];
822 linuxdvb_frontend_t *lfe = aux;
823 mpegts_mux_instance_t *mmi = LIST_FIRST(&lfe->mi_mux_active);
824 mpegts_mux_t *mm;
825 fe_status_t fe_status;
826 signal_state_t status;
827 signal_status_t sigstat;
828 streaming_message_t sm;
829 service_t *s;
830 int logit = 0, retune, e;
831 uint32_t period = MINMAX(lfe->lfe_status_period, 250, 8000);
832 #if DVB_VER_ATLEAST(5,10)
833 struct dtv_property fe_properties[6];
834 struct dtv_properties dtv_prop;
835 int gotprop;
836 #endif
837
838 lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf));
839 tvhtrace(LS_LINUXDVB, "%s - checking FE status%s", buf, lfe->lfe_ready ? " (ready)" : "");
840
841 /* Disabled */
842 if (!lfe->mi_enabled && mmi)
843 mmi->mmi_mux->mm_stop(mmi->mmi_mux, 1, SM_CODE_ABORTED);
844
845 /* Close FE */
846 if (lfe->lfe_fe_fd > 0 && !lfe->lfe_refcount && lfe->lfe_powersave) {
847 linuxdvb_frontend_close_fd(lfe, buf);
848 return;
849 }
850
851 /* Check accessibility */
852 if (lfe->lfe_fe_fd <= 0) {
853 if (lfe->lfe_fe_path && access(lfe->lfe_fe_path, R_OK | W_OK)) {
854 tvherror(LS_LINUXDVB, "%s - device is not accessible", buf);
855 // TODO: disable device
856 return;
857 }
858 }
859
860 /* Stop timer */
861 if (!mmi || !lfe->lfe_ready) return;
862
863 /* re-arm */
864 mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, ms2mono(period));
865
866 /* Get current status */
867 if (ioctl(lfe->lfe_fe_fd, FE_READ_STATUS, &fe_status) == -1) {
868 tvhwarn(LS_LINUXDVB, "%s - FE_READ_STATUS error %s", buf, strerror(errno));
869 /* TODO: check error value */
870 return;
871
872 } else if (fe_status & FE_HAS_LOCK)
873 status = SIGNAL_GOOD;
874 else if (fe_status & (FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER))
875 status = SIGNAL_BAD;
876 else if (fe_status & FE_HAS_SIGNAL)
877 status = SIGNAL_FAINT;
878 else
879 status = SIGNAL_NONE;
880
881 /* Set default period */
882 if (fe_status != lfe->lfe_status) {
883 tvhdebug(LS_LINUXDVB, "%s - status %7s (%s%s%s%s%s%s)", buf,
884 signal2str(status),
885 (fe_status & FE_HAS_SIGNAL) ? "SIGNAL" : "",
886 (fe_status & FE_HAS_CARRIER) ? " | CARRIER" : "",
887 (fe_status & FE_HAS_VITERBI) ? " | VITERBI" : "",
888 (fe_status & FE_HAS_SYNC) ? " | SYNC" : "",
889 (fe_status & FE_HAS_LOCK) ? " | LOCK" : "",
890 (fe_status & FE_TIMEDOUT) ? "TIMEOUT" : "");
891 } else {
892 tvhtrace(LS_LINUXDVB, "%s - status %d (%04X)", buf, status, fe_status);
893 }
894 retune = NOSIGNAL(fe_status) && NOSIGNAL(lfe->lfe_status) && !NOSIGNAL(lfe->lfe_status2);
895 lfe->lfe_status2 = lfe->lfe_status;
896 lfe->lfe_status = fe_status;
897
898 /* Retune check - we lost signal or no data were received */
899 if (retune || lfe->lfe_nodata) {
900 lfe->lfe_nodata = 0;
901 if (lfe->lfe_locked && lfe->lfe_freq > 0) {
902 tvhwarn(LS_LINUXDVB, "%s - %s", buf, retune ? "retune" : "retune nodata");
903 linuxdvb_frontend_tune0(lfe, mmi, lfe->lfe_freq);
904 mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, ms2mono(50));
905 lfe->lfe_locked = 1;
906 }
907 }
908
909 /* Get current mux */
910 mm = mmi->mmi_mux;
911
912 /* Waiting for lock */
913 if (!lfe->lfe_locked) {
914
915 /* Locked */
916 if (status == SIGNAL_GOOD) {
917 tvhdebug(LS_LINUXDVB, "%s - locked", buf);
918 lfe->lfe_locked = 1;
919
920 /* Start input */
921 tvh_pipe(O_NONBLOCK, &lfe->lfe_dvr_pipe);
922 pthread_mutex_lock(&lfe->lfe_dvr_lock);
923 tvhthread_create(&lfe->lfe_dvr_thread, NULL,
924 linuxdvb_frontend_input_thread, lfe, "lnxdvb-front");
925 do {
926 e = tvh_cond_wait(&lfe->lfe_dvr_cond, &lfe->lfe_dvr_lock);
927 if (e == ETIMEDOUT)
928 break;
929 } while (ERRNO_AGAIN(e));
930 pthread_mutex_unlock(&lfe->lfe_dvr_lock);
931
932 /* Table handlers */
933 psi_tables_install((mpegts_input_t *)lfe, mm,
934 ((dvb_mux_t *)mm)->lm_tuning.dmc_fe_delsys);
935
936 /* Re-arm (quick) */
937 } else {
938 mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor,
939 lfe, ms2mono(50));
940
941 /* Monitor 1 per sec */
942 if (mclk() < lfe->lfe_monitor)
943 return;
944 lfe->lfe_monitor = mclk() + sec2mono(1);
945 }
946 } else {
947 if (mclk() < lfe->lfe_monitor)
948 return;
949 lfe->lfe_monitor = mclk() + ms2mono(period);
950 }
951
952
953 pthread_mutex_lock(&mmi->tii_stats_mutex);
954
955 /* Statistics - New API */
956 #if DVB_VER_ATLEAST(5,10)
957 memset(&fe_properties, 0, sizeof(fe_properties));
958
959 /* Signal strength */
960 fe_properties[0].cmd = DTV_STAT_SIGNAL_STRENGTH;
961
962 /* BER */
963 fe_properties[1].cmd = DTV_STAT_PRE_ERROR_BIT_COUNT;
964 fe_properties[2].cmd = DTV_STAT_PRE_TOTAL_BIT_COUNT;
965
966 /* SNR */
967 fe_properties[3].cmd = DTV_STAT_CNR;
968
969 /* PER / UNC */
970 fe_properties[4].cmd = DTV_STAT_ERROR_BLOCK_COUNT;
971 fe_properties[5].cmd = DTV_STAT_TOTAL_BLOCK_COUNT;
972 dtv_prop.num = 6;
973 dtv_prop.props = fe_properties;
974
975 logit = tvhlog_limit(&lfe->lfe_status_log, 3600);
976
977 if(ioctl_check(lfe, 0) && !lfe->lfe_old_status &&
978 !ioctl(lfe->lfe_fe_fd, FE_GET_PROPERTY, &dtv_prop)) {
979 /* Signal strength */
980 gotprop = 0;
981 if(ioctl_check(lfe, 1) && fe_properties[0].u.st.len > 0) {
982 if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
983 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
984 mmi->tii_stats.signal = fe_properties[0].u.st.stat[0].uvalue;
985 gotprop = 1;
986 }
987 else if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
988 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_DECIBEL;
989 mmi->tii_stats.signal = fe_properties[0].u.st.stat[0].svalue;
990 gotprop = 1;
991 }
992 else if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
993 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
994 gotprop = 1;
995 }
996 else {
997 ioctl_bad(lfe, 1);
998 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
999 if (logit)
1000 tvhwarn(LS_LINUXDVB, "Unhandled signal scale: %d",
1001 fe_properties[0].u.st.stat[0].scale);
1002 }
1003 }
1004 if(!gotprop && ioctl_check(lfe, 2)) {
1005 /* try old API */
1006 if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
1007 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
1008 mmi->tii_stats.signal = u16;
1009 }
1010 else {
1011 ioctl_bad(lfe, 2);
1012 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
1013 if (logit)
1014 tvhwarn(LS_LINUXDVB, "Unable to provide signal strength value.");
1015 }
1016 }
1017
1018 /* ERROR_BIT_COUNT */
1019 gotprop = 0;
1020 if(ioctl_check(lfe, 3) && fe_properties[1].u.st.len > 0) {
1021 if(fe_properties[1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
1022 mmi->tii_stats.ec_bit = fe_properties[1].u.st.stat[0].uvalue;
1023 gotprop = 1;
1024 }
1025 else {
1026 ioctl_bad(lfe, 3);
1027 if (logit)
1028 tvhwarn(LS_LINUXDVB, "Unhandled ERROR_BIT_COUNT scale: %d",
1029 fe_properties[1].u.st.stat[0].scale);
1030 }
1031 }
1032 /* TOTAL_BIT_COUNT */
1033 if(gotprop && (fe_properties[2].u.st.len > 0)) {
1034 gotprop = 0;
1035 if(ioctl_check(lfe, 4) && fe_properties[2].u.st.stat[0].scale == FE_SCALE_COUNTER) {
1036 mmi->tii_stats.tc_bit = fe_properties[2].u.st.stat[0].uvalue;
1037 gotprop = 1;
1038 }
1039 else {
1040 ioctl_bad(lfe, 4);
1041 mmi->tii_stats.ec_bit = 0; /* both values or none */
1042 if (logit)
1043 tvhwarn(LS_LINUXDVB, "Unhandled TOTAL_BIT_COUNT scale: %d",
1044 fe_properties[2].u.st.stat[0].scale);
1045 }
1046 }
1047 if(!gotprop && ioctl_check(lfe, 5)) {
1048 /* try old API */
1049 if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
1050 mmi->tii_stats.ber = u32;
1051 else {
1052 ioctl_bad(lfe, 5);
1053 if (logit)
1054 tvhwarn(LS_LINUXDVB, "Unable to provide BER value.");
1055 }
1056 }
1057
1058 /* SNR */
1059 gotprop = 0;
1060 if(ioctl_check(lfe, 6) && fe_properties[3].u.st.len > 0) {
1061 if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
1062 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
1063 mmi->tii_stats.snr = fe_properties[3].u.st.stat[0].uvalue;
1064 gotprop = 1;
1065 }
1066 else if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
1067 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_DECIBEL;
1068 mmi->tii_stats.snr = fe_properties[3].u.st.stat[0].svalue;
1069 gotprop = 1;
1070 }
1071 else if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_NOT_AVAILABLE) {
1072 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
1073 gotprop = 1;
1074 }
1075 else {
1076 ioctl_bad(lfe, 6);
1077 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
1078 if (logit)
1079 tvhwarn(LS_LINUXDVB, "Unhandled SNR scale: %d",
1080 fe_properties[3].u.st.stat[0].scale);
1081 }
1082 }
1083 if(!gotprop && ioctl_check(lfe, 7)) {
1084 /* try old API */
1085 if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
1086 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
1087 mmi->tii_stats.snr = u16;
1088 }
1089 else {
1090 ioctl_bad(lfe, 7);
1091 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
1092 if (logit)
1093 tvhwarn(LS_LINUXDVB, "Unable to provide SNR value.");
1094 }
1095 }
1096
1097 /* ERROR_BLOCK_COUNT == Uncorrected blocks (UNC) */
1098 gotprop = 0;
1099 if(ioctl_check(lfe, 8) && fe_properties[4].u.st.len > 0) {
1100 if(fe_properties[4].u.st.stat[0].scale == FE_SCALE_COUNTER) {
1101 atomic_set(&mmi->tii_stats.unc, fe_properties[4].u.st.stat[0].uvalue);
1102 mmi->tii_stats.ec_block = fe_properties[4].u.st.stat[0].uvalue;
1103 gotprop = 1;
1104 }
1105 else {
1106 ioctl_bad(lfe, 8);
1107 if (logit)
1108 tvhwarn(LS_LINUXDVB, "Unhandled ERROR_BLOCK_COUNT scale: %d",
1109 fe_properties[4].u.st.stat[0].scale);
1110 }
1111 }
1112
1113 /* TOTAL_BLOCK_COUNT */
1114 if(gotprop && (fe_properties[5].u.st.len > 0)) {
1115 gotprop = 0;
1116 if(ioctl_check(lfe, 9) && fe_properties[5].u.st.stat[0].scale == FE_SCALE_COUNTER) {
1117 mmi->tii_stats.tc_block = fe_properties[5].u.st.stat[0].uvalue;
1118 gotprop = 1;
1119 }
1120 else {
1121 ioctl_bad(lfe, 9);
1122 /* both values to none */
1123 mmi->tii_stats.ec_block = 0;
1124 atomic_set(&mmi->tii_stats.unc, 0);
1125 if (logit)
1126 tvhwarn(LS_LINUXDVB, "Unhandled TOTAL_BLOCK_COUNT scale: %d",
1127 fe_properties[5].u.st.stat[0].scale);
1128 }
1129 }
1130 if(!gotprop && ioctl_check(lfe, 10)) {
1131 /* try old API */
1132 if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32)) {
1133 atomic_set(&mmi->tii_stats.unc, u32);
1134 gotprop = 1;
1135 }
1136 else {
1137 ioctl_bad(lfe, 10);
1138 if (logit)
1139 tvhwarn(LS_LINUXDVB, "Unable to provide UNC value.");
1140 }
1141 }
1142 /* Older API */
1143 } else
1144 #endif
1145 {
1146 ioctl_bad(lfe, 0);
1147 if (ioctl_check(lfe, 1) && !ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
1148 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_RELATIVE;
1149 mmi->tii_stats.signal = u16;
1150 }
1151 else {
1152 ioctl_bad(lfe, 1);
1153 mmi->tii_stats.signal_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
1154 if (logit)
1155 tvhwarn(LS_LINUXDVB, "Unable to provide signal strength value.");
1156 }
1157 if (ioctl_check(lfe, 2) && !ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
1158 mmi->tii_stats.ber = u32;
1159 else {
1160 ioctl_bad(lfe, 2);
1161 if (logit)
1162 tvhwarn(LS_LINUXDVB, "Unable to provide BER value.");
1163 }
1164 if (ioctl_check(lfe, 3) && !ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
1165 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_RELATIVE;
1166 mmi->tii_stats.snr = u16;
1167 }
1168 else {
1169 ioctl_bad(lfe, 3);
1170 mmi->tii_stats.snr_scale = SIGNAL_STATUS_SCALE_UNKNOWN;
1171 if (logit)
1172 tvhwarn(LS_LINUXDVB, "Unable to provide SNR value.");
1173 }
1174 if (ioctl_check(lfe, 4) && !ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32))
1175 atomic_set(&mmi->tii_stats.unc, u32);
1176 else {
1177 ioctl_bad(lfe, 4);
1178 if (logit)
1179 tvhwarn(LS_LINUXDVB, "Unable to provide UNC value.");
1180 }
1181 }
1182
1183 /* Send message */
1184 sigstat.status_text = signal2str(status);
1185 sigstat.snr = mmi->tii_stats.snr;
1186 sigstat.signal = mmi->tii_stats.signal;
1187 sigstat.ber = mmi->tii_stats.ber;
1188 sigstat.unc = atomic_get(&mmi->tii_stats.unc);
1189 sigstat.signal_scale = mmi->tii_stats.signal_scale;
1190 sigstat.snr_scale = mmi->tii_stats.snr_scale;
1191 sigstat.ec_bit = mmi->tii_stats.ec_bit;
1192 sigstat.tc_bit = mmi->tii_stats.tc_bit;
1193 sigstat.ec_block = mmi->tii_stats.ec_block;
1194 sigstat.tc_block = mmi->tii_stats.tc_block;
1195 sm.sm_type = SMT_SIGNAL_STATUS;
1196 sm.sm_data = &sigstat;
1197
1198 pthread_mutex_unlock(&mmi->tii_stats_mutex);
1199
1200 LIST_FOREACH(s, &mmi->mmi_mux->mm_transports, s_active_link) {
1201 pthread_mutex_lock(&s->s_stream_mutex);
1202 streaming_pad_deliver(&s->s_streaming_pad, streaming_msg_clone(&sm));
1203 pthread_mutex_unlock(&s->s_stream_mutex);
1204 }
1205 }
1206
1207 typedef struct linuxdvb_pid {
1208 int fd;
1209 int pid;
1210 } linuxdvb_pid_t;
1211
1212 static void
linuxdvb_frontend_open_pid0(linuxdvb_frontend_t * lfe,const char * name,linuxdvb_pid_t * pids,int pids_size,int pid)1213 linuxdvb_frontend_open_pid0
1214 ( linuxdvb_frontend_t *lfe, const char *name,
1215 linuxdvb_pid_t *pids, int pids_size, int pid )
1216 {
1217 struct dmx_pes_filter_params dmx_param;
1218 int fd;
1219
1220 for ( ; pids_size > 0 && pids->fd >= 0; pids_size--, pids++);
1221 if (pids_size == 0) {
1222 tvherror(LS_LINUXDVB, "%s - maximum PID count reached, pid %d ignored",
1223 name, pid);
1224 return;
1225 }
1226
1227 /* Open DMX */
1228 fd = tvh_open(lfe->lfe_dmx_path, O_RDWR, 0);
1229 if(fd == -1) {
1230 tvherror(LS_LINUXDVB, "%s - failed to open dmx for pid %d [e=%s]",
1231 name, pid, strerror(errno));
1232 return;
1233 }
1234
1235 /* Install filter */
1236 tvhtrace(LS_LINUXDVB, "%s - open PID %04X (%d) fd %d", name, pid, pid, fd);
1237 memset(&dmx_param, 0, sizeof(dmx_param));
1238 dmx_param.pid = pid;
1239 dmx_param.input = DMX_IN_FRONTEND;
1240 dmx_param.output = DMX_OUT_TS_TAP;
1241 dmx_param.pes_type = DMX_PES_OTHER;
1242 dmx_param.flags = DMX_IMMEDIATE_START;
1243
1244 if(ioctl(fd, DMX_SET_PES_FILTER, &dmx_param)) {
1245 tvherror(LS_LINUXDVB, "%s - failed to config dmx for pid %d [e=%s]",
1246 name, pid, strerror(errno));
1247 close(fd);
1248 return;
1249 }
1250
1251 /* Store */
1252 pids->fd = fd;
1253 pids->pid = pid;
1254 }
1255
1256 static void
linuxdvb_frontend_close_pid0(linuxdvb_frontend_t * lfe,const char * name,linuxdvb_pid_t * pids,int pids_size,int pid)1257 linuxdvb_frontend_close_pid0
1258 ( linuxdvb_frontend_t *lfe, const char *name,
1259 linuxdvb_pid_t *pids, int pids_size, int pid )
1260 {
1261 for ( ; pids_size > 0 && pids->pid != pid;
1262 pids_size--, pids++);
1263 if (pids_size == 0)
1264 return;
1265 tvhtrace(LS_LINUXDVB, "%s - close PID %04X (%d) fd %d", name, pid, pid, pids->fd);
1266 close(pids->fd);
1267 pids->fd = -1;
1268 pids->pid = -1;
1269 }
1270
1271 static int
linuxdvb_pid_exists(linuxdvb_pid_t * pids,int pids_size,int pid)1272 linuxdvb_pid_exists ( linuxdvb_pid_t *pids, int pids_size, int pid )
1273 {
1274 int i;
1275 for (i = 0; i < pids_size; i++)
1276 if (pids[i].fd >= 0 && pids[i].pid == pid)
1277 return 1;
1278 return 0;
1279 }
1280
1281 static void
linuxdvb_update_pids(linuxdvb_frontend_t * lfe,const char * name,mpegts_apids_t * tuned,linuxdvb_pid_t * pids,int pids_size)1282 linuxdvb_update_pids ( linuxdvb_frontend_t *lfe, const char *name,
1283 mpegts_apids_t *tuned, linuxdvb_pid_t *pids,
1284 int pids_size )
1285 {
1286 mpegts_apids_t wpid, padd, pdel;
1287 int i, max = MAX(14, lfe->lfe_pids_max);
1288 int all = lfe->lfe_pids.all;
1289
1290 pthread_mutex_lock(&lfe->lfe_dvr_lock);
1291
1292 if (!all) {
1293 mpegts_pid_weighted(&wpid, &lfe->lfe_pids, max);
1294 if (wpid.count > max && lfe->lfe_pids_use_all) {
1295 all = 1;
1296 mpegts_pid_done(&wpid);
1297 } else {
1298 mpegts_pid_compare(&wpid, tuned, &padd, &pdel);
1299 mpegts_pid_done(&wpid);
1300 for (i = 0; i < pdel.count; i++)
1301 linuxdvb_frontend_close_pid0(lfe, name, pids, pids_size, pdel.pids[i].pid);
1302 for (i = 0; i < padd.count; i++)
1303 linuxdvb_frontend_open_pid0(lfe, name, pids, pids_size, padd.pids[i].pid);
1304 mpegts_pid_done(&padd);
1305 mpegts_pid_done(&pdel);
1306 mpegts_pid_done(tuned);
1307 mpegts_pid_weighted(tuned, &lfe->lfe_pids, max);
1308 }
1309 }
1310
1311 if (all && !linuxdvb_pid_exists(pids, pids_size, MPEGTS_FULLMUX_PID))
1312 linuxdvb_frontend_open_pid0(lfe, name, pids, pids_size, MPEGTS_FULLMUX_PID);
1313 else if (!all && linuxdvb_pid_exists(pids, pids_size, MPEGTS_FULLMUX_PID))
1314 linuxdvb_frontend_close_pid0(lfe, name, pids, pids_size, MPEGTS_FULLMUX_PID);
1315
1316 tuned->all = lfe->lfe_pids.all;
1317
1318 pthread_mutex_unlock(&lfe->lfe_dvr_lock);
1319 }
1320
1321 static void *
linuxdvb_frontend_input_thread(void * aux)1322 linuxdvb_frontend_input_thread ( void *aux )
1323 {
1324 linuxdvb_frontend_t *lfe = aux;
1325 mpegts_mux_instance_t *mmi;
1326 char name[256], b;
1327 tvhpoll_event_t ev[2];
1328 tvhpoll_t *efd;
1329 ssize_t n;
1330 size_t skip = (MIN(lfe->lfe_skip_bytes, 1024*1024) / 188) * 188;
1331 size_t counter = 0;
1332 linuxdvb_pid_t pids[128];
1333 mpegts_apids_t tuned;
1334 sbuf_t sb;
1335 int i, dvr = -1, nfds, nodata = 4;
1336
1337 mpegts_pid_init(&tuned);
1338 for (i = 0; i < ARRAY_SIZE(pids); i++) {
1339 pids[i].fd = -1;
1340 pids[i].pid = -1;
1341 }
1342
1343 /* Get MMI */
1344 pthread_mutex_lock(&lfe->lfe_dvr_lock);
1345 lfe->mi_display_name((mpegts_input_t*)lfe, name, sizeof(name));
1346 mmi = LIST_FIRST(&lfe->mi_mux_active);
1347 tvh_cond_signal(&lfe->lfe_dvr_cond, 0);
1348 pthread_mutex_unlock(&lfe->lfe_dvr_lock);
1349 if (mmi == NULL) return NULL;
1350
1351 /* Open DVR */
1352 dvr = tvh_open(lfe->lfe_dvr_path, O_RDONLY | O_NONBLOCK, 0);
1353 if (dvr < 0) {
1354 tvherror(LS_LINUXDVB, "%s - failed to open %s", name, lfe->lfe_dvr_path);
1355 return NULL;
1356 }
1357
1358 /* Setup poll */
1359 efd = tvhpoll_create(2);
1360 memset(ev, 0, sizeof(ev));
1361 ev[0].events = TVHPOLL_IN;
1362 ev[0].fd = ev[0].data.fd = dvr;
1363 ev[1].events = TVHPOLL_IN;
1364 ev[1].fd = ev[1].data.fd = lfe->lfe_dvr_pipe.rd;
1365 tvhpoll_add(efd, ev, 2);
1366
1367 /* Allocate memory */
1368 sbuf_init_fixed(&sb, MINMAX(lfe->lfe_ibuf_size, 18800, 1880000));
1369
1370 /* Subscribe PIDs */
1371 linuxdvb_update_pids(lfe, name, &tuned, pids, ARRAY_SIZE(pids));
1372
1373 /* Read */
1374 while (tvheadend_is_running()) {
1375 nfds = tvhpoll_wait(efd, ev, 1, 150);
1376 if (nfds == 0) { /* timeout */
1377 if (nodata == 0) {
1378 tvhwarn(LS_LINUXDVB, "%s - poll TIMEOUT", name);
1379 nodata = 50;
1380 lfe->lfe_nodata = 1;
1381 } else {
1382 nodata--;
1383 }
1384 }
1385 if (nfds < 1) continue;
1386 if (ev[0].data.fd == lfe->lfe_dvr_pipe.rd) {
1387 if (read(lfe->lfe_dvr_pipe.rd, &b, 1) > 0) {
1388 if (b == 'c')
1389 linuxdvb_update_pids(lfe, name, &tuned, pids, ARRAY_SIZE(pids));
1390 else
1391 break;
1392 }
1393 continue;
1394 }
1395 if (ev[0].data.fd != dvr) break;
1396
1397 nodata = 50;
1398 lfe->lfe_nodata = 0;
1399
1400 /* Read */
1401 if ((n = sbuf_tsdebug_read(mmi->mmi_mux, &sb, dvr)) < 0) {
1402 if (ERRNO_AGAIN(errno))
1403 continue;
1404 if (errno == EOVERFLOW) {
1405 tvhwarn(LS_LINUXDVB, "%s - read() EOVERFLOW", name);
1406 continue;
1407 }
1408 tvherror(LS_LINUXDVB, "%s - read() error %d (%s)",
1409 name, errno, strerror(errno));
1410 break;
1411 }
1412
1413 /* Skip the initial bytes */
1414 if (counter < skip) {
1415 counter += n;
1416 if (counter < skip) {
1417 sbuf_cut(&sb, n);
1418 } else {
1419 sbuf_cut(&sb, skip - (counter - n));
1420 }
1421 }
1422
1423 /* Process */
1424 mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi, &sb, 0, NULL);
1425 }
1426
1427 sbuf_free(&sb);
1428 tvhpoll_destroy(efd);
1429 for (i = 0; i < ARRAY_SIZE(pids); i++)
1430 if (pids[i].fd >= 0)
1431 close(pids[i].fd);
1432 mpegts_pid_done(&tuned);
1433 close(dvr);
1434 return NULL;
1435 }
1436
1437 /* **************************************************************************
1438 * Tuning
1439 * *************************************************************************/
1440
1441 typedef struct linuxdvb_tbl {
1442 int t; ///< TVH internal value
1443 int l; ///< LinuxDVB API value
1444 } linuxdvb_tbl_t;
1445
1446 #define TABLE_EOD -1
1447
1448 #if DVB_API_VERSION >= 5
1449 static int
linuxdvb2tvh(const char * prefix,linuxdvb_tbl_t * tbl,int key,int defval)1450 linuxdvb2tvh ( const char *prefix, linuxdvb_tbl_t *tbl, int key, int defval )
1451 {
1452 while (tbl->t != TABLE_EOD) {
1453 if (tbl->l == key)
1454 return tbl->t;
1455 tbl++;
1456 }
1457 tvhtrace(LS_LINUXDVB, "%s - linuxdvb2tvh failed %d", prefix, key);
1458 return defval;
1459 }
1460 #endif
1461
1462 static int
tvh2linuxdvb(const char * prefix,linuxdvb_tbl_t * tbl,int key,int defval)1463 tvh2linuxdvb ( const char *prefix, linuxdvb_tbl_t *tbl, int key, int defval )
1464 {
1465 while (tbl->t != TABLE_EOD) {
1466 if (tbl->t == key)
1467 return tbl->l;
1468 tbl++;
1469 }
1470 tvhtrace(LS_LINUXDVB, "%s - tvh2linuxdvb failed %d", prefix, key);
1471 return defval;
1472 }
1473
1474 #define TOSTR(s) #s
1475 #define TR(s, t, d) tvh2linuxdvb(TOSTR(s), t, dmc->dmc_fe_##s , d)
1476 #define TRU(s, t, d) tvh2linuxdvb(TOSTR(s), t, dmc->u.dmc_fe_##s , d)
1477
1478 #if DVB_API_VERSION >= 5
1479 static linuxdvb_tbl_t delsys_tbl[] = {
1480 { .t = DVB_SYS_DVBC_ANNEX_B, .l = SYS_DVBC_ANNEX_B },
1481 #if DVB_VER_ATLEAST(5,6)
1482 { .t = DVB_SYS_DVBC_ANNEX_A, .l = SYS_DVBC_ANNEX_A },
1483 { .t = DVB_SYS_DVBC_ANNEX_C, .l = SYS_DVBC_ANNEX_C },
1484 #else
1485 { .t = DVB_SYS_DVBC_ANNEX_A, .l = SYS_DVBC_ANNEX_AC },
1486 { .t = DVB_SYS_DVBC_ANNEX_C, .l = SYS_DVBC_ANNEX_AC },
1487 #endif
1488 { .t = DVB_SYS_DVBT, .l = SYS_DVBT },
1489 #if DVB_VER_ATLEAST(5,3)
1490 { .t = DVB_SYS_DVBT2, .l = SYS_DVBT2 },
1491 #endif
1492 { .t = DVB_SYS_DVBS, .l = SYS_DVBS },
1493 { .t = DVB_SYS_DVBS2, .l = SYS_DVBS2 },
1494 { .t = DVB_SYS_DVBH, .l = SYS_DVBH },
1495 #if DVB_VER_ATLEAST(5,1)
1496 { .t = DVB_SYS_DSS, .l = SYS_DSS },
1497 #endif
1498 { .t = DVB_SYS_ISDBT, .l = SYS_ISDBT },
1499 { .t = DVB_SYS_ISDBS, .l = SYS_ISDBS },
1500 { .t = DVB_SYS_ISDBC, .l = SYS_ISDBC },
1501 { .t = DVB_SYS_ATSC, .l = SYS_ATSC },
1502 { .t = DVB_SYS_ATSCMH, .l = SYS_ATSCMH },
1503 #if DVB_VER_ATLEAST(5,7)
1504 { .t = DVB_SYS_DTMB, .l = SYS_DTMB },
1505 #endif
1506 { .t = DVB_SYS_CMMB, .l = SYS_CMMB },
1507 { .t = DVB_SYS_DAB, .l = SYS_DAB },
1508 #if DVB_VER_ATLEAST(5,4)
1509 { .t = DVB_SYS_TURBO, .l = SYS_TURBO },
1510 #endif
1511 { .t = TABLE_EOD }
1512 };
linuxdvb2tvh_delsys(int delsys)1513 int linuxdvb2tvh_delsys ( int delsys )
1514 {
1515 return linuxdvb2tvh("delsys", delsys_tbl, delsys, DVB_SYS_NONE);
1516 }
1517 #endif
1518
1519 int
linuxdvb_frontend_clear(linuxdvb_frontend_t * lfe,mpegts_mux_instance_t * mmi)1520 linuxdvb_frontend_clear
1521 ( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi )
1522 {
1523 char buf1[256];
1524
1525 /* Open FE */
1526 lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1));
1527 tvhtrace(LS_LINUXDVB, "%s - frontend clear", buf1);
1528
1529 if (linuxdvb_frontend_open_fd(lfe, buf1))
1530 return SM_CODE_TUNING_FAILED;
1531
1532 lfe->lfe_locked = 0;
1533 lfe->lfe_status = 0;
1534 lfe->lfe_status2 = 0;
1535
1536 #if DVB_API_VERSION >= 5
1537 static struct dtv_property clear_p[] = {
1538 { .cmd = DTV_CLEAR },
1539 };
1540 static struct dtv_properties clear_cmdseq = {
1541 .num = 1,
1542 .props = clear_p
1543 };
1544 if ((ioctl(lfe->lfe_fe_fd, FE_SET_PROPERTY, &clear_cmdseq)) != 0) {
1545 tvherror(LS_LINUXDVB, "%s - DTV_CLEAR failed [e=%s]", buf1, strerror(errno));
1546 return -1;
1547 }
1548
1549 if (mmi) {
1550 dvb_mux_t *lm = (dvb_mux_t*)mmi->mmi_mux;
1551 dvb_mux_conf_t *dmc = &lm->lm_tuning;
1552
1553 struct dtv_property delsys_p;
1554 struct dtv_properties delsys_cmdseq = {
1555 .num = 1,
1556 .props = &delsys_p
1557 };
1558 delsys_p.cmd = DTV_DELIVERY_SYSTEM;
1559 delsys_p.u.data = TR(delsys, delsys_tbl, SYS_UNDEFINED);
1560 if ((ioctl(lfe->lfe_fe_fd, FE_SET_PROPERTY, &delsys_cmdseq)) != 0) {
1561 tvherror(LS_LINUXDVB, "%s - DTV_DELIVERY_SYSTEM failed [e=%s]", buf1, strerror(errno));
1562 return -1;
1563 }
1564 }
1565 #endif
1566
1567 return 0;
1568 }
1569
1570 int
linuxdvb_frontend_tune0(linuxdvb_frontend_t * lfe,mpegts_mux_instance_t * mmi,uint32_t freq)1571 linuxdvb_frontend_tune0
1572 ( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq )
1573 {
1574 static linuxdvb_tbl_t inv_tbl[] = {
1575 { .t = DVB_INVERSION_AUTO, .l = INVERSION_AUTO },
1576 { .t = DVB_INVERSION_OFF, .l = INVERSION_OFF },
1577 { .t = DVB_INVERSION_ON, .l = INVERSION_ON },
1578 { .t = TABLE_EOD }
1579 };
1580 static linuxdvb_tbl_t bw_tbl[] = {
1581 { .t = DVB_BANDWIDTH_AUTO, .l = BANDWIDTH_AUTO },
1582 #if DVB_VER_ATLEAST(5,3)
1583 { .t = DVB_BANDWIDTH_1_712_MHZ, .l = BANDWIDTH_1_712_MHZ },
1584 { .t = DVB_BANDWIDTH_5_MHZ, .l = BANDWIDTH_5_MHZ },
1585 #endif
1586 { .t = DVB_BANDWIDTH_6_MHZ, .l = BANDWIDTH_6_MHZ },
1587 { .t = DVB_BANDWIDTH_7_MHZ, .l = BANDWIDTH_7_MHZ },
1588 { .t = DVB_BANDWIDTH_8_MHZ, .l = BANDWIDTH_8_MHZ },
1589 #if DVB_VER_ATLEAST(5,3)
1590 { .t = DVB_BANDWIDTH_10_MHZ, .l = BANDWIDTH_10_MHZ },
1591 #endif
1592 { .t = TABLE_EOD }
1593 };
1594 static linuxdvb_tbl_t fec_tbl[] = {
1595 { .t = DVB_FEC_NONE, .l = FEC_NONE },
1596 { .t = DVB_FEC_AUTO, .l = FEC_AUTO },
1597 { .t = DVB_FEC_1_2, .l = FEC_1_2 },
1598 { .t = DVB_FEC_2_3, .l = FEC_2_3 },
1599 #if DVB_VER_ATLEAST(5,7)
1600 { .t = DVB_FEC_2_5, .l = FEC_2_5 },
1601 #endif
1602 { .t = DVB_FEC_3_4, .l = FEC_3_4 },
1603 #if DVB_VER_ATLEAST(5,0)
1604 { .t = DVB_FEC_3_5, .l = FEC_3_5 },
1605 #endif
1606 { .t = DVB_FEC_4_5, .l = FEC_4_5 },
1607 { .t = DVB_FEC_5_6, .l = FEC_5_6 },
1608 { .t = DVB_FEC_6_7, .l = FEC_6_7 },
1609 { .t = DVB_FEC_7_8, .l = FEC_7_8 },
1610 { .t = DVB_FEC_8_9, .l = FEC_8_9 },
1611 #if DVB_VER_ATLEAST(5,0)
1612 { .t = DVB_FEC_9_10, .l = FEC_9_10 },
1613 #endif
1614 { .t = TABLE_EOD }
1615 };
1616 static linuxdvb_tbl_t mod_tbl[] = {
1617 { .t = DVB_MOD_AUTO, .l = QAM_AUTO },
1618 { .t = DVB_MOD_QPSK, .l = QPSK },
1619 { .t = DVB_MOD_QAM_16, .l = QAM_16 },
1620 { .t = DVB_MOD_QAM_32, .l = QAM_32 },
1621 { .t = DVB_MOD_QAM_64, .l = QAM_64 },
1622 { .t = DVB_MOD_QAM_128, .l = QAM_128 },
1623 { .t = DVB_MOD_QAM_256, .l = QAM_256 },
1624 { .t = DVB_MOD_QAM_AUTO, .l = QAM_AUTO },
1625 { .t = DVB_MOD_VSB_8, .l = VSB_8 },
1626 { .t = DVB_MOD_VSB_16, .l = VSB_16 },
1627 #if DVB_VER_ATLEAST(5,1)
1628 { .t = DVB_MOD_PSK_8, .l = PSK_8, },
1629 { .t = DVB_MOD_APSK_16, .l = APSK_16 },
1630 { .t = DVB_MOD_APSK_32, .l = APSK_32 },
1631 #endif
1632 #if DVB_VER_ATLEAST(5,0)
1633 { .t = DVB_MOD_DQPSK, .l = DQPSK },
1634 #endif
1635 #if DVB_VER_ATLEAST(5,7)
1636 { .t = DVB_MOD_QAM_4_NR, .l = QAM_4_NR },
1637 #endif
1638 { .t = TABLE_EOD }
1639 };
1640 static linuxdvb_tbl_t trans_tbl[] = {
1641 { .t = DVB_TRANSMISSION_MODE_AUTO, .l = TRANSMISSION_MODE_AUTO },
1642 #if DVB_VER_ATLEAST(5,3)
1643 { .t = DVB_TRANSMISSION_MODE_1K, .l = TRANSMISSION_MODE_1K },
1644 #endif
1645 { .t = DVB_TRANSMISSION_MODE_2K, .l = TRANSMISSION_MODE_2K },
1646 #if DVB_VER_ATLEAST(5,1)
1647 { .t = DVB_TRANSMISSION_MODE_4K, .l = TRANSMISSION_MODE_4K },
1648 #endif
1649 { .t = DVB_TRANSMISSION_MODE_8K, .l = TRANSMISSION_MODE_8K },
1650 #if DVB_VER_ATLEAST(5,3)
1651 { .t = DVB_TRANSMISSION_MODE_16K, .l = TRANSMISSION_MODE_16K },
1652 { .t = DVB_TRANSMISSION_MODE_32K, .l = TRANSMISSION_MODE_32K },
1653 #endif
1654 #if DVB_VER_ATLEAST(5,7)
1655 { .t = DVB_TRANSMISSION_MODE_C3780, .l = TRANSMISSION_MODE_C3780 },
1656 { .t = DVB_TRANSMISSION_MODE_C1, .l = TRANSMISSION_MODE_C1 },
1657 #endif
1658 { .t = TABLE_EOD }
1659 };
1660 static linuxdvb_tbl_t guard_tbl[] = {
1661 { .t = DVB_GUARD_INTERVAL_AUTO, .l = GUARD_INTERVAL_AUTO },
1662 { .t = DVB_GUARD_INTERVAL_1_4, .l = GUARD_INTERVAL_1_4 },
1663 { .t = DVB_GUARD_INTERVAL_1_8, .l = GUARD_INTERVAL_1_8 },
1664 { .t = DVB_GUARD_INTERVAL_1_16, .l = GUARD_INTERVAL_1_16 },
1665 { .t = DVB_GUARD_INTERVAL_1_32, .l = GUARD_INTERVAL_1_32 },
1666 #if DVB_VER_ATLEAST(5,3)
1667 { .t = DVB_GUARD_INTERVAL_1_128, .l = GUARD_INTERVAL_1_128 },
1668 { .t = DVB_GUARD_INTERVAL_19_128, .l = GUARD_INTERVAL_19_128 },
1669 { .t = DVB_GUARD_INTERVAL_19_256, .l = GUARD_INTERVAL_19_256 },
1670 #endif
1671 { .t = TABLE_EOD }
1672 };
1673 static linuxdvb_tbl_t h_tbl[] = {
1674 { .t = DVB_HIERARCHY_NONE, .l = HIERARCHY_NONE },
1675 { .t = DVB_HIERARCHY_AUTO, .l = HIERARCHY_AUTO },
1676 { .t = DVB_HIERARCHY_1, .l = HIERARCHY_1 },
1677 { .t = DVB_HIERARCHY_2, .l = HIERARCHY_2 },
1678 { .t = DVB_HIERARCHY_4, .l = HIERARCHY_4 },
1679 { .t = TABLE_EOD }
1680 };
1681 #if DVB_API_VERSION >= 5
1682 static linuxdvb_tbl_t pilot_tbl[] = {
1683 { .t = DVB_PILOT_AUTO, .l = PILOT_AUTO },
1684 { .t = DVB_PILOT_ON, .l = PILOT_ON },
1685 { .t = DVB_PILOT_OFF, .l = PILOT_OFF },
1686 { .t = TABLE_EOD }
1687 };
1688 static linuxdvb_tbl_t rolloff_tbl[] = {
1689 { .t = DVB_HIERARCHY_AUTO, .l = ROLLOFF_AUTO },
1690 { .t = DVB_ROLLOFF_20, .l = ROLLOFF_20 },
1691 { .t = DVB_ROLLOFF_25, .l = ROLLOFF_25 },
1692 { .t = DVB_ROLLOFF_35, .l = ROLLOFF_35 },
1693 { .t = TABLE_EOD },
1694 };
1695 #endif
1696 int r;
1697 struct dvb_frontend_event ev;
1698 char buf1[256];
1699 dvb_mux_t *lm = (dvb_mux_t*)mmi->mmi_mux;
1700 dvb_mux_conf_t *dmc;
1701 struct dvb_frontend_parameters p;
1702
1703 r = linuxdvb_frontend_clear(lfe, NULL);
1704 if (r) return r;
1705
1706 lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1));
1707
1708 /*
1709 * copy the universal parameters to the Linux kernel structure
1710 */
1711
1712 dmc = &lm->lm_tuning;
1713 if (tvhtrace_enabled()) {
1714 char buf2[256];
1715 dvb_mux_conf_str(&lm->lm_tuning, buf2, sizeof(buf2));
1716 tvhtrace(LS_LINUXDVB, "tuner %s tuning to %s (freq %i)", buf1, buf2, freq);
1717 }
1718 memset(&p, 0, sizeof(p));
1719 p.frequency = dmc->dmc_fe_freq;
1720 p.inversion = TR(inversion, inv_tbl, INVERSION_AUTO);
1721 switch (dmc->dmc_fe_type) {
1722 case DVB_TYPE_T:
1723 #define _OFDM(xyz) p.u.ofdm.xyz
1724 _OFDM(bandwidth) = TRU(ofdm.bandwidth, bw_tbl, BANDWIDTH_AUTO);
1725 _OFDM(code_rate_HP) = TRU(ofdm.code_rate_HP, fec_tbl, FEC_AUTO);
1726 _OFDM(code_rate_LP) = TRU(ofdm.code_rate_LP, fec_tbl, FEC_AUTO);
1727 _OFDM(constellation) = TR(modulation, mod_tbl, QAM_AUTO);
1728 _OFDM(transmission_mode) = TRU(ofdm.transmission_mode, trans_tbl, TRANSMISSION_MODE_AUTO);
1729 _OFDM(guard_interval) = TRU(ofdm.guard_interval, guard_tbl, GUARD_INTERVAL_AUTO);
1730 _OFDM(hierarchy_information)
1731 = TRU(ofdm.hierarchy_information, h_tbl, HIERARCHY_AUTO);
1732 #undef _OFDM
1733 break;
1734 case DVB_TYPE_C:
1735 case DVB_TYPE_ATSC_C:
1736 case DVB_TYPE_ISDB_C:
1737 p.u.qam.symbol_rate = dmc->u.dmc_fe_qam.symbol_rate;
1738 p.u.qam.fec_inner = TRU(qam.fec_inner, fec_tbl, FEC_AUTO);
1739 p.u.qam.modulation = TR(modulation, mod_tbl, QAM_AUTO);
1740 break;
1741 case DVB_TYPE_S:
1742 p.u.qpsk.symbol_rate = dmc->u.dmc_fe_qpsk.symbol_rate;
1743 p.u.qpsk.fec_inner = TRU(qpsk.fec_inner, fec_tbl, FEC_AUTO);
1744 break;
1745 case DVB_TYPE_ATSC_T:
1746 p.u.vsb.modulation = TR(modulation, mod_tbl, QAM_AUTO);
1747 break;
1748 #if DVB_API_VERSION >= 5
1749 case DVB_TYPE_ISDB_T:
1750 case DVB_TYPE_DAB:
1751 break;
1752 #endif
1753 default:
1754 tvherror(LS_LINUXDVB, "%s - unknown FE type %d", buf1, dmc->dmc_fe_type);
1755 return SM_CODE_TUNING_FAILED;
1756 }
1757
1758 if (freq != (uint32_t)-1)
1759 p.frequency = lfe->lfe_freq = freq;
1760
1761 if (dmc->dmc_fe_type != lfe->lfe_type) {
1762 tvherror(LS_LINUXDVB, "%s - failed to tune [type does not match %i != %i]", buf1, dmc->dmc_fe_type, lfe->lfe_type);
1763 return SM_CODE_TUNING_FAILED;
1764 }
1765
1766 /* S2 tuning */
1767 #if DVB_API_VERSION >= 5
1768 struct dtv_property cmds[32];
1769 struct dtv_properties cmdseq;
1770
1771
1772 if (freq == (uint32_t)-1)
1773 freq = p.frequency;
1774
1775 memset(&cmdseq, 0, sizeof(cmdseq));
1776 cmdseq.props = cmds;
1777 memset(&cmds, 0, sizeof(cmds));
1778
1779 /* Tune */
1780 #define S2CMD(c, d) do { \
1781 cmds[cmdseq.num].cmd = c; \
1782 cmds[cmdseq.num++].u.data = d; \
1783 } while (0)
1784
1785 memset(&cmds, 0, sizeof(cmds));
1786 S2CMD(DTV_DELIVERY_SYSTEM, TR(delsys, delsys_tbl, SYS_UNDEFINED));
1787 S2CMD(DTV_FREQUENCY, freq);
1788 S2CMD(DTV_INVERSION, p.inversion);
1789
1790 /* DVB-T */
1791 if (lfe->lfe_type == DVB_TYPE_T) {
1792 S2CMD(DTV_BANDWIDTH_HZ, dvb_bandwidth(dmc->u.dmc_fe_ofdm.bandwidth));
1793 #if DVB_VER_ATLEAST(5,1)
1794 S2CMD(DTV_CODE_RATE_HP, p.u.ofdm.code_rate_HP);
1795 S2CMD(DTV_CODE_RATE_LP, p.u.ofdm.code_rate_LP);
1796 #endif
1797 S2CMD(DTV_MODULATION, p.u.ofdm.constellation);
1798 #if DVB_VER_ATLEAST(5,1)
1799 S2CMD(DTV_TRANSMISSION_MODE, p.u.ofdm.transmission_mode);
1800 S2CMD(DTV_GUARD_INTERVAL, p.u.ofdm.guard_interval);
1801 S2CMD(DTV_HIERARCHY, p.u.ofdm.hierarchy_information);
1802 #endif
1803 if (lm->lm_tuning.dmc_fe_delsys == DVB_SYS_DVBT2) {
1804 #if DVB_VER_ATLEAST(5,9)
1805 S2CMD(DTV_STREAM_ID, dmc->dmc_fe_stream_id);
1806 #elif DVB_VER_ATLEAST(5,3)
1807 S2CMD(DTV_DVBT2_PLP_ID, dmc->dmc_fe_stream_id);
1808 #endif
1809 }
1810 #if DVB_VER_ATLEAST(5,9)
1811 if (lfe->lfe_lna)
1812 S2CMD(DTV_LNA, 1);
1813 #endif
1814
1815 /* DVB-C */
1816 } else if (lfe->lfe_type == DVB_TYPE_C ||
1817 lfe->lfe_type == DVB_TYPE_ATSC_C ||
1818 lfe->lfe_type == DVB_TYPE_ISDB_C) {
1819 S2CMD(DTV_SYMBOL_RATE, p.u.qam.symbol_rate);
1820 S2CMD(DTV_MODULATION, p.u.qam.modulation);
1821 S2CMD(DTV_INNER_FEC, p.u.qam.fec_inner);
1822 r = dmc->dmc_fe_stream_id != DVB_NO_STREAM_ID_FILTER ? (dmc->dmc_fe_stream_id & 0xFF) |
1823 ((dmc->dmc_fe_data_slice & 0xFF)<<8) : DVB_NO_STREAM_ID_FILTER;
1824 #if DVB_VER_ATLEAST(5,9)
1825 S2CMD(DTV_STREAM_ID, r);
1826 #endif
1827
1828 /* DVB-S */
1829 } else if (lfe->lfe_type == DVB_TYPE_S) {
1830 S2CMD(DTV_SYMBOL_RATE, p.u.qpsk.symbol_rate);
1831 S2CMD(DTV_INNER_FEC, p.u.qpsk.fec_inner);
1832 S2CMD(DTV_MODULATION, TR(modulation, mod_tbl, QPSK));
1833 if (lm->lm_tuning.dmc_fe_delsys == DVB_SYS_DVBS) {
1834 S2CMD(DTV_ROLLOFF, ROLLOFF_35);
1835 } else {
1836 S2CMD(DTV_PILOT, TR(pilot, pilot_tbl, PILOT_AUTO));
1837 S2CMD(DTV_ROLLOFF, TR(rolloff, rolloff_tbl, ROLLOFF_AUTO));
1838 r = dmc->dmc_fe_stream_id != DVB_NO_STREAM_ID_FILTER ? (dmc->dmc_fe_stream_id & 0xFF) |
1839 ((dmc->dmc_fe_pls_code & 0x3FFFF)<<8) | ((dmc->dmc_fe_pls_mode & 0x3)<<26) :
1840 DVB_NO_STREAM_ID_FILTER;
1841 #if DVB_VER_ATLEAST(5,9)
1842 S2CMD(DTV_STREAM_ID, r);
1843 #if DVB_VER_ATLEAST(5,11)
1844 r = dvb_sat_pls(dmc);
1845 if (r != 0) /* default PLS gold code */
1846 S2CMD(DTV_SCRAMBLING_SEQUENCE_INDEX, r);
1847 #endif
1848 #elif DVB_VER_ATLEAST(5,3)
1849 S2CMD(DTV_DVBT2_PLP_ID, r);
1850 #endif
1851 }
1852
1853 /* ATSC-T */
1854 } else if (lfe->lfe_type == DVB_TYPE_ATSC_T) {
1855 S2CMD(DTV_MODULATION, p.u.vsb.modulation);
1856
1857 #if DVB_VER_ATLEAST(5,0)
1858 /* ISDB-T */
1859 } else if (lfe->lfe_type == DVB_TYPE_ISDB_T) {
1860 int i, j;
1861 S2CMD(DTV_BANDWIDTH_HZ, dvb_bandwidth(dmc->u.dmc_fe_isdbt.bandwidth));
1862 #if DVB_VER_ATLEAST(5,1)
1863 S2CMD(DTV_GUARD_INTERVAL, TRU(isdbt.guard_interval, guard_tbl, GUARD_INTERVAL_AUTO));
1864 S2CMD(DTV_TRANSMISSION_MODE, TRANSMISSION_MODE_AUTO);
1865 S2CMD(DTV_ISDBT_LAYER_ENABLED, 7);
1866 S2CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1);
1867 S2CMD(DTV_ISDBT_SOUND_BROADCASTING,0);
1868 S2CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0);
1869 S2CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0);
1870 S2CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0);
1871 for (i = j = 0; i < 3; i++, j += DTV_ISDBT_LAYERB_FEC - DTV_ISDBT_LAYERA_FEC) {
1872 S2CMD(DTV_ISDBT_LAYERA_FEC + j, TRU(isdbt.layers[i].fec, fec_tbl, FEC_AUTO));
1873 S2CMD(DTV_ISDBT_LAYERA_MODULATION + j, TRU(isdbt.layers[i].modulation, mod_tbl, QAM_AUTO));
1874 S2CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT + j, dmc->u.dmc_fe_isdbt.layers[i].segment_count);
1875 S2CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING + j, dmc->u.dmc_fe_isdbt.layers[i].time_interleaving);
1876 }
1877 #endif
1878
1879 /* ISDB-S */
1880 } else if (lfe->lfe_type == DVB_TYPE_ISDB_S) {
1881 r = dmc->dmc_fe_stream_id != DVB_NO_STREAM_ID_FILTER ? (dmc->dmc_fe_stream_id & 0xFF) |
1882 ((dmc->dmc_fe_pls_code & 0x3FFFF)<<8) | ((dmc->dmc_fe_pls_mode & 0x3)<<26) :
1883 DVB_NO_STREAM_ID_FILTER;
1884 #if DVB_VER_ATLEAST(5,9)
1885 S2CMD(DTV_STREAM_ID, r);
1886 #if DVB_VER_ATLEAST(5,11)
1887 r = dvb_sat_pls(dmc);
1888 if (r != 0) /* default PLS gold code */
1889 S2CMD(DTV_SCRAMBLING_SEQUENCE_INDEX, r);
1890 #endif
1891 #elif DVB_VER_ATLEAST(5,3)
1892 S2CMD(DTV_DVBT2_PLP_ID, r);
1893 #endif
1894
1895 /* DAB */
1896 } else if (lfe->lfe_type == DVB_TYPE_DAB) {
1897 #endif /* 5.0+ */
1898 }
1899
1900 /* Tune */
1901 S2CMD(DTV_TUNE, 0);
1902 #undef S2CMD
1903 #endif
1904
1905 /* discard stale events */
1906 while (1) {
1907 if (ioctl(lfe->lfe_fe_fd, FE_GET_EVENT, &ev) < 0)
1908 break;
1909 }
1910
1911 /* S2 tuning */
1912 #if DVB_API_VERSION >= 5
1913 if (tvhtrace_enabled()) {
1914 int i;
1915 for (i = 0; i < cmdseq.num; i++)
1916 tvhtrace(LS_LINUXDVB, "S2CMD %02u => %u", cmds[i].cmd, cmds[i].u.data);
1917 }
1918 r = ioctl(lfe->lfe_fe_fd, FE_SET_PROPERTY, &cmdseq);
1919
1920 /* v3 tuning */
1921 #else
1922 r = ioctl(lfe->lfe_fe_fd, FE_SET_FRONTEND, p);
1923 #endif
1924
1925 /* Failed */
1926 if (r != 0) {
1927 tvherror(LS_LINUXDVB, "%s - failed to tune [e=%s]", buf1, strerror(errno));
1928 if (errno == EINVAL)
1929 mmi->mmi_tune_failed = 1;
1930 return SM_CODE_TUNING_FAILED;
1931 }
1932
1933 return r;
1934 }
1935
1936 int
linuxdvb_frontend_tune1(linuxdvb_frontend_t * lfe,mpegts_mux_instance_t * mmi,uint32_t freq)1937 linuxdvb_frontend_tune1
1938 ( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq )
1939 {
1940 int r = 0, i, rep;
1941 char buf1[256], buf2[256];
1942
1943 lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1));
1944 mpegts_mux_nice_name(mmi->mmi_mux, buf2, sizeof(buf2));
1945 tvhdebug(LS_LINUXDVB, "%s - starting %s", buf1, buf2);
1946
1947 /* Tune */
1948 tvhtrace(LS_LINUXDVB, "%s - tuning", buf1);
1949 rep = lfe->lfe_tune_repeats > 0 ? lfe->lfe_tune_repeats : 0;
1950 for (i = 0; i <= rep; i++) {
1951 if (i > 0)
1952 tvh_safe_usleep(15000);
1953 r = linuxdvb_frontend_tune0(lfe, mmi, freq);
1954 if (r)
1955 break;
1956 }
1957
1958 /* Start monitor */
1959 if (!r) {
1960 time(&lfe->lfe_monitor);
1961 lfe->lfe_monitor += 4;
1962 mtimer_arm_rel(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, ms2mono(50));
1963 lfe->lfe_ready = 1;
1964 }
1965
1966 lfe->lfe_in_setup = 0;
1967
1968 return r;
1969 }
1970
1971
1972 /* **************************************************************************
1973 * Creation/Config
1974 * *************************************************************************/
1975
1976 static mpegts_network_t *
linuxdvb_frontend_wizard_network(linuxdvb_frontend_t * lfe)1977 linuxdvb_frontend_wizard_network ( linuxdvb_frontend_t *lfe )
1978 {
1979 linuxdvb_satconf_ele_t *ele = NULL;
1980
1981 if (lfe->lfe_satconf) {
1982 ele = TAILQ_FIRST(&lfe->lfe_satconf->ls_elements);
1983 if (ele && ele->lse_networks && ele->lse_networks->is_count > 0)
1984 return (mpegts_network_t *)ele->lse_networks->is_array[0];
1985 }
1986 return (mpegts_network_t *)LIST_FIRST(&lfe->mi_networks);
1987 }
1988
1989 static htsmsg_t *
linuxdvb_frontend_wizard_get(tvh_input_t * ti,const char * lang)1990 linuxdvb_frontend_wizard_get( tvh_input_t *ti, const char *lang )
1991 {
1992 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)ti;
1993 mpegts_network_t *mn;
1994 const idclass_t *idc = NULL;
1995
1996 mn = linuxdvb_frontend_wizard_network(lfe);
1997 if ((lfe->lfe_master == 0 && mn == NULL) || (mn && mn->mn_wizard))
1998 idc = dvb_network_class_by_fe_type(lfe->lfe_type);
1999 return mpegts_network_wizard_get((mpegts_input_t *)lfe, idc, mn, lang);
2000 }
2001
2002 static void
linuxdvb_frontend_wizard_set(tvh_input_t * ti,htsmsg_t * conf,const char * lang)2003 linuxdvb_frontend_wizard_set( tvh_input_t *ti, htsmsg_t *conf, const char *lang )
2004 {
2005 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)ti;
2006 const char *ntype = htsmsg_get_str(conf, "mpegts_network_type");
2007 mpegts_network_t *mn;
2008 htsmsg_t *nlist;
2009
2010 if (LIST_FIRST(&lfe->mi_mux_active))
2011 return;
2012 mpegts_network_wizard_create(ntype, &nlist, lang);
2013 mn = linuxdvb_frontend_wizard_network(lfe);
2014 if (ntype && (mn == NULL || mn->mn_wizard)) {
2015 if (lfe->lfe_satconf) {
2016 htsmsg_t *conf = htsmsg_create_map();
2017 htsmsg_t *elems = htsmsg_create_list();
2018 htsmsg_t *elem = htsmsg_create_map();
2019 htsmsg_add_str(conf, "type", "4port");
2020 htsmsg_add_bool(elem, "enable", 1);
2021 htsmsg_add_msg(elem, "networks", nlist);
2022 htsmsg_add_msg(elems, NULL, elem);
2023 htsmsg_add_msg(conf, "elements", elems);
2024 if (lfe->lfe_satconf) {
2025 linuxdvb_satconf_delete(lfe->lfe_satconf, 0);
2026 lfe->lfe_satconf = NULL;
2027 }
2028 lfe->lfe_satconf = linuxdvb_satconf_create(lfe, conf);
2029 htsmsg_destroy(conf);
2030 } else {
2031 mpegts_input_set_networks((mpegts_input_t *)lfe, nlist);
2032 htsmsg_destroy(nlist);
2033 }
2034 if (linuxdvb_frontend_wizard_network(lfe))
2035 mpegts_input_set_enabled((mpegts_input_t *)lfe, 1);
2036 linuxdvb_adapter_changed(lfe->lfe_adapter);
2037 } else {
2038 htsmsg_destroy(nlist);
2039 }
2040 }
2041
2042 linuxdvb_frontend_t *
linuxdvb_frontend_create(htsmsg_t * conf,linuxdvb_adapter_t * la,int number,const char * fe_path,const char * dmx_path,const char * dvr_path,dvb_fe_type_t type,const char * name)2043 linuxdvb_frontend_create
2044 ( htsmsg_t *conf, linuxdvb_adapter_t *la, int number,
2045 const char *fe_path, const char *dmx_path, const char *dvr_path,
2046 dvb_fe_type_t type, const char *name )
2047 {
2048 const idclass_t *idc;
2049 const char *str, *uuid = NULL, *muuid = NULL;
2050 char id[16], lname[256], buf[256];
2051 linuxdvb_frontend_t *lfe;
2052 htsmsg_t *scconf;
2053 ssize_t r;
2054
2055 /* Tuner slave */
2056 snprintf(id, sizeof(id), "master for #%d", number);
2057 if (conf && type == DVB_TYPE_S) {
2058 muuid = htsmsg_get_str(conf, id);
2059 if (muuid && uuid && !strcmp(muuid, uuid))
2060 muuid = NULL;
2061 }
2062
2063 /* Internal config ID */
2064 snprintf(id, sizeof(id), "%s #%d", dvb_type2str(type), number);
2065 if (conf)
2066 conf = htsmsg_get_map(conf, id);
2067 if (conf)
2068 uuid = htsmsg_get_str(conf, "uuid");
2069
2070 /* Fudge configuration for old network entry */
2071 if (conf) {
2072 if (!htsmsg_get_list(conf, "networks") &&
2073 (str = htsmsg_get_str(conf, "network"))) {
2074 htsmsg_t *l = htsmsg_create_list();
2075 htsmsg_add_str(l, NULL, str);
2076 htsmsg_add_msg(conf, "networks", l);
2077 }
2078 }
2079
2080 /* Class */
2081 if (type == DVB_TYPE_S)
2082 idc = muuid ? &linuxdvb_frontend_dvbs_slave_class :
2083 &linuxdvb_frontend_dvbs_class;
2084 else if (type == DVB_TYPE_C)
2085 idc = &linuxdvb_frontend_dvbc_class;
2086 else if (type == DVB_TYPE_T)
2087 idc = &linuxdvb_frontend_dvbt_class;
2088 else if (type == DVB_TYPE_ATSC_T)
2089 idc = &linuxdvb_frontend_atsc_t_class;
2090 else if (type == DVB_TYPE_ATSC_C)
2091 idc = &linuxdvb_frontend_atsc_c_class;
2092 else if (type == DVB_TYPE_ISDB_T)
2093 idc = &linuxdvb_frontend_isdb_t_class;
2094 else if (type == DVB_TYPE_ISDB_C)
2095 idc = &linuxdvb_frontend_isdb_c_class;
2096 else if (type == DVB_TYPE_ISDB_S)
2097 idc = &linuxdvb_frontend_isdb_s_class;
2098 else if (type == DVB_TYPE_DAB)
2099 idc = &linuxdvb_frontend_dab_class;
2100 else {
2101 tvherror(LS_LINUXDVB, "unknown FE type %d", type);
2102 return NULL;
2103 }
2104
2105 /* Create */
2106 // Note: there is a bit of a chicken/egg issue below, without the
2107 // correct "fe_type" we cannot set the network (which is done
2108 // in mpegts_input_create()). So we must set early.
2109 lfe = calloc(1, sizeof(linuxdvb_frontend_t));
2110 lfe->lfe_number = number;
2111 lfe->lfe_type = type;
2112 lfe->lfe_master = muuid ? strdup(muuid) : NULL;
2113 strncpy(lfe->lfe_name, name, sizeof(lfe->lfe_name));
2114 lfe->lfe_name[sizeof(lfe->lfe_name)-1] = '\0';
2115 lfe->lfe_ibuf_size = 188000;
2116 lfe->lfe_status_period = 1000;
2117 lfe->lfe_pids_max = 32;
2118 lfe->lfe_pids_use_all = 1;
2119 lfe = (linuxdvb_frontend_t*)mpegts_input_create0((mpegts_input_t*)lfe, idc, uuid, conf);
2120 if (!lfe) return NULL;
2121
2122 /* Sysfs path */
2123 snprintf(lname, sizeof(lname), "/sys/class/dvb/dvb%d.frontend%d", la->la_dvb_number, number);
2124 r = readlink(lname, buf, sizeof(buf));
2125 if (r > 0) {
2126 if (r == sizeof(buf)) r--;
2127 buf[r] = '\0';
2128 if (strncmp(str = buf, "../../", 6) == 0) str += 6;
2129 lfe->lfe_sysfs = strdup(str);
2130 }
2131
2132 /* Callbacks */
2133 lfe->mi_get_weight = linuxdvb_frontend_get_weight;
2134 lfe->mi_get_priority = linuxdvb_frontend_get_priority;
2135 lfe->mi_get_grace = linuxdvb_frontend_get_grace;
2136
2137 /* Default name */
2138 if (!lfe->mi_name) {
2139 snprintf(lname, sizeof(lname), "%s : %s", name, id);
2140 lfe->mi_name = strdup(lname);
2141 }
2142
2143 /* Set paths */
2144 lfe->lfe_fe_path = strdup(fe_path);
2145 lfe->lfe_dmx_path = strdup(dmx_path);
2146 lfe->lfe_dvr_path = strdup(dvr_path);
2147
2148 /* Input callbacks */
2149 lfe->ti_wizard_get = linuxdvb_frontend_wizard_get;
2150 lfe->ti_wizard_set = linuxdvb_frontend_wizard_set;
2151 lfe->mi_is_enabled = linuxdvb_frontend_is_enabled;
2152 lfe->mi_warm_mux = linuxdvb_frontend_warm_mux;
2153 lfe->mi_start_mux = linuxdvb_frontend_start_mux;
2154 lfe->mi_stop_mux = linuxdvb_frontend_stop_mux;
2155 lfe->mi_network_list = linuxdvb_frontend_network_list;
2156 lfe->mi_update_pids = linuxdvb_frontend_update_pids;
2157 lfe->mi_enabled_updated = linuxdvb_frontend_enabled_updated;
2158 lfe->mi_empty_status = mpegts_input_empty_status;
2159
2160 /* Adapter link */
2161 lfe->lfe_adapter = la;
2162 LIST_INSERT_HEAD(&la->la_frontends, lfe, lfe_link);
2163
2164 /* DVR lock/cond */
2165 pthread_mutex_init(&lfe->lfe_dvr_lock, NULL);
2166 tvh_cond_init(&lfe->lfe_dvr_cond);
2167 mpegts_pid_init(&lfe->lfe_pids);
2168
2169 /* Create satconf */
2170 if (lfe->lfe_type == DVB_TYPE_S && !lfe->lfe_satconf && !muuid) {
2171 scconf = conf ? htsmsg_get_map(conf, "satconf") : NULL;
2172 lfe->lfe_satconf = linuxdvb_satconf_create(lfe, scconf);
2173 }
2174
2175 /* Double check enabled */
2176 linuxdvb_frontend_enabled_updated((mpegts_input_t*)lfe);
2177
2178 return lfe;
2179 }
2180
2181 void
linuxdvb_frontend_save(linuxdvb_frontend_t * lfe,htsmsg_t * fe)2182 linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *fe )
2183 {
2184 char id[16], ubuf[UUID_HEX_SIZE];
2185 htsmsg_t *m = htsmsg_create_map();
2186
2187 /* Save frontend */
2188 mpegts_input_save((mpegts_input_t*)lfe, m);
2189 htsmsg_add_str(m, "type", dvb_type2str(lfe->lfe_type));
2190 htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&lfe->ti_id, ubuf));
2191 if (lfe->lfe_satconf && !lfe->lfe_master) {
2192 htsmsg_t *s = htsmsg_create_map();
2193 linuxdvb_satconf_save(lfe->lfe_satconf, s);
2194 htsmsg_add_str(s, "uuid", idnode_uuid_as_str(&lfe->lfe_satconf->ls_id, ubuf));
2195 htsmsg_add_msg(m, "satconf", s);
2196 }
2197 htsmsg_delete_field(m, "fe_master");
2198
2199 /* Add to list */
2200 snprintf(id, sizeof(id), "%s #%d", dvb_type2str(lfe->lfe_type), lfe->lfe_number);
2201 htsmsg_add_msg(fe, id, m);
2202
2203 if (lfe->lfe_master) {
2204 snprintf(id, sizeof(id), "master for #%d", lfe->lfe_number);
2205 htsmsg_add_str(fe, id, lfe->lfe_master);
2206 }
2207 }
2208
2209 void
linuxdvb_frontend_delete(linuxdvb_frontend_t * lfe)2210 linuxdvb_frontend_delete ( linuxdvb_frontend_t *lfe )
2211 {
2212 lock_assert(&global_lock);
2213
2214 /* Ensure we're stopped */
2215 mpegts_input_stop_all((mpegts_input_t*)lfe);
2216
2217 /* Stop monitor */
2218 mtimer_disarm(&lfe->lfe_monitor_timer);
2219
2220 /* Close FDs */
2221 if (lfe->lfe_fe_fd > 0)
2222 close(lfe->lfe_fe_fd);
2223
2224 /* Remove from adapter */
2225 LIST_REMOVE(lfe, lfe_link);
2226
2227 /* Free memory */
2228 free(lfe->lfe_sysfs);
2229 free(lfe->lfe_fe_path);
2230 free(lfe->lfe_dmx_path);
2231 free(lfe->lfe_dvr_path);
2232 free(lfe->lfe_master);
2233
2234 /* Delete satconf */
2235 if (lfe->lfe_satconf)
2236 linuxdvb_satconf_delete(lfe->lfe_satconf, 0);
2237
2238 /* Finish */
2239 mpegts_input_delete((mpegts_input_t*)lfe, 0);
2240 }
2241
2242 /******************************************************************************
2243 * Editor Configuration
2244 *
2245 * vim:sts=2:ts=2:sw=2:et
2246 *****************************************************************************/
2247