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