Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] Re: saa7146 and teletext (vbi)



Karsten Kreyenburg wrote:
> 
> The reason is, that I would like to run Nextview EPG:
> http://nxtvepg.sourceforge.net/intro.html
> 
> From the description:
> "...,if you have an internal SAT TV card, a Linux driver which supports the
> video4linux VBI API (i.e. if other VBI applications like alevt work too.)"
> 
> You might have discovered that RTL World (RTL, RTL2, VOX, Super RTL) doesn't
> provide much EPG data on their channel. In fact you only get the name of the
> actual running movie. With Nextview, you could access the teletext
> information on "Kabel 1", which seems to contain a complete electronic TV
> programme guide also covering RTL Worlds stations. Furthermore, Nextview can
> export the received information into the xmltv format.
> 
> That would be a very reliable (and legal!) way to obtain an electronic TV
> programme guide.

Attached is a three year old experimental patch I wrote for
nxtvepg-0.5.2 to see if the Nextview data is actually present
in DVB VBI data (it was). The patch was a very quick hack, and
was for the ancient OST API, but maybe one can still see how
it works in principal. IIRC I just copied the exisiting
analog vbi module and hacked on it, so the "Author:" line
isn't completely true; the description is also partially bogus...

See also dvb-apps/test/test_tt.c.

HTH,
Johannes
diff --recursive -u --new-file nxtvepg-0.5.2/Makefile nxtvepg-0.5.2-dvb/Makefile
--- nxtvepg-0.5.2/Makefile	Mon Jun  4 21:25:11 2001
+++ nxtvepg-0.5.2-dvb/Makefile	Mon Jul 30 17:13:12 2001
@@ -46,13 +46,14 @@
 INCS   += -I. -I/usr/X11R6/include
 # path to Tcl/Tk headers, if not properly installed
 #INCS   += -I/usr/local/tcl/tcl8.0/generic -I/usr/local/tcl/tk8.0/generic
+INCS    += -I/usr/include/tcl8.3
 
 # path to Tcl/Tk script library (Tk is usually in X11/lib/tk#.#)
 DEFS   += -DTK_LIBRARY_PATH=\"/usr/lib/tk8.3\"
 DEFS   += -DTCL_LIBRARY_PATH=\"/usr/lib/tcl8.3\"
 
 # path to the directory where the provider database files are kept
-DEFS   += -DEPG_DB_DIR=\"/usr/tmp/nxtvdb\"
+DEFS   += -DEPG_DB_DIR=\"/tmp/nxtvdb\"
 
 #WARN    = -Wall -Wpointer-arith -Wnested-externs \
 #          -Werror -Wstrict-prototypes -Wmissing-prototypes
@@ -62,7 +63,7 @@
 
 # ----- don't change anything below ------------------------------------------
 
-CSRC    = epgvbi/vbidecode epgvbi/tvchan epgvbi/btdrv4linux epgvbi/hamming \
+CSRC    = epgvbi/vbidecode epgvbi/tvchan epgvbi/btdrv4linuxdvb epgvbi/hamming \
           epgctl/debug epgctl/epgacqctl epgctl/epgscan epgctl/epgctxctl \
           epgctl/epgctxmerge \
           epgdb/epgdbacq epgdb/epgstream epgdb/epgdbmerge epgdb/epgdbsav \
diff --recursive -u --new-file nxtvepg-0.5.2/epgvbi/btdrv4linuxdvb.c nxtvepg-0.5.2-dvb/epgvbi/btdrv4linuxdvb.c
--- nxtvepg-0.5.2/epgvbi/btdrv4linuxdvb.c	Thu Jan  1 01:00:00 1970
+++ nxtvepg-0.5.2-dvb/epgvbi/btdrv4linuxdvb.c	Mon Jul 30 16:52:37 2001
@@ -0,0 +1,617 @@
+/*
+ *  DVB VBI driver interface for Linux
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License Version 2 as
+ *  published by the Free Software Foundation. You find a copy of this
+ *  license in the file COPYRIGHT in the root directory of this release.
+ *
+ *  THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
+ *  BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
+ *  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *
+ *  Description:
+ *
+ *    This module works as interface between acquisition control and
+ *    the DVB kernel driver. The actual data acquisition is done in
+ *    a slave process; the main reason is that it has to work under
+ *    real-time conditions, i.e. every 20 ms it *must* get the CPU
+ *    to read in one frame's worth of VBI lines.
+ *
+ *    Master and slave process communicate through shared memory.
+ *    It contains control parameters that allow to pass commands
+ *    like acquisition on/off, plus a ring buffer for teletext
+ *    packets. This buffer is managed in the epgdbacq module. When
+ *    you read the code in the module, always remember that some
+ *    of it is executed in the master process, some in the slave.
+ *
+ *
+ *  Author: Johannes Stezenbach
+ *
+ */
+
+#if !defined(linux)
+#error "This module is for Linux only"
+#endif
+
+#define DEBUG_SWITCH DEBUG_SWITCH_VBI
+#define DPRINTF_OFF
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h> // for htonl
+
+#include "epgctl/mytypes.h"
+#include "epgctl/debug.h"
+#include "epgdb/epgblock.h"
+#include "epgdb/epgdbacq.h"
+#include "epgvbi/vbidecode.h"
+#include "epgvbi/btdrv.h"
+#include "epgvbi/hamming.h"
+
+
+#include <linux/ost/dmx.h>
+#define VBI_MAXLINES 16
+#define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
+
+#define VBINAME      "/dev/ost/demux"
+#define PIDFILENAME   "/tmp/.vbi%u.pid"
+
+#define VBI_LINENUM VBI_MAXLINES
+#define VBI_BPL     2048
+#define VBI_BPF     (VBI_LINENUM*2*VBI_BPL)
+
+#define DEV_MAX_NAME_LEN 32
+
+EPGACQ_BUF *pVbiBuf;
+
+// vars used in both processes
+static bool isVbiProcess;
+static bool recvWakeUpSig;
+
+// vars used in the acq slave process
+static bool acqShouldExit;
+static bool freeDevice;
+static int vbiCardIndex;
+static int vbi_fdin;
+static int shmId;
+
+// vars used in the control process
+static int video_fd = -1;
+
+// ---------------------------------------------------------------------------
+// Close video device (in the master process/thread)
+//
+void BtDriver_CloseDevice( void )
+{
+}
+
+// ---------------------------------------------------------------------------
+// Change the video input source
+//
+bool BtDriver_SetInputSource( int inputIdx, bool keepOpen, bool * pIsTuner )
+{
+   return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+// Tune a given frequency
+//
+bool BtDriver_TuneChannel( ulong freq, bool keepOpen )
+{
+   // unsupported for DVB
+   return FALSE;
+}
+
+// ---------------------------------------------------------------------------
+// Query current tuner frequency
+// - returns 0 in case of error
+//
+ulong BtDriver_QueryChannel( void )
+{
+   // unsupported for DVB
+   return 0L;
+}
+
+// ---------------------------------------------------------------------------
+// Get signal strength on current tuner frequency
+//
+bool BtDriver_IsVideoPresent( void )
+{
+   return TRUE;
+}
+
+// ---------------------------------------------------------------------------
+// Return name for given TV card
+//
+const char * BtDriver_GetCardName( uint cardIndex )
+{
+   const char * pName = NULL;
+   #define MAX_CARD_NAME_LEN 32
+   static char name[MAX_CARD_NAME_LEN + 1];
+
+   if (cardIndex > 1)
+     return NULL;
+
+   snprintf(name, MAX_CARD_NAME_LEN, "DVB Card %d", cardIndex);
+   pName = (const char *) name;
+
+   return pName;
+}
+
+// ---------------------------------------------------------------------------
+// Return name for given input source index
+// - has to be called repeatedly with incremented indices until NULL is returned
+// - video device is kept open inbetween calls and only closed upon final call
+//
+const char * BtDriver_GetInputName( uint cardIndex, uint inputIdx )
+{
+   const char * pName = NULL;
+   #define MAX_INPUT_NAME_LEN 32
+   static char name[MAX_INPUT_NAME_LEN + 1];
+
+   if (inputIdx > 0)
+     return NULL;
+
+   snprintf(name, MAX_INPUT_NAME_LEN, "DVB Demux %d/%d", cardIndex, inputIdx);
+   name[MAX_INPUT_NAME_LEN] = 0;
+   pName = (const char *) name;
+
+   return pName;
+}
+
+// ---------------------------------------------------------------------------
+// Set parameters for acquisition
+// - the card index is simply passed to the slave process, which switches
+//   the device automatically if neccessary; if the device is busy, acquisition
+//   is stopped
+// - tuner type and PLL are already configured in the kernel
+//   hence these parameters can be ignored in Linux
+// - there isn't any need for priority adaptions, so that's not supported either
+//
+void BtDriver_Configure( int cardIndex, int tunerType, int pll, int prio )
+{
+   pVbiBuf->cardIndex = cardIndex;
+}
+
+// ---------------------------------------------------------------------------
+// The Acquisition process bows out on the usual signals
+//
+static void BtDriver_SignalHandler( int sigval )
+{
+   acqShouldExit = TRUE;
+   signal(sigval, BtDriver_SignalHandler);
+}
+
+// ---------------------------------------------------------------------------
+// Receive wake-up signal or ACK
+//
+static void BtDriver_SignalWakeUp( int sigval )
+{
+   // do nothing
+   recvWakeUpSig = TRUE;
+   signal(sigval, BtDriver_SignalWakeUp);
+}
+
+// ---------------------------------------------------------------------------
+// Receive signal to free or take vbi device
+//
+static void BtDriver_SignalHangup( int sigval )
+{
+   freeDevice = TRUE;
+   signal(sigval, BtDriver_SignalHangup);
+}
+
+// ---------------------------------------------------------------------------
+// Wake-up the acq child process to start acquisition
+// - the child signals back after it completed the operation
+// - the status of the operation is in the isEnabled flag
+//
+bool BtDriver_StartAcq( void )
+{
+   bool result = FALSE;
+   struct timeval tv;
+
+   if ((pVbiBuf != NULL) && (pVbiBuf->vbiPid != -1))
+   {
+      recvWakeUpSig = FALSE;
+      if (kill(pVbiBuf->vbiPid, SIGUSR1) != -1)
+      {
+         if ((recvWakeUpSig == FALSE) && (pVbiBuf->isEnabled == FALSE))
+         {
+            tv.tv_sec = 1;
+            tv.tv_usec = 0;
+            select(0, NULL, NULL, NULL, &tv);
+         }
+         result = pVbiBuf->isEnabled;
+      }
+   }
+
+   return result;
+}
+
+// ---------------------------------------------------------------------------
+// Stop acquisition
+// - not needed in UNIX, since acq main loop checks variable in shm
+//
+void BtDriver_StopAcq( void )
+{
+}
+
+// ---------------------------------------------------------------------------
+// Terminate the acquisition process
+//
+void BtDriver_Exit( void )
+{
+   struct shmid_ds stat;
+
+   if (pVbiBuf != NULL)
+   {
+      if ((isVbiProcess == FALSE) && (pVbiBuf->vbiPid != -1))
+      {  // this is the parent process -> kill the child process first
+         if (kill(pVbiBuf->vbiPid, SIGTERM) == 0)
+         {
+            waitpid(pVbiBuf->vbiPid, NULL, 0);
+         }
+      }
+
+      // mark the process as detached
+      if (isVbiProcess == FALSE)
+         pVbiBuf->epgPid = -1;
+      else
+         pVbiBuf->vbiPid = -1;
+
+      // detatch and free the shared memory
+      shmdt(pVbiBuf);
+      if (shmctl(shmId, IPC_STAT, &stat) == 0)
+      {
+         if (stat.shm_nattch == 0)
+         {  // the last one switches off the light
+            shmctl(shmId, IPC_RMID, NULL);
+         }
+      }
+
+      pVbiBuf = NULL;
+   }
+}
+
+// ---------------------------------------------------------------------------
+// Die if the parent is no longer alive
+// - called upon VBI ring buffer overlow
+//
+void BtDriver_CheckParent( void )
+{
+   if (pVbiBuf != NULL)
+   {
+      if ((isVbiProcess == TRUE) && (pVbiBuf->epgPid != -1))
+      {
+         if ((kill(pVbiBuf->epgPid, 0) == -1) && (errno == ESRCH))
+         {  // process no longer exists -> kill acquisition
+            debug1("parent is dead - terminate acq pid %d", pVbiBuf->vbiPid);
+            acqShouldExit = TRUE;
+         }
+      }
+   }
+}
+
+// ---------------------------------------------------------------------------
+// Determine the size of the VBI buffer
+// - the buffer size depends on the number of VBI lines that are captured
+//   for each frame; each read on the vbi device should request all the lines
+//   of one frame, else the rest will be overwritten by the next frame
+//
+static void BtDriver_OpenVbiBuf( void )
+{
+   struct dmxPesFilterParams pesFilterParams;
+
+   printf("DMX_SET_PES_FILTER\n");
+
+   pesFilterParams.pid = 0xe6; // teletext for 3sat on Astra 19.2E
+   pesFilterParams.input = DMX_IN_FRONTEND; 
+   pesFilterParams.output = DMX_OUT_TAP; 
+   pesFilterParams.pesType = DMX_PES_OTHER; 
+   pesFilterParams.flags = DMX_IMMEDIATE_START;
+ 
+   if (ioctl(vbi_fdin, DMX_SET_PES_FILTER, &pesFilterParams) == -1) 
+   {
+      perror("DMX_SET_PES_FLTER");
+   }
+}
+
+// ---------------------------------------------------------------------------
+// Decode teletext packet header
+// - all packets are forwarded to the ring buffer
+//
+static void VbiDecodePacket(const uchar * data)
+{
+   sint tmp1, tmp2, tmp3;
+   uchar mag, pkgno;
+   uint page;
+   uint sub;
+
+   if (UnHam84Byte(data, &tmp1))
+   {
+      mag = tmp1 & 7;
+      pkgno = (tmp1 >> 3) & 0x1f;
+
+      if (pkgno == 0)
+      {  // this is a page header - start of a new page
+         if (UnHam84Byte(data + 2, &tmp1) &&
+             UnHam84Byte(data + 4, &tmp2) &&
+             UnHam84Byte(data + 6, &tmp3))
+         {
+            page = tmp1 | (mag << 8);
+            sub = (tmp2 | (tmp3 << 8)) & 0x3f7f;
+            //printf("**** page=%03x.%04X\n", page, sub);
+
+            EpgDbAcqAddPacket(page, sub, 0, data + 2);
+         }
+         //else debug0("page number or subcode hamming error - skipping page");
+      }
+      else
+      {
+         EpgDbAcqAddPacket((uint) mag << 8, 0, pkgno, data + 2);
+         //printf("**** pkgno=%d\n", pkgno);
+      }
+   }
+   //else debug0("packet header decoding error - skipping");
+}
+
+// ---------------------------------------------------------------------------
+// Decode all VBI lines of the last seen frame
+//
+static unsigned char reverse[] = {
+0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
+};
+
+
+static void BtDriver_DecodeFrame( void )
+{
+   uchar *pData;
+   uint  line;
+   unsigned char buf[4096];
+   int len;
+   int i;
+
+   if (read (vbi_fdin, buf, 4) != 4)
+     {
+       perror ("read");
+       return;
+     }
+   if (htonl (*(uint32_t *)buf) != 0x00001bd)
+     {
+       //fprintf (stderr, "not 0x000001bd\n");
+       return;
+     }
+   if (read (vbi_fdin, buf + 4, 2) != 2)
+     {
+       perror ("read");
+       return;
+     }
+   len = (buf[4] << 8) | buf[5];
+   if (read (vbi_fdin, buf + 6, len) != len)
+     {
+       perror ("read");
+       return;
+     }
+   //fprintf(stderr,"read %d bytes PES\n", len+6);
+   if (buf[45] < 0x10 || buf[45] > 0x1f)
+     {
+       fprintf(stderr,"skipping non-EBU data, data id %#02x\n", buf[45]);
+       return;
+     }
+
+   for (pData = buf + 46; pData < buf + len + 6; pData += 46)
+     {
+       //fprintf(stderr,"unit id %#02x, length %d\n", pData[0], pData[1]);
+       line = pData[2] & 0x1f;
+       //fprintf(stderr,"line %d\n", line);
+       if (pData[3] != 0xe4)
+        {
+          //fprintf(stderr,"framing %#02x != 0xe4\n", pData[3]);
+          continue;
+        }
+
+       // correct bit reversal
+       for (i = 4; i <= 46; i++)
+        pData[i]=reverse[pData[i]];
+
+       VbiDecodePacket(pData + 4);
+       continue;
+     }
+}
+
+// ---------------------------------------------------------------------------
+// VBI decoder main loop
+//
+static void BtDriver_Main( void )
+{
+   char devName[DEV_MAX_NAME_LEN];
+   struct timeval tv;
+   FILE *fp;
+
+   while (acqShouldExit == FALSE)
+   {
+      if (freeDevice)
+      {  // hang-up signal received -> switch acq off
+         pVbiBuf->isEnabled = FALSE;
+         freeDevice = FALSE;
+      }
+
+      if (pVbiBuf->isEnabled)
+      {
+         if ((vbiCardIndex != pVbiBuf->cardIndex) && (vbi_fdin != -1))
+         {
+            sprintf(devName, PIDFILENAME, vbiCardIndex);
+            unlink(devName);
+
+            close(vbi_fdin);
+            vbi_fdin = -1;
+         }
+         if (vbi_fdin == -1)
+         {  // acq was switched on -> open device
+            vbiCardIndex = pVbiBuf->cardIndex;
+           sprintf(devName, VBINAME "%u", vbiCardIndex);
+           vbi_fdin = open(devName, O_RDWR);
+            if (vbi_fdin == -1)
+            {
+               printf("VBI open %s failed: errno=%d", devName, errno);
+               pVbiBuf->isEnabled = FALSE;
+            }
+            else
+            {  // open successful -> write pid in file
+               sprintf(devName, PIDFILENAME, vbiCardIndex);
+               fp = fopen(devName, "w");
+               if (fp != NULL)
+               {
+                  fprintf(fp, "%d", pVbiBuf->vbiPid);
+                  fclose(fp);
+               }
+               // allocate memory for the VBI data buffer
+               BtDriver_OpenVbiBuf();
+            }
+            // notify the parent that the operation is completed
+            kill(pVbiBuf->epgPid, SIGUSR1);
+         }
+         else
+         {  // device is open -> capture the VBI lines of this frame
+            BtDriver_DecodeFrame();
+         }
+      }
+      else
+      {
+         if (vbi_fdin != -1)
+         {  // acq was switched off -> close device
+            sprintf(devName, PIDFILENAME, vbiCardIndex);
+            unlink(devName);
+
+            close(vbi_fdin);
+            vbi_fdin = -1;
+         }
+         // sleep until signal; check parent every 30 secs
+         tv.tv_sec = 30;
+         tv.tv_usec = 0;
+         select(0, NULL, NULL, NULL, &tv);
+         BtDriver_CheckParent();
+      }
+   }
+
+   if (vbi_fdin != -1)
+   {
+      sprintf(devName, PIDFILENAME, vbiCardIndex);
+      unlink(devName);
+      close(vbi_fdin);
+      vbi_fdin = -1;
+   }
+}
+
+// ---------------------------------------------------------------------------
+// Create the VBI slave process - also slave main loop
+//
+bool BtDriver_Init( void )
+{
+   struct timeval tv;
+   int dbTaskPid;
+
+   pVbiBuf = NULL;
+   isVbiProcess = FALSE;
+   video_fd = -1;
+
+   shmId = shmget(IPC_PRIVATE, sizeof(EPGACQ_BUF), IPC_CREAT|IPC_EXCL|0600);
+   if (shmId == -1)
+   {  // failed to create a new segment with this key
+      perror("shmget");
+      return FALSE;
+   }
+   pVbiBuf = shmat(shmId, NULL, 0);
+   if (pVbiBuf == (EPGACQ_BUF *) -1)
+   {
+      perror("shmat");
+      return FALSE;
+   }
+
+   memset(pVbiBuf, 0, sizeof(EPGACQ_BUF));
+   pVbiBuf->epgPid = getpid();
+
+   recvWakeUpSig = FALSE;
+   signal(SIGHUP,  SIG_IGN);
+   signal(SIGUSR1, BtDriver_SignalWakeUp);
+
+   dbTaskPid = fork();
+   if (dbTaskPid == -1)
+   {
+      perror("fork");
+      return FALSE;
+   }
+   else if (dbTaskPid != 0)
+   {  // parent
+      // wait until child is ready
+      pVbiBuf->vbiPid = dbTaskPid;
+      if (recvWakeUpSig == FALSE)
+      {
+         tv.tv_sec = 1;
+         tv.tv_usec = 0;
+         select(0, NULL, NULL, NULL, &tv);
+      }
+      // slightly lower priority to relatively raise prio of the acq process
+      setpriority(PRIO_PROCESS, getpid(), getpriority(PRIO_PROCESS, getpid()) + 1);
+      // install handler for HUP signal - notification to free vbi device
+      return recvWakeUpSig;
+   }
+   else
+   {
+      isVbiProcess = TRUE;
+      pVbiBuf->vbiPid = getpid();
+      signal(SIGINT,  BtDriver_SignalHandler);
+      signal(SIGTERM, BtDriver_SignalHandler);
+      signal(SIGQUIT, BtDriver_SignalHandler);
+      signal(SIGHUP,  BtDriver_SignalHangup);
+
+      vbi_fdin = -1;
+
+      acqShouldExit = FALSE;
+      freeDevice = FALSE;
+      // notify parent that child is ready
+      kill(pVbiBuf->epgPid, SIGUSR1);
+
+      // enter main loop
+      BtDriver_Main();
+
+      BtDriver_Exit();
+      exit(0);
+   }
+}
+

Home | Main Index | Thread Index