Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 <sys/ioctl.h>
18 #include <stdio.h>
19 #include <stdint.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <time.h>
24 #include <unistd.h>
25
26 #include <linux/dvb/dmx.h>
27 #include <linux/dvb/frontend.h>
28 #include <linux/dvb/sec.h>
29 #include <sys/poll.h>
30
31 #define DMX "/dev/dvb/adapter0/demux1"
32 #define FRONT "/dev/dvb/adapter0/frontend1"
33 #define SEC "/dev/dvb/adapter0/sec1"
34
35 /⋆ routine for checking if we have a signal and other status information⋆/
36 int FEReadStatus(int fd, fe_status_t ⋆stat)
37 {
38 int ans;
39
40 if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
41 perror("FE READ STATUS: ");
42 return -1;
43 }
44
45 if (⋆stat & FE_HAS_POWER)
46 printf("FE HAS POWER\n");
47
48 if (⋆stat & FE_HAS_SIGNAL)
49 printf("FE HAS SIGNAL\n");
50
51 if (⋆stat & FE_SPECTRUM_INV)
52 printf("SPEKTRUM INV\n");
53
54 return 0;
55 }
56
57
58 /⋆ tune qpsk ⋆/
59 /⋆ freq: frequency of transponder ⋆/
60 /⋆ vpid, apid, tpid: PIDs of video, audio and teletext TS packets ⋆/
61 /⋆ diseqc: DiSEqC address of the used LNB ⋆/
62 /⋆ pol: Polarisation ⋆/
63 /⋆ srate: Symbol Rate ⋆/
64 /⋆ fec. FEC ⋆/
65 /⋆ lnb_lof1: local frequency of lower LNB band ⋆/
66 /⋆ lnb_lof2: local frequency of upper LNB band ⋆/
67 /⋆ lnb_slof: switch frequency of LNB ⋆/
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)) < 0){
85 perror("FRONTEND DEVICE: ");
86 return -1;
87 }
88
89 if((sec = open(SEC,O_RDWR)) < 0){
90 perror("SEC DEVICE: ");
91 return -1;
92 }
93
94 if (demux1 < 0){
95 if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
96 < 0){
97 perror("DEMUX DEVICE: ");
98 return -1;
99 }
100 }
101
102 if (demux2 < 0){
103 if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
104 < 0){
105 perror("DEMUX DEVICE: ");
106 return -1;
107 }
108 }
109
110 if (demux3 < 0){
111 if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
112 < 0){
113 perror("DEMUX DEVICE: ");
114 return -1;
115 }
116 }
117
118 if (freq < 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 ⋆ 4) & 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=&scmd;
140 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
141 perror("SEC SEND: ");
142 return -1;
143 }
144
145 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 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, &frp) < 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 & POLLIN){
163 printf("Getting QPSK event\n");
164 if ( ioctl(front, FE_GET_EVENT, &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, &pesFilterParams) < 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, &pesFilterParams) < 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, &pesFilterParams) < 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 <sys/ioctl.h>
234 #include <stdio.h>
235 #include <stdint.h>
236 #include <sys/types.h>
237 #include <sys/stat.h>
238 #include <fcntl.h>
239 #include <time.h>
240 #include <unistd.h>
241
242 #include <linux/dvb/dmx.h>
243 #include <linux/dvb/video.h>
244 #include <sys/poll.h>
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⋆20)
250 #define MAX_LENGTH (1024⋆1024⋆5) /⋆ record 5MB ⋆/
251
252
253 /⋆ switch the demuxes to recording, assuming the transponder is tuned ⋆/
254
255 /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/
256 /⋆ vpid, apid: PIDs of video and audio channels ⋆/
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 < 0){
263 if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
264 < 0){
265 perror("DEMUX DEVICE: ");
266 return -1;
267 }
268 }
269
270 if (demux2 < 0){
271 if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
272 < 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, &pesFilterParams) < 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, &pesFilterParams) < 0){
293 perror("DEMUX DEVICE");
294 return -1;
295 }
296 return 0;
297 }
298
299 /⋆ start recording MAX_LENGTH , assuming the transponder is tuned ⋆/
300
301 /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/
302 /⋆ vpid, apid: PIDs of video and audio channels ⋆/
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 /⋆ open dvr device ⋆/
314 if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
315 perror("DVR DEVICE");
316 return -1;
317 }
318
319 /⋆ switch video and audio demuxes to dvr ⋆/
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⋆1024.0));
326 length = 0;
327
328 /⋆ open output file ⋆/
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)) < 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 /⋆ poll for dvr data and write to file ⋆/
341 while (length < MAX_LENGTH ) {
342 if (poll(pfd,1,1)){
343 if (pfd[0].revents & POLLIN){
344 len = read(dvr, buf, BUFFY);
345 if (len < 0){
346 perror("recording");
347 return -1;
348 }
349 if (len > 0){
350 written = 0;
351 while (written < 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>