blob: f037e568eb6e7d2ef50a30b8b0aa62fc05c86dfd [file] [log] [blame]
Mauro Carvalho Chehab8e080c22009-09-13 22:16:04 -03001<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
Mauro Carvalho Chehab62b122a2009-09-15 21:03:45 -03005with the driver distribution from <ulink url="http://linuxtv.org/hg/dvb-apps" />.
Mauro Carvalho Chehab8e080c22009-09-13 22:16:04 -03006</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>