Merge branch 'for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[sfrench/cifs-2.6.git] / Documentation / media / uapi / dvb / examples.rst
1 .. -*- coding: utf-8; mode: rst -*-
2
3 .. _dvb_examples:
4
5 ********
6 Examples
7 ********
8
9 In this section we would like to present some examples for using the DVB
10 API.
11
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.
16
17
18 .. _tuning:
19
20 Example: Tuning
21 ===============
22
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.
26
27
28 .. code-block:: c
29
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>
38
39      #include <linux/dvb/dmx.h>
40      #include <linux/dvb/frontend.h>
41      #include <linux/dvb/sec.h>
42      #include <sys/poll.h>
43
44      #define DMX "/dev/dvb/adapter0/demux1"
45      #define FRONT "/dev/dvb/adapter0/frontend1"
46      #define SEC "/dev/dvb/adapter0/sec1"
47
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;
52
53          if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
54              perror("FE READ STATUS: ");
55              return -1;
56          }
57
58          if (*stat & FE_HAS_POWER)
59              printf("FE HAS POWER\\n");
60
61          if (*stat & FE_HAS_SIGNAL)
62              printf("FE HAS SIGNAL\\n");
63
64          if (*stat & FE_SPECTRUM_INV)
65              printf("SPEKTRUM INV\\n");
66
67          return 0;
68      }
69
70
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                       */
81
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;
93
94          frequency = (uint32_t) freq;
95          symbolrate = (uint32_t) srate;
96
97          if((front = open(FRONT,O_RDWR)) < 0){
98              perror("FRONTEND DEVICE: ");
99              return -1;
100          }
101
102          if((sec = open(SEC,O_RDWR)) < 0){
103              perror("SEC DEVICE: ");
104              return -1;
105          }
106
107          if (demux1 < 0){
108              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
109                  < 0){
110                  perror("DEMUX DEVICE: ");
111                  return -1;
112              }
113          }
114
115          if (demux2 < 0){
116              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
117                  < 0){
118                  perror("DEMUX DEVICE: ");
119                  return -1;
120              }
121          }
122
123          if (demux3 < 0){
124              if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
125                  < 0){
126                  perror("DEMUX DEVICE: ");
127                  return -1;
128              }
129          }
130
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;
141
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);
149
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          }
157
158          if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
159              perror("SEC SEND: ");
160              return -1;
161          }
162
163          frp.u.qpsk.SymbolRate = srate;
164          frp.u.qpsk.FEC_inner = fec;
165
166          if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){
167              perror("QPSK TUNE: ");
168              return -1;
169          }
170
171          pfd[0].fd = front;
172          pfd[0].events = POLLIN;
173
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)
178
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;
191
192                  case FE_COMPLETION_EV:
193                      printf("completion event\\n");
194                  }
195              }
196          }
197
198
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          }
208
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          }
218
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          }
228
229          return has_signal(fds);
230      }
231
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.
237
238
239 .. _the_dvr_device:
240
241 Example: The DVR device
242 ========================
243
244 The following program code shows how to use the DVR device for
245 recording.
246
247
248 .. code-block:: c
249
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>
258
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"
265
266      #define BUFFY (188*20)
267      #define MAX_LENGTH (1024*1024*5) /* record 5MB */
268
269
270      /* switch the demuxes to recording, assuming the transponder is tuned */
271
272      /* demux1, demux2: file descriptor of video and audio filters */
273      /* vpid, apid:     PIDs of video and audio channels           */
274
275      int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
276      {
277          struct dmx_pes_filter_params pesFilterParams;
278
279          if (demux1 < 0){
280              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
281                  < 0){
282                  perror("DEMUX DEVICE: ");
283                  return -1;
284              }
285          }
286
287          if (demux2 < 0){
288              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
289                  < 0){
290                  perror("DEMUX DEVICE: ");
291                  return -1;
292              }
293          }
294
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      }
315
316      /* start recording MAX_LENGTH , assuming the transponder is tuned */
317
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;
329
330          /* open dvr device */
331          if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
332                  perror("DVR DEVICE");
333                  return -1;
334          }
335
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: ");
340
341          printf("Recording %2.0f MB of test file in TS format\\n",
342             MAX_LENGTH/(1024.0*1024.0));
343          length = 0;
344
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          }
353
354          pfd[0].fd = dvr;
355          pfd[0].events = POLLIN;
356
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      }