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