]> git.sesse.net Git - vlc/blob - modules/access/dtv/linux.c
udp: restore original flow without else block
[vlc] / modules / access / dtv / linux.c
1 /**
2  * @file linux.c
3  * @brief Linux DVB API version 5
4  */
5 /*****************************************************************************
6  * Copyright © 2011 Rémi Denis-Courmont
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <vlc_common.h>
28 #include <vlc_fs.h>
29
30 #include <errno.h>
31 #include <assert.h>
32 #include <fcntl.h>
33 #include <poll.h>
34 #include <unistd.h>
35 #include <sys/ioctl.h>
36 #include <linux/dvb/version.h>
37 #include <linux/dvb/frontend.h>
38 #include <linux/dvb/dmx.h>
39
40 #include "dtv/dtv.h"
41 #ifdef HAVE_DVBPSI
42 # include "dtv/en50221.h"
43 #endif
44
45 #ifndef O_SEARCH
46 # define O_SEARCH O_RDONLY
47 #endif
48
49 #define DVBv5(minor) \
50         (DVB_API_VERSION > 5 \
51      || (DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= (minor)))
52
53 typedef struct
54 {
55     int vlc;
56     int linux_;
57 } dvb_int_map_t;
58
59 static int icmp (const void *a, const void *b)
60 {
61     int key = (intptr_t)a;
62     const dvb_int_map_t *entry = b;
63     return key - entry->vlc;
64 }
65
66 /** Maps a VLC config integer to a Linux DVB enum value */
67 static int dvb_parse_int (int i, const dvb_int_map_t *map, size_t n, int def)
68 {
69     const void *k = (const void *)(intptr_t)i;
70     const dvb_int_map_t *p = bsearch (k, map, n, sizeof (*map), icmp);
71     return (p != NULL) ? p->linux_ : def;
72 }
73
74 typedef const struct
75 {
76     char vlc[8];
77     int linux_;
78 } dvb_str_map_t;
79
80 static int scmp (const void *a, const void *b)
81 {
82     const char *key = a;
83     dvb_str_map_t *entry = b;
84     return strcmp (key, entry->vlc);
85 }
86
87 /** Maps a VLC config string to a Linux DVB enum value */
88 static int dvb_parse_str (const char *str, const dvb_str_map_t *map, size_t n,
89                           int def)
90 {
91     if (str != NULL)
92     {
93         const dvb_str_map_t *p = bsearch (str, map, n, sizeof (*map), scmp);
94         if (p != NULL)
95             def = p->linux_;
96     }
97     return def;
98 }
99
100 /*** Modulations ***/
101 static int dvb_parse_modulation (const char *str, int def)
102 {
103     static const dvb_str_map_t mods[] =
104     {
105         { "128QAM",  QAM_128  },
106         { "16APSK", APSK_16   },
107         { "16QAM",   QAM_16   },
108         { "16VSB",   VSB_16   },
109         { "256QAM",  QAM_256  },
110         { "32APSK", APSK_32   },
111         { "32QAM",   QAM_32   },
112         { "64QAM",   QAM_64   },
113         { "8PSK",    PSK_8    },
114         { "8VSB",    VSB_8    },
115         { "DQPSK", DQPSK      },
116         { "QAM",     QAM_AUTO },
117         { "QPSK",   QPSK      },
118     };
119     return dvb_parse_str (str, mods, sizeof (mods) / sizeof (*mods), def);
120 }
121
122 static int dvb_parse_fec (uint32_t fec)
123 {
124     static const dvb_int_map_t rates[] =
125     {
126         { 0,             FEC_NONE },
127         { VLC_FEC(1,2),  FEC_1_2  },
128         // TODO: 1/3
129         // TODO: 1/4
130         { VLC_FEC(2,3),  FEC_2_3  },
131         { VLC_FEC(3,4),  FEC_3_4  },
132         { VLC_FEC(3,5),  FEC_3_5  },
133         { VLC_FEC(4,5),  FEC_4_5  },
134         { VLC_FEC(5,6),  FEC_5_6  },
135         { VLC_FEC(6,7),  FEC_6_7  },
136         { VLC_FEC(7,8),  FEC_7_8  },
137         { VLC_FEC(8,9),  FEC_8_9  },
138         { VLC_FEC(9,10), FEC_9_10 },
139         { VLC_FEC_AUTO,  FEC_AUTO },
140     };
141     return dvb_parse_int (fec, rates, sizeof (rates) / sizeof (*rates),
142                           FEC_AUTO);
143 }
144
145
146 struct dvb_device
147 {
148     vlc_object_t *obj;
149     int dir;
150     int demux;
151     int frontend;
152 #ifndef USE_DMX
153 # define MAX_PIDS 256
154     struct
155     {
156         int fd;
157         uint16_t pid;
158     } pids[MAX_PIDS];
159 #endif
160 #ifdef HAVE_DVBPSI
161     cam_t *cam;
162 #endif
163     uint8_t device;
164     bool budget;
165     //size_t buffer_size;
166 };
167
168 /** Opens the device directory for the specified DVB adapter */
169 static int dvb_open_adapter (uint8_t adapter)
170 {
171     char dir[20];
172
173     snprintf (dir, sizeof (dir), "/dev/dvb/adapter%"PRIu8, adapter);
174     return vlc_open (dir, O_SEARCH|O_DIRECTORY);
175 }
176
177 /** Opens the DVB device node of the specified type */
178 static int dvb_open_node (dvb_device_t *d, const char *type, int flags)
179 {
180     char path[strlen (type) + 4];
181
182     snprintf (path, sizeof (path), "%s%u", type, d->device);
183     return vlc_openat (d->dir, path, flags | O_NONBLOCK);
184 }
185
186 /**
187  * Opens the DVB tuner
188  */
189 dvb_device_t *dvb_open (vlc_object_t *obj)
190 {
191     dvb_device_t *d = malloc (sizeof (*d));
192     if (unlikely(d == NULL))
193         return NULL;
194
195     d->obj = obj;
196
197     uint8_t adapter = var_InheritInteger (obj, "dvb-adapter");
198     d->device = var_InheritInteger (obj, "dvb-device");
199
200     d->dir = dvb_open_adapter (adapter);
201     if (d->dir == -1)
202     {
203         msg_Err (obj, "cannot access adapter %"PRIu8": %s", adapter,
204                  vlc_strerror_c(errno));
205         free (d);
206         return NULL;
207     }
208     d->frontend = -1;
209 #ifdef HAVE_DVBPSI
210     d->cam = NULL;
211 #endif
212     d->budget = var_InheritBool (obj, "dvb-budget-mode");
213
214 #ifndef USE_DMX
215     if (d->budget)
216 #endif
217     {
218        d->demux = dvb_open_node (d, "demux", O_RDONLY);
219        if (d->demux == -1)
220        {
221            msg_Err (obj, "cannot access demultiplexer: %s",
222                     vlc_strerror_c(errno));
223            close (d->dir);
224            free (d);
225            return NULL;
226        }
227
228        if (ioctl (d->demux, DMX_SET_BUFFER_SIZE, 1 << 20) < 0)
229            msg_Warn (obj, "cannot expand demultiplexing buffer: %s",
230                      vlc_strerror_c(errno));
231
232        /* We need to filter at least one PID. The tap for TS demultiplexing
233         * cannot be configured otherwise. So add the PAT. */
234         struct dmx_pes_filter_params param;
235
236         param.pid = d->budget ? 0x2000 : 0x000;
237         param.input = DMX_IN_FRONTEND;
238         param.output = DMX_OUT_TSDEMUX_TAP;
239         param.pes_type = DMX_PES_OTHER;
240         param.flags = DMX_IMMEDIATE_START;
241         if (ioctl (d->demux, DMX_SET_PES_FILTER, &param) < 0)
242         {
243             msg_Err (obj, "cannot setup TS demultiplexer: %s",
244                      vlc_strerror_c(errno));
245             goto error;
246         }
247 #ifndef USE_DMX
248     }
249     else
250     {
251         for (size_t i = 0; i < MAX_PIDS; i++)
252             d->pids[i].pid = d->pids[i].fd = -1;
253         d->demux = dvb_open_node (d, "dvr", O_RDONLY);
254         if (d->demux == -1)
255         {
256             msg_Err (obj, "cannot access DVR: %s", vlc_strerror_c(errno));
257             close (d->dir);
258             free (d);
259             return NULL;
260         }
261 #endif
262     }
263
264 #ifdef HAVE_DVBPSI
265     int ca = dvb_open_node (d, "ca", O_RDWR);
266     if (ca != -1)
267     {
268         d->cam = en50221_Init (obj, ca);
269         if (d->cam == NULL)
270             close (ca);
271     }
272     else
273         msg_Dbg (obj, "conditional access module not available: %s",
274                  vlc_strerror_c(errno));
275 #endif
276     return d;
277
278 error:
279     dvb_close (d);
280     return NULL;
281 }
282
283 void dvb_close (dvb_device_t *d)
284 {
285 #ifndef USE_DMX
286     if (!d->budget)
287     {
288         for (size_t i = 0; i < MAX_PIDS; i++)
289             if (d->pids[i].fd != -1)
290                 close (d->pids[i].fd);
291     }
292 #endif
293 #ifdef HAVE_DVBPSI
294     if (d->cam != NULL)
295         en50221_End (d->cam);
296 #endif
297     if (d->frontend != -1)
298         close (d->frontend);
299     close (d->demux);
300     close (d->dir);
301     free (d);
302 }
303
304 static void dvb_frontend_status(vlc_object_t *obj, fe_status_t s)
305 {
306     msg_Dbg(obj, "frontend status:");
307 #define S(f) \
308     if (s & FE_ ## f) \
309         msg_Dbg(obj, "\t%s", #f);
310
311     S(HAS_SIGNAL);
312     S(HAS_CARRIER);
313     S(HAS_VITERBI);
314     S(HAS_SYNC);
315     S(HAS_LOCK);
316     S(TIMEDOUT);
317     S(REINIT);
318 #undef S
319 }
320
321 /**
322  * Reads TS data from the tuner.
323  * @return number of bytes read, 0 on EOF, -1 if no data (yet).
324  */
325 ssize_t dvb_read (dvb_device_t *d, void *buf, size_t len)
326 {
327     struct pollfd ufd[2];
328     int n;
329
330 #ifdef HAVE_DVBPSI
331     if (d->cam != NULL)
332         en50221_Poll (d->cam);
333 #endif
334
335     ufd[0].fd = d->demux;
336     ufd[0].events = POLLIN;
337     if (d->frontend != -1)
338     {
339         ufd[1].fd = d->frontend;
340         ufd[1].events = POLLIN;
341         n = 2;
342     }
343     else
344         n = 1;
345
346     if (poll (ufd, n, 500 /* FIXME */) < 0)
347         return -1;
348
349     if (d->frontend != -1 && ufd[1].revents)
350     {
351         struct dvb_frontend_event ev;
352
353         if (ioctl (d->frontend, FE_GET_EVENT, &ev) < 0)
354         {
355             if (errno == EOVERFLOW)
356             {
357                 msg_Err (d->obj, "cannot dequeue events fast enough!");
358                 return -1;
359             }
360             msg_Err (d->obj, "cannot dequeue frontend event: %s",
361                      vlc_strerror_c(errno));
362             return 0;
363         }
364
365         dvb_frontend_status(d->obj, ev.status);
366     }
367
368     if (ufd[0].revents)
369     {
370         ssize_t val = read (d->demux, buf, len);
371         if (val == -1 && (errno != EAGAIN && errno != EINTR))
372         {
373             if (errno == EOVERFLOW)
374             {
375                 msg_Err (d->obj, "cannot demux data fast enough!");
376                 return -1;
377             }
378             msg_Err (d->obj, "cannot demux: %s", vlc_strerror_c(errno));
379             return 0;
380         }
381         return val;
382     }
383
384     return -1;
385 }
386
387 int dvb_add_pid (dvb_device_t *d, uint16_t pid)
388 {
389     if (d->budget)
390         return 0;
391 #ifdef USE_DMX
392     if (pid == 0 || ioctl (d->demux, DMX_ADD_PID, &pid) >= 0)
393         return 0;
394 #else
395     for (size_t i = 0; i < MAX_PIDS; i++)
396     {
397         if (d->pids[i].pid == pid)
398             return 0;
399         if (d->pids[i].fd != -1)
400             continue;
401
402         int fd = dvb_open_node (d, "demux", O_RDONLY);
403         if (fd == -1)
404             goto error;
405
406        /* We need to filter at least one PID. The tap for TS demultiplexing
407         * cannot be configured otherwise. So add the PAT. */
408         struct dmx_pes_filter_params param;
409
410         param.pid = pid;
411         param.input = DMX_IN_FRONTEND;
412         param.output = DMX_OUT_TS_TAP;
413         param.pes_type = DMX_PES_OTHER;
414         param.flags = DMX_IMMEDIATE_START;
415         if (ioctl (fd, DMX_SET_PES_FILTER, &param) < 0)
416         {
417             close (fd);
418             goto error;
419         }
420         d->pids[i].fd = fd;
421         d->pids[i].pid = pid;
422         return 0;
423     }
424     errno = EMFILE;
425 error:
426 #endif
427     msg_Err (d->obj, "cannot add PID 0x%04"PRIu16": %s", pid,
428              vlc_strerror_c(errno));
429     return -1;
430 }
431
432 void dvb_remove_pid (dvb_device_t *d, uint16_t pid)
433 {
434     if (d->budget)
435         return;
436 #ifdef USE_DMX
437     if (pid != 0)
438         ioctl (d->demux, DMX_REMOVE_PID, &pid);
439 #else
440     for (size_t i = 0; i < MAX_PIDS; i++)
441     {
442         if (d->pids[i].pid == pid)
443         {
444             close (d->pids[i].fd);
445             d->pids[i].pid = d->pids[i].fd = -1;
446             return;
447         }
448     }
449 #endif
450 }
451
452 /** Finds a frontend of the correct type */
453 static int dvb_open_frontend (dvb_device_t *d)
454 {
455     if (d->frontend != -1)
456         return 0;
457     int fd = dvb_open_node (d, "frontend", O_RDWR);
458     if (fd == -1)
459     {
460         msg_Err (d->obj, "cannot access frontend: %s", vlc_strerror_c(errno));
461         return -1;
462     }
463
464     d->frontend = fd;
465     return 0;
466 }
467 #define dvb_find_frontend(d, sys) (dvb_open_frontend(d))
468
469 /**
470  * Detects supported delivery systems.
471  * @return a bit mask of supported systems (zero on failure)
472  */
473 unsigned dvb_enum_systems (dvb_device_t *d)
474 {
475     if (dvb_open_frontend (d))
476         return 0;
477 #if DVBv5(5)
478     struct dtv_property prop[2] = {
479         { .cmd = DTV_API_VERSION },
480         { .cmd = DTV_ENUM_DELSYS },
481     };
482     struct dtv_properties props = {
483         .num = 2,
484         .props = prop
485     };
486
487     if (ioctl (d->frontend, FE_GET_PROPERTY, &props) < 0)
488     {
489          msg_Err (d->obj, "cannot enumerate frontend systems: %s",
490                   vlc_strerror_c(errno));
491          goto legacy;
492     }
493
494     static const unsigned systab[] = {
495         [SYS_UNDEFINED]    = 0,
496         [SYS_DVBC_ANNEX_A] = DVB_C,
497         [SYS_DVBC_ANNEX_B] = CQAM,
498         [SYS_DVBT]         = DVB_T,
499         //[SYS_DSS]
500         [SYS_DVBS]         = DVB_S,
501         [SYS_DVBS2]        = DVB_S2,
502         //[SYS_DVBH]
503         [SYS_ISDBT]        = ISDB_T,
504         [SYS_ISDBS]        = ISDB_S,
505         [SYS_ISDBC]        = ISDB_C, // no drivers exist (as of 3.3-rc6)
506         [SYS_ATSC]         = ATSC,
507         //[SYS_ATSCMH]
508         //[SYS_DMBTH]
509         //[SYS_CMMB]
510         //[SYS_DAB]
511         [SYS_DVBT2]        = DVB_T2,
512         //[SYS_TURBO]
513         [SYS_DVBC_ANNEX_C] = ISDB_C, // another name for ISDB-C?
514     };
515     unsigned systems = 0;
516
517     msg_Dbg (d->obj, "probing frontend (kernel API v%u.%u, user API v%u.%u)",
518              prop[0].u.data >> 8, prop[0].u.data & 0xFF,
519              DVB_API_VERSION, DVB_API_VERSION_MINOR);
520
521     for (size_t i = 0; i < prop[1].u.buffer.len; i++)
522     {
523         unsigned sys = prop[1].u.buffer.data[i];
524
525         if (sys >= (sizeof (systab) / sizeof (systab[0])) || !systab[sys])
526         {
527             msg_Warn (d->obj, "unknown delivery system %u", sys);
528             continue;
529         }
530         msg_Dbg (d->obj, " system %u", sys);
531         systems |= systab[sys];
532     }
533
534     return systems;
535 legacy:
536     props.num = 1;
537 #else
538     struct dtv_property prop[1] = {
539         { .cmd = DTV_API_VERSION },
540     };
541     struct dtv_properties props = {
542         .num = 1,
543         .props = prop
544     };
545     unsigned systems = 0;
546 #endif
547     if (ioctl (d->frontend, FE_GET_PROPERTY, &props) < 0)
548     {
549         msg_Err (d->obj, "unsupported kernel DVB version 3 or older (%s)",
550                  vlc_strerror_c(errno));
551         return 0;
552     }
553
554     msg_Dbg (d->obj, "probing frontend (kernel API v%u.%u, user API v%u.%u)",
555              prop[0].u.data >> 8, prop[0].u.data & 0xFF,
556              DVB_API_VERSION, DVB_API_VERSION_MINOR);
557 #if !DVBv5(5)
558     /* Some delivery systems cannot be detected without the DVB API v5.5.
559      * To run correctly on recent kernels (Linux >= 3.3),
560      * VLC needs to be compiled with up-to-date kernel headers. */
561     if ((prop[0].u.data >> 8) > 5
562      || ((prop[0].u.data >> 8) == 5 && (prop[0].u.data & 0xFF) >= 5))
563         msg_Err (d->obj, "obsolete user API version running on a new kernel");
564         msg_Info (d->obj, "please recompile "PACKAGE_NAME" "PACKAGE_VERSION);
565 #endif
566     struct dvb_frontend_info info;
567     if (ioctl (d->frontend, FE_GET_INFO, &info) < 0)
568     {
569         msg_Err (d->obj, "cannot get frontend info: %s",
570                  vlc_strerror_c(errno));
571         return 0;
572     }
573     msg_Dbg (d->obj, " name %s", info.name);
574     msg_Dbg (d->obj, " type %u, capabilities 0x%08X", info.type, info.caps);
575     msg_Dbg (d->obj, " frequencies %10"PRIu32" to %10"PRIu32,
576              info.frequency_min, info.frequency_max);
577     msg_Dbg (d->obj, " (%"PRIu32" tolerance, %"PRIu32" per step)",
578              info.frequency_tolerance, info.frequency_stepsize);
579     msg_Dbg (d->obj, " bauds rates %10"PRIu32" to %10"PRIu32,
580              info.symbol_rate_min, info.symbol_rate_max);
581     msg_Dbg (d->obj, " (%"PRIu32" tolerance)", info.symbol_rate_tolerance);
582
583     /* DVB first generation and ATSC */
584     switch (info.type)
585     {
586         case FE_QPSK: systems = DVB_S; break;
587         case FE_QAM:  systems = DVB_C; break;
588         case FE_OFDM: systems = DVB_T; break;
589         case FE_ATSC: systems = ATSC | CQAM; break;
590         default:
591             msg_Err (d->obj, "unknown frontend type %u", info.type);
592     }
593
594     /* DVB 2nd generation */
595     switch (info.type)
596     {
597         case FE_QPSK:
598         case FE_QAM:
599         case FE_OFDM:
600             if (info.caps & FE_CAN_2G_MODULATION)
601                 systems |= systems << 1; /* DVB_foo -> DVB_foo|DVB_foo2 */
602         default:
603             break;
604     }
605
606     /* ISDB (only terrestrial before DVBv5.5)  */
607     if (info.type == FE_OFDM)
608         systems |= ISDB_T;
609
610     return systems;
611 }
612
613 float dvb_get_signal_strength (dvb_device_t *d)
614 {
615     uint16_t strength;
616
617     if (d->frontend == -1
618      || ioctl (d->frontend, FE_READ_SIGNAL_STRENGTH, &strength) < 0)
619         return 0.;
620     return strength / 65535.;
621 }
622
623 float dvb_get_snr (dvb_device_t *d)
624 {
625     uint16_t snr;
626
627     if (d->frontend == -1 || ioctl (d->frontend, FE_READ_SNR, &snr) < 0)
628         return 0.;
629     return snr / 65535.;
630 }
631
632 #ifdef HAVE_DVBPSI
633 void dvb_set_ca_pmt (dvb_device_t *d, struct dvbpsi_pmt_s *pmt)
634 {
635     if (d->cam != NULL)
636         en50221_SetCAPMT (d->cam, pmt);
637 }
638 #endif
639
640 static int dvb_vset_props (dvb_device_t *d, size_t n, va_list ap)
641 {
642     assert (n <= DTV_IOCTL_MAX_MSGS);
643
644     struct dtv_property buf[n], *prop = buf;
645     struct dtv_properties props = { .num = n, .props = buf };
646
647     memset (buf, 0, sizeof (buf));
648
649     while (n > 0)
650     {
651         prop->cmd = va_arg (ap, uint32_t);
652         prop->u.data = va_arg (ap, uint32_t);
653         msg_Dbg (d->obj, "setting property %2"PRIu32" to %"PRIu32,
654                  prop->cmd, prop->u.data);
655         prop++;
656         n--;
657     }
658
659     if (ioctl (d->frontend, FE_SET_PROPERTY, &props) < 0)
660     {
661         msg_Err (d->obj, "cannot set frontend tuning parameters: %s",
662                  vlc_strerror_c(errno));
663         return -1;
664     }
665     return 0;
666 }
667
668 static int dvb_set_props (dvb_device_t *d, size_t n, ...)
669 {
670     va_list ap;
671     int ret;
672
673     va_start (ap, n);
674     ret = dvb_vset_props (d, n, ap);
675     va_end (ap);
676     return ret;
677 }
678
679 static int dvb_set_prop (dvb_device_t *d, uint32_t prop, uint32_t val)
680 {
681     return dvb_set_props (d, 1, prop, val);
682 }
683
684 int dvb_set_inversion (dvb_device_t *d, int v)
685 {
686     switch (v)
687     {
688         case 0:  v = INVERSION_OFF;  break;
689         case 1:  v = INVERSION_ON;   break;
690         default: v = INVERSION_AUTO; break;
691     }
692     return dvb_set_prop (d, DTV_INVERSION, v);
693 }
694
695 int dvb_tune (dvb_device_t *d)
696 {
697     return dvb_set_prop (d, DTV_TUNE, 0 /* dummy */);
698 }
699
700
701 /*** DVB-C ***/
702 int dvb_set_dvbc (dvb_device_t *d, uint32_t freq, const char *modstr,
703                   uint32_t srate, uint32_t fec)
704 {
705     unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
706     fec = dvb_parse_fec (fec);
707
708     if (dvb_find_frontend (d, DVB_C))
709         return -1;
710     return dvb_set_props (d, 6, DTV_CLEAR, 0,
711 #if DVBv5(5)
712                           DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_A,
713 #else
714                           DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_AC,
715 #endif
716                           DTV_FREQUENCY, freq, DTV_MODULATION, mod,
717                           DTV_SYMBOL_RATE, srate, DTV_INNER_FEC, fec);
718 }
719
720
721 /*** DVB-S ***/
722 static unsigned dvb_parse_polarization (char pol)
723 {
724     static const dvb_int_map_t tab[5] = {
725         { 0,   SEC_VOLTAGE_OFF },
726         { 'H', SEC_VOLTAGE_18  },
727         { 'L', SEC_VOLTAGE_18  },
728         { 'R', SEC_VOLTAGE_13  },
729         { 'V', SEC_VOLTAGE_13  },
730     };
731     return dvb_parse_int (pol, tab, 5, SEC_VOLTAGE_OFF);
732 }
733
734 int dvb_set_sec (dvb_device_t *d, uint64_t freq_Hz, char pol,
735                  uint32_t lowf, uint32_t highf, uint32_t switchf)
736 {
737     uint32_t freq = freq_Hz / 1000;
738
739     /* Always try to configure high voltage, but only warn on enable failure */
740     int val = var_InheritBool (d->obj, "dvb-high-voltage");
741     if (ioctl (d->frontend, FE_ENABLE_HIGH_LNB_VOLTAGE, &val) < 0 && val)
742         msg_Err (d->obj, "cannot enable high LNB voltage: %s",
743                  vlc_strerror_c(errno));
744
745     /* Windows BDA exposes a higher-level API covering LNB oscillators.
746      * So lets pretend this is platform-specific stuff and do it here. */
747     if (!lowf)
748     {   /* Default oscillator frequencies */
749         static const struct
750         {
751              uint16_t min, max, low, high;
752         } tab[] =
753         {    /*  min    max    low   high */
754              { 10700, 13250,  9750, 10600 }, /* Ku band */
755              {  4500,  4800,  5950,     0 }, /* C band (high) */
756              {  3400,  4200,  5150,     0 }, /* C band (low) */
757              {  2500,  2700,  3650,     0 }, /* S band */
758              {   950,  2150,     0,     0 }, /* adjusted IF (L band) */
759         };
760         uint_fast16_t mHz = freq / 1000;
761
762         for (size_t i = 0; i < sizeof (tab) / sizeof (tab[0]); i++)
763              if (mHz >= tab[i].min && mHz <= tab[i].max)
764              {
765                  lowf = tab[i].low * 1000;
766                  highf = tab[i].high * 1000;
767                  goto known;
768              }
769
770         msg_Err (d->obj, "no known band for frequency %u kHz", freq);
771 known:
772         msg_Dbg (d->obj, "selected LNB low: %u kHz, LNB high: %u kHz",
773                  lowf, highf);
774     }
775
776     /* Use high oscillator frequency? */
777     bool high = highf != 0 && freq > switchf;
778
779     freq -= high ? highf : lowf;
780     if ((int32_t)freq < 0)
781         freq *= -1;
782     assert (freq < 0x7fffffff);
783
784     int tone;
785     switch (var_InheritInteger (d->obj, "dvb-tone"))
786     {
787         case 0:  tone = SEC_TONE_OFF; break;
788         case 1:  tone = SEC_TONE_ON;  break;
789         default: tone = high ? SEC_TONE_ON : SEC_TONE_OFF;
790     }
791
792     /*** LNB selection / DiSEqC ***/
793     unsigned voltage = dvb_parse_polarization (pol);
794     if (dvb_set_props (d, 2, DTV_TONE, SEC_TONE_OFF, DTV_VOLTAGE, voltage))
795         return -1;
796
797     unsigned satno = var_InheritInteger (d->obj, "dvb-satno");
798     if (satno > 0)
799     {
800 #undef msleep /* we know what we are doing! */
801
802         /* DiSEqC Bus Specification:
803  http://www.eutelsat.com/satellites/pdf/Diseqc/Reference%20docs/bus_spec.pdf */
804
805         /* DiSEqC 1.1 */
806         struct dvb_diseqc_master_cmd uncmd;
807
808         /* DiSEqC 1.0 */
809         struct dvb_diseqc_master_cmd cmd;
810
811         satno = (satno - 1) & 3;
812         cmd.msg[0] = 0xE0; /* framing: master, no reply, 1st TX */
813         cmd.msg[1] = 0x10; /* address: all LNB/switch */
814         cmd.msg[2] = 0x38; /* command: Write Port Group 0 (committed) */
815         cmd.msg[3] = 0xF0  /* data[0]: clear all bits */
816                    | (satno << 2) /* LNB (A, B, C or D) */
817                    | ((voltage == SEC_VOLTAGE_18) << 1) /* polarization */
818                    | (tone == SEC_TONE_ON); /* option */
819         cmd.msg[4] = cmd.msg[5] = 0; /* unused */
820         cmd.msg_len = 4; /* length */
821
822         msleep (15000); /* wait 15 ms before DiSEqC command */
823         unsigned uncommitted = var_InheritInteger (d->obj, "dvb-uncommitted");
824         if (uncommitted > 0)
825         {
826           uncommitted = (uncommitted - 1) & 3;
827           uncmd.msg[0] = 0xE0; /* framing: master, no reply, 1st TX */
828           uncmd.msg[1] = 0x10; /* address: all LNB/switch */
829           uncmd.msg[2] = 0x39; /* command: Write Port Group 1 (uncommitted) */
830           uncmd.msg[3] = 0xF0  /* data[0]: clear all bits */
831                        | (uncommitted << 2) /* LNB (A, B, C or D) */
832                        | ((voltage == SEC_VOLTAGE_18) << 1) /* polarization */
833                        | (tone == SEC_TONE_ON); /* option */
834           uncmd.msg[4] = uncmd.msg[5] = 0; /* unused */
835           uncmd.msg_len = 4; /* length */
836           if (ioctl (d->frontend, FE_DISEQC_SEND_MASTER_CMD, &uncmd) < 0)
837           {
838               msg_Err (d->obj, "cannot send uncommitted DiSEqC command: %s",
839                        vlc_strerror_c(errno));
840               return -1;
841           }
842           /* Repeat uncommitted command */
843           uncmd.msg[0] = 0xE1; /* framing: master, no reply, repeated TX */
844           if (ioctl (d->frontend, FE_DISEQC_SEND_MASTER_CMD, &uncmd) < 0)
845           {
846               msg_Err (d->obj,
847                        "cannot send repeated uncommitted DiSEqC command: %s",
848                        vlc_strerror_c(errno));
849               return -1;
850           }
851           msleep(125000); /* wait 125 ms before committed DiSEqC command */
852         }
853         if (ioctl (d->frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd) < 0)
854         {
855             msg_Err (d->obj, "cannot send committed DiSEqC command: %s",
856                      vlc_strerror_c(errno));
857             return -1;
858         }
859         msleep (54000 + 15000);
860
861         /* Mini-DiSEqC */
862         satno &= 1;
863         if (ioctl (d->frontend, FE_DISEQC_SEND_BURST,
864                    satno ? SEC_MINI_B : SEC_MINI_A) < 0)
865         {
866             msg_Err (d->obj, "cannot send Mini-DiSEqC tone burst: %s",
867                      vlc_strerror_c(errno));
868             return -1;
869         }
870         msleep (15000);
871     }
872
873     /* Continuous tone (to select high oscillator frequency) */
874     return dvb_set_props (d, 2, DTV_FREQUENCY, freq, DTV_TONE, tone);
875 }
876
877 int dvb_set_dvbs (dvb_device_t *d, uint64_t freq_Hz,
878                   uint32_t srate, uint32_t fec)
879 {
880     uint32_t freq = freq_Hz / 1000;
881     fec = dvb_parse_fec (fec);
882
883     if (dvb_find_frontend (d, DVB_S))
884         return -1;
885     return dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS,
886                           DTV_FREQUENCY, freq, DTV_SYMBOL_RATE, srate,
887                           DTV_INNER_FEC, fec);
888 }
889
890 int dvb_set_dvbs2 (dvb_device_t *d, uint64_t freq_Hz, const char *modstr,
891                    uint32_t srate, uint32_t fec, int pilot, int rolloff)
892 {
893     uint32_t freq = freq_Hz / 1000;
894     unsigned mod = dvb_parse_modulation (modstr, QPSK);
895     fec = dvb_parse_fec (fec);
896
897     switch (pilot)
898     {
899         case 0:  pilot = PILOT_OFF;  break;
900         case 1:  pilot = PILOT_ON;   break;
901         default: pilot = PILOT_AUTO; break;
902     }
903
904     switch (rolloff)
905     {
906         case 20: rolloff = ROLLOFF_20;  break;
907         case 25: rolloff = ROLLOFF_25;  break;
908         case 35: rolloff = ROLLOFF_35;  break;
909         default: rolloff = PILOT_AUTO; break;
910     }
911
912     if (dvb_find_frontend (d, DVB_S2))
913         return -1;
914     return dvb_set_props (d, 8, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBS2,
915                           DTV_FREQUENCY, freq, DTV_MODULATION, mod,
916                           DTV_SYMBOL_RATE, srate, DTV_INNER_FEC, fec,
917                           DTV_PILOT, pilot, DTV_ROLLOFF, rolloff);
918 }
919
920
921 /*** DVB-T ***/
922 static uint32_t dvb_parse_bandwidth (uint32_t i)
923 {
924     switch (i)
925     {
926       //case  0: return 0;
927         case  2: return 1712000;
928         default: return i * 1000000;
929     }
930 }
931
932 static int dvb_parse_transmit_mode (int i)
933 {
934     static const dvb_int_map_t tab[] = {
935         { -1, TRANSMISSION_MODE_AUTO },
936 #if DVBv5(3)
937         {  1, TRANSMISSION_MODE_1K   },
938 #endif
939         {  2, TRANSMISSION_MODE_2K   },
940         {  4, TRANSMISSION_MODE_4K   },
941         {  8, TRANSMISSION_MODE_8K   },
942 #if DVBv5(3)
943         { 16, TRANSMISSION_MODE_16K  },
944         { 32, TRANSMISSION_MODE_32K  },
945 #endif
946     };
947     return dvb_parse_int (i, tab, sizeof (tab) / sizeof (*tab),
948                           TRANSMISSION_MODE_AUTO);
949 }
950
951 static int dvb_parse_guard (uint32_t guard)
952 {
953     static const dvb_int_map_t tab[] = {
954         { VLC_GUARD(1,4),    GUARD_INTERVAL_1_4 },
955         { VLC_GUARD(1,8),    GUARD_INTERVAL_1_8 },
956         { VLC_GUARD(1,16),   GUARD_INTERVAL_1_16 },
957         { VLC_GUARD(1,32),   GUARD_INTERVAL_1_32 },
958 #if DVBv5(3)
959         { VLC_GUARD(1,128),  GUARD_INTERVAL_1_128 },
960         { VLC_GUARD(19,128), GUARD_INTERVAL_19_128 },
961         { VLC_GUARD(19,256), GUARD_INTERVAL_19_256 },
962 #endif
963         { VLC_GUARD_AUTO,    GUARD_INTERVAL_AUTO },
964     };
965     return dvb_parse_int (guard, tab, sizeof (tab) / sizeof (*tab),
966                           GUARD_INTERVAL_AUTO);
967 }
968
969 static int dvb_parse_hierarchy (int i)
970 {
971     static const dvb_int_map_t tab[] = {
972         { HIERARCHY_AUTO, -1 },
973         { HIERARCHY_NONE,  0 },
974         { HIERARCHY_1,     1 },
975         { HIERARCHY_2,     2 },
976         { HIERARCHY_4,     4 },
977     };
978     return dvb_parse_int (i, tab, sizeof (tab) / sizeof (*tab),
979                           HIERARCHY_AUTO);
980 }
981
982 int dvb_set_dvbt (dvb_device_t *d, uint32_t freq, const char *modstr,
983                   uint32_t fec_hp, uint32_t fec_lp, uint32_t bandwidth,
984                   int transmit_mode, uint32_t guard, int hierarchy)
985 {
986     uint32_t mod = dvb_parse_modulation (modstr, QAM_AUTO);
987     fec_hp = dvb_parse_fec (fec_hp);
988     fec_lp = dvb_parse_fec (fec_lp);
989     bandwidth = dvb_parse_bandwidth (bandwidth);
990     transmit_mode = dvb_parse_transmit_mode (transmit_mode);
991     guard = dvb_parse_guard (guard);
992     hierarchy = dvb_parse_hierarchy (hierarchy);
993
994     if (dvb_find_frontend (d, DVB_T))
995         return -1;
996     return dvb_set_props (d, 10, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT,
997                           DTV_FREQUENCY, freq, DTV_MODULATION, mod,
998                           DTV_CODE_RATE_HP, fec_hp, DTV_CODE_RATE_LP, fec_lp,
999                           DTV_BANDWIDTH_HZ, bandwidth,
1000                           DTV_TRANSMISSION_MODE, transmit_mode,
1001                           DTV_GUARD_INTERVAL, guard,
1002                           DTV_HIERARCHY, hierarchy);
1003 }
1004
1005 int dvb_set_dvbt2 (dvb_device_t *d, uint32_t freq, const char *modstr,
1006                    uint32_t fec, uint32_t bandwidth,
1007                    int transmit_mode, uint32_t guard, uint32_t plp)
1008 {
1009 #if DVBv5(3)
1010     uint32_t mod = dvb_parse_modulation (modstr, QAM_AUTO);
1011     fec = dvb_parse_fec (fec);
1012     bandwidth = dvb_parse_bandwidth (bandwidth);
1013     transmit_mode = dvb_parse_transmit_mode (transmit_mode);
1014     guard = dvb_parse_guard (guard);
1015
1016     if (dvb_find_frontend (d, DVB_T2))
1017         return -1;
1018     return dvb_set_props (d, 9, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_DVBT2,
1019                           DTV_FREQUENCY, freq, DTV_MODULATION, mod,
1020                           DTV_INNER_FEC, fec, DTV_BANDWIDTH_HZ, bandwidth,
1021                           DTV_TRANSMISSION_MODE, transmit_mode,
1022                           DTV_GUARD_INTERVAL, guard,
1023 # if DVBv5(8)
1024                           DTV_STREAM_ID,
1025 # else
1026                           DTV_DVBT2_PLP_ID,
1027 # endif
1028                           plp);
1029 #else
1030 # warning DVB-T2 needs Linux DVB version 5.3 or later.
1031     msg_Err (d->obj, "DVB-T2 support not compiled-in");
1032     (void) freq; (void) modstr; (void) fec; (void) bandwidth;
1033     (void) transmit_mode; (void) guard;
1034     return -1;
1035 #endif
1036 }
1037
1038
1039 /*** ISDB-C ***/
1040 int dvb_set_isdbc (dvb_device_t *d, uint32_t freq, const char *modstr,
1041                    uint32_t srate, uint32_t fec)
1042 {
1043     unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
1044     fec = dvb_parse_fec (fec);
1045
1046     if (dvb_find_frontend (d, ISDB_C))
1047         return -1;
1048     return dvb_set_props (d, 6, DTV_CLEAR, 0,
1049 #if DVBv5(5)
1050                           DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_C,
1051 #else
1052 # warning ISDB-C might need Linux DVB version 5.5 or later.
1053                           DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_AC,
1054 #endif
1055                           DTV_FREQUENCY, freq, DTV_MODULATION, mod,
1056                           DTV_SYMBOL_RATE, srate, DTV_INNER_FEC, fec);
1057 }
1058
1059
1060 /*** ISDB-S ***/
1061 int dvb_set_isdbs (dvb_device_t *d, uint64_t freq_Hz, uint16_t ts_id)
1062 {
1063     uint32_t freq = freq_Hz / 1000;
1064
1065     if (dvb_find_frontend (d, ISDB_S))
1066         return -1;
1067     return dvb_set_props (d, 4, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBS,
1068                           DTV_FREQUENCY, freq,
1069 #if DVBv5(8)
1070                           DTV_STREAM_ID,
1071 #else
1072                           DTV_ISDBS_TS_ID,
1073 #endif
1074                           (uint32_t)ts_id);
1075 }
1076
1077
1078 /*** ISDB-T ***/
1079 static int dvb_set_isdbt_layer (dvb_device_t *d, unsigned num,
1080                                 const isdbt_layer_t *l)
1081 {
1082     uint32_t mod = dvb_parse_modulation (l->modulation, QAM_AUTO);
1083     uint32_t fec = dvb_parse_fec (l->code_rate);
1084     uint32_t count = l->segment_count;
1085     uint32_t ti = l->time_interleaving;
1086
1087     num *= DTV_ISDBT_LAYERB_FEC - DTV_ISDBT_LAYERA_FEC;
1088
1089     return dvb_set_props (d, 5, DTV_DELIVERY_SYSTEM, SYS_ISDBT,
1090                           DTV_ISDBT_LAYERA_FEC + num, fec,
1091                           DTV_ISDBT_LAYERA_MODULATION + num, mod,
1092                           DTV_ISDBT_LAYERA_SEGMENT_COUNT + num, count,
1093                           DTV_ISDBT_LAYERA_TIME_INTERLEAVING + num, ti);
1094 }
1095
1096 int dvb_set_isdbt (dvb_device_t *d, uint32_t freq, uint32_t bandwidth,
1097                    int transmit_mode, uint32_t guard,
1098                    const isdbt_layer_t layers[3])
1099 {
1100     bandwidth = dvb_parse_bandwidth (bandwidth);
1101     transmit_mode = dvb_parse_transmit_mode (transmit_mode);
1102     guard = dvb_parse_guard (guard);
1103
1104     if (dvb_find_frontend (d, ISDB_T))
1105         return -1;
1106     if (dvb_set_props (d, 5, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ISDBT,
1107                        DTV_FREQUENCY, freq, DTV_BANDWIDTH_HZ, bandwidth,
1108                        DTV_GUARD_INTERVAL, guard))
1109         return -1;
1110     for (unsigned i = 0; i < 3; i++)
1111         if (dvb_set_isdbt_layer (d, i, layers + i))
1112             return -1;
1113     return 0;
1114 }
1115
1116
1117 /*** ATSC ***/
1118 int dvb_set_atsc (dvb_device_t *d, uint32_t freq, const char *modstr)
1119 {
1120     unsigned mod = dvb_parse_modulation (modstr, VSB_8);
1121
1122     if (dvb_find_frontend (d, ATSC))
1123         return -1;
1124     return dvb_set_props (d, 4, DTV_CLEAR, 0, DTV_DELIVERY_SYSTEM, SYS_ATSC,
1125                           DTV_FREQUENCY, freq, DTV_MODULATION, mod);
1126 }
1127
1128 int dvb_set_cqam (dvb_device_t *d, uint32_t freq, const char *modstr)
1129 {
1130     unsigned mod = dvb_parse_modulation (modstr, QAM_AUTO);
1131
1132     if (dvb_find_frontend (d, CQAM))
1133         return -1;
1134     return dvb_set_props (d, 4, DTV_CLEAR, 0,
1135                           DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B,
1136                           DTV_FREQUENCY, freq, DTV_MODULATION, mod);
1137 }