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