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