blob: 1a94966312c05fe2888c3b9a4990852924ca7927 [file] [log] [blame]
Markus Heiser5377d912016-06-30 15:18:56 +02001.. -*- coding: utf-8; mode: rst -*-
2
3.. _dvb_examples:
4
5********
6Examples
7********
8
9In this section we would like to present some examples for using the DVB
10API.
11
Mauro Carvalho Chehab8d4b2312016-08-22 09:19:46 -030012.. note::
Mauro Carvalho Chehabb6b6e672016-08-15 17:49:50 -030013
14 This section is out of date, and the code below won't even
Mauro Carvalho Chehab706f8a92016-07-10 11:57:43 -030015 compile. Please refer to the
16 `libdvbv5 <https://linuxtv.org/docs/libdvbv5/index.html>`__ for
17 updated/recommended examples.
Markus Heiser5377d912016-06-30 15:18:56 +020018
19
20.. _tuning:
21
Mauro Carvalho Chehab282f02c2016-07-10 08:22:19 -030022Example: Tuning
23===============
Markus Heiser5377d912016-06-30 15:18:56 +020024
25We will start with a generic tuning subroutine that uses the frontend
26and SEC, as well as the demux devices. The example is given for QPSK
27tuners, but can easily be adjusted for QAM.
28
29
30.. code-block:: c
31
32 #include <sys/ioctl.h>
33 #include <stdio.h>
34 #include <stdint.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <time.h>
39 #include <unistd.h>
40
41 #include <linux/dvb/dmx.h>
42 #include <linux/dvb/frontend.h>
43 #include <linux/dvb/sec.h>
44 #include <sys/poll.h>
45
46 #define DMX "/dev/dvb/adapter0/demux1"
47 #define FRONT "/dev/dvb/adapter0/frontend1"
48 #define SEC "/dev/dvb/adapter0/sec1"
49
50 /* routine for checking if we have a signal and other status information*/
51 int FEReadStatus(int fd, fe_status_t *stat)
52 {
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030053 int ans;
Markus Heiser5377d912016-06-30 15:18:56 +020054
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030055 if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
56 perror("FE READ STATUS: ");
57 return -1;
58 }
Markus Heiser5377d912016-06-30 15:18:56 +020059
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030060 if (*stat & FE_HAS_POWER)
61 printf("FE HAS POWER\\n");
Markus Heiser5377d912016-06-30 15:18:56 +020062
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030063 if (*stat & FE_HAS_SIGNAL)
64 printf("FE HAS SIGNAL\\n");
Markus Heiser5377d912016-06-30 15:18:56 +020065
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030066 if (*stat & FE_SPECTRUM_INV)
67 printf("SPEKTRUM INV\\n");
Markus Heiser5377d912016-06-30 15:18:56 +020068
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030069 return 0;
Markus Heiser5377d912016-06-30 15:18:56 +020070 }
71
72
73 /* tune qpsk */
74 /* freq: frequency of transponder */
75 /* vpid, apid, tpid: PIDs of video, audio and teletext TS packets */
76 /* diseqc: DiSEqC address of the used LNB */
77 /* pol: Polarisation */
78 /* srate: Symbol Rate */
79 /* fec. FEC */
80 /* lnb_lof1: local frequency of lower LNB band */
81 /* lnb_lof2: local frequency of upper LNB band */
82 /* lnb_slof: switch frequency of LNB */
83
84 int set_qpsk_channel(int freq, int vpid, int apid, int tpid,
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030085 int diseqc, int pol, int srate, int fec, int lnb_lof1,
86 int lnb_lof2, int lnb_slof)
Markus Heiser5377d912016-06-30 15:18:56 +020087 {
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030088 struct secCommand scmd;
89 struct secCmdSequence scmds;
90 struct dmx_pes_filter_params pesFilterParams;
91 FrontendParameters frp;
Mauro Carvalho Chehab8968da92016-07-13 08:43:30 -030092 struct pollfd pfd[1];
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030093 FrontendEvent event;
94 int demux1, demux2, demux3, front;
Markus Heiser5377d912016-06-30 15:18:56 +020095
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030096 frequency = (uint32_t) freq;
97 symbolrate = (uint32_t) srate;
Markus Heiser5377d912016-06-30 15:18:56 +020098
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -030099 if((front = open(FRONT,O_RDWR)) < 0){
100 perror("FRONTEND DEVICE: ");
101 return -1;
102 }
Markus Heiser5377d912016-06-30 15:18:56 +0200103
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300104 if((sec = open(SEC,O_RDWR)) < 0){
105 perror("SEC DEVICE: ");
106 return -1;
107 }
Markus Heiser5377d912016-06-30 15:18:56 +0200108
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300109 if (demux1 < 0){
110 if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
111 < 0){
112 perror("DEMUX DEVICE: ");
113 return -1;
114 }
115 }
Markus Heiser5377d912016-06-30 15:18:56 +0200116
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300117 if (demux2 < 0){
118 if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
119 < 0){
120 perror("DEMUX DEVICE: ");
121 return -1;
122 }
123 }
Markus Heiser5377d912016-06-30 15:18:56 +0200124
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300125 if (demux3 < 0){
126 if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
127 < 0){
128 perror("DEMUX DEVICE: ");
129 return -1;
130 }
131 }
Markus Heiser5377d912016-06-30 15:18:56 +0200132
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300133 if (freq < lnb_slof) {
134 frp.Frequency = (freq - lnb_lof1);
135 scmds.continuousTone = SEC_TONE_OFF;
136 } else {
137 frp.Frequency = (freq - lnb_lof2);
138 scmds.continuousTone = SEC_TONE_ON;
139 }
140 frp.Inversion = INVERSION_AUTO;
141 if (pol) scmds.voltage = SEC_VOLTAGE_18;
142 else scmds.voltage = SEC_VOLTAGE_13;
Markus Heiser5377d912016-06-30 15:18:56 +0200143
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300144 scmd.type=0;
145 scmd.u.diseqc.addr=0x10;
146 scmd.u.diseqc.cmd=0x38;
147 scmd.u.diseqc.numParams=1;
Mauro Carvalho Chehab8968da92016-07-13 08:43:30 -0300148 scmd.u.diseqc.params[0] = 0xF0 | ((diseqc * 4) & 0x0F) |
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300149 (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
150 (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
Markus Heiser5377d912016-06-30 15:18:56 +0200151
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300152 scmds.miniCommand=SEC_MINI_NONE;
153 scmds.numCommands=1;
154 scmds.commands=&scmd;
155 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
156 perror("SEC SEND: ");
157 return -1;
158 }
Markus Heiser5377d912016-06-30 15:18:56 +0200159
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300160 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
161 perror("SEC SEND: ");
162 return -1;
163 }
Markus Heiser5377d912016-06-30 15:18:56 +0200164
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300165 frp.u.qpsk.SymbolRate = srate;
166 frp.u.qpsk.FEC_inner = fec;
Markus Heiser5377d912016-06-30 15:18:56 +0200167
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300168 if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){
169 perror("QPSK TUNE: ");
170 return -1;
171 }
Markus Heiser5377d912016-06-30 15:18:56 +0200172
Mauro Carvalho Chehab8968da92016-07-13 08:43:30 -0300173 pfd[0].fd = front;
174 pfd[0].events = POLLIN;
Markus Heiser5377d912016-06-30 15:18:56 +0200175
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300176 if (poll(pfd,1,3000)){
Mauro Carvalho Chehab8968da92016-07-13 08:43:30 -0300177 if (pfd[0].revents & POLLIN){
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300178 printf("Getting QPSK event\\n");
179 if ( ioctl(front, FE_GET_EVENT, &event)
Markus Heiser5377d912016-06-30 15:18:56 +0200180
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300181 == -EOVERFLOW){
182 perror("qpsk get event");
183 return -1;
184 }
185 printf("Received ");
186 switch(event.type){
187 case FE_UNEXPECTED_EV:
188 printf("unexpected event\\n");
189 return -1;
190 case FE_FAILURE_EV:
191 printf("failure event\\n");
192 return -1;
Markus Heiser5377d912016-06-30 15:18:56 +0200193
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300194 case FE_COMPLETION_EV:
195 printf("completion event\\n");
196 }
197 }
198 }
Markus Heiser5377d912016-06-30 15:18:56 +0200199
200
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300201 pesFilterParams.pid = vpid;
202 pesFilterParams.input = DMX_IN_FRONTEND;
203 pesFilterParams.output = DMX_OUT_DECODER;
204 pesFilterParams.pes_type = DMX_PES_VIDEO;
205 pesFilterParams.flags = DMX_IMMEDIATE_START;
206 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
207 perror("set_vpid");
208 return -1;
209 }
Markus Heiser5377d912016-06-30 15:18:56 +0200210
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300211 pesFilterParams.pid = apid;
212 pesFilterParams.input = DMX_IN_FRONTEND;
213 pesFilterParams.output = DMX_OUT_DECODER;
214 pesFilterParams.pes_type = DMX_PES_AUDIO;
215 pesFilterParams.flags = DMX_IMMEDIATE_START;
216 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
217 perror("set_apid");
218 return -1;
219 }
Markus Heiser5377d912016-06-30 15:18:56 +0200220
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300221 pesFilterParams.pid = tpid;
222 pesFilterParams.input = DMX_IN_FRONTEND;
223 pesFilterParams.output = DMX_OUT_DECODER;
224 pesFilterParams.pes_type = DMX_PES_TELETEXT;
225 pesFilterParams.flags = DMX_IMMEDIATE_START;
226 if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
227 perror("set_tpid");
228 return -1;
229 }
Markus Heiser5377d912016-06-30 15:18:56 +0200230
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300231 return has_signal(fds);
Markus Heiser5377d912016-06-30 15:18:56 +0200232 }
233
234The program assumes that you are using a universal LNB and a standard
235DiSEqC switch with up to 4 addresses. Of course, you could build in some
236more checking if tuning was successful and maybe try to repeat the
237tuning process. Depending on the external hardware, i.e. LNB and DiSEqC
238switch, and weather conditions this may be necessary.
239
240
241.. _the_dvr_device:
242
Mauro Carvalho Chehab282f02c2016-07-10 08:22:19 -0300243Example: The DVR device
244========================
Markus Heiser5377d912016-06-30 15:18:56 +0200245
246The following program code shows how to use the DVR device for
247recording.
248
249
250.. code-block:: c
251
252 #include <sys/ioctl.h>
253 #include <stdio.h>
254 #include <stdint.h>
255 #include <sys/types.h>
256 #include <sys/stat.h>
257 #include <fcntl.h>
258 #include <time.h>
259 #include <unistd.h>
260
261 #include <linux/dvb/dmx.h>
262 #include <linux/dvb/video.h>
263 #include <sys/poll.h>
264 #define DVR "/dev/dvb/adapter0/dvr1"
265 #define AUDIO "/dev/dvb/adapter0/audio1"
266 #define VIDEO "/dev/dvb/adapter0/video1"
267
268 #define BUFFY (188*20)
269 #define MAX_LENGTH (1024*1024*5) /* record 5MB */
270
271
272 /* switch the demuxes to recording, assuming the transponder is tuned */
273
274 /* demux1, demux2: file descriptor of video and audio filters */
275 /* vpid, apid: PIDs of video and audio channels */
276
277 int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
278 {
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300279 struct dmx_pes_filter_params pesFilterParams;
Markus Heiser5377d912016-06-30 15:18:56 +0200280
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300281 if (demux1 < 0){
282 if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
283 < 0){
284 perror("DEMUX DEVICE: ");
285 return -1;
286 }
287 }
Markus Heiser5377d912016-06-30 15:18:56 +0200288
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300289 if (demux2 < 0){
290 if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
291 < 0){
292 perror("DEMUX DEVICE: ");
293 return -1;
294 }
295 }
Markus Heiser5377d912016-06-30 15:18:56 +0200296
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300297 pesFilterParams.pid = vpid;
298 pesFilterParams.input = DMX_IN_FRONTEND;
299 pesFilterParams.output = DMX_OUT_TS_TAP;
300 pesFilterParams.pes_type = DMX_PES_VIDEO;
301 pesFilterParams.flags = DMX_IMMEDIATE_START;
302 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
303 perror("DEMUX DEVICE");
304 return -1;
305 }
306 pesFilterParams.pid = apid;
307 pesFilterParams.input = DMX_IN_FRONTEND;
308 pesFilterParams.output = DMX_OUT_TS_TAP;
309 pesFilterParams.pes_type = DMX_PES_AUDIO;
310 pesFilterParams.flags = DMX_IMMEDIATE_START;
311 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
312 perror("DEMUX DEVICE");
313 return -1;
314 }
315 return 0;
Markus Heiser5377d912016-06-30 15:18:56 +0200316 }
317
318 /* start recording MAX_LENGTH , assuming the transponder is tuned */
319
320 /* demux1, demux2: file descriptor of video and audio filters */
321 /* vpid, apid: PIDs of video and audio channels */
322 int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid)
323 {
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300324 int i;
325 int len;
326 int written;
327 uint8_t buf[BUFFY];
328 uint64_t length;
Mauro Carvalho Chehab8968da92016-07-13 08:43:30 -0300329 struct pollfd pfd[1];
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300330 int dvr, dvr_out;
Markus Heiser5377d912016-06-30 15:18:56 +0200331
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300332 /* open dvr device */
333 if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
334 perror("DVR DEVICE");
335 return -1;
336 }
Markus Heiser5377d912016-06-30 15:18:56 +0200337
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300338 /* switch video and audio demuxes to dvr */
339 printf ("Switching dvr on\\n");
340 i = switch_to_record(demux1, demux2, vpid, apid);
341 printf("finished: ");
Markus Heiser5377d912016-06-30 15:18:56 +0200342
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300343 printf("Recording %2.0f MB of test file in TS format\\n",
344 MAX_LENGTH/(1024.0*1024.0));
345 length = 0;
Markus Heiser5377d912016-06-30 15:18:56 +0200346
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300347 /* open output file */
348 if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT
349 |O_TRUNC, S_IRUSR|S_IWUSR
350 |S_IRGRP|S_IWGRP|S_IROTH|
351 S_IWOTH)) < 0){
352 perror("Can't open file for dvr test");
353 return -1;
354 }
Markus Heiser5377d912016-06-30 15:18:56 +0200355
Mauro Carvalho Chehab8968da92016-07-13 08:43:30 -0300356 pfd[0].fd = dvr;
357 pfd[0].events = POLLIN;
Markus Heiser5377d912016-06-30 15:18:56 +0200358
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300359 /* poll for dvr data and write to file */
360 while (length < MAX_LENGTH ) {
361 if (poll(pfd,1,1)){
Mauro Carvalho Chehab8968da92016-07-13 08:43:30 -0300362 if (pfd[0].revents & POLLIN){
Mauro Carvalho Chehab0579e6e2016-07-04 16:25:48 -0300363 len = read(dvr, buf, BUFFY);
364 if (len < 0){
365 perror("recording");
366 return -1;
367 }
368 if (len > 0){
369 written = 0;
370 while (written < len)
371 written +=
372 write (dvr_out,
373 buf, len);
374 length += len;
375 printf("written %2.0f MB\\r",
376 length/1024./1024.);
377 }
378 }
379 }
380 }
381 return 0;
Markus Heiser5377d912016-06-30 15:18:56 +0200382 }