Linux 4.11-rc6
[linux/fpc-iii.git] / Documentation / media / uapi / dvb / examples.rst
blob1a94966312c05fe2888c3b9a4990852924ca7927
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::
14    This section is out of date, and the code below won't even
15    compile. Please refer to the
16    `libdvbv5 <https://linuxtv.org/docs/libdvbv5/index.html>`__ for
17    updated/recommended examples.
20 .. _tuning:
22 Example: Tuning
23 ===============
25 We will start with a generic tuning subroutine that uses the frontend
26 and SEC, as well as the demux devices. The example is given for QPSK
27 tuners, but can easily be adjusted for QAM.
30 .. code-block:: c
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>
41      #include <linux/dvb/dmx.h>
42      #include <linux/dvb/frontend.h>
43      #include <linux/dvb/sec.h>
44      #include <sys/poll.h>
46      #define DMX "/dev/dvb/adapter0/demux1"
47      #define FRONT "/dev/dvb/adapter0/frontend1"
48      #define SEC "/dev/dvb/adapter0/sec1"
50      /* routine for checking if we have a signal and other status information*/
51      int FEReadStatus(int fd, fe_status_t *stat)
52      {
53          int ans;
55          if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
56              perror("FE READ STATUS: ");
57              return -1;
58          }
60          if (*stat & FE_HAS_POWER)
61              printf("FE HAS POWER\\n");
63          if (*stat & FE_HAS_SIGNAL)
64              printf("FE HAS SIGNAL\\n");
66          if (*stat & FE_SPECTRUM_INV)
67              printf("SPEKTRUM INV\\n");
69          return 0;
70      }
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                       */
84      int set_qpsk_channel(int freq, int vpid, int apid, int tpid,
85              int diseqc, int pol, int srate, int fec, int lnb_lof1,
86              int lnb_lof2, int lnb_slof)
87      {
88          struct secCommand scmd;
89          struct secCmdSequence scmds;
90          struct dmx_pes_filter_params pesFilterParams;
91          FrontendParameters frp;
92          struct pollfd pfd[1];
93          FrontendEvent event;
94          int demux1, demux2, demux3, front;
96          frequency = (uint32_t) freq;
97          symbolrate = (uint32_t) srate;
99          if((front = open(FRONT,O_RDWR)) < 0){
100              perror("FRONTEND DEVICE: ");
101              return -1;
102          }
104          if((sec = open(SEC,O_RDWR)) < 0){
105              perror("SEC DEVICE: ");
106              return -1;
107          }
109          if (demux1 < 0){
110              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
111                  < 0){
112                  perror("DEMUX DEVICE: ");
113                  return -1;
114              }
115          }
117          if (demux2 < 0){
118              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
119                  < 0){
120                  perror("DEMUX DEVICE: ");
121                  return -1;
122              }
123          }
125          if (demux3 < 0){
126              if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
127                  < 0){
128                  perror("DEMUX DEVICE: ");
129                  return -1;
130              }
131          }
133          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;
144          scmd.type=0;
145          scmd.u.diseqc.addr=0x10;
146          scmd.u.diseqc.cmd=0x38;
147          scmd.u.diseqc.numParams=1;
148          scmd.u.diseqc.params[0] = 0xF0 | ((diseqc * 4) & 0x0F) |
149              (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
150              (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
152          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          }
160          if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
161              perror("SEC SEND: ");
162              return -1;
163          }
165          frp.u.qpsk.SymbolRate = srate;
166          frp.u.qpsk.FEC_inner = fec;
168          if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){
169              perror("QPSK TUNE: ");
170              return -1;
171          }
173          pfd[0].fd = front;
174          pfd[0].events = POLLIN;
176          if (poll(pfd,1,3000)){
177              if (pfd[0].revents & POLLIN){
178                  printf("Getting QPSK event\\n");
179                  if ( ioctl(front, FE_GET_EVENT, &event)
181                       == -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;
194                  case FE_COMPLETION_EV:
195                      printf("completion event\\n");
196                  }
197              }
198          }
201          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          }
211          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          }
221          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          }
231          return has_signal(fds);
232      }
234 The program assumes that you are using a universal LNB and a standard
235 DiSEqC switch with up to 4 addresses. Of course, you could build in some
236 more checking if tuning was successful and maybe try to repeat the
237 tuning process. Depending on the external hardware, i.e. LNB and DiSEqC
238 switch, and weather conditions this may be necessary.
241 .. _the_dvr_device:
243 Example: The DVR device
244 ========================
246 The following program code shows how to use the DVR device for
247 recording.
250 .. code-block:: c
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>
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"
268      #define BUFFY (188*20)
269      #define MAX_LENGTH (1024*1024*5) /* record 5MB */
272      /* switch the demuxes to recording, assuming the transponder is tuned */
274      /* demux1, demux2: file descriptor of video and audio filters */
275      /* vpid, apid:     PIDs of video and audio channels           */
277      int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
278      {
279          struct dmx_pes_filter_params pesFilterParams;
281          if (demux1 < 0){
282              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
283                  < 0){
284                  perror("DEMUX DEVICE: ");
285                  return -1;
286              }
287          }
289          if (demux2 < 0){
290              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
291                  < 0){
292                  perror("DEMUX DEVICE: ");
293                  return -1;
294              }
295          }
297          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;
316      }
318      /* start recording MAX_LENGTH , assuming the transponder is tuned */
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      {
324          int i;
325          int len;
326          int written;
327          uint8_t buf[BUFFY];
328          uint64_t length;
329          struct pollfd pfd[1];
330          int dvr, dvr_out;
332          /* open dvr device */
333          if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
334                  perror("DVR DEVICE");
335                  return -1;
336          }
338          /* 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: ");
343          printf("Recording %2.0f MB of test file in TS format\\n",
344             MAX_LENGTH/(1024.0*1024.0));
345          length = 0;
347          /* 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          }
356          pfd[0].fd = dvr;
357          pfd[0].events = POLLIN;
359          /* poll for dvr data and write to file */
360          while (length < MAX_LENGTH ) {
361              if (poll(pfd,1,1)){
362                  if (pfd[0].revents & POLLIN){
363                      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;
382      }