Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/Documentation/DocBook/dvb/examples.xml
10821 views
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>
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
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;
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
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>
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
367