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