Selaa lähdekoodia

sonyEw1000: Tune tool & pes recorder tool:

In one terminal start the tune tool:

$ cd /home/pi/Desktop/sonyEw100/tuneTool
$ ./tune -c channels.conf -r 'BTV'

In another terminal start the pes tool:

$ cd /home/pi/Desktop/sonyEw100/pesTool
$ ./test_pes 0x13f9 audioPes

The transport stream can be dumped directly
from the dvr device:

cat /dev/dvb/adapter0/dvr0 > /tmp/recording.ts

Signed-off-by: Iliya Iliev <iliyailiev3592@gmail.com>
Iliya Iliev 5 vuotta sitten
vanhempi
commit
2d3da3117c

+ 74 - 0
sonyEw100/Make.rules

@@ -0,0 +1,74 @@
+CC = arm-linux-gnueabi-gcc
+CFLAGS ?= -g -Wall -W -Wshadow -Wpointer-arith -Wstrict-prototypes
+
+ifneq ($(lib_name),)
+
+# additional rules for libraries
+
+CFLAGS_LIB ?= -fPIC
+CFLAGS += $(CFLAGS_LIB)
+
+libraries = $(lib_name).so $(lib_name).a
+
+.PHONY: library
+
+library: $(libraries)
+
+$(libraries): $(objects)
+
+endif
+
+prerequisites = $(subst .o,.d,$(objects)) $(addsuffix .d,$(binaries))
+
+.PHONY: clean install
+
+ifeq ($(static),1)
+LDFLAGS += -static
+endif
+
+prefix ?= /usr
+
+bindir     ?= $(prefix)/bin
+includedir ?= $(prefix)/include
+libdir     ?= $(prefix)/lib
+sharedir   ?= $(prefix)/share
+
+ifneq ($(DESTDIR),)
+DESTDIR := $(DESTDIR)/
+endif
+
+ifeq ($(V),1)
+%.o: %.c
+	$(CC) -c $(CPPFLAGS) $(CFLAGS) -MMD -o $@ $< $(filter-out %.h %.c,$^)
+%: %.o
+	$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
+%: %.c
+	$(CC) $(CPPFLAGS) $(CFLAGS) -MMD $(LDFLAGS) -o $@ $< $(filter-out %.h %.c,$^) $(LOADLIBES) $(LDLIBS)
+%.so:
+	$(CC) -shared -o $@ $^
+%.a:
+	$(AR) rcs $@ $^
+clean::
+	$(RM) -f $(prerequisites) $(objects) $(libraries) $(binaries) $(removing) *~
+else
+%.o: %.c
+	@echo CC $@
+	@$(CC) -c $(CPPFLAGS) $(CFLAGS) -MMD -o $@ $< $(filter-out %.h %.c,$^)
+%: %.o
+	@echo CC $@
+	@$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
+%: %.c
+	@echo CC $@
+	@$(CC) $(CPPFLAGS) $(CFLAGS) -MMD $(LDFLAGS) -o $@ $< $(filter-out %.h %.c,$^) $(LOADLIBES) $(LDLIBS)
+%.so:
+	@echo CC $@
+	@$(CC) -shared -o $@ $^
+%.a:
+	@echo AR $@
+	@$(AR) rcs $@ $^
+clean::
+	@echo cleaning
+	@$(RM) -f $(prerequisites) $(objects) $(libraries) $(binaries) $(removing) *~
+endif
+
+-include $(prerequisites)

+ 11 - 0
sonyEw100/Makefile

@@ -0,0 +1,11 @@
+# get DVB API version
+VERSION_FILE := "dvbVersion"
+
+DVB_API_MAJOR := $(word 3, $(shell grep -m1 "DVB_API_VERSION" $(VERSION_FILE)) )
+DVB_API_MINOR := $(word 3, $(shell grep -m1 "DVB_API_VERSION_MINOR" $(VERSION_FILE)) )
+
+.PHONY: all clean
+
+all clean install:
+	$(MAKE) -C pesTool $@
+	$(MAKE) -C tuneTool $@

+ 95 - 0
sonyEw100/README

@@ -0,0 +1,95 @@
+################# SETUP ######################
+1. ./setup
+2. ./getVersion ip_address_of_Pi_target_device
+3. make
+4. ./deploy ip_address_of_Pi_target_device
+
+
+################# TUNE TOOL ######################
+
+Use SSH in order to use the applications:
+ssh pi@ip_address_of_Pi_target_device
+
+The default passowrd is:
+raspberry
+
+
+The status messages have the following meaning:
+
+status 0x1f              --- The demodulator status bits.
+			      0x1f means all bits set, everything ok.
+
+signal [0x0000...0xffff] --- Signal Strength. Values above 0x8000 should be ok.
+snr [0x0000...0xffff]    --- Signal/Noise Ratio. Values above 0x8000 are ok.
+ber [0...0xffffffff]     --- Bit Error Rate. The less the better.
+unc [0...0xffffffff]     --- Number of Uncorrectable Blocks.
+            			     Small numbers are Preferable.
+
+If everything is alright and all frontend circuits are working stable
+(are locked) you should see a FE_HAS_LOCK in the rightmost line.
+
+################ Example usage ######################
+ON THE PI Device
+
+
+$ cd /home/pi/Desktop/sonyEw100/tuneTool
+$ ./tune -c channels.conf -r 'BTV'
+[keep it running in one console]
+
+The output of the program should look like this:
+
+using '/dev/dvb/adapter0/frontend0' and '/dev/dvb/adapter0/demux0'
+reading channels from file 'channels.conf'
+Version: 5.11    FE_CAN { DVB-T + DVB-T2 }
+tuning to 626000000 Hz
+video pid 0x13f8, audio pid 0x13f9
+status 00 | signal 9eb7 | snr 07dc | ber 00000000 | unc 76f434f8 |
+status 1f | signal 9f24 | snr 7a65 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9e4a | snr 7a33 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9d02 | snr 77dc | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9d02 | snr 7980 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9d70 | snr 7972 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9e4a | snr 7d07 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9f24 | snr 74f2 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9ddd | snr 78a6 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9d02 | snr 791d | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9ddd | snr 6fe3 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+status 1f | signal 9c95 | snr 79b2 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+
+2. In another terminal window start the ./test_pes tool which
+takes the output of an audio/video encoder(MPEG2) stream. The content
+of the outfile is in PES(Packetized Elementary Stream) packets.
+
+*Notice that the audio pid must match the one of our channel.
+It is also displayed on line 19.
+
+$ cd /home/pi/Desktop/sonyEw100/pesTool
+$ ./test_pes 0x13f9 audioPes
+test_pes: using '/dev/dvb/adapter0/demux0'
+          PID 0x13f9
+          output to 'audioPes'
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+got 4096 bytes
+Press Ctrl+C to stop and record the file.
+
+3. Alternatively dump the MPEG transport stream to a file using another terminal window
+$ cat /dev/dvb/adapter0/dvr0 > /tmp/recording.ts
+

BIN
sonyEw100/build/sonyEw100/pesTool/test_pes


+ 2 - 0
sonyEw100/build/sonyEw100/tuneTool/channels.conf

@@ -0,0 +1,2 @@
+BTV:626000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_3_4:QAM_AUTO:TRANSMISSION_MODE_2K:GUARD_INTERVAL_1_32:HIERARCHY_NONE:5112:5113:5300
+BBC ONE:641833330:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_3_4:QAM_16:TRANSMISSION_MODE_2K:GUARD_INTERVAL_1_32:HIERARCHY_NONE:600:601:4173

BIN
sonyEw100/build/sonyEw100/tuneTool/tune


+ 37 - 0
sonyEw100/deploy

@@ -0,0 +1,37 @@
+#!/bin/bash
+
+if [ "$#" -ne 1 ]; then
+    echo "./deploy  <ip_address_of_Pi_target_device>"
+    exit
+fi
+
+getBins() {
+    utilBinList="$(find $1  -executable -type f)"
+    for bin in $utilBinList; do cp $bin $2; done
+}  &>/dev/null
+
+setup() {
+    rm -rf $1
+    mkdir $1
+
+
+    mkdir ./$1/sonyEw100
+    mkdir ./$1/sonyEw100/pesTool
+    mkdir ./$1/sonyEw100/tuneTool
+}  &>/dev/null
+
+upload() {
+    scp -r $1/* pi@$2:/home/pi/Desktop
+}
+
+setup build
+
+getBins ./pesTool ./build/sonyEw100/pesTool
+getBins ./tuneTool ./build/sonyEw100/tuneTool
+
+cp ./tuneTool/channels.conf ./build/sonyEw100/tuneTool
+
+echo "Deploying sonyEw100 to the target device. [$1]"
+upload build $1
+
+

+ 30 - 0
sonyEw100/dvbVersion

@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
+/*
+ * version.h
+ *
+ * Copyright (C) 2000 Holger Waechtler <holger@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef _DVBVERSION_H_
+#define _DVBVERSION_H_
+
+#define DVB_API_VERSION 5
+#define DVB_API_VERSION_MINOR 11
+
+#endif /*_DVBVERSION_H_*/

+ 3 - 0
sonyEw100/getVersion

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+scp pi@$1:/usr/include/linux/dvb/version.h dvbVersion

+ 19 - 0
sonyEw100/pesTool/Makefile

@@ -0,0 +1,19 @@
+VERSION_FILE := "../dvbVersion"
+
+DVB_API_MAJOR := $(word 3, $(shell grep -m1 "DVB_API_VERSION" $(VERSION_FILE)) )
+DVB_API_MINOR := $(word 3, $(shell grep -m1 "DVB_API_VERSION_MINOR" $(VERSION_FILE)) )
+
+objects  = hex_dump.o
+binaries = test_pes
+
+inst_bin = $(binaries)
+
+.PHONY: all
+
+all: $(binaries)
+$(info DVB API is $(DVB_API_MAJOR).$(DVB_API_MINOR))
+
+$(binaries): $(objects)
+
+include ../Make.rules
+

+ 62 - 0
sonyEw100/pesTool/hex_dump.c

@@ -0,0 +1,62 @@
+/* hex_dump.h -- simple hex dump routine
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "hex_dump.h"
+
+
+void hex_dump(uint8_t data[], int bytes)
+{
+	int i, j;
+	uint8_t c;
+
+	for (i = 0; i < bytes; i++) {
+		if (!(i % 8) && i)
+			printf(" ");
+		if (!(i % 16) && i) {
+			printf("  ");
+			for (j = 0; j < 16; j++) {
+				c = data[i+j-16];
+				if ((c < 0x20) || (c >= 0x7f))
+					c = '.';
+				printf("%c", c);
+			}
+			printf("\n");
+		}
+		printf("%.2x ", data[i]);
+	}
+	j = (bytes % 16);
+	j = (j != 0 ? j : 16);
+	for (i = j; i < 16; i++) {
+		if (!(i % 8) && i)
+			printf(" ");
+		printf("   ");
+	}
+	printf("   ");
+	for (i = bytes - j; i < bytes; i++) {
+		c = data[i];
+		if ((c < 0x20) || (c >= 0x7f))
+			c = '.';
+		printf("%c", c);
+	}
+	printf("\n");
+}

+ 28 - 0
sonyEw100/pesTool/hex_dump.h

@@ -0,0 +1,28 @@
+#ifndef _HEXDUMP_H_
+#define _HEXDUMP_H_
+/* hex_dump.h -- simple hex dump routine
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <stdint.h>
+
+extern void hex_dump(uint8_t data[], int bytes);
+
+
+#endif /* _HEXDUMP_H_ */

+ 137 - 0
sonyEw100/pesTool/test_pes.c

@@ -0,0 +1,137 @@
+/* test_pes.c - Test for PES filters.
+ * usage: DEMUX=/dev/dvb/adapterX/demuxX test_pes PID
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/dvb/dmx.h>
+
+#include "hex_dump.h"
+
+#define MAX_PES_SIZE (4*1024)
+
+
+void usage(void)
+{
+	fprintf(stderr, "usage: test_pes PID [filename]\n");
+	fprintf(stderr, "       Print a hexdump of PES packets from PID to stdout.\n");
+	fprintf(stderr, "  filename : Write binary PES data to file (no hexdump).\n");
+	fprintf(stderr, "       The default demux device used can be changed\n");
+	fprintf(stderr, "       using the DEMUX environment variable\n");
+	exit(1);
+}
+
+void process_pes(int fd, FILE *out)
+{
+	uint8_t buf[MAX_PES_SIZE];
+	int bytes;
+
+	bytes = read(fd, buf, sizeof(buf));
+	if (bytes < 0) {
+		if (errno == EOVERFLOW) {
+			fprintf(stderr, "read error: buffer overflow (%d)\n",
+					EOVERFLOW);
+			return;
+		}
+		else {
+			perror("read");
+			exit(1);
+		}
+	}
+	if (out == stdout) {
+		hex_dump(buf, bytes);
+		printf("\n");
+	}
+	else {
+		printf("got %d bytes\n", bytes);
+		if (fwrite(buf, 1, bytes, out) == 0)
+			perror("write output");
+	}
+}
+
+int set_filter(int fd, unsigned int pid)
+{
+	struct dmx_pes_filter_params f;
+
+	f.pid = (uint16_t) pid;
+	f.input = DMX_IN_FRONTEND;
+	f.output = DMX_OUT_TAP;
+	f.pes_type = DMX_PES_OTHER;
+	f.flags = DMX_IMMEDIATE_START;
+	if (ioctl(fd, DMX_SET_PES_FILTER, &f) == -1) {
+		perror("ioctl DMX_SET_PES_FILTER");
+		return 1;
+	}
+	return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+	int dmxfd;
+	unsigned long pid;
+	char *dmxdev = "/dev/dvb/adapter0/demux0";
+	FILE *out = stdout;
+
+	if (argc != 2 && argc != 3)
+		usage();
+
+	pid = strtoul(argv[1], NULL, 0);
+	if (pid > 0x1fff)
+		usage();
+	if (getenv("DEMUX"))
+		dmxdev = getenv("DEMUX");
+
+	fprintf(stderr, "test_pes: using '%s'\n", dmxdev);
+	fprintf(stderr, "          PID 0x%04lx\n", pid);
+
+	if (argc == 3) {
+		out = fopen(argv[2], "wb");
+		if (!out) {
+			perror("open output file");
+			exit(1);
+		}
+		fprintf(stderr, "          output to '%s'\n", argv[2]);
+	}
+
+	if ((dmxfd = open(dmxdev, O_RDWR)) < 0){
+		perror("open");
+		return 1;
+	}
+
+	if (set_filter(dmxfd, pid) != 0)
+		return 1;
+
+	for (;;) {
+		process_pes(dmxfd, out);
+	}
+
+	close(dmxfd);
+	return 0;
+}

+ 49 - 0
sonyEw100/setup

@@ -0,0 +1,49 @@
+#!/bin/bash
+
+ask_forUpdate() {
+    printf "\n Do you want to update the system? [y/n]\n"
+    while : ; do
+    read -n 1 k <&1
+    if [[ $k = n ]] ; then
+    printf "\n Skipping system update...\n"
+    break
+    elif [[ $k = y ]] ; then
+    printf "\ Updating system packages...\n"
+    sudo apt-get update
+    break
+    else
+    printf "\n Skipping dependencies update...\n"
+    break
+    fi
+    done
+}
+
+install_ubuntuPackage() {
+    dpkg -s $1 &> /dev/null
+
+    if [ $? -eq 0 ]; then
+        echo "[+] $1 found"
+    else
+        echo "[+] $1 not found"
+        echo "Installing $1 ..."
+        sudo apt-get -y install $1
+    fi
+}
+
+checkPackages() {
+    ask_forUpdate
+
+    printf "\n Checking for required Ubuntu packages...\n\n"
+    install_ubuntuPackage libc6-armel-cross
+    install_ubuntuPackage libc6-dev-armel-cross
+    install_ubuntuPackage binutils-arm-linux-gnueabi
+
+    install_ubuntuPackage gcc-arm-linux-gnueabihf
+    install_ubuntuPackage g++-arm-linux-gnueabihf
+
+    echo ""
+    echo " All the required packages are installed.
+         "
+}
+
+checkPackages

+ 22 - 0
sonyEw100/tuneTool/Makefile

@@ -0,0 +1,22 @@
+# Makefile for linuxtv.org dvb-apps/util/szap
+
+# get DVB API version
+VERSION_FILE := "../dvbVersion"
+
+DVB_API_MAJOR := $(word 3, $(shell grep -m1 "DVB_API_VERSION" $(VERSION_FILE)) )
+DVB_API_MINOR := $(word 3, $(shell grep -m1 "DVB_API_VERSION_MINOR" $(VERSION_FILE)) )
+
+objects  = util.o
+
+binaries = tune
+
+inst_bin = $(binaries)
+
+.PHONY: all
+
+all: $(binaries)
+$(info DVB API is $(DVB_API_MAJOR).$(DVB_API_MINOR))
+
+$(binaries): $(objects)
+
+include ../Make.rules

+ 2 - 0
sonyEw100/tuneTool/channels.conf

@@ -0,0 +1,2 @@
+BTV:626000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_3_4:QAM_AUTO:TRANSMISSION_MODE_2K:GUARD_INTERVAL_1_32:HIERARCHY_NONE:5112:5113:5300
+BBC ONE:641833330:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_3_4:QAM_16:TRANSMISSION_MODE_2K:GUARD_INTERVAL_1_32:HIERARCHY_NONE:600:601:4173

+ 677 - 0
sonyEw100/tuneTool/tune.c

@@ -0,0 +1,677 @@
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+#define _LARGEFILE64_SOURCE 1
+
+/******************************** INCLUDE FILES *******************************/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+
+#include "util.h"
+
+/******************************* LOCAL TYPEDEFS ******************************/
+
+
+/********************************* LOCAL DATA *********************************/
+static char FRONTEND_DEV [80];
+static char DEMUX_DEV [80];
+static char DVR_DEV [80];
+static int timeout_flag=0;
+static int silent=0,timeout=0;
+static int exit_after_tuning;
+
+/******************************** LOCAL DEFINES *******************************/
+#define CHANNEL_FILE "channels.conf"
+
+#define ERROR(x...)                    	\
+	do {                                \
+		fprintf(stderr, "ERROR: ");     \
+		fprintf(stderr, x);             \
+		fprintf (stderr, "\n");         \
+	} while (0)
+
+#define PERROR(x...)                    				\
+	do {                                                \
+		fprintf(stderr, "ERROR: ");                     \
+		fprintf(stderr, x);                             \
+		fprintf (stderr, " (%s)\n", strerror(errno));	\
+	} while (0)
+
+
+typedef struct {
+	char *name;
+	int value;
+} Param;
+
+static const Param inversion_list [] = {
+	{ "INVERSION_OFF", INVERSION_OFF },
+	{ "INVERSION_ON", INVERSION_ON },
+	{ "INVERSION_AUTO", INVERSION_AUTO }
+};
+
+static const Param bw_list [] = {
+	{ "BANDWIDTH_6_MHZ", BANDWIDTH_6_MHZ },
+	{ "BANDWIDTH_7_MHZ", BANDWIDTH_7_MHZ },
+	{ "BANDWIDTH_8_MHZ", BANDWIDTH_8_MHZ }
+};
+
+static const Param fec_list [] = {
+	{ "FEC_1_2", FEC_1_2 },
+	{ "FEC_2_3", FEC_2_3 },
+	{ "FEC_3_4", FEC_3_4 },
+	{ "FEC_4_5", FEC_4_5 },
+	{ "FEC_5_6", FEC_5_6 },
+	{ "FEC_6_7", FEC_6_7 },
+	{ "FEC_7_8", FEC_7_8 },
+	{ "FEC_8_9", FEC_8_9 },
+	{ "FEC_AUTO", FEC_AUTO },
+	{ "FEC_NONE", FEC_NONE }
+};
+
+static const Param guard_list [] = {
+	{"GUARD_INTERVAL_1_16", GUARD_INTERVAL_1_16},
+	{"GUARD_INTERVAL_1_32", GUARD_INTERVAL_1_32},
+	{"GUARD_INTERVAL_1_4", GUARD_INTERVAL_1_4},
+	{"GUARD_INTERVAL_1_8", GUARD_INTERVAL_1_8},
+	{"GUARD_INTERVAL_AUTO", GUARD_INTERVAL_AUTO}
+};
+
+static const Param hierarchy_list [] = {
+	{ "HIERARCHY_1", HIERARCHY_1 },
+	{ "HIERARCHY_2", HIERARCHY_2 },
+	{ "HIERARCHY_4", HIERARCHY_4 },
+	{ "HIERARCHY_NONE", HIERARCHY_NONE },
+	{ "HIERARCHY_AUTO", HIERARCHY_AUTO }
+};
+
+static const Param constellation_list [] = {
+	{ "QPSK", QPSK },
+	{ "QAM_128", QAM_128 },
+	{ "QAM_16", QAM_16 },
+	{ "QAM_256", QAM_256 },
+	{ "QAM_32", QAM_32 },
+	{ "QAM_64", QAM_64 },
+	{ "QAM_AUTO", QAM_AUTO }
+};
+
+static const Param transmissionmode_list [] = {
+	{ "TRANSMISSION_MODE_2K", TRANSMISSION_MODE_2K },
+	{ "TRANSMISSION_MODE_8K", TRANSMISSION_MODE_8K },
+	{ "TRANSMISSION_MODE_AUTO", TRANSMISSION_MODE_AUTO }
+};
+
+#define LIST_SIZE(x) sizeof(x)/sizeof(Param)
+
+static int parse_param (int fd, const Param * plist, int list_size, int *param)
+{
+	char c;
+	int character = 0;
+	int _index = 0;
+
+	while (1) {
+		if (read(fd, &c, 1) < 1)
+			return -1;	/*  EOF? */
+
+		if ((c == ':' || c == '\n')
+		    && plist->name[character] == '\0')
+			break;
+
+		while (toupper(c) != plist->name[character]) {
+			_index++;
+			plist++;
+			if (_index >= list_size)	 /*  parse error, no valid */
+				return -2;	 /*  parameter name found  */
+		}
+
+		character++;
+	}
+
+	*param = plist->value;
+
+	return 0;
+}
+
+
+static int parse_int(int fd, int *val)
+{
+	char number[11];	/* 2^32 needs 10 digits... */
+	int character = 0;
+
+	while (1) {
+		if (read(fd, &number[character], 1) < 1)
+			return -1;	/*  EOF? */
+
+		if (number[character] == ':' || number[character] == '\n') {
+			number[character] = '\0';
+			break;
+		}
+
+		if (!isdigit(number[character]))
+			return -2;	/*  parse error, not a digit... */
+
+		character++;
+
+		if (character > 10)	/*  overflow, number too big */
+			return -3;	/*  to fit in 32 bit */
+	};
+
+	errno = 0;
+	*val = strtol(number, NULL, 10);
+	if (errno == ERANGE)
+		return -4;
+
+	return 0;
+}
+
+
+static int find_channel(int fd, const char *channel)
+{
+	int character = 0;
+
+	while (1) {
+		char c;
+
+		if (read(fd, &c, 1) < 1)
+			return -1;	/*  EOF! */
+
+		if ( '\n' == c ) /* start of line */
+			character = 0;
+		else if ( character >= 0 ) { /* we are in the namefield */
+
+			if (c == ':' && channel[character] == '\0')
+				break;
+
+			if (toupper(c) == toupper(channel[character]))
+				character++;
+			else
+				character = -1;
+		}
+	};
+
+	return 0;
+}
+
+
+static
+int try_parse_int(int fd, int *val, const char *pname)
+{
+	int err;
+
+	err = parse_int(fd, val);
+
+	if (err)
+		ERROR("error while parsing %s (%s)", pname,
+		      err == -1 ? "end of file" :
+		      err == -2 ? "not a number" : "number too big");
+
+	return err;
+}
+
+
+static
+int try_parse_param(int fd, const Param * plist, int list_size, int *param,
+		    const char *pname)
+{
+	int err;
+
+	err = parse_param(fd, plist, list_size, param);
+
+	if (err)
+		ERROR("error while parsing %s (%s)", pname,
+		      err == -1 ? "end of file" : "syntax error");
+
+	return err;
+}
+
+static int check_fec(fe_code_rate_t *fec)
+{
+	switch (*fec)
+	{
+	case FEC_NONE:
+		*fec = FEC_AUTO;
+	case FEC_AUTO:
+	case FEC_1_2:
+	case FEC_2_3:
+	case FEC_3_4:
+	case FEC_5_6:
+	case FEC_7_8:
+		return 0;
+	default:
+		;
+	}
+	return 1;
+}
+
+
+int parse(const char *fname, const char *channel,
+	  struct dvb_frontend_parameters *frontend, int *vpid, int *apid,
+	  int *sid)
+{
+	int fd;
+	int err;
+	int tmp;
+
+	if ((fd = open(fname, O_RDONLY | O_NONBLOCK)) < 0) {
+		PERROR ("could not open file '%s'", fname);
+		perror ("");
+		return -1;
+	}
+
+	if (find_channel(fd, channel) < 0) {
+		ERROR("could not find channel '%s' in channel list", channel);
+		return -2;
+	}
+
+	if ((err = try_parse_int(fd, &tmp, "frequency")))
+		return -3;
+	frontend->frequency = tmp;
+
+	if ((err = try_parse_param(fd,
+				   inversion_list, LIST_SIZE(inversion_list),
+				   &tmp, "inversion")))
+		return -4;
+	frontend->inversion = tmp;
+
+	if ((err = try_parse_param(fd, bw_list, LIST_SIZE(bw_list),
+				   &tmp, "bandwidth")))
+		return -5;
+	frontend->u.ofdm.bandwidth = tmp;
+
+	if ((err = try_parse_param(fd, fec_list, LIST_SIZE(fec_list),
+				   &tmp, "code_rate_HP")))
+		return -6;
+	frontend->u.ofdm.code_rate_HP = tmp;
+	if (check_fec(&frontend->u.ofdm.code_rate_HP))
+		return -6;
+
+	if ((err = try_parse_param(fd, fec_list, LIST_SIZE(fec_list),
+				   &tmp, "code_rate_LP")))
+		return -7;
+	frontend->u.ofdm.code_rate_LP = tmp;
+	if (check_fec(&frontend->u.ofdm.code_rate_LP))
+		return -7;
+
+	if ((err = try_parse_param(fd, constellation_list,
+				   LIST_SIZE(constellation_list),
+				   &tmp, "constellation")))
+		return -8;
+	frontend->u.ofdm.constellation = tmp;
+
+	if ((err = try_parse_param(fd, transmissionmode_list,
+				   LIST_SIZE(transmissionmode_list),
+				   &tmp, "transmission_mode")))
+		return -9;
+	frontend->u.ofdm.transmission_mode = tmp;
+
+	if ((err = try_parse_param(fd, guard_list, LIST_SIZE(guard_list),
+				   &tmp, "guard_interval")))
+		return -10;
+	frontend->u.ofdm.guard_interval = tmp;
+
+	if ((err = try_parse_param(fd, hierarchy_list,
+				   LIST_SIZE(hierarchy_list),
+				   &tmp, "hierarchy_information")))
+		return -11;
+	frontend->u.ofdm.hierarchy_information = tmp;
+
+	if ((err = try_parse_int(fd, vpid, "Video PID")))
+		return -12;
+
+	if ((err = try_parse_int(fd, apid, "Audio PID")))
+		return -13;
+
+	if ((err = try_parse_int(fd, sid, "Service ID")))
+	    return -14;
+
+	close(fd);
+	return 0;
+}
+
+
+static int setup_frontend (int fe_fd, struct dvb_frontend_parameters *frontend)
+{
+	int ret;
+	uint32_t mstd;
+
+	if (check_frontend(fe_fd, FE_OFDM, &mstd) < 0) {
+		close(fe_fd);
+		return -1;
+	}
+	ret = dvbfe_set_delsys(fe_fd, SYS_DVBT);
+	if (ret) {
+		PERROR("SET Delsys failed");
+		return -1;
+	}
+	if (silent < 2)
+		fprintf (stderr,"tuning to %i Hz\n", frontend->frequency);
+
+	if (ioctl(fe_fd, FE_SET_FRONTEND, frontend) < 0) {
+		PERROR("ioctl FE_SET_FRONTEND failed");
+		return -1;
+	}
+	return 0;
+}
+
+static void do_timeout(int x)
+{
+	(void)x;
+	if (timeout_flag == 0) {
+		timeout_flag = 1;
+		alarm(2);
+		signal(SIGALRM, do_timeout);
+	} else {
+		/* something has gone wrong ... exit */
+		exit(1);
+	}
+}
+
+static void print_frontend_stats(int fe_fd, int human_readable)
+{
+	fe_status_t status;
+	uint16_t snr, _signal;
+	uint32_t ber, uncorrected_blocks;
+
+	ioctl(fe_fd, FE_READ_STATUS, &status);
+	ioctl(fe_fd, FE_READ_SIGNAL_STRENGTH, &_signal);
+	ioctl(fe_fd, FE_READ_SNR, &snr);
+	ioctl(fe_fd, FE_READ_BER, &ber);
+	ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks);
+
+	if (human_readable) {
+		printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | unc %d | ",
+			status, (_signal * 100) / 0xffff, (snr * 100) / 0xffff, ber, uncorrected_blocks);
+	} else {
+		fprintf (stderr, "status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ",
+			status, _signal, snr, ber, uncorrected_blocks);
+	}
+
+	if (status & FE_HAS_LOCK)
+		fprintf(stderr,"FE_HAS_LOCK");
+
+	fprintf(stderr,"\n");
+}
+
+static
+int monitor_frontend (int fe_fd, int human_readable)
+{
+	fe_status_t status;
+	do {
+	        ioctl(fe_fd, FE_READ_STATUS, &status);
+		if (!silent)
+			print_frontend_stats(fe_fd, human_readable);
+		if (exit_after_tuning && (status & FE_HAS_LOCK))
+			break;
+		usleep(1000000);
+	} while (!timeout_flag);
+	if (silent < 2)
+		print_frontend_stats (fe_fd, human_readable);
+
+	return 0;
+}
+
+#define BUFLEN (188*256)
+static void copy_to_file(int in_fd, int out_fd)
+{
+	char buf[BUFLEN];
+	int r;
+	long long int rc = 0LL;
+
+	while (timeout_flag==0) {
+		r=read(in_fd,buf,BUFLEN);
+		if (r < 0) {
+			if (errno == EOVERFLOW) {
+				printf("buffer overrun\n");
+				continue;
+			}
+			PERROR("Read failed");
+			break;
+		}
+		if (write(out_fd,buf,r) < 0) {
+			PERROR("Write failed");
+			break;
+		}
+		rc+=r;
+	}
+
+	if (silent<2) {
+		fprintf(stderr, "copied %lld bytes (%lld Kbytes/sec)\n",rc,rc/(1024*timeout));
+	}
+}
+
+static char *usage =
+	"usage:\n"
+	"       tzap [options] <channel_name>\n"
+	"         zap to channel channel_name (case insensitive)\n"
+	"     -a number : use given adapter (default 0)\n"
+	"     -f number : use given frontend (default 0)\n"
+	"     -d number : use given demux (default 0)\n"
+	"     -c file   : read channels list from 'file'\n"
+	"     -x        : exit after tuning\n"
+	"     -r        : set up /dev/dvb/adapterX/dvr0 for TS recording\n"
+	"     -p        : add pat and pmt to TS recording (implies -r)\n"
+	"     -s        : only print summary\n"
+	"     -S        : run silently (no output)\n"
+	"     -H        : human readable output\n"
+	"     -F        : set up frontend only, don't touch demux\n"
+	"     -t number : timeout (seconds)\n"
+	"     -o file   : output filename (use -o - for stdout)\n"
+	"     -h -?     : display this help and exit\n";
+
+
+int main(int argc, char **argv)
+{
+	struct dvb_frontend_parameters frontend_param;
+	char *homedir = getenv("HOME");
+	char *confname = NULL;
+	char *channel = NULL;
+	int adapter = 0, frontend = 0, demux = 0, dvr = 0;
+	int vpid, apid, sid, pmtpid = 0;
+	int pat_fd, pmt_fd;
+	int frontend_fd, audio_fd = 0, video_fd = 0, dvr_fd, file_fd;
+	int opt;
+	int record = 0;
+	int frontend_only = 0;
+	char *filename = NULL;
+	int human_readable = 0, rec_psi = 0;
+
+	while ((opt = getopt(argc, argv, "H?hrpxRsFSn:a:f:d:c:t:o:")) != -1) {
+		switch (opt) {
+		case 'a':
+			adapter = strtoul(optarg, NULL, 0);
+			break;
+		case 'f':
+			frontend = strtoul(optarg, NULL, 0);
+			break;
+		case 'd':
+			demux = strtoul(optarg, NULL, 0);
+			break;
+		case 't':
+			timeout = strtoul(optarg, NULL, 0);
+			break;
+		case 'o':
+			filename = strdup(optarg);
+			record=1;
+			/* fall through */
+		case 'r':
+			dvr = 1;
+			break;
+		case 'p':
+			rec_psi = 1;
+			break;
+		case 'x':
+			exit_after_tuning = 1;
+			break;
+		case 'c':
+			confname = optarg;
+			break;
+		case 's':
+			silent = 1;
+			break;
+		case 'S':
+			silent = 2;
+			break;
+		case 'F':
+			frontend_only = 1;
+			break;
+		case 'H':
+			human_readable = 1;
+			break;
+		case '?':
+		case 'h':
+		default:
+			fprintf (stderr, usage, argv[0]);
+			return -1;
+		};
+	}
+
+	if (optind < argc)
+		channel = argv[optind];
+
+	if (!channel) {
+		fprintf (stderr, usage, argv[0]);
+		return -1;
+	}
+
+	snprintf(FRONTEND_DEV,
+		 sizeof(FRONTEND_DEV),
+		 "/dev/dvb/adapter%i/frontend%i",
+	  	 adapter,
+	  	 frontend);
+
+	snprintf(DEMUX_DEV,
+		 sizeof(DEMUX_DEV),
+		 "/dev/dvb/adapter%i/demux%i",
+	  	 adapter,
+	  	 demux);
+
+	snprintf(DVR_DEV,
+		 sizeof(DVR_DEV),
+		 "/dev/dvb/adapter%i/dvr%i",
+	  	 adapter,
+	  	 demux);
+
+	if (silent < 2)
+		fprintf (stderr,"using '%s' and '%s'\n", FRONTEND_DEV, DEMUX_DEV);
+
+	if (!confname) {
+		int len = strlen(homedir) + strlen(CHANNEL_FILE) + 18;
+		if (!homedir)
+			ERROR ("$HOME not set");
+		confname = malloc (len);
+		snprintf(confname, len, "%s/.tzap/%i/%s", homedir, adapter, CHANNEL_FILE);
+		if (access (confname, R_OK))
+			snprintf(confname, len, "%s/.tzap/%s", homedir, CHANNEL_FILE);
+	}
+	printf("reading channels from file '%s'\n", confname);
+	memset(&frontend_param, 0, sizeof(struct dvb_frontend_parameters));
+
+	if (parse (confname, channel, &frontend_param, &vpid, &apid, &sid))
+		return -1;
+
+	if ((frontend_fd = open(FRONTEND_DEV, O_RDWR | O_NONBLOCK)) < 0) {
+		PERROR ("failed opening '%s'", FRONTEND_DEV);
+		return -1;
+	}
+
+	if (setup_frontend (frontend_fd, &frontend_param) < 0)
+		return -1;
+
+	if (frontend_only)
+		goto just_the_frontend_dude;
+
+	if (rec_psi) {
+	    	pmtpid = get_pmt_pid(DEMUX_DEV, sid);
+	    	if (pmtpid <= 0) {
+			fprintf(stderr,"couldn't find pmt-pid for sid %04x\n",sid);
+			return -1;
+	    	}
+
+	    	if ((pat_fd = open(DEMUX_DEV, O_RDWR)) < 0) {
+			perror("opening pat demux failed");
+			return -1;
+	    	}
+	    	if (set_pesfilter(pat_fd, 0, DMX_PES_OTHER, dvr) < 0)
+			return -1;
+
+	    	if ((pmt_fd = open(DEMUX_DEV, O_RDWR)) < 0) {
+			perror("opening pmt demux failed");
+			return -1;
+	    	}
+	    	if (set_pesfilter(pmt_fd, pmtpid, DMX_PES_OTHER, dvr) < 0)
+			return -1;
+	}
+
+	if ((video_fd = open(DEMUX_DEV, O_RDWR)) < 0) {
+		PERROR("failed opening '%s'", DEMUX_DEV);
+		return -1;
+	}
+
+	if (silent<2)
+		fprintf(stderr,"video pid 0x%04x, audio pid 0x%04x\n", vpid, apid);
+
+	if (set_pesfilter(video_fd, vpid, DMX_PES_VIDEO, dvr) < 0)
+		return -1;
+
+	if ((audio_fd = open(DEMUX_DEV, O_RDWR)) < 0) {
+		PERROR("failed opening '%s'", DEMUX_DEV);
+		return -1;
+	}
+
+	if (set_pesfilter(audio_fd, apid, DMX_PES_AUDIO, dvr) < 0)
+		return -1;
+
+	signal(SIGALRM,do_timeout);
+	if (timeout > 0)
+		alarm(timeout);
+
+	if (record) {
+		if (filename!=NULL) {
+			if (strcmp(filename,"-")!=0) {
+				file_fd = open(filename,O_WRONLY|O_LARGEFILE|O_CREAT,0644);
+				if (file_fd<0) {
+					PERROR("open of '%s' failed",filename);
+					return -1;
+				}
+			} else {
+				file_fd=1;
+			}
+		} else {
+			PERROR("Record mode but no filename!");
+			return -1;
+		}
+
+		if ((dvr_fd = open(DVR_DEV, O_RDONLY)) < 0) {
+	                PERROR("failed opening '%s'", DVR_DEV);
+	                return -1;
+	        }
+		if (silent<2)
+			print_frontend_stats(frontend_fd, human_readable);
+
+		copy_to_file(dvr_fd,file_fd);
+
+		if (silent<2)
+			print_frontend_stats(frontend_fd, human_readable);
+	} else {
+just_the_frontend_dude:
+		monitor_frontend(frontend_fd, human_readable);
+	}
+
+	close(pat_fd);
+	close(pmt_fd);
+	close(audio_fd);
+	close(video_fd);
+	close(frontend_fd);
+	return 0;
+}

+ 347 - 0
sonyEw100/tuneTool/util.c

@@ -0,0 +1,347 @@
+/*
+ * util functions for various ?zap implementations
+ *
+ * Copyright (C) 2001 Johannes Stezenbach (js@convergence.de)
+ * for convergence integrated media
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+
+
+int set_pesfilter(int dmxfd, int pid, int pes_type, int dvr)
+{
+	struct dmx_pes_filter_params pesfilter;
+
+	/* ignore this pid to allow radio services */
+	if (pid < 0 || pid >= 0x1fff || (pid == 0 && pes_type != DMX_PES_OTHER))
+		return 0;
+
+	if (dvr) {
+		int buffersize = 64 * 1024;
+		if (ioctl(dmxfd, DMX_SET_BUFFER_SIZE, buffersize) == -1)
+			perror("DMX_SET_BUFFER_SIZE failed");
+	}
+
+	pesfilter.pid = pid;
+	pesfilter.input = DMX_IN_FRONTEND;
+	pesfilter.output = dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER;
+	pesfilter.pes_type = pes_type;
+	pesfilter.flags = DMX_IMMEDIATE_START;
+
+	if (ioctl(dmxfd, DMX_SET_PES_FILTER, &pesfilter) == -1) {
+		fprintf(stderr, "DMX_SET_PES_FILTER failed "
+			"(PID = 0x%04x): %d %m\n", pid, errno);
+		return -1;
+	}
+	return 0;
+}
+
+
+int get_pmt_pid(char *dmxdev, int sid)
+{
+	int patfd, count;
+	int pmt_pid = 0;
+	int patread = 0;
+	int section_length;
+	unsigned char buft[4096];
+	unsigned char *buf = buft;
+	struct dmx_sct_filter_params f;
+
+	memset(&f, 0, sizeof(f));
+	f.pid = 0;
+	f.filter.filter[0] = 0x00;
+	f.filter.mask[0] = 0xff;
+	f.timeout = 0;
+	f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
+
+	if ((patfd = open(dmxdev, O_RDWR)) < 0) {
+		perror("openening pat demux failed");
+		return -1;
+	}
+
+	if (ioctl(patfd, DMX_SET_FILTER, &f) == -1) {
+		perror("ioctl DMX_SET_FILTER failed");
+		close(patfd);
+		return -1;
+	}
+
+	while (!patread) {
+		if (((count = read(patfd, buf, sizeof(buft))) < 0) && errno == EOVERFLOW)
+			count = read(patfd, buf, sizeof(buft));
+
+		if (count < 0) {
+			perror("read_sections: read error");
+			close(patfd);
+			return -1;
+		}
+		section_length = ((buf[1] & 0x0f) << 8) | buf[2];
+		if (count != section_length + 3)
+			continue;
+
+		buf += 8;
+		section_length -= 8;
+
+		patread = 1; /* assumes one section contains the whole pat */
+		while (section_length > 0) {
+			int service_id = (buf[0] << 8) | buf[1];
+
+			if (service_id == sid) {
+				pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3];
+				section_length = 0;
+			}
+			buf += 4;
+			section_length -= 4;
+		}
+	}
+	close(patfd);
+	return pmt_pid;
+}
+
+char *type_str[] = {
+	"QPSK",
+	"QAM",
+	"OFDM",
+	"ATSC",
+};
+
+/* to be used with v3 drivers */
+int check_frontend_v3(int fd, enum fe_type type)
+{
+	struct dvb_frontend_info info;
+	int ret;
+
+	ret = ioctl(fd, FE_GET_INFO, &info);
+	if (ret < 0) {
+		perror("ioctl FE_GET_INFO failed");
+		close(fd);
+		ret = -1;
+		goto exit;
+	}
+	if (info.type != type) {
+		fprintf(stderr, "Not a valid %s device!\n", type_str[type]);
+		close(fd);
+		ret = -EINVAL;
+		goto exit;
+	}
+exit:
+	return ret;
+}
+
+char *del_str[] = {
+	"UNDEFINED",
+	"DVB-C (A)",
+	"DVB-C (B)",
+	"DVB-T",
+	"DSS",
+	"DVB-S",
+	"DVB-S2",
+	"DVB-H",
+	"ISDB-T",
+	"ISDB-S",
+	"ISDB-C",
+	"ATSC",
+	"ATSC-M/H",
+	"DTMB",
+	"CMMB",
+	"DAB",
+	"DVB-T2",
+	"TURBO",
+	"QAM (C)",
+};
+
+static int map_delivery_mode(fe_type_t *type, enum fe_delivery_system delsys)
+{
+	switch (delsys) {
+	case SYS_DSS:
+	case SYS_DVBS:
+	case SYS_DVBS2:
+	case SYS_TURBO:
+		*type = FE_QPSK;
+		break;
+	case SYS_DVBT:
+	case SYS_DVBT2:
+	case SYS_DVBH:
+	case SYS_ISDBT:
+		*type = FE_OFDM;
+		break;
+	case SYS_DVBC_ANNEX_A:
+	case SYS_DVBC_ANNEX_C:
+		*type = FE_QAM;
+		break;
+	case SYS_ATSC:
+	case SYS_DVBC_ANNEX_B:
+		*type = FE_ATSC;
+		break;
+	default:
+		fprintf(stderr, "Delivery system unsupported, please report to linux-media ML\n");
+		return -1;
+	}
+	return 0;
+}
+
+int get_property(int fd, uint32_t pcmd, uint32_t *len, uint8_t *data)
+{
+	struct dtv_property p, *b;
+	struct dtv_properties cmd;
+	int ret;
+
+	p.cmd = pcmd;
+	cmd.num = 1;
+	cmd.props = &p;
+	b = &p;
+
+	ret = ioctl(fd, FE_GET_PROPERTY, &cmd);
+	if (ret < 0) {
+		fprintf(stderr, "FE_SET_PROPERTY returned %d\n", ret);
+		return -1;
+	}
+	memcpy(len, &b->u.buffer.len, sizeof (uint32_t));
+	memcpy(data, b->u.buffer.data, *len);
+	return 0;
+}
+
+int set_property(int fd, uint32_t cmd, uint32_t data)
+{
+	struct dtv_property p, *b;
+	struct dtv_properties c;
+	int ret;
+
+	p.cmd = cmd;
+	c.num = 1;
+	c.props = &p;
+	b = &p;
+	b->u.data = data;
+	ret = ioctl(fd, FE_SET_PROPERTY, &c);
+	if (ret < 0) {
+		fprintf(stderr, "FE_SET_PROPERTY returned %d\n", ret);
+		return -1;
+	}
+	return 0;
+}
+
+int dvbfe_get_delsys(int fd, fe_delivery_system_t *delsys)
+{
+	uint32_t len;
+	/* Buggy API design */
+	return get_property(fd, DTV_DELIVERY_SYSTEM, &len, (uint8_t *)delsys);
+}
+
+int dvbfe_set_delsys(int fd, enum fe_delivery_system delsys)
+{
+	return set_property(fd, DTV_DELIVERY_SYSTEM, delsys);
+}
+
+int dvbfe_enum_delsys(int fd, uint32_t *len, uint8_t *data)
+{
+	return get_property(fd, DTV_ENUM_DELSYS, len, data);
+}
+
+int dvbfe_get_version(int fd, int *major, int *minor)
+{
+	struct dtv_property p, *b;
+	struct dtv_properties cmd;
+	int ret;
+
+	p.cmd = DTV_API_VERSION;
+	cmd.num = 1;
+	cmd.props = &p;
+	b = &p;
+
+	ret = ioctl(fd, FE_GET_PROPERTY, &cmd);
+	if (ret < 0) {
+		fprintf(stderr, "FE_GET_PROPERTY failed, ret=%d\n", ret);
+		return -1;
+	}
+	*major = (b->u.data >> 8) & 0xff;
+	*minor = b->u.data & 0xff;
+	return 0;
+}
+
+int check_frontend_multi(int fd, enum fe_type type, uint32_t *mstd)
+{
+	int ret;
+
+	enum fe_type delmode;
+	unsigned int i, valid_delsys = 0;
+	uint32_t len;
+	uint8_t data[32];
+
+	ret = dvbfe_enum_delsys(fd, &len, data);
+	if (ret) {
+		fprintf(stderr, "enum_delsys failed, ret=%d\n", ret);
+		ret = -EIO;
+		goto exit;
+	}
+	fprintf(stderr, "\t FE_CAN { ");
+	for (i = 0; i < len; i++) {
+		if (i < len - 1)
+			fprintf(stderr, "%s + ", del_str[data[i]]);
+		else
+			fprintf(stderr, "%s", del_str[data[i]]);
+	}
+	fprintf(stderr, " }\n");
+	/* check whether frontend can support our delivery */
+	for (i = 0; i < len; i++) {
+		map_delivery_mode(&delmode, data[i]);
+		if (type == delmode) {
+			valid_delsys = 1;
+			ret = 0;
+			break;
+		}
+	}
+	if (!valid_delsys) {
+		fprintf(stderr, "Not a valid %s device!\n", type_str[type]);
+		ret = -EINVAL;
+		goto exit;
+	}
+	*mstd = len; /* mstd has supported delsys count */
+exit:
+	return ret;
+}
+
+int check_frontend(int fd, enum fe_type type, uint32_t *mstd)
+{
+	int major, minor, ret;
+
+	ret = dvbfe_get_version(fd, &major, &minor);
+	if (ret)
+		goto exit;
+	fprintf(stderr, "Version: %d.%d  ", major, minor);
+	if ((major == 5) && (minor > 8)) {
+		ret = check_frontend_multi(fd, type, mstd);
+		if (ret)
+			goto exit;
+	} else {
+		ret = check_frontend_v3(fd, type);
+		if (ret)
+			goto exit;
+	}
+exit:
+	return ret;
+}

+ 28 - 0
sonyEw100/tuneTool/util.h

@@ -0,0 +1,28 @@
+/*
+ * util functions for various ?zap implementations
+ *
+ * Copyright (C) 2001 Johannes Stezenbach (js@convergence.de)
+ * for convergence integrated media
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+int set_pesfilter(int dmxfd, int pid, int pes_type, int dvr);
+
+int get_pmt_pid(char *dmxdev, int sid);
+
+int check_frontend(int fd, enum fe_type type, uint32_t *mstd);
+
+int dvbfe_set_delsys(int fd, enum fe_delivery_system delsys);