Merge branch 'pm-cpufreq'
[cascardo/linux.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::
13
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.
18
19
20 .. _tuning:
21
22 Example: Tuning
23 ===============
24
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.
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      {
53          int ans;
54
55          if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
56              perror("FE READ STATUS: ");
57              return -1;
58          }
59
60          if (*stat & FE_HAS_POWER)
61              printf("FE HAS POWER\\n");
62
63          if (*stat & FE_HAS_SIGNAL)
64              printf("FE HAS SIGNAL\\n");
65
66          if (*stat & FE_SPECTRUM_INV)
67              printf("SPEKTRUM INV\\n");
68
69          return 0;
70      }
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,
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;
95
96          frequency = (uint32_t) freq;
97          symbolrate = (uint32_t) srate;
98
99          if((front = open(FRONT,O_RDWR)) < 0){
100              perror("FRONTEND DEVICE: ");
101              return -1;
102          }
103
104          if((sec = open(SEC,O_RDWR)) < 0){
105              perror("SEC DEVICE: ");
106              return -1;
107          }
108
109          if (demux1 < 0){
110              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
111                  < 0){
112                  perror("DEMUX DEVICE: ");
113                  return -1;
114              }
115          }
116
117          if (demux2 < 0){
118              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
119                  < 0){
120                  perror("DEMUX DEVICE: ");
121                  return -1;
122              }
123          }
124
125          if (demux3 < 0){
126              if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
127                  < 0){
128                  perror("DEMUX DEVICE: ");
129                  return -1;
130              }
131          }
132
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;
143
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);
151
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          }
159
160          if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
161              perror("SEC SEND: ");
162              return -1;
163          }
164
165          frp.u.qpsk.SymbolRate = srate;
166          frp.u.qpsk.FEC_inner = fec;
167
168          if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){
169              perror("QPSK TUNE: ");
170              return -1;
171          }
172
173          pfd[0].fd = front;
174          pfd[0].events = POLLIN;
175
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)
180
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;
193
194                  case FE_COMPLETION_EV:
195                      printf("completion event\\n");
196                  }
197              }
198          }
199
200
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          }
210
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          }
220
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          }
230
231          return has_signal(fds);
232      }
233
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.
239
240
241 .. _the_dvr_device:
242
243 Example: The DVR device
244 ========================
245
246 The following program code shows how to use the DVR device for
247 recording.
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      {
279          struct dmx_pes_filter_params pesFilterParams;
280
281          if (demux1 < 0){
282              if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
283                  < 0){
284                  perror("DEMUX DEVICE: ");
285                  return -1;
286              }
287          }
288
289          if (demux2 < 0){
290              if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
291                  < 0){
292                  perror("DEMUX DEVICE: ");
293                  return -1;
294              }
295          }
296
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      }
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      {
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;
331
332          /* open dvr device */
333          if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
334                  perror("DVR DEVICE");
335                  return -1;
336          }
337
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: ");
342
343          printf("Recording %2.0f MB of test file in TS format\\n",
344             MAX_LENGTH/(1024.0*1024.0));
345          length = 0;
346
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          }
355
356          pfd[0].fd = dvr;
357          pfd[0].events = POLLIN;
358
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      }