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
5with the driver distribution from <ulink url="http://linuxtv.org/hg/dvb-apps" />.
6</para>
7
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
11the demux devices. The example is given for QPSK tuners, but can easily be adjusted for
12QAM.
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;
23
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;
28
29 #define DMX "/dev/dvb/adapter0/demux1"
30 #define FRONT "/dev/dvb/adapter0/frontend1"
31 #define SEC "/dev/dvb/adapter0/sec1"
32
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;
37
38	 if ( (ans = ioctl(fd,FE_READ_STATUS,stat) &#x003C; 0)){
39		 perror("FE READ STATUS: ");
40		 return -1;
41	 }
42
43	 if (&#x22C6;stat &amp; FE_HAS_POWER)
44		 printf("FE HAS POWER\n");
45
46	 if (&#x22C6;stat &amp; FE_HAS_SIGNAL)
47		 printf("FE HAS SIGNAL\n");
48
49	 if (&#x22C6;stat &amp; FE_SPECTRUM_INV)
50		 printf("SPEKTRUM INV\n");
51
52	 return 0;
53 }
54
55
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;/
66
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;
78
79	 frequency = (uint32_t) freq;
80	 symbolrate = (uint32_t) srate;
81
82	 if((front = open(FRONT,O_RDWR)) &#x003C; 0){
83		 perror("FRONTEND DEVICE: ");
84		 return -1;
85	 }
86
87	 if((sec = open(SEC,O_RDWR)) &#x003C; 0){
88		 perror("SEC DEVICE: ");
89		 return -1;
90	 }
91
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	 }
99
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	 }
107
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	 }
115
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;
126
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);
134
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	 }
142
143	 if (ioctl(sec, SEC_SEND_SEQUENCE, &amp;scmds) &#x003C; 0){
144		 perror("SEC SEND: ");
145		 return -1;
146	 }
147
148	 frp.u.qpsk.SymbolRate = srate;
149	 frp.u.qpsk.FEC_inner = fec;
150
151	 if (ioctl(front, FE_SET_FRONTEND, &amp;frp) &#x003C; 0){
152		 perror("QPSK TUNE: ");
153		 return -1;
154	 }
155
156	 pfd[0].fd = front;
157	 pfd[0].events = POLLIN;
158
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)
163
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;
176
177			 case FE_COMPLETION_EV:
178				 printf("completion event\n");
179			 }
180		 }
181	 }
182
183
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	 }
193
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	 }
203
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	 }
213
214	 return has_signal(fds);
215 }
216
217</programlisting>
218<para>The program assumes that you are using a universal LNB and a standard DiSEqC
219switch with up to 4 addresses. Of course, you could build in some more checking if
220tuning was successful and maybe try to repeat the tuning process. Depending on the
221external hardware, i.e. LNB and DiSEqC switch, and weather conditions this may be
222necessary.
223</para>
224</section>
225
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;
239
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"
246
247 #define BUFFY (188&#x22C6;20)
248 #define MAX_LENGTH (1024&#x22C6;1024&#x22C6;5) /&#x22C6; record 5MB &#x22C6;/
249
250
251 /&#x22C6; switch the demuxes to recording, assuming the transponder is tuned &#x22C6;/
252
253 /&#x22C6; demux1, demux2: file descriptor of video and audio filters &#x22C6;/
254 /&#x22C6; vpid, apid:     PIDs of video and audio channels           &#x22C6;/
255
256 int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
257 {
258	 struct dmx_pes_filter_params pesFilterParams;
259
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	 }
267
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	 }
275
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;
295 }
296
297 /&#x22C6; start recording MAX_LENGTH , assuming the transponder is tuned &#x22C6;/
298
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)
302 {
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;
310
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	 }
316
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: ");
321
322	 printf("Recording %2.0f MB of test file in TS format\n",
323		MAX_LENGTH/(1024.0&#x22C6;1024.0));
324	 length = 0;
325
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	 }
334
335	 pfd[0].fd = dvr;
336	 pfd[0].events = POLLIN;
337
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;
361 }
362
363</programlisting>
364
365</section>
366