Linux 4.8.3
[linux/fpc-iii.git] / Documentation / media / uapi / dvb / examples.rst
blobbf0a8617de9244a4794f4e37c2d217c14ebb8a38
1 .. -*- coding: utf-8; mode: rst -*-
3 .. _dvb_examples:
5 ********
6 Examples
7 ********
9 In this section we would like to present some examples for using the DVB
10 API.
12 ..note:: This section is out of date, and the code below won't even
13    compile. Please refer to the
14    `libdvbv5 <https://linuxtv.org/docs/libdvbv5/index.html>`__ for
15    updated/recommended examples.
18 .. _tuning:
20 Example: Tuning
21 ===============
23 We will start with a generic tuning subroutine that uses the frontend
24 and SEC, as well as the demux devices. The example is given for QPSK
25 tuners, but can easily be adjusted for QAM.
28 .. code-block:: c
30      #include <sys/ioctl.h>
31      #include <stdio.h>
32      #include <stdint.h>
33      #include <sys/types.h>
34      #include <sys/stat.h>
35      #include <fcntl.h>
36      #include <time.h>
37      #include <unistd.h>
39      #include <linux/dvb/dmx.h>
40      #include <linux/dvb/frontend.h>
41      #include <linux/dvb/sec.h>
42      #include <sys/poll.h>
44      #define DMX "/dev/dvb/adapter0/demux1"
45      #define FRONT "/dev/dvb/adapter0/frontend1"
46      #define SEC "/dev/dvb/adapter0/sec1"
48      /* routine for checking if we have a signal and other status information*/
49      int FEReadStatus(int fd, fe_status_t *stat)
50      {
51          int ans;
53          if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
54              perror("FE READ STATUS: ");
55              return -1;
56          }
58          if (*stat & FE_HAS_POWER)
59              printf("FE HAS POWER\\n");
61          if (*stat & FE_HAS_SIGNAL)
62              printf("FE HAS SIGNAL\\n");
64          if (*stat & FE_SPECTRUM_INV)
65              printf("SPEKTRUM INV\\n");
67          return 0;
68      }
71      /* tune qpsk */
72      /* freq:             frequency of transponder                      */
73      /* vpid, apid, tpid: PIDs of video, audio and teletext TS packets  */
74      /* diseqc:           DiSEqC address of the used LNB                */
75      /* pol:              Polarisation                                  */
76      /* srate:            Symbol Rate                                   */
77      /* fec.              FEC                                           */
78      /* lnb_lof1:         local frequency of lower LNB band             */
79      /* lnb_lof2:         local frequency of upper LNB band             */
80      /* lnb_slof:         switch frequency of LNB                       */
82      int set_qpsk_channel(int freq, int vpid, int apid, int tpid,
83              int diseqc, int pol, int srate, int fec, int lnb_lof1,
84              int lnb_lof2, int lnb_slof)
85      {
86          struct secCommand scmd;
87          struct secCmdSequence scmds;
88          struct dmx_pes_filter_params pesFilterParams;
89          FrontendParameters frp;
90          struct pollfd pfd[1];
91          FrontendEvent event;
92          int demux1, demux2, demux3, front;
94          frequency = (uint32_t) freq;
95          symbolrate = (uint32_t) srate;
97          if((front = open(FRONT,O_RDWR)) < 0){
98              perror("FRONTEND DEVICE: ");
99              return -1;
100          }
102          if((sec = open(SEC,O_RDWR)) < 0){
103              perror("SEC DEVICE: ");
104              return -1;
105          }
107          if (demux1 < 0){
108              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
109                  < 0){
110                  perror("DEMUX DEVICE: ");
111                  return -1;
112              }
113          }
115          if (demux2 < 0){
116              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
117                  < 0){
118                  perror("DEMUX DEVICE: ");
119                  return -1;
120              }
121          }
123          if (demux3 < 0){
124              if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
125                  < 0){
126                  perror("DEMUX DEVICE: ");
127                  return -1;
128              }
129          }
131          if (freq < lnb_slof) {
132              frp.Frequency = (freq - lnb_lof1);
133              scmds.continuousTone = SEC_TONE_OFF;
134          } else {
135              frp.Frequency = (freq - lnb_lof2);
136              scmds.continuousTone = SEC_TONE_ON;
137          }
138          frp.Inversion = INVERSION_AUTO;
139          if (pol) scmds.voltage = SEC_VOLTAGE_18;
140          else scmds.voltage = SEC_VOLTAGE_13;
142          scmd.type=0;
143          scmd.u.diseqc.addr=0x10;
144          scmd.u.diseqc.cmd=0x38;
145          scmd.u.diseqc.numParams=1;
146          scmd.u.diseqc.params[0] = 0xF0 | ((diseqc * 4) & 0x0F) |
147              (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
148              (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
150          scmds.miniCommand=SEC_MINI_NONE;
151          scmds.numCommands=1;
152          scmds.commands=&scmd;
153          if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
154              perror("SEC SEND: ");
155              return -1;
156          }
158          if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
159              perror("SEC SEND: ");
160              return -1;
161          }
163          frp.u.qpsk.SymbolRate = srate;
164          frp.u.qpsk.FEC_inner = fec;
166          if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){
167              perror("QPSK TUNE: ");
168              return -1;
169          }
171          pfd[0].fd = front;
172          pfd[0].events = POLLIN;
174          if (poll(pfd,1,3000)){
175              if (pfd[0].revents & POLLIN){
176                  printf("Getting QPSK event\\n");
177                  if ( ioctl(front, FE_GET_EVENT, &event)
179                       == -EOVERFLOW){
180                      perror("qpsk get event");
181                      return -1;
182                  }
183                  printf("Received ");
184                  switch(event.type){
185                  case FE_UNEXPECTED_EV:
186                      printf("unexpected event\\n");
187                      return -1;
188                  case FE_FAILURE_EV:
189                      printf("failure event\\n");
190                      return -1;
192                  case FE_COMPLETION_EV:
193                      printf("completion event\\n");
194                  }
195              }
196          }
199          pesFilterParams.pid     = vpid;
200          pesFilterParams.input   = DMX_IN_FRONTEND;
201          pesFilterParams.output  = DMX_OUT_DECODER;
202          pesFilterParams.pes_type = DMX_PES_VIDEO;
203          pesFilterParams.flags   = DMX_IMMEDIATE_START;
204          if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
205              perror("set_vpid");
206              return -1;
207          }
209          pesFilterParams.pid     = apid;
210          pesFilterParams.input   = DMX_IN_FRONTEND;
211          pesFilterParams.output  = DMX_OUT_DECODER;
212          pesFilterParams.pes_type = DMX_PES_AUDIO;
213          pesFilterParams.flags   = DMX_IMMEDIATE_START;
214          if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
215              perror("set_apid");
216              return -1;
217          }
219          pesFilterParams.pid     = tpid;
220          pesFilterParams.input   = DMX_IN_FRONTEND;
221          pesFilterParams.output  = DMX_OUT_DECODER;
222          pesFilterParams.pes_type = DMX_PES_TELETEXT;
223          pesFilterParams.flags   = DMX_IMMEDIATE_START;
224          if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
225              perror("set_tpid");
226              return -1;
227          }
229          return has_signal(fds);
230      }
232 The program assumes that you are using a universal LNB and a standard
233 DiSEqC switch with up to 4 addresses. Of course, you could build in some
234 more checking if tuning was successful and maybe try to repeat the
235 tuning process. Depending on the external hardware, i.e. LNB and DiSEqC
236 switch, and weather conditions this may be necessary.
239 .. _the_dvr_device:
241 Example: The DVR device
242 ========================
244 The following program code shows how to use the DVR device for
245 recording.
248 .. code-block:: c
250      #include <sys/ioctl.h>
251      #include <stdio.h>
252      #include <stdint.h>
253      #include <sys/types.h>
254      #include <sys/stat.h>
255      #include <fcntl.h>
256      #include <time.h>
257      #include <unistd.h>
259      #include <linux/dvb/dmx.h>
260      #include <linux/dvb/video.h>
261      #include <sys/poll.h>
262      #define DVR "/dev/dvb/adapter0/dvr1"
263      #define AUDIO "/dev/dvb/adapter0/audio1"
264      #define VIDEO "/dev/dvb/adapter0/video1"
266      #define BUFFY (188*20)
267      #define MAX_LENGTH (1024*1024*5) /* record 5MB */
270      /* switch the demuxes to recording, assuming the transponder is tuned */
272      /* demux1, demux2: file descriptor of video and audio filters */
273      /* vpid, apid:     PIDs of video and audio channels           */
275      int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
276      {
277          struct dmx_pes_filter_params pesFilterParams;
279          if (demux1 < 0){
280              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
281                  < 0){
282                  perror("DEMUX DEVICE: ");
283                  return -1;
284              }
285          }
287          if (demux2 < 0){
288              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
289                  < 0){
290                  perror("DEMUX DEVICE: ");
291                  return -1;
292              }
293          }
295          pesFilterParams.pid = vpid;
296          pesFilterParams.input = DMX_IN_FRONTEND;
297          pesFilterParams.output = DMX_OUT_TS_TAP;
298          pesFilterParams.pes_type = DMX_PES_VIDEO;
299          pesFilterParams.flags = DMX_IMMEDIATE_START;
300          if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
301              perror("DEMUX DEVICE");
302              return -1;
303          }
304          pesFilterParams.pid = apid;
305          pesFilterParams.input = DMX_IN_FRONTEND;
306          pesFilterParams.output = DMX_OUT_TS_TAP;
307          pesFilterParams.pes_type = DMX_PES_AUDIO;
308          pesFilterParams.flags = DMX_IMMEDIATE_START;
309          if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
310              perror("DEMUX DEVICE");
311              return -1;
312          }
313          return 0;
314      }
316      /* start recording MAX_LENGTH , assuming the transponder is tuned */
318      /* demux1, demux2: file descriptor of video and audio filters */
319      /* vpid, apid:     PIDs of video and audio channels           */
320      int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid)
321      {
322          int i;
323          int len;
324          int written;
325          uint8_t buf[BUFFY];
326          uint64_t length;
327          struct pollfd pfd[1];
328          int dvr, dvr_out;
330          /* open dvr device */
331          if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
332                  perror("DVR DEVICE");
333                  return -1;
334          }
336          /* switch video and audio demuxes to dvr */
337          printf ("Switching dvr on\\n");
338          i = switch_to_record(demux1, demux2, vpid, apid);
339          printf("finished: ");
341          printf("Recording %2.0f MB of test file in TS format\\n",
342             MAX_LENGTH/(1024.0*1024.0));
343          length = 0;
345          /* open output file */
346          if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT
347                       |O_TRUNC, S_IRUSR|S_IWUSR
348                       |S_IRGRP|S_IWGRP|S_IROTH|
349                       S_IWOTH)) < 0){
350              perror("Can't open file for dvr test");
351              return -1;
352          }
354          pfd[0].fd = dvr;
355          pfd[0].events = POLLIN;
357          /* poll for dvr data and write to file */
358          while (length < MAX_LENGTH ) {
359              if (poll(pfd,1,1)){
360                  if (pfd[0].revents & POLLIN){
361                      len = read(dvr, buf, BUFFY);
362                      if (len < 0){
363                          perror("recording");
364                          return -1;
365                      }
366                      if (len > 0){
367                          written = 0;
368                          while (written < len)
369                              written +=
370                                  write (dvr_out,
371                                     buf, len);
372                          length += len;
373                          printf("written %2.0f MB\\r",
374                             length/1024./1024.);
375                      }
376                  }
377              }
378          }
379          return 0;
380      }