mm-only debug patch...
[mmotm.git] / Documentation / DocBook / dvb / examples.xml
blobf037e568eb6e7d2ef50a30b8b0aa62fc05c86dfd
1 <title>Examples</title>
2 <para>In this section we would like to present some examples for using the DVB API.
3 </para>
4 <para>Maintainer note: This section is out of date. Please refer to the sample programs packaged
5 with the driver distribution from <ulink url="http://linuxtv.org/hg/dvb-apps" />.
6 </para>
8 <section id="tuning">
9 <title>Tuning</title>
10 <para>We will start with a generic tuning subroutine that uses the frontend and SEC, as well as
11 the demux devices. The example is given for QPSK tuners, but can easily be adjusted for
12 QAM.
13 </para>
14 <programlisting>
15  #include &#x003C;sys/ioctl.h&#x003E;
16  #include &#x003C;stdio.h&#x003E;
17  #include &#x003C;stdint.h&#x003E;
18  #include &#x003C;sys/types.h&#x003E;
19  #include &#x003C;sys/stat.h&#x003E;
20  #include &#x003C;fcntl.h&#x003E;
21  #include &#x003C;time.h&#x003E;
22  #include &#x003C;unistd.h&#x003E;
24  #include &#x003C;linux/dvb/dmx.h&#x003E;
25  #include &#x003C;linux/dvb/frontend.h&#x003E;
26  #include &#x003C;linux/dvb/sec.h&#x003E;
27  #include &#x003C;sys/poll.h&#x003E;
29  #define DMX "/dev/dvb/adapter0/demux1"
30  #define FRONT "/dev/dvb/adapter0/frontend1"
31  #define SEC "/dev/dvb/adapter0/sec1"
33  /&#x22C6; routine for checking if we have a signal and other status information&#x22C6;/
34  int FEReadStatus(int fd, fe_status_t &#x22C6;stat)
35  {
36          int ans;
38          if ( (ans = ioctl(fd,FE_READ_STATUS,stat) &#x003C; 0)){
39                  perror("FE READ STATUS: ");
40                  return -1;
41          }
43          if (&#x22C6;stat &amp; FE_HAS_POWER)
44                  printf("FE HAS POWER\n");
46          if (&#x22C6;stat &amp; FE_HAS_SIGNAL)
47                  printf("FE HAS SIGNAL\n");
49          if (&#x22C6;stat &amp; FE_SPECTRUM_INV)
50                  printf("SPEKTRUM INV\n");
52          return 0;
53  }
56  /&#x22C6; tune qpsk &#x22C6;/
57  /&#x22C6; freq:             frequency of transponder                      &#x22C6;/
58  /&#x22C6; vpid, apid, tpid: PIDs of video, audio and teletext TS packets  &#x22C6;/
59  /&#x22C6; diseqc:           DiSEqC address of the used LNB                &#x22C6;/
60  /&#x22C6; pol:              Polarisation                                  &#x22C6;/
61  /&#x22C6; srate:            Symbol Rate                                   &#x22C6;/
62  /&#x22C6; fec.              FEC                                           &#x22C6;/
63  /&#x22C6; lnb_lof1:         local frequency of lower LNB band             &#x22C6;/
64  /&#x22C6; lnb_lof2:         local frequency of upper LNB band             &#x22C6;/
65  /&#x22C6; lnb_slof:         switch frequency of LNB                       &#x22C6;/
67  int set_qpsk_channel(int freq, int vpid, int apid, int tpid,
68                  int diseqc, int pol, int srate, int fec, int lnb_lof1,
69                  int lnb_lof2, int lnb_slof)
70  {
71          struct secCommand scmd;
72          struct secCmdSequence scmds;
73          struct dmx_pes_filter_params pesFilterParams;
74          FrontendParameters frp;
75          struct pollfd pfd[1];
76          FrontendEvent event;
77          int demux1, demux2, demux3, front;
79          frequency = (uint32_t) freq;
80          symbolrate = (uint32_t) srate;
82          if((front = open(FRONT,O_RDWR)) &#x003C; 0){
83                  perror("FRONTEND DEVICE: ");
84                  return -1;
85          }
87          if((sec = open(SEC,O_RDWR)) &#x003C; 0){
88                  perror("SEC DEVICE: ");
89                  return -1;
90          }
92          if (demux1 &#x003C; 0){
93                  if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
94                      &#x003C; 0){
95                          perror("DEMUX DEVICE: ");
96                          return -1;
97                  }
98          }
100          if (demux2 &#x003C; 0){
101                  if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
102                      &#x003C; 0){
103                          perror("DEMUX DEVICE: ");
104                          return -1;
105                  }
106          }
108          if (demux3 &#x003C; 0){
109                  if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
110                      &#x003C; 0){
111                          perror("DEMUX DEVICE: ");
112                          return -1;
113                  }
114          }
116          if (freq &#x003C; lnb_slof) {
117                  frp.Frequency = (freq - lnb_lof1);
118                  scmds.continuousTone = SEC_TONE_OFF;
119          } else {
120                  frp.Frequency = (freq - lnb_lof2);
121                  scmds.continuousTone = SEC_TONE_ON;
122          }
123          frp.Inversion = INVERSION_AUTO;
124          if (pol) scmds.voltage = SEC_VOLTAGE_18;
125          else scmds.voltage = SEC_VOLTAGE_13;
127          scmd.type=0;
128          scmd.u.diseqc.addr=0x10;
129          scmd.u.diseqc.cmd=0x38;
130          scmd.u.diseqc.numParams=1;
131          scmd.u.diseqc.params[0] = 0xF0 | ((diseqc &#x22C6; 4) &amp; 0x0F) |
132                  (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
133                  (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
135          scmds.miniCommand=SEC_MINI_NONE;
136          scmds.numCommands=1;
137          scmds.commands=&amp;scmd;
138          if (ioctl(sec, SEC_SEND_SEQUENCE, &amp;scmds) &#x003C; 0){
139                  perror("SEC SEND: ");
140                  return -1;
141          }
143          if (ioctl(sec, SEC_SEND_SEQUENCE, &amp;scmds) &#x003C; 0){
144                  perror("SEC SEND: ");
145                  return -1;
146          }
148          frp.u.qpsk.SymbolRate = srate;
149          frp.u.qpsk.FEC_inner = fec;
151          if (ioctl(front, FE_SET_FRONTEND, &amp;frp) &#x003C; 0){
152                  perror("QPSK TUNE: ");
153                  return -1;
154          }
156          pfd[0].fd = front;
157          pfd[0].events = POLLIN;
159          if (poll(pfd,1,3000)){
160                  if (pfd[0].revents &amp; POLLIN){
161                          printf("Getting QPSK event\n");
162                          if ( ioctl(front, FE_GET_EVENT, &amp;event)
164                               == -EOVERFLOW){
165                                  perror("qpsk get event");
166                                  return -1;
167                          }
168                          printf("Received ");
169                          switch(event.type){
170                          case FE_UNEXPECTED_EV:
171                                  printf("unexpected event\n");
172                                  return -1;
173                          case FE_FAILURE_EV:
174                                  printf("failure event\n");
175                                  return -1;
177                          case FE_COMPLETION_EV:
178                                  printf("completion event\n");
179                          }
180                  }
181          }
184          pesFilterParams.pid     = vpid;
185          pesFilterParams.input   = DMX_IN_FRONTEND;
186          pesFilterParams.output  = DMX_OUT_DECODER;
187          pesFilterParams.pes_type = DMX_PES_VIDEO;
188          pesFilterParams.flags   = DMX_IMMEDIATE_START;
189          if (ioctl(demux1, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
190                  perror("set_vpid");
191                  return -1;
192          }
194          pesFilterParams.pid     = apid;
195          pesFilterParams.input   = DMX_IN_FRONTEND;
196          pesFilterParams.output  = DMX_OUT_DECODER;
197          pesFilterParams.pes_type = DMX_PES_AUDIO;
198          pesFilterParams.flags   = DMX_IMMEDIATE_START;
199          if (ioctl(demux2, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
200                  perror("set_apid");
201                  return -1;
202          }
204          pesFilterParams.pid     = tpid;
205          pesFilterParams.input   = DMX_IN_FRONTEND;
206          pesFilterParams.output  = DMX_OUT_DECODER;
207          pesFilterParams.pes_type = DMX_PES_TELETEXT;
208          pesFilterParams.flags   = DMX_IMMEDIATE_START;
209          if (ioctl(demux3, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
210                  perror("set_tpid");
211                  return -1;
212          }
214          return has_signal(fds);
217 </programlisting>
218 <para>The program assumes that you are using a universal LNB and a standard DiSEqC
219 switch with up to 4 addresses. Of course, you could build in some more checking if
220 tuning was successful and maybe try to repeat the tuning process. Depending on the
221 external hardware, i.e. LNB and DiSEqC switch, and weather conditions this may be
222 necessary.
223 </para>
224 </section>
226 <section id="the_dvr_device">
227 <title>The DVR device</title>
228 <para>The following program code shows how to use the DVR device for recording.
229 </para>
230 <programlisting>
231  #include &#x003C;sys/ioctl.h&#x003E;
232  #include &#x003C;stdio.h&#x003E;
233  #include &#x003C;stdint.h&#x003E;
234  #include &#x003C;sys/types.h&#x003E;
235  #include &#x003C;sys/stat.h&#x003E;
236  #include &#x003C;fcntl.h&#x003E;
237  #include &#x003C;time.h&#x003E;
238  #include &#x003C;unistd.h&#x003E;
240  #include &#x003C;linux/dvb/dmx.h&#x003E;
241  #include &#x003C;linux/dvb/video.h&#x003E;
242  #include &#x003C;sys/poll.h&#x003E;
243  #define DVR "/dev/dvb/adapter0/dvr1"
244  #define AUDIO "/dev/dvb/adapter0/audio1"
245  #define VIDEO "/dev/dvb/adapter0/video1"
247  #define BUFFY (188&#x22C6;20)
248  #define MAX_LENGTH (1024&#x22C6;1024&#x22C6;5) /&#x22C6; record 5MB &#x22C6;/
251  /&#x22C6; switch the demuxes to recording, assuming the transponder is tuned &#x22C6;/
253  /&#x22C6; demux1, demux2: file descriptor of video and audio filters &#x22C6;/
254  /&#x22C6; vpid, apid:     PIDs of video and audio channels           &#x22C6;/
256  int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
258          struct dmx_pes_filter_params pesFilterParams;
260          if (demux1 &#x003C; 0){
261                  if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
262                      &#x003C; 0){
263                          perror("DEMUX DEVICE: ");
264                          return -1;
265                  }
266          }
268          if (demux2 &#x003C; 0){
269                  if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
270                      &#x003C; 0){
271                          perror("DEMUX DEVICE: ");
272                          return -1;
273                  }
274          }
276          pesFilterParams.pid = vpid;
277          pesFilterParams.input = DMX_IN_FRONTEND;
278          pesFilterParams.output = DMX_OUT_TS_TAP;
279          pesFilterParams.pes_type = DMX_PES_VIDEO;
280          pesFilterParams.flags = DMX_IMMEDIATE_START;
281          if (ioctl(demux1, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
282                  perror("DEMUX DEVICE");
283                  return -1;
284          }
285          pesFilterParams.pid = apid;
286          pesFilterParams.input = DMX_IN_FRONTEND;
287          pesFilterParams.output = DMX_OUT_TS_TAP;
288          pesFilterParams.pes_type = DMX_PES_AUDIO;
289          pesFilterParams.flags = DMX_IMMEDIATE_START;
290          if (ioctl(demux2, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
291                  perror("DEMUX DEVICE");
292                  return -1;
293          }
294          return 0;
297  /&#x22C6; start recording MAX_LENGTH , assuming the transponder is tuned &#x22C6;/
299  /&#x22C6; demux1, demux2: file descriptor of video and audio filters &#x22C6;/
300  /&#x22C6; vpid, apid:     PIDs of video and audio channels           &#x22C6;/
301  int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid)
303          int i;
304          int len;
305          int written;
306          uint8_t buf[BUFFY];
307          uint64_t length;
308          struct pollfd pfd[1];
309          int dvr, dvr_out;
311          /&#x22C6; open dvr device &#x22C6;/
312          if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) &#x003C; 0){
313                          perror("DVR DEVICE");
314                          return -1;
315          }
317          /&#x22C6; switch video and audio demuxes to dvr &#x22C6;/
318          printf ("Switching dvr on\n");
319          i = switch_to_record(demux1, demux2, vpid, apid);
320          printf("finished: ");
322          printf("Recording %2.0f MB of test file in TS format\n",
323                 MAX_LENGTH/(1024.0&#x22C6;1024.0));
324          length = 0;
326          /&#x22C6; open output file &#x22C6;/
327          if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT
328                                   |O_TRUNC, S_IRUSR|S_IWUSR
329                                   |S_IRGRP|S_IWGRP|S_IROTH|
330                                   S_IWOTH)) &#x003C; 0){
331                  perror("Can't open file for dvr test");
332                  return -1;
333          }
335          pfd[0].fd = dvr;
336          pfd[0].events = POLLIN;
338          /&#x22C6; poll for dvr data and write to file &#x22C6;/
339          while (length &#x003C; MAX_LENGTH ) {
340                  if (poll(pfd,1,1)){
341                          if (pfd[0].revents &amp; POLLIN){
342                                  len = read(dvr, buf, BUFFY);
343                                  if (len &#x003C; 0){
344                                          perror("recording");
345                                          return -1;
346                                  }
347                                  if (len &#x003E; 0){
348                                          written = 0;
349                                          while (written &#x003C; len)
350                                                  written +=
351                                                          write (dvr_out,
352                                                                 buf, len);
353                                          length += len;
354                                          printf("written %2.0f MB\r",
355                                                 length/1024./1024.);
356                                  }
357                          }
358                  }
359          }
360          return 0;
363 </programlisting>
365 </section>