smb2: add libdsm netbios resolver
[vlc.git] / modules / access / dtv / linux.c
blob1c097620a3be912ca4035b345ac9336a2e68de8c
1 /**
2 * @file linux.c
3 * @brief Linux DVB API version 5
4 */
5 /*****************************************************************************
6 * Copyright © 2011 Rémi Denis-Courmont
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
27 #include <vlc_common.h>
28 #include <vlc_fs.h>
29 #include <vlc_interrupt.h>
31 #include <errno.h>
32 #include <assert.h>
33 #include <fcntl.h>
34 #include <poll.h>
35 #include <unistd.h>
36 #include <sys/ioctl.h>
37 #include <linux/dvb/version.h>
38 #include <linux/dvb/frontend.h>
39 #include <linux/dvb/dmx.h>
41 #include "dtv/dtv.h"
42 #include "dtv/en50221.h"
44 #ifndef O_SEARCH
45 # define O_SEARCH O_RDONLY
46 #endif
48 #define DVBv5(minor) \
49 (DVB_API_VERSION > 5 \
50 || (DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= (minor)))
52 typedef struct
54 int vlc;
55 int linux_;
56 } dvb_int_map_t;
58 static int icmp (const void *a, const void *b)
60 const int *key = a;
61 const dvb_int_map_t *entry = b;
62 return *key - entry->vlc;
65 /** Maps a VLC config integer to a Linux DVB enum value */
66 static int dvb_parse_int (int i, const dvb_int_map_t *map, size_t n, int def)
68 const dvb_int_map_t *p = bsearch(&i, map, n, sizeof (*map), icmp);
69 return (p != NULL) ? p->linux_ : def;
72 typedef const struct
74 char vlc[8];
75 int linux_;
76 } dvb_str_map_t;
78 static int scmp (const void *a, const void *b)
80 const char *key = a;
81 dvb_str_map_t *entry = b;
82 return strcmp (key, entry->vlc);
85 /** Maps a VLC config string to a Linux DVB enum value */
86 static int dvb_parse_str (const char *str, const dvb_str_map_t *map, size_t n,
87 int def)
89 if (str != NULL)
91 const dvb_str_map_t *p = bsearch (str, map, n, sizeof (*map), scmp);
92 if (p != NULL)
93 def = p->linux_;
95 return def;
98 /*** Modulations ***/
99 static int dvb_parse_modulation (const char *str, int def)
101 static const dvb_str_map_t mods[] =
103 { "128QAM", QAM_128 },
104 { "16APSK", APSK_16 },
105 { "16QAM", QAM_16 },
106 { "16VSB", VSB_16 },
107 { "256QAM", QAM_256 },
108 { "32APSK", APSK_32 },
109 { "32QAM", QAM_32 },
110 { "64QAM", QAM_64 },
111 { "8PSK", PSK_8 },
112 { "8VSB", VSB_8 },
113 { "DQPSK", DQPSK },
114 { "QAM", QAM_AUTO },
115 { "QPSK", QPSK },
117 return dvb_parse_str (str, mods, sizeof (mods) / sizeof (*mods), def);
120 static int dvb_parse_fec (uint32_t fec)
122 static const dvb_int_map_t rates[] =
124 { 0, FEC_NONE },
125 { VLC_FEC(1,2), FEC_1_2 },
126 // TODO: 1/3
127 // TODO: 1/4
128 { VLC_FEC(2,3), FEC_2_3 },
129 { VLC_FEC(3,4), FEC_3_4 },
130 { VLC_FEC(3,5), FEC_3_5 },
131 { VLC_FEC(4,5), FEC_4_5 },
132 { VLC_FEC(5,6), FEC_5_6 },
133 { VLC_FEC(6,7), FEC_6_7 },
134 { VLC_FEC(7,8), FEC_7_8 },
135 { VLC_FEC(8,9), FEC_8_9 },
136 { VLC_FEC(9,10), FEC_9_10 },
137 { VLC_FEC_AUTO, FEC_AUTO },
139 return dvb_parse_int (fec, rates, sizeof (rates) / sizeof (*rates),
140 FEC_AUTO);
144 struct dvb_device
146 vlc_object_t *obj;
147 int dir;
148 int demux;
149 int frontend;
150 #ifndef USE_DMX
151 # define MAX_PIDS 256
152 struct
154 int fd;
155 uint16_t pid;
156 } pids[MAX_PIDS];
157 #endif
158 cam_t *cam;
159 uint8_t device;
160 bool budget;
161 //size_t buffer_size;
164 /** Opens the device directory for the specified DVB adapter */
165 static int dvb_open_adapter (uint8_t adapter)
167 char dir[20];
169 snprintf (dir, sizeof (dir), "/dev/dvb/adapter%"PRIu8, adapter);
170 return vlc_open (dir, O_SEARCH|O_DIRECTORY);
173 /** Opens the DVB device node of the specified type */
174 static int dvb_open_node (dvb_device_t *d, const char *type, int flags)
176 char path[strlen (type) + 4];
178 snprintf (path, sizeof (path), "%s%u", type, d->device);
179 return vlc_openat (d->dir, path, flags | O_NONBLOCK);
183 * Opens the DVB tuner
185 dvb_device_t *dvb_open (vlc_object_t *obj)
187 dvb_device_t *d = malloc (sizeof (*d));
188 if (unlikely(d == NULL))
189 return NULL;
191 d->obj = obj;
193 uint8_t adapter = var_InheritInteger (obj, "dvb-adapter");
194 d->device = var_InheritInteger (obj, "dvb-device");
196 d->dir = dvb_open_adapter (adapter);
197 if (d->dir == -1)
199 msg_Err (obj, "cannot access adapter %"PRIu8": %s", adapter,
200 vlc_strerror_c(errno));
201 free (d);
202 return NULL;
204 d->frontend = -1;
205 d->cam = NULL;
206 d->budget = var_InheritBool (obj, "dvb-budget-mode");
208 #ifndef USE_DMX
209 if (d->budget)
210 #endif
212 d->demux = dvb_open_node (d, "demux", O_RDONLY);
213 if (d->demux == -1)
215 msg_Err (obj, "cannot access demultiplexer: %s",
216 vlc_strerror_c(errno));
217 vlc_close (d->dir);
218 free (d);
219 return NULL;
222 if (ioctl (d->demux, DMX_SET_BUFFER_SIZE, 1 << 20) < 0)
223 msg_Warn (obj, "cannot expand demultiplexing buffer: %s",
224 vlc_strerror_c(errno));
226 /* We need to filter at least one PID. The tap for TS demultiplexing
227 * cannot be configured otherwise. So add the PAT. */
228 struct dmx_pes_filter_params param;
230 param.pid = d->budget ? 0x2000 : 0x000;
231 param.input = DMX_IN_FRONTEND;
232 param.output = DMX_OUT_TSDEMUX_TAP;
233 param.pes_type = DMX_PES_OTHER;
234 param.flags = DMX_IMMEDIATE_START;
235 if (ioctl (d->demux, DMX_SET_PES_FILTER, &param) < 0)
237 msg_Err (obj, "cannot setup TS demultiplexer: %s",
238 vlc_strerror_c(errno));
239 goto error;
241 #ifndef USE_DMX
243 else
245 for (size_t i = 0; i < MAX_PIDS; i++)
246 d->pids[i].pid = d->pids[i].fd = -1;
247 d->demux = dvb_open_node (d, "dvr", O_RDONLY);
248 if (d->demux == -1)
250 msg_Err (obj, "cannot access DVR: %s", vlc_strerror_c(errno));
251 vlc_close (d->dir);
252 free (d);
253 return NULL;
255 #endif
258 int ca = dvb_open_node (d, "ca", O_RDWR);
259 if (ca != -1)
261 d->cam = en50221_Init (obj, ca);
262 if (d->cam == NULL)
263 vlc_close (ca);
265 else
266 msg_Dbg (obj, "conditional access module not available: %s",
267 vlc_strerror_c(errno));
268 return d;
270 error:
271 dvb_close (d);
272 return NULL;
275 void dvb_close (dvb_device_t *d)
277 #ifndef USE_DMX
278 if (!d->budget)
280 for (size_t i = 0; i < MAX_PIDS; i++)
281 if (d->pids[i].fd != -1)
282 vlc_close (d->pids[i].fd);
284 #endif
285 if (d->cam != NULL)
286 en50221_End (d->cam);
287 if (d->frontend != -1)
288 vlc_close (d->frontend);
289 vlc_close (d->demux);
290 vlc_close (d->dir);
291 free (d);
294 static void dvb_frontend_status(vlc_object_t *obj, fe_status_t s)
296 msg_Dbg(obj, "frontend status:");
297 #define S(f) \
298 if (s & FE_ ## f) \
299 msg_Dbg(obj, "\t%s", #f);
301 S(HAS_SIGNAL);
302 S(HAS_CARRIER);
303 S(HAS_VITERBI);
304 S(HAS_SYNC);
305 S(HAS_LOCK);
306 S(TIMEDOUT);
307 S(REINIT);
308 #undef S
312 * Reads TS data from the tuner.
313 * @return number of bytes read, 0 on EOF, -1 if no data (yet).
315 ssize_t dvb_read (dvb_device_t *d, void *buf, size_t len, int ms)
317 struct pollfd ufd[2];
318 int n;
320 if (d->cam != NULL)
321 en50221_Poll (d->cam);
323 ufd[0].fd = d->demux;
324 ufd[0].events = POLLIN;
325 if (d->frontend != -1)
327 ufd[1].fd = d->frontend;
328 ufd[1].events = POLLPRI;
329 n = 2;
331 else
332 n = 1;
334 errno = 0;
335 n = vlc_poll_i11e (ufd, n, ms);
336 if (n == 0)
337 errno = EAGAIN;
338 if (n <= 0)
339 return -1;
341 if (d->frontend != -1 && ufd[1].revents)
343 struct dvb_frontend_event ev;
345 if (ioctl (d->frontend, FE_GET_EVENT, &ev) < 0)
347 if (errno == EOVERFLOW)
349 msg_Err (d->obj, "cannot dequeue events fast enough!");
350 return -1;
352 msg_Err (d->obj, "cannot dequeue frontend event: %s",
353 vlc_strerror_c(errno));
354 return 0;
357 dvb_frontend_status(d->obj, ev.status);
360 if (ufd[0].revents)
362 ssize_t val = read (d->demux, buf, len);
363 if (val == -1 && (errno != EAGAIN && errno != EINTR))
365 if (errno == EOVERFLOW)
367 msg_Err (d->obj, "cannot demux data fast enough!");
368 return -1;
370 msg_Err (d->obj, "cannot demux: %s", vlc_strerror_c(errno));
371 return 0;
373 return val;
376 return -1;
379 int dvb_add_pid (dvb_device_t *d, uint16_t pid)
381 if (d->budget)
382 return 0;
383 #ifdef USE_DMX
384 if (pid == 0 || ioctl (d->demux, DMX_ADD_PID, &pid) >= 0)
385 return 0;
386 #else
387 for (size_t i = 0; i < MAX_PIDS; i++)
389 if (d->pids[i].pid == pid)
390 return 0;
391 if (d->pids[i].fd != -1)
392 continue;
394 int fd = dvb_open_node (d, "demux", O_RDONLY);
395 if (fd == -1)
396 goto error;
398 /* We need to filter at least one PID. The tap for TS demultiplexing
399 * cannot be configured otherwise. So add the PAT. */
400 struct dmx_pes_filter_params param;
402 param.pid = pid;
403 param.input = DMX_IN_FRONTEND;
404 param.output = DMX_OUT_TS_TAP;
405 param.pes_type = DMX_PES_OTHER;
406 param.flags = DMX_IMMEDIATE_START;
407 if (ioctl (fd, DMX_SET_PES_FILTER, &param) < 0)
409 vlc_close (fd);
410 goto error;
412 d->pids[i].fd = fd;
413 d->pids[i].pid = pid;
414 return 0;
416 errno = EMFILE;
417 error:
418 #endif
419 msg_Err (d->obj, "cannot add PID 0x%04"PRIu16": %s", pid,
420 vlc_strerror_c(errno));
421 return -1;
424 void dvb_remove_pid (dvb_device_t *d, uint16_t pid)
426 if (d->budget)
427 return;
428 #ifdef USE_DMX
429 if (pid != 0)
430 ioctl (d->demux, DMX_REMOVE_PID, &pid);
431 #else
432 for (size_t i = 0; i < MAX_PIDS; i++)
434 if (d->pids[i].pid == pid)
436 vlc_close (d->pids[i].fd);
437 d->pids[i].pid = d->pids[i].fd = -1;
438 return;
441 #endif
444 bool dvb_get_pid_state (const dvb_device_t *d, uint16_t pid)
446 if (d->budget)
447 return true;
449 for (size_t i = 0; i < MAX_PIDS; i++)
450 if (d->pids[i].pid == pid)
451 return true;
453 return false;
456 /** Finds a frontend of the correct type */
457 static int dvb_open_frontend (dvb_device_t *d)
459 if (d->frontend != -1)
460 return 0;
461 int fd = dvb_open_node (d, "frontend", O_RDWR);
462 if (fd == -1)
464 msg_Err (d->obj, "cannot access frontend: %s", vlc_strerror_c(errno));
465 return -1;
468 d->frontend = fd;
469 return 0;
471 #define dvb_find_frontend(d, sys) (dvb_open_frontend(d))
474 * Detects supported delivery systems.
475 * @return a bit mask of supported systems (zero on failure)
477 unsigned dvb_enum_systems (dvb_device_t *d)
479 if (dvb_open_frontend (d))
480 return 0;
481 #if DVBv5(5)
482 struct dtv_property prop[2] = {
483 { .cmd = DTV_API_VERSION },
484 { .cmd = DTV_ENUM_DELSYS },
486 struct dtv_properties props = {
487 .num = 2,
488 .props = prop
491 if (ioctl (d->frontend, FE_GET_PROPERTY, &props) < 0)
493 msg_Err (d->obj, "cannot enumerate frontend systems: %s",
494 vlc_strerror_c(errno));
495 goto legacy;
498 static const unsigned systab[] = {
499 [SYS_UNDEFINED] = 0,
500 [SYS_DVBC_ANNEX_A] = DTV_DELIVERY_DVB_C,
501 [SYS_DVBC_ANNEX_B] = DTV_DELIVERY_CQAM,
502 [SYS_DVBT] = DTV_DELIVERY_DVB_T,
503 //[SYS_DSS]
504 [SYS_DVBS] = DTV_DELIVERY_DVB_S,
505 [SYS_DVBS2] = DTV_DELIVERY_DVB_S2,
506 //[SYS_DVBH]
507 [SYS_ISDBT] = DTV_DELIVERY_ISDB_T,
508 [SYS_ISDBS] = DTV_DELIVERY_ISDB_S,
509 [SYS_ISDBC] = DTV_DELIVERY_ISDB_C, // no drivers exist (as of 3.3-rc6)
510 [SYS_ATSC] = DTV_DELIVERY_ATSC,
511 //[SYS_ATSCMH]
512 //[SYS_DMBTH]
513 //[SYS_CMMB]
514 //[SYS_DAB]
515 [SYS_DVBT2] = DTV_DELIVERY_DVB_T2,
516 //[SYS_TURBO]
517 [SYS_DVBC_ANNEX_C] = DTV_DELIVERY_ISDB_C, // another name for ISDB-C?
519 unsigned systems = 0;
521 msg_Dbg (d->obj, "probing frontend (kernel API v%u.%u, user API v%u.%u)",
522 prop[0].u.data >> 8, prop[0].u.data & 0xFF,
523 DVB_API_VERSION, DVB_API_VERSION_MINOR);
525 for (size_t i = 0; i < prop[1].u.buffer.len; i++)
527 unsigned sys = prop[1].u.buffer.data[i];
529 if (sys >= (sizeof (systab) / sizeof (systab[0])) || !systab[sys])
531 msg_Warn (d->obj, "unknown delivery system %u", sys);
532 continue;
534 msg_Dbg (d->obj, " system %u", sys);
535 systems |= systab[sys];
538 return systems;
539 legacy:
540 props.num = 1;
541 #else
542 struct dtv_property prop[1] = {
543 { .cmd = DTV_API_VERSION },
545 struct dtv_properties props = {
546 .num = 1,
547 .props = prop
549 unsigned systems = 0;
550 #endif
551 if (ioctl (d->frontend, FE_GET_PROPERTY, &props) < 0)
553 msg_Err (d->obj, "unsupported kernel DVB version 3 or older (%s)",
554 vlc_strerror_c(errno));
555 return 0;
558 msg_Dbg (d->obj, "probing frontend (kernel API v%u.%u, user API v%u.%u)",
559 prop[0].u.data >> 8, prop[0].u.data & 0xFF,
560 DVB_API_VERSION, DVB_API_VERSION_MINOR);
561 #if !DVBv5(5)
562 /* Some delivery systems cannot be detected without the DVB API v5.5.
563 * To run correctly on recent kernels (Linux >= 3.3),
564 * VLC needs to be compiled with up-to-date kernel headers. */
565 if ((prop[0].u.data >> 8) > 5
566 || ((prop[0].u.data >> 8) == 5 && (prop[0].u.data & 0xFF) >= 5))
567 msg_Err (d->obj, "obsolete user API version running on a new kernel");
568 msg_Info (d->obj, "please recompile "PACKAGE_NAME" "PACKAGE_VERSION);
569 #endif
570 struct dvb_frontend_info info;
571 if (ioctl (d->frontend, FE_GET_INFO, &info) < 0)
573 msg_Err (d->obj, "cannot get frontend info: %s",
574 vlc_strerror_c(errno));
575 return 0;
577 msg_Dbg (d->obj, " name %s", info.name);
578 msg_Dbg (d->obj, " type %u, capabilities 0x%08X", info.type, info.caps);
579 msg_Dbg (d->obj, " frequencies %10"PRIu32" to %10"PRIu32,
580 info.frequency_min, info.frequency_max);
581 msg_Dbg (d->obj, " (%"PRIu32" tolerance, %"PRIu32" per step)",
582 info.frequency_tolerance, info.frequency_stepsize);
583 msg_Dbg (d->obj, " bauds rates %10"PRIu32" to %10"PRIu32,
584 info.symbol_rate_min, info.symbol_rate_max);
585 msg_Dbg (d->obj, " (%"PRIu32" tolerance)", info.symbol_rate_tolerance);
587 /* DVB first generation and ATSC */
588 switch (info.type)
590 case FE_QPSK: systems = DTV_DELIVERY_DVB_S; break;
591 case FE_QAM: systems = DTV_DELIVERY_DVB_C; break;
592 case FE_OFDM: systems = DTV_DELIVERY_DVB_T; break;
593 case FE_ATSC: systems = DTV_DELIVERY_ATSC | DTV_DELIVERY_CQAM; break;
594 default:
595 msg_Err (d->obj, "unknown frontend type %u", info.type);
598 /* DVB 2nd generation */
599 switch (info.type)
601 case FE_QPSK:
602 case FE_QAM:
603 case FE_OFDM:
604 if (info.caps & FE_CAN_2G_MODULATION)
605 systems |= systems << 1; /* DVB_foo -> DVB_foo|DVB_foo2 */
606 default:
607 break;
610 /* ISDB (only terrestrial before DVBv5.5) */
611 if (info.type == FE_OFDM)
612 systems |= DTV_DELIVERY_ISDB_T;
614 return systems;
617 float dvb_get_signal_strength (dvb_device_t *d)
619 uint16_t strength;
621 if (d->frontend == -1
622 || ioctl (d->frontend, FE_READ_SIGNAL_STRENGTH, &strength) < 0)
623 return 0.;
624 return strength / 65535.;
627 float dvb_get_snr (dvb_device_t *d)
629 uint16_t snr;
631 if (d->frontend == -1 || ioctl (d->frontend, FE_READ_SNR, &snr) < 0)
632 return 0.;
633 return snr / 65535.;
636 bool dvb_set_ca_pmt (dvb_device_t *d, en50221_capmt_info_t *p_capmtinfo)
638 if (d->cam != NULL)
640 en50221_SetCAPMT (d->cam, p_capmtinfo);
641 return true;
643 return false;
646 static int dvb_vset_props (dvb_device_t *d, size_t n, va_list ap)
648 assert (n <= DTV_IOCTL_MAX_MSGS);
650 struct dtv_property buf[n], *prop = buf;
651 struct dtv_properties props = { .num = n, .props = buf };
653 memset (buf, 0, sizeof (buf));
655 while (n > 0)
657 prop->cmd = va_arg (ap, uint32_t);
658 prop->u.data = va_arg (ap, uint32_t);
659 msg_Dbg (d->obj, "setting property %2"PRIu32" to %"PRIu32,
660 prop->cmd, prop->u.data);
661 prop++;
662 n--;
665 if (ioctl (d->frontend, FE_SET_PROPERTY, &props) < 0)
667 msg_Err (d->obj, "cannot set frontend tuning parameters: %s",
668 vlc_strerror_c(errno));
669 return -1;
671 return 0;
674 static int dvb_set_props (dvb_device_t *d, size_t n, ...)
676 va_list ap;
677 int ret;
679 va_start (ap, n);
680 ret = dvb_vset_props (d, n, ap);
681 va_end (ap);
682 return ret;
685 static int dvb_set_prop (dvb_device_t *d, uint32_t prop, uint32_t val)
687 return dvb_set_props (d, 1, prop, val);
690 int dvb_set_inversion (dvb_device_t *d, int v)
692 switch (v)
694 case 0: v = INVERSION_OFF; break;
695 case 1: v = INVERSION_ON; break;
696 default: v = INVERSION_AUTO; break;
698 return dvb_set_prop (d, DTV_INVERSION, v);
701 int dvb_tune (dvb_device_t *d)
703 return dvb_set_prop (d, DTV_TUNE, 0 /* dummy */);
706 int dvb_fill_device_caps(dvb_device_t *d, dvb_device_caps_t *caps)
708 struct dvb_frontend_info info;
709 if (ioctl (d->frontend, FE_GET_INFO, &info) < 0)
711 msg_Err (d->obj, "cannot get frontend info: %s",
712 vlc_strerror_c(errno));
713 return -1;
716 caps->frequency.min = info.frequency_min;
717 caps->frequency.max = info.frequency_max;
718 caps->symbolrate.min = info.symbol_rate_min;
719 caps->symbolrate.max = info.symbol_rate_max;
720 caps->b_can_cam_auto = ( info.caps & FE_CAN_QAM_AUTO );
722 return 0;
725 /*** DVB-C ***/
726 int dvb_set_dvbc (dvb_device_t *d, uint32_t freq, const char *modstr,
727 uint32_t srate, uint32_t fec)
729 unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
730 fec = dvb_parse_fec (fec);
732 if (dvb_find_frontend (d, DTV_DELIVERY_DVB_C))
733 return -1;
734 return dvb_set_props (d, 6, DTV_CLEAR, 0,
735 #if DVBv5(5)
736 DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_A,
737 #else
738 DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_AC,
739 #endif
740 DTV_FREQUENCY, freq, DTV_MODULATION, mod,
741 DTV_SYMBOL_RATE, srate, DTV_INNER_FEC, fec);
745 /*** DVB-S ***/
746 static unsigned dvb_parse_polarization (char pol)
748 static const dvb_int_map_t tab[5] = {
749 { 0, SEC_VOLTAGE_OFF },
750 { 'H', SEC_VOLTAGE_18 },
751 { 'L', SEC_VOLTAGE_18 },
752 { 'R', SEC_VOLTAGE_13 },
753 { 'V', SEC_VOLTAGE_13 },
755 return dvb_parse_int (pol, tab, 5, SEC_VOLTAGE_OFF);
758 int dvb_set_sec (dvb_device_t *d, uint64_t freq_Hz, char pol,
759 uint32_t lowf, uint32_t highf, uint32_t switchf)
761 uint32_t freq = freq_Hz / 1000;
763 /* Always try to configure high voltage, but only warn on enable failure */
764 int val = var_InheritBool (d->obj, "dvb-high-voltage");
765 if (ioctl (d->frontend, FE_ENABLE_HIGH_LNB_VOLTAGE, &val) < 0 && val)
766 msg_Err (d->obj, "cannot enable high LNB voltage: %s",
767 vlc_strerror_c(errno));
769 /* Windows BDA exposes a higher-level API covering LNB oscillators.
770 * So lets pretend this is platform-specific stuff and do it here. */
771 if (!lowf)
772 { /* Default oscillator frequencies */
773 static const struct
775 uint16_t min, max, low, high;
776 } tab[] =
777 { /* min max low high */
778 { 10700, 13250, 9750, 10600 }, /* Ku band */
779 { 4500, 4800, 5950, 0 }, /* C band (high) */
780 { 3400, 4200, 5150, 0 }, /* C band (low) */
781 { 2500, 2700, 3650, 0 }, /* S band */
782 { 950, 2150, 0, 0 }, /* adjusted IF (L band) */
784 uint_fast16_t mHz = freq / 1000;
786 for (size_t i = 0; i < sizeof (tab) / sizeof (tab[0]); i++)
787 if (mHz >= tab[i].min && mHz <= tab[i].max)
789 lowf = tab[i].low * 1000;
790 highf = tab[i].high * 1000;
791 goto known;
794 msg_Err (d->obj, "no known band for frequency %u kHz", freq);
795 known:
796 msg_Dbg (d->obj, "selected LNB low: %u kHz, LNB high: %u kHz",
797 lowf, highf);
800 /* Use high oscillator frequency? */
801 bool high = highf != 0 && freq > switchf;
803 freq -= high ? highf : lowf;
804 if ((int32_t)freq < 0)
805 freq *= -1;
806 assert (freq < 0x7fffffff);
808 int tone;
809 switch (var_InheritInteger (d->obj, "dvb-tone"))
811 case 0: tone = SEC_TONE_OFF; break;
812 case 1: tone = SEC_TONE_ON; break;
813 default: tone = high ? SEC_TONE_ON : SEC_TONE_OFF;
816 /*** LNB selection / DiSEqC ***/
817 unsigned voltage = dvb_parse_polarization (pol);
818 if (dvb_set_props (d, 2, DTV_TONE, SEC_TONE_OFF, DTV_VOLTAGE, voltage))
819 return -1;
821 unsigned satno = var_InheritInteger (d->obj, "dvb-satno");
822 if (satno > 0)
824 #undef vlc_tick_sleep /* we know what we are doing! */
826 /* DiSEqC Bus Specification:
827 http://www.eutelsat.com/satellites/pdf/Diseqc/Reference%20docs/bus_spec.pdf */
829 /* DiSEqC 1.1 */
830 struct dvb_diseqc_master_cmd uncmd;
832 /* DiSEqC 1.0 */
833 struct dvb_diseqc_master_cmd cmd;
835 satno = (satno - 1) & 3;
836 cmd.msg[0] = 0xE0; /* framing: master, no reply, 1st TX */
837 cmd.msg[1] = 0x10; /* address: all LNB/switch */
838 cmd.msg[2] = 0x38; /* command: Write Port Group 0 (committed) */
839 cmd.msg[3] = 0xF0 /* data[0]: clear all bits */
840 | (satno << 2) /* LNB (A, B, C or D) */
841 | ((voltage == SEC_VOLTAGE_18) << 1) /* polarization */
842 | (tone == SEC_TONE_ON); /* option */
843 cmd.msg[4] = cmd.msg[5] = 0; /* unused */
844 cmd.msg_len = 4; /* length */
846 vlc_tick_sleep (VLC_TICK_FROM_MS(15)); /* wait 15 ms before DiSEqC command */
847 unsigned uncommitted = var_InheritInteger (d->obj, "dvb-uncommitted");
848 if (uncommitted > 0)
850 uncommitted = (uncommitted - 1) & 3;
851 uncmd.msg[0] = 0xE0; /* framing: master, no reply, 1st TX */
852 uncmd.msg[1] = 0x10; /* address: all LNB/switch */
853 uncmd.msg[2] = 0x39; /* command: Write Port Group 1 (uncommitted) */
854 uncmd.msg[3] = 0xF0 /* data[0]: clear all bits */
855 | (uncommitted << 2) /* LNB (A, B, C or D) */
856 | ((voltage == SEC_VOLTAGE_18) << 1) /* polarization */
857 | (tone == SEC_TONE_ON); /* option */
858 uncmd.msg[4] = uncmd.msg[5] = 0; /* unused */
859 uncmd.msg_len = 4; /* length */
860 if (ioctl (d->frontend, FE_DISEQC_SEND_MASTER_CMD, &uncmd) < 0)
862 msg_Err (d->obj, "cannot send uncommitted DiSEqC command: %s",
863 vlc_strerror_c(errno));
864 return -1;
866 /* Repeat uncommitted command */
867 uncmd.msg[0] = 0xE1; /* framing: master, no reply, repeated TX */
868 if (ioctl (d->frontend, FE_DISEQC_SEND_MASTER_CMD, &uncmd) < 0)
870 msg_Err (d->obj,
871 "cannot send repeated uncommitted DiSEqC command: %s",
872 vlc_strerror_c(errno));
873 return -1;
875 vlc_tick_sleep(VLC_TICK_FROM_MS(125)); /* wait 125 ms before committed DiSEqC command */
877 if (ioctl (d->frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) < 0)
879 msg_Err (d->obj, "cannot send committed DiSEqC command: %s",
880 vlc_strerror_c(errno));
881 return -1;
883 vlc_tick_sleep (VLC_TICK_FROM_MS(54 + 15));
885 /* Mini-DiSEqC */
886 satno &= 1;
887 if (ioctl (d->frontend, FE_DISEQC_SEND_BURST,
888 satno ? SEC_MINI_B : SEC_MINI_A) < 0)
890 msg_Err (d->obj, "cannot send Mini-DiSEqC tone burst: %s",
891 vlc_strerror_c(errno));
892 return -1;
894 vlc_tick_sleep (VLC_TICK_FROM_MS(15));
897 /* Continuous tone (to select high oscillator frequency) */
898 return dvb_set_props (d, 2, DTV_FREQUENCY, freq, DTV_TONE, tone);
901 int dvb_set_dvbs (dvb_device_t *d, uint64_t freq_Hz,
902 uint32_t srate, uint32_t fec)
904 uint32_t freq = freq_Hz / 1000;
905 fec = dvb_parse_fec (fec);
907 if (dvb_find_frontend (d, DTV_DELIVERY_DVB_S))
908 return -1;
909 return dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS,
910 DTV_FREQUENCY, freq, DTV_SYMBOL_RATE, srate,
911 DTV_INNER_FEC, fec);
914 int dvb_set_dvbs2 (dvb_device_t *d, uint64_t freq_Hz, const char *modstr,
915 uint32_t srate, uint32_t fec, int pilot, int rolloff,
916 uint8_t sid)
918 uint32_t freq = freq_Hz / 1000;
919 unsigned mod = dvb_parse_modulation (modstr, QPSK);
920 fec = dvb_parse_fec (fec);
922 switch (pilot)
924 case 0: pilot = PILOT_OFF; break;
925 case 1: pilot = PILOT_ON; break;
926 default: pilot = PILOT_AUTO; break;
929 switch (rolloff)
931 case 20: rolloff = ROLLOFF_20; break;
932 case 25: rolloff = ROLLOFF_25; break;
933 case 35: rolloff = ROLLOFF_35; break;
934 default: rolloff = PILOT_AUTO; break;
937 if (dvb_find_frontend (d, DTV_DELIVERY_DVB_S2))
938 return -1;
939 #if DVBv5(8)
940 return dvb_set_props (d, 9, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS2,
941 DTV_FREQUENCY, freq, DTV_MODULATION, mod,
942 DTV_SYMBOL_RATE, srate, DTV_INNER_FEC, fec,
943 DTV_PILOT, pilot, DTV_ROLLOFF, rolloff,
944 DTV_STREAM_ID, (uint32_t)sid);
945 #else
946 # warning DVB-S2 needs Linux DVB version 5.8 or later.
947 if (sid != 0)
949 msg_Err (d->obj, "DVB-S2 stream ID support not compiled-in");
950 return -1;
952 return dvb_set_props (d, 8, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS2,
953 DTV_FREQUENCY, freq, DTV_MODULATION, mod,
954 DTV_SYMBOL_RATE, srate, DTV_INNER_FEC, fec,
955 DTV_PILOT, pilot, DTV_ROLLOFF, rolloff);
956 #endif
960 /*** DVB-T ***/
961 static uint32_t dvb_parse_bandwidth (uint32_t i)
963 switch (i)
965 //case 0: return 0;
966 case 2: return 1712000;
967 default: return i * 1000000;
971 static int dvb_parse_transmit_mode (int i)
973 static const dvb_int_map_t tab[] = {
974 { -1, TRANSMISSION_MODE_AUTO },
975 #if DVBv5(3)
976 { 1, TRANSMISSION_MODE_1K },
977 #endif
978 { 2, TRANSMISSION_MODE_2K },
979 { 4, TRANSMISSION_MODE_4K },
980 { 8, TRANSMISSION_MODE_8K },
981 #if DVBv5(3)
982 { 16, TRANSMISSION_MODE_16K },
983 { 32, TRANSMISSION_MODE_32K },
984 #endif
986 return dvb_parse_int (i, tab, sizeof (tab) / sizeof (*tab),
987 TRANSMISSION_MODE_AUTO);
990 static int dvb_parse_guard (uint32_t guard)
992 static const dvb_int_map_t tab[] = {
993 { VLC_GUARD(1,4), GUARD_INTERVAL_1_4 },
994 { VLC_GUARD(1,8), GUARD_INTERVAL_1_8 },
995 { VLC_GUARD(1,16), GUARD_INTERVAL_1_16 },
996 { VLC_GUARD(1,32), GUARD_INTERVAL_1_32 },
997 #if DVBv5(3)
998 { VLC_GUARD(1,128), GUARD_INTERVAL_1_128 },
999 { VLC_GUARD(19,128), GUARD_INTERVAL_19_128 },
1000 { VLC_GUARD(19,256), GUARD_INTERVAL_19_256 },
1001 #endif
1002 { VLC_GUARD_AUTO, GUARD_INTERVAL_AUTO },
1004 return dvb_parse_int (guard, tab, sizeof (tab) / sizeof (*tab),
1005 GUARD_INTERVAL_AUTO);
1008 static int dvb_parse_hierarchy (int i)
1010 static const dvb_int_map_t tab[] = {
1011 { HIERARCHY_AUTO, -1 },
1012 { HIERARCHY_NONE, 0 },
1013 { HIERARCHY_1, 1 },
1014 { HIERARCHY_2, 2 },
1015 { HIERARCHY_4, 4 },
1017 return dvb_parse_int (i, tab, sizeof (tab) / sizeof (*tab),
1018 HIERARCHY_AUTO);
1021 int dvb_set_dvbt (dvb_device_t *d, uint32_t freq, const char *modstr,
1022 uint32_t fec_hp, uint32_t fec_lp, uint32_t bandwidth,
1023 int transmit_mode, uint32_t guard, int hierarchy)
1025 uint32_t mod = dvb_parse_modulation (modstr, QAM_AUTO);
1026 fec_hp = dvb_parse_fec (fec_hp);
1027 fec_lp = dvb_parse_fec (fec_lp);
1028 bandwidth = dvb_parse_bandwidth (bandwidth);
1029 transmit_mode = dvb_parse_transmit_mode (transmit_mode);
1030 guard = dvb_parse_guard (guard);
1031 hierarchy = dvb_parse_hierarchy (hierarchy);
1033 if (dvb_find_frontend (d, DTV_DELIVERY_DVB_T))
1034 return -1;
1035 return dvb_set_props (d, 10, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT,
1036 DTV_FREQUENCY, freq, DTV_MODULATION, mod,
1037 DTV_CODE_RATE_HP, fec_hp, DTV_CODE_RATE_LP, fec_lp,
1038 DTV_BANDWIDTH_HZ, bandwidth,
1039 DTV_TRANSMISSION_MODE, transmit_mode,
1040 DTV_GUARD_INTERVAL, guard,
1041 DTV_HIERARCHY, hierarchy);
1044 int dvb_set_dvbt2 (dvb_device_t *d, uint32_t freq, const char *modstr,
1045 uint32_t fec, uint32_t bandwidth,
1046 int transmit_mode, uint32_t guard, uint8_t plp)
1048 #if DVBv5(3)
1049 uint32_t mod = dvb_parse_modulation (modstr, QAM_AUTO);
1050 fec = dvb_parse_fec (fec);
1051 bandwidth = dvb_parse_bandwidth (bandwidth);
1052 transmit_mode = dvb_parse_transmit_mode (transmit_mode);
1053 guard = dvb_parse_guard (guard);
1055 if (dvb_find_frontend (d, DVB_T2))
1056 return -1;
1057 return dvb_set_props (d, 9, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT2,
1058 DTV_FREQUENCY, freq, DTV_MODULATION, mod,
1059 DTV_INNER_FEC, fec, DTV_BANDWIDTH_HZ, bandwidth,
1060 DTV_TRANSMISSION_MODE, transmit_mode,
1061 DTV_GUARD_INTERVAL, guard,
1062 # if DVBv5(8)
1063 DTV_STREAM_ID,
1064 # else
1065 DTV_DVBT2_PLP_ID,
1066 # endif
1067 (uint32_t)plp);
1068 #else
1069 # warning DVB-T2 needs Linux DVB version 5.3 or later.
1070 msg_Err (d->obj, "DVB-T2 support not compiled-in");
1071 (void) freq; (void) modstr; (void) fec; (void) bandwidth;
1072 (void) transmit_mode; (void) guard;
1073 return -1;
1074 #endif
1078 /*** ISDB-C ***/
1079 int dvb_set_isdbc (dvb_device_t *d, uint32_t freq, const char *modstr,
1080 uint32_t srate, uint32_t fec)
1082 unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
1083 fec = dvb_parse_fec (fec);
1085 if (dvb_find_frontend (d, DTV_DELIVERY_ISDB_C))
1086 return -1;
1087 return dvb_set_props (d, 6, DTV_CLEAR, 0,
1088 #if DVBv5(5)
1089 DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_C,
1090 #else
1091 # warning ISDB-C might need Linux DVB version 5.5 or later.
1092 DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_AC,
1093 #endif
1094 DTV_FREQUENCY, freq, DTV_MODULATION, mod,
1095 DTV_SYMBOL_RATE, srate, DTV_INNER_FEC, fec);
1099 /*** ISDB-S ***/
1100 int dvb_set_isdbs (dvb_device_t *d, uint64_t freq_Hz, uint16_t ts_id)
1102 uint32_t freq = freq_Hz / 1000;
1104 if (dvb_find_frontend (d, DTV_DELIVERY_ISDB_S))
1105 return -1;
1106 return dvb_set_props (d, 4, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBS,
1107 DTV_FREQUENCY, freq,
1108 #if DVBv5(8)
1109 DTV_STREAM_ID,
1110 #else
1111 DTV_ISDBS_TS_ID,
1112 #endif
1113 (uint32_t)ts_id);
1117 /*** ISDB-T ***/
1118 static int dvb_set_isdbt_layer (dvb_device_t *d, unsigned num,
1119 const isdbt_layer_t *l)
1121 uint32_t mod = dvb_parse_modulation (l->modulation, QAM_AUTO);
1122 uint32_t fec = dvb_parse_fec (l->code_rate);
1123 uint32_t count = l->segment_count;
1124 uint32_t ti = l->time_interleaving;
1126 num *= DTV_ISDBT_LAYERB_FEC - DTV_ISDBT_LAYERA_FEC;
1128 return dvb_set_props (d, 5, DTV_DELIVERY_SYSTEM, SYS_ISDBT,
1129 DTV_ISDBT_LAYERA_FEC + num, fec,
1130 DTV_ISDBT_LAYERA_MODULATION + num, mod,
1131 DTV_ISDBT_LAYERA_SEGMENT_COUNT + num, count,
1132 DTV_ISDBT_LAYERA_TIME_INTERLEAVING + num, ti);
1135 int dvb_set_isdbt (dvb_device_t *d, uint32_t freq, uint32_t bandwidth,
1136 int transmit_mode, uint32_t guard,
1137 const isdbt_layer_t layers[3])
1139 bandwidth = dvb_parse_bandwidth (bandwidth);
1140 transmit_mode = dvb_parse_transmit_mode (transmit_mode);
1141 guard = dvb_parse_guard (guard);
1143 if (dvb_find_frontend (d, DTV_DELIVERY_ISDB_T))
1144 return -1;
1145 if (dvb_set_props (d, 6, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBT,
1146 DTV_FREQUENCY, freq, DTV_BANDWIDTH_HZ, bandwidth,
1147 DTV_GUARD_INTERVAL, guard,
1148 DTV_ISDBT_LAYER_ENABLED, 0x7 /* all layers enabled */))
1149 return -1;
1150 for (unsigned i = 0; i < 3; i++)
1151 if (dvb_set_isdbt_layer (d, i, layers + i))
1152 return -1;
1153 return 0;
1157 /*** ATSC ***/
1158 int dvb_set_atsc (dvb_device_t *d, uint32_t freq, const char *modstr)
1160 unsigned mod = dvb_parse_modulation (modstr, VSB_8);
1162 if (dvb_find_frontend (d, DTV_DELIVERY_ATSC))
1163 return -1;
1164 return dvb_set_props (d, 4, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ATSC,
1165 DTV_FREQUENCY, freq, DTV_MODULATION, mod);
1168 int dvb_set_cqam (dvb_device_t *d, uint32_t freq, const char *modstr)
1170 unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
1172 if (dvb_find_frontend (d, DTV_DELIVERY_CQAM))
1173 return -1;
1174 return dvb_set_props (d, 4, DTV_CLEAR, 0,
1175 DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B,
1176 DTV_FREQUENCY, freq, DTV_MODULATION, mod);