summary refs log tree commit diff
path: root/Documentation/media/uapi/dvb/examples.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/media/uapi/dvb/examples.rst')
-rw-r--r--Documentation/media/uapi/dvb/examples.rst380
1 files changed, 380 insertions, 0 deletions
diff --git a/Documentation/media/uapi/dvb/examples.rst b/Documentation/media/uapi/dvb/examples.rst
new file mode 100644
index 000000000000..64e029ecd047
--- /dev/null
+++ b/Documentation/media/uapi/dvb/examples.rst
@@ -0,0 +1,380 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _dvb_examples:
+
+********
+Examples
+********
+
+In this section we would like to present some examples for using the DVB
+API.
+
+NOTE: This section is out of date, and the code below won't even
+compile. Please refer to the
+`libdvbv5 <https://linuxtv.org/docs/libdvbv5/index.html>`__ for
+updated/recommended examples.
+
+
+.. _tuning:
+
+Tuning
+======
+
+We will start with a generic tuning subroutine that uses the frontend
+and SEC, as well as the demux devices. The example is given for QPSK
+tuners, but can easily be adjusted for QAM.
+
+
+.. code-block:: c
+
+     #include <sys/ioctl.h>
+     #include <stdio.h>
+     #include <stdint.h>
+     #include <sys/types.h>
+     #include <sys/stat.h>
+     #include <fcntl.h>
+     #include <time.h>
+     #include <unistd.h>
+
+     #include <linux/dvb/dmx.h>
+     #include <linux/dvb/frontend.h>
+     #include <linux/dvb/sec.h>
+     #include <sys/poll.h>
+
+     #define DMX "/dev/dvb/adapter0/demux1"
+     #define FRONT "/dev/dvb/adapter0/frontend1"
+     #define SEC "/dev/dvb/adapter0/sec1"
+
+     /* routine for checking if we have a signal and other status information*/
+     int FEReadStatus(int fd, fe_status_t *stat)
+     {
+	 int ans;
+
+	 if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
+	     perror("FE READ STATUS: ");
+	     return -1;
+	 }
+
+	 if (*stat & FE_HAS_POWER)
+	     printf("FE HAS POWER\\n");
+
+	 if (*stat & FE_HAS_SIGNAL)
+	     printf("FE HAS SIGNAL\\n");
+
+	 if (*stat & FE_SPECTRUM_INV)
+	     printf("SPEKTRUM INV\\n");
+
+	 return 0;
+     }
+
+
+     /* tune qpsk */
+     /* freq:             frequency of transponder                      */
+     /* vpid, apid, tpid: PIDs of video, audio and teletext TS packets  */
+     /* diseqc:           DiSEqC address of the used LNB                */
+     /* pol:              Polarisation                                  */
+     /* srate:            Symbol Rate                                   */
+     /* fec.              FEC                                           */
+     /* lnb_lof1:         local frequency of lower LNB band             */
+     /* lnb_lof2:         local frequency of upper LNB band             */
+     /* lnb_slof:         switch frequency of LNB                       */
+
+     int set_qpsk_channel(int freq, int vpid, int apid, int tpid,
+	     int diseqc, int pol, int srate, int fec, int lnb_lof1,
+	     int lnb_lof2, int lnb_slof)
+     {
+	 struct secCommand scmd;
+	 struct secCmdSequence scmds;
+	 struct dmx_pes_filter_params pesFilterParams;
+	 FrontendParameters frp;
+	 struct pollfd pfd[1];
+	 FrontendEvent event;
+	 int demux1, demux2, demux3, front;
+
+	 frequency = (uint32_t) freq;
+	 symbolrate = (uint32_t) srate;
+
+	 if((front = open(FRONT,O_RDWR)) < 0){
+	     perror("FRONTEND DEVICE: ");
+	     return -1;
+	 }
+
+	 if((sec = open(SEC,O_RDWR)) < 0){
+	     perror("SEC DEVICE: ");
+	     return -1;
+	 }
+
+	 if (demux1 < 0){
+	     if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
+		 < 0){
+		 perror("DEMUX DEVICE: ");
+		 return -1;
+	     }
+	 }
+
+	 if (demux2 < 0){
+	     if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
+		 < 0){
+		 perror("DEMUX DEVICE: ");
+		 return -1;
+	     }
+	 }
+
+	 if (demux3 < 0){
+	     if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
+		 < 0){
+		 perror("DEMUX DEVICE: ");
+		 return -1;
+	     }
+	 }
+
+	 if (freq < lnb_slof) {
+	     frp.Frequency = (freq - lnb_lof1);
+	     scmds.continuousTone = SEC_TONE_OFF;
+	 } else {
+	     frp.Frequency = (freq - lnb_lof2);
+	     scmds.continuousTone = SEC_TONE_ON;
+	 }
+	 frp.Inversion = INVERSION_AUTO;
+	 if (pol) scmds.voltage = SEC_VOLTAGE_18;
+	 else scmds.voltage = SEC_VOLTAGE_13;
+
+	 scmd.type=0;
+	 scmd.u.diseqc.addr=0x10;
+	 scmd.u.diseqc.cmd=0x38;
+	 scmd.u.diseqc.numParams=1;
+	 scmd.u.diseqc.params[0] = 0xF0 | ((diseqc * 4) & 0x0F) |
+	     (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
+	     (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
+
+	 scmds.miniCommand=SEC_MINI_NONE;
+	 scmds.numCommands=1;
+	 scmds.commands=&scmd;
+	 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
+	     perror("SEC SEND: ");
+	     return -1;
+	 }
+
+	 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
+	     perror("SEC SEND: ");
+	     return -1;
+	 }
+
+	 frp.u.qpsk.SymbolRate = srate;
+	 frp.u.qpsk.FEC_inner = fec;
+
+	 if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){
+	     perror("QPSK TUNE: ");
+	     return -1;
+	 }
+
+	 pfd[0].fd = front;
+	 pfd[0].events = POLLIN;
+
+	 if (poll(pfd,1,3000)){
+	     if (pfd[0].revents & POLLIN){
+		 printf("Getting QPSK event\\n");
+		 if ( ioctl(front, FE_GET_EVENT, &event)
+
+		      == -EOVERFLOW){
+		     perror("qpsk get event");
+		     return -1;
+		 }
+		 printf("Received ");
+		 switch(event.type){
+		 case FE_UNEXPECTED_EV:
+		     printf("unexpected event\\n");
+		     return -1;
+		 case FE_FAILURE_EV:
+		     printf("failure event\\n");
+		     return -1;
+
+		 case FE_COMPLETION_EV:
+		     printf("completion event\\n");
+		 }
+	     }
+	 }
+
+
+	 pesFilterParams.pid     = vpid;
+	 pesFilterParams.input   = DMX_IN_FRONTEND;
+	 pesFilterParams.output  = DMX_OUT_DECODER;
+	 pesFilterParams.pes_type = DMX_PES_VIDEO;
+	 pesFilterParams.flags   = DMX_IMMEDIATE_START;
+	 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
+	     perror("set_vpid");
+	     return -1;
+	 }
+
+	 pesFilterParams.pid     = apid;
+	 pesFilterParams.input   = DMX_IN_FRONTEND;
+	 pesFilterParams.output  = DMX_OUT_DECODER;
+	 pesFilterParams.pes_type = DMX_PES_AUDIO;
+	 pesFilterParams.flags   = DMX_IMMEDIATE_START;
+	 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
+	     perror("set_apid");
+	     return -1;
+	 }
+
+	 pesFilterParams.pid     = tpid;
+	 pesFilterParams.input   = DMX_IN_FRONTEND;
+	 pesFilterParams.output  = DMX_OUT_DECODER;
+	 pesFilterParams.pes_type = DMX_PES_TELETEXT;
+	 pesFilterParams.flags   = DMX_IMMEDIATE_START;
+	 if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
+	     perror("set_tpid");
+	     return -1;
+	 }
+
+	 return has_signal(fds);
+     }
+
+The program assumes that you are using a universal LNB and a standard
+DiSEqC switch with up to 4 addresses. Of course, you could build in some
+more checking if tuning was successful and maybe try to repeat the
+tuning process. Depending on the external hardware, i.e. LNB and DiSEqC
+switch, and weather conditions this may be necessary.
+
+
+.. _the_dvr_device:
+
+The DVR device
+==============
+
+The following program code shows how to use the DVR device for
+recording.
+
+
+.. code-block:: c
+
+     #include <sys/ioctl.h>
+     #include <stdio.h>
+     #include <stdint.h>
+     #include <sys/types.h>
+     #include <sys/stat.h>
+     #include <fcntl.h>
+     #include <time.h>
+     #include <unistd.h>
+
+     #include <linux/dvb/dmx.h>
+     #include <linux/dvb/video.h>
+     #include <sys/poll.h>
+     #define DVR "/dev/dvb/adapter0/dvr1"
+     #define AUDIO "/dev/dvb/adapter0/audio1"
+     #define VIDEO "/dev/dvb/adapter0/video1"
+
+     #define BUFFY (188*20)
+     #define MAX_LENGTH (1024*1024*5) /* record 5MB */
+
+
+     /* switch the demuxes to recording, assuming the transponder is tuned */
+
+     /* demux1, demux2: file descriptor of video and audio filters */
+     /* vpid, apid:     PIDs of video and audio channels           */
+
+     int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
+     {
+	 struct dmx_pes_filter_params pesFilterParams;
+
+	 if (demux1 < 0){
+	     if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
+		 < 0){
+		 perror("DEMUX DEVICE: ");
+		 return -1;
+	     }
+	 }
+
+	 if (demux2 < 0){
+	     if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
+		 < 0){
+		 perror("DEMUX DEVICE: ");
+		 return -1;
+	     }
+	 }
+
+	 pesFilterParams.pid = vpid;
+	 pesFilterParams.input = DMX_IN_FRONTEND;
+	 pesFilterParams.output = DMX_OUT_TS_TAP;
+	 pesFilterParams.pes_type = DMX_PES_VIDEO;
+	 pesFilterParams.flags = DMX_IMMEDIATE_START;
+	 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
+	     perror("DEMUX DEVICE");
+	     return -1;
+	 }
+	 pesFilterParams.pid = apid;
+	 pesFilterParams.input = DMX_IN_FRONTEND;
+	 pesFilterParams.output = DMX_OUT_TS_TAP;
+	 pesFilterParams.pes_type = DMX_PES_AUDIO;
+	 pesFilterParams.flags = DMX_IMMEDIATE_START;
+	 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
+	     perror("DEMUX DEVICE");
+	     return -1;
+	 }
+	 return 0;
+     }
+
+     /* start recording MAX_LENGTH , assuming the transponder is tuned */
+
+     /* demux1, demux2: file descriptor of video and audio filters */
+     /* vpid, apid:     PIDs of video and audio channels           */
+     int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid)
+     {
+	 int i;
+	 int len;
+	 int written;
+	 uint8_t buf[BUFFY];
+	 uint64_t length;
+	 struct pollfd pfd[1];
+	 int dvr, dvr_out;
+
+	 /* open dvr device */
+	 if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
+		 perror("DVR DEVICE");
+		 return -1;
+	 }
+
+	 /* switch video and audio demuxes to dvr */
+	 printf ("Switching dvr on\\n");
+	 i = switch_to_record(demux1, demux2, vpid, apid);
+	 printf("finished: ");
+
+	 printf("Recording %2.0f MB of test file in TS format\\n",
+	    MAX_LENGTH/(1024.0*1024.0));
+	 length = 0;
+
+	 /* open output file */
+	 if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT
+		      |O_TRUNC, S_IRUSR|S_IWUSR
+		      |S_IRGRP|S_IWGRP|S_IROTH|
+		      S_IWOTH)) < 0){
+	     perror("Can't open file for dvr test");
+	     return -1;
+	 }
+
+	 pfd[0].fd = dvr;
+	 pfd[0].events = POLLIN;
+
+	 /* poll for dvr data and write to file */
+	 while (length < MAX_LENGTH ) {
+	     if (poll(pfd,1,1)){
+		 if (pfd[0].revents & POLLIN){
+		     len = read(dvr, buf, BUFFY);
+		     if (len < 0){
+			 perror("recording");
+			 return -1;
+		     }
+		     if (len > 0){
+			 written = 0;
+			 while (written < len)
+			     written +=
+				 write (dvr_out,
+				    buf, len);
+			 length += len;
+			 printf("written %2.0f MB\\r",
+			    length/1024./1024.);
+		     }
+		 }
+	     }
+	 }
+	 return 0;
+     }