diff options
| author | Mark Purcell <msp@debian.org> | 2008-06-22 11:00:40 +1000 | 
|---|---|---|
| committer | etobi <git@e-tobi.net> | 2013-09-03 09:48:42 +0200 | 
| commit | 891c51ff368ed700dec6025eeb47ce4d96f76418 (patch) | |
| tree | 3729664829e4faa691d403274f38eb10890b533c /util/zap | |
| parent | 1c6e1f28f54ec2606c23936c1d8689f2be55a86c (diff) | |
| parent | ab959d7b4194715870128e616b8e29d4a101e488 (diff) | |
| download | linux-dvb-apps-891c51ff368ed700dec6025eeb47ce4d96f76418.tar.gz | |
Imported Debian patch 1.1.1+rev1207-1debian/1.1.1+rev1207-1
Diffstat (limited to '')
| -rw-r--r-- | util/zap/Makefile | 20 | ||||
| -rw-r--r-- | util/zap/zap.c | 226 | ||||
| -rw-r--r-- | util/zap/zap_ca.c | 198 | ||||
| -rw-r--r-- | util/zap/zap_ca.h | 37 | ||||
| -rw-r--r-- | util/zap/zap_dvb.c | 353 | ||||
| -rw-r--r-- | util/zap/zap_dvb.h | 41 | 
6 files changed, 875 insertions, 0 deletions
| diff --git a/util/zap/Makefile b/util/zap/Makefile new file mode 100644 index 0000000..35e0c6d --- /dev/null +++ b/util/zap/Makefile @@ -0,0 +1,20 @@ +# Makefile for linuxtv.org dvb-apps/util/zap + +objects  = zap_ca.o  \ +           zap_dvb.o + +binaries = zap + +inst_bin = $(binaries) + +CPPFLAGS += -I../../lib +LDFLAGS  += -L../../lib/libdvbapi -L../../lib/libdvbsec  -L../../lib/libdvbcfg -L../../lib/libdvben50221 -L../../lib/libucsi +LDLIBS   += -ldvbcfg -ldvben50221 -ldvbsec -ldvbapi -lucsi -lpthread + +.PHONY: all + +all: $(binaries) + +$(binaries): $(objects) + +include ../../Make.rules diff --git a/util/zap/zap.c b/util/zap/zap.c new file mode 100644 index 0000000..6f3df33 --- /dev/null +++ b/util/zap/zap.c @@ -0,0 +1,226 @@ +/* +	ZAP utility + +	Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	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 Lesser General Public License for more details. + +	You should have received a copy of the GNU Lesser General Public +	License along with this library; if not, write to the Free Software +	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <fcntl.h> +#include <signal.h> +#include <pthread.h> +#include <sys/poll.h> +#include <libdvbapi/dvbdemux.h> +#include <libdvbapi/dvbaudio.h> +#include <libdvbsec/dvbsec_cfg.h> +#include <libucsi/mpeg/section.h> +#include "zap_dvb.h" +#include "zap_ca.h" + + +static void signal_handler(int _signal); + +static int quit_app = 0; + +void usage(void) +{ +	static const char *_usage = "\n" +		" ZAP: A zapping application\n" +		" Copyright (C) 2004, 2005, 2006 Manu Abraham (manu@kromtek.com)\n" +		" Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)\n\n" +		" usage: zap <options> as follows:\n" +		" -h			help\n" +		" -adapter <id>		adapter to use (default 0)\n" +		" -frontend <id>	frontend to use (default 0)\n" +		" -demux <id>		demux to use (default 0)\n" +		" -caslotnum <id>	ca slot number to use (default 0)\n" +		" -channels <filename>	channels.conf file.\n" +		" -secfile <filename>	Optional sec.conf file.\n" +		" -secid <secid>	ID of the SEC configuration to use, one of:\n" +		" -nomoveca		Do not attempt to move CA descriptors from stream to programme level\n" +		" <channel name>\n"; +	fprintf(stderr, "%s\n", _usage); + +	exit(1); +} + +int find_channel(struct dvbcfg_zapchannel *channel, void *private_data) +{ +	struct dvbcfg_zapchannel *tmpchannel = private_data; + +	if (strcmp(channel->name, tmpchannel->name) == 0) { +		memcpy(tmpchannel, channel, sizeof(struct dvbcfg_zapchannel)); +		return 1; +	} + +	return 0; +} + +int main(int argc, char *argv[]) +{ +	int adapter_id = 0; +	int frontend_id = 0; +	int demux_id = 0; +	int caslot_num = 0; +	char *chanfile = "/etc/channels.conf"; +	char *secfile = NULL; +	char *secid = NULL; +	char *channel_name = NULL; +	int moveca = 1; +	int argpos = 1; +	struct zap_dvb_params zap_dvb_params; +	struct zap_ca_params zap_ca_params; + +	while(argpos != argc) { +		if (!strcmp(argv[argpos], "-h")) { +			usage(); +		} else if (!strcmp(argv[argpos], "-adapter")) { +			if ((argc - argpos) < 2) +				usage(); +			if (sscanf(argv[argpos+1], "%i", &adapter_id) != 1) +				usage(); +			argpos+=2; +		} else if (!strcmp(argv[argpos], "-frontend")) { +			if ((argc - argpos) < 2) +				usage(); +			if (sscanf(argv[argpos+1], "%i", &frontend_id) != 1) +				usage(); +			argpos+=2; +		} else if (!strcmp(argv[argpos], "-demux")) { +			if ((argc - argpos) < 2) +				usage(); +			if (sscanf(argv[argpos+1], "%i", &demux_id) != 1) +				usage(); +			argpos+=2; +		} else if (!strcmp(argv[argpos], "-caslotnum")) { +			if ((argc - argpos) < 2) +				usage(); +			if (sscanf(argv[argpos+1], "%i", &caslot_num) != 1) +				usage(); +			argpos+=2; +		} else if (!strcmp(argv[argpos], "-channels")) { +			if ((argc - argpos) < 2) +				usage(); +			chanfile = argv[argpos+1]; +			argpos+=2; +		} else if (!strcmp(argv[argpos], "-secfile")) { +			if ((argc - argpos) < 2) +				usage(); +			secfile = argv[argpos+1]; +			argpos+=2; +		} else if (!strcmp(argv[argpos], "-secid")) { +			if ((argc - argpos) < 2) +				usage(); +			secid = argv[argpos+1]; +			argpos+=2; +		} else if (!strcmp(argv[argpos], "-nomoveca")) { +			moveca = 0; +			argpos++; +		} else { +			if ((argc - argpos) != 1) +				usage(); +			channel_name = argv[argpos]; +			argpos++; +		} +	} + +	// the user didn't select anything! +	if (channel_name == NULL) +		usage(); + +	// setup any signals +	signal(SIGINT, signal_handler); +	signal(SIGPIPE, SIG_IGN); + +	// start the CA stuff +	zap_ca_params.adapter_id = adapter_id; +	zap_ca_params.caslot_num = caslot_num; +	zap_ca_params.moveca = moveca; +	zap_ca_start(&zap_ca_params); + +	// find the requested channel +	if (strlen(channel_name) >= sizeof(zap_dvb_params.channel.name)) { +		fprintf(stderr, "Channel name is too long %s\n", channel_name); +		exit(1); +	} +	FILE *channel_file = fopen(chanfile, "r"); +	if (channel_file == NULL) { +		fprintf(stderr, "Could open channel file %s\n", chanfile); +		exit(1); +	} +	memcpy(zap_dvb_params.channel.name, channel_name, strlen(channel_name) + 1); +	if (dvbcfg_zapchannel_parse(channel_file, find_channel, &zap_dvb_params.channel) != 1) { +		fprintf(stderr, "Unable to find requested channel %s\n", channel_name); +		exit(1); +	} +	fclose(channel_file); + +	// default SEC with a DVBS card +	if ((secid == NULL) && (zap_dvb_params.channel.fe_type == DVBFE_TYPE_DVBS)) +		secid = "UNIVERSAL"; + +	// look it up if one were supplied +	zap_dvb_params.valid_sec = 0; +	if (secid != NULL) { +		if (dvbsec_cfg_find(secfile, secid, +				&zap_dvb_params.sec)) { +			fprintf(stderr, "Unable to find suitable sec/lnb configuration for channel\n"); +			exit(1); +		} +		zap_dvb_params.valid_sec = 1; +	} + +	// open the frontend +	zap_dvb_params.fe = dvbfe_open(adapter_id, frontend_id, 0); +	if (zap_dvb_params.fe == NULL) { +		fprintf(stderr, "Failed to open frontend\n"); +		exit(1); +	} + +	// start the DVB stuff +	zap_dvb_params.adapter_id = adapter_id; +	zap_dvb_params.frontend_id = frontend_id; +	zap_dvb_params.demux_id = demux_id; +	zap_dvb_start(&zap_dvb_params); + +	// the UI +	while(!quit_app) { +		sleep(1); +	} + +	// shutdown DVB stuff +	if (channel_name != NULL) +		zap_dvb_stop(); + +	// shutdown CA stuff +	zap_ca_stop(); + +	// done +	exit(0); +} + +static void signal_handler(int _signal) +{ +	(void) _signal; + +	if (!quit_app) { +		quit_app = 1; +	} +} diff --git a/util/zap/zap_ca.c b/util/zap/zap_ca.c new file mode 100644 index 0000000..b78fdcf --- /dev/null +++ b/util/zap/zap_ca.c @@ -0,0 +1,198 @@ +/* +	ZAP utility CA functions + +	Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	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 Lesser General Public License for more details. + +	You should have received a copy of the GNU Lesser General Public +	License along with this library; 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/poll.h> +#include <pthread.h> +#include <libdvben50221/en50221_stdcam.h> +#include "zap_ca.h" + + +static int zap_ca_info_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids); +static int zap_ai_callback(void *arg, uint8_t slot_id, uint16_t session_number, +			     uint8_t application_type, uint16_t application_manufacturer, +			     uint16_t manufacturer_code, uint8_t menu_string_length, +			     uint8_t *menu_string); +static void *camthread_func(void* arg); + +static struct en50221_transport_layer *tl = NULL; +static struct en50221_session_layer *sl = NULL; +static struct en50221_stdcam *stdcam = NULL; + +static int ca_resource_connected = 0; + +static int camthread_shutdown = 0; +static pthread_t camthread; +static int seenpmt = 0; +static int moveca = 0; + +void zap_ca_start(struct zap_ca_params *params) +{ +	// create transport layer +	tl = en50221_tl_create(1, 16); +	if (tl == NULL) { +		fprintf(stderr, "Failed to create transport layer\n"); +		return; +	} + +	// create session layer +	sl = en50221_sl_create(tl, 16); +	if (sl == NULL) { +		fprintf(stderr, "Failed to create session layer\n"); +		en50221_tl_destroy(tl); +		return; +	} + +	// create the stdcam instance +	stdcam = en50221_stdcam_create(params->adapter_id, params->caslot_num, tl, sl); +	if (stdcam == NULL) { +		en50221_sl_destroy(sl); +		en50221_tl_destroy(tl); +		return; +	} + +	// hook up the AI callbacks +	if (stdcam->ai_resource) { +		en50221_app_ai_register_callback(stdcam->ai_resource, zap_ai_callback, stdcam); +	} + +	// hook up the CA callbacks +	if (stdcam->ca_resource) { +		en50221_app_ca_register_info_callback(stdcam->ca_resource, zap_ca_info_callback, stdcam); +	} + +	// any other stuff +	moveca = params->moveca; + +	// start the cam thread +	pthread_create(&camthread, NULL, camthread_func, NULL); +} + +void zap_ca_stop(void) +{ +	if (stdcam == NULL) +		return; + +	// shutdown the cam thread +	camthread_shutdown = 1; +	pthread_join(camthread, NULL); + +	// destroy session layer +	en50221_sl_destroy(sl); + +	// destroy transport layer +	en50221_tl_destroy(tl); + +	// destroy the stdcam +	if (stdcam->destroy) +		stdcam->destroy(stdcam, 1); +} + +int zap_ca_new_pmt(struct mpeg_pmt_section *pmt) +{ +	uint8_t capmt[4096]; +	int size; + +	if (stdcam == NULL) +		return -1; + +	if (ca_resource_connected) { +		fprintf(stderr, "Received new PMT - sending to CAM...\n"); + +		// translate it into a CA PMT +		int listmgmt = CA_LIST_MANAGEMENT_ONLY; +		if (seenpmt) { +			listmgmt = CA_LIST_MANAGEMENT_UPDATE; +		} +		seenpmt = 1; + +		if ((size = en50221_ca_format_pmt(pmt, capmt, sizeof(capmt), moveca, listmgmt, +						  CA_PMT_CMD_ID_OK_DESCRAMBLING)) < 0) { +			fprintf(stderr, "Failed to format PMT\n"); +			return -1; +		} + +		// set it +		if (en50221_app_ca_pmt(stdcam->ca_resource, stdcam->ca_session_number, capmt, size)) { +			fprintf(stderr, "Failed to send PMT\n"); +			return -1; +		} + +		// we've seen this PMT +		return 1; +	} + +	return 0; +} + +void zap_ca_new_dvbtime(time_t dvb_time) +{ +	if (stdcam == NULL) +		return; + +	if (stdcam->dvbtime) +		stdcam->dvbtime(stdcam, dvb_time); +} + +static void *camthread_func(void* arg) +{ +	(void) arg; + +	while(!camthread_shutdown) { +		stdcam->poll(stdcam); +	} + +	return 0; +} + +static int zap_ai_callback(void *arg, uint8_t slot_id, uint16_t session_number, +			     uint8_t application_type, uint16_t application_manufacturer, +			     uint16_t manufacturer_code, uint8_t menu_string_length, +			     uint8_t *menu_string) +{ +	(void) arg; +	(void) slot_id; +	(void) session_number; + +	printf("CAM Application type: %02x\n", application_type); +	printf("CAM Application manufacturer: %04x\n", application_manufacturer); +	printf("CAM Manufacturer code: %04x\n", manufacturer_code); +	printf("CAM Menu string: %.*s\n", menu_string_length, menu_string); + +	return 0; +} + +static int zap_ca_info_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids) +{ +	(void) arg; +	(void) slot_id; +	(void) session_number; + +	printf("CAM supports the following ca system ids:\n"); +	uint32_t i; +	for(i=0; i< ca_id_count; i++) { +		printf("  0x%04x\n", ca_ids[i]); +	} +	ca_resource_connected = 1; +	return 0; +} diff --git a/util/zap/zap_ca.h b/util/zap/zap_ca.h new file mode 100644 index 0000000..5df45fd --- /dev/null +++ b/util/zap/zap_ca.h @@ -0,0 +1,37 @@ +/* +	ZAP utility CA functions + +	Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	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 Lesser General Public License for more details. + +	You should have received a copy of the GNU Lesser General Public +	License along with this library; if not, write to the Free Software +	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef ZAP_CA_H +#define ZAP_CA_H 1 + +struct zap_ca_params { +	int adapter_id; +	int caslot_num; +	int moveca; +}; + +extern void zap_ca_start(struct zap_ca_params *params); +extern void zap_ca_stop(void); + +extern int zap_ca_new_pmt(struct mpeg_pmt_section *pmt); +extern void zap_ca_new_dvbtime(time_t dvb_time); + +#endif diff --git a/util/zap/zap_dvb.c b/util/zap/zap_dvb.c new file mode 100644 index 0000000..677e05e --- /dev/null +++ b/util/zap/zap_dvb.c @@ -0,0 +1,353 @@ +/* +	ZAP utility DVB functions + +	Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	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 Lesser General Public License for more details. + +	You should have received a copy of the GNU Lesser General Public +	License along with this library; if not, write to the Free Software +	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#include <stdio.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <signal.h> +#include <pthread.h> +#include <sys/poll.h> +#include <libdvbapi/dvbdemux.h> +#include <libucsi/section.h> +#include <libucsi/mpeg/section.h> +#include <libucsi/dvb/section.h> +#include "zap_dvb.h" +#include "zap_ca.h" + +#define FE_STATUS_PARAMS (DVBFE_INFO_LOCKSTATUS|DVBFE_INFO_SIGNAL_STRENGTH|DVBFE_INFO_BER|DVBFE_INFO_SNR|DVBFE_INFO_UNCORRECTED_BLOCKS) + +static int dvbthread_shutdown = 0; +static pthread_t dvbthread; + +static int pat_version = -1; +static int ca_pmt_version = -1; + +static void *dvbthread_func(void* arg); + +static void process_pat(int pat_fd, struct zap_dvb_params *params, int *pmt_fd, struct pollfd *pollfd); +static void process_tdt(int tdt_fd); +static void process_pmt(int pmt_fd, struct zap_dvb_params *params); +static int create_section_filter(int adapter, int demux, uint16_t pid, uint8_t table_id); + + +int zap_dvb_start(struct zap_dvb_params *params) +{ +	pthread_create(&dvbthread, NULL, dvbthread_func, (void*) params); +	return 0; +} + +void zap_dvb_stop(void) +{ +	dvbthread_shutdown = 1; +	pthread_join(dvbthread, NULL); +} + +static void *dvbthread_func(void* arg) +{ +	int tune_state = 0; +	int pat_fd = -1; +	int pmt_fd = -1; +	int tdt_fd = -1; +	struct pollfd pollfds[3]; + +	struct zap_dvb_params *params = (struct zap_dvb_params *) arg; + +	// create PAT filter +	if ((pat_fd = create_section_filter(params->adapter_id, params->demux_id, +	     TRANSPORT_PAT_PID, stag_mpeg_program_association)) < 0) { +		fprintf(stderr, "Failed to create PAT section filter\n"); +		exit(1); +	} +	pollfds[0].fd = pat_fd; +	pollfds[0].events = POLLIN|POLLPRI|POLLERR; + +	// create TDT filter +	if ((tdt_fd = create_section_filter(params->adapter_id, params->demux_id, TRANSPORT_TDT_PID, stag_dvb_time_date)) < 0) { +		fprintf(stderr, "Failed to create TDT section filter\n"); +		exit(1); +	} +	pollfds[1].fd = tdt_fd; +	pollfds[1].events = POLLIN|POLLPRI|POLLERR; + +	// zero PMT filter +	pollfds[2].fd = 0; +	pollfds[2].events = 0; + +	// the DVB loop +	while(!dvbthread_shutdown) { +		// tune frontend + monitor lock status +		if (tune_state == 0) { +			// get the type of frontend +			struct dvbfe_info result; +			char *types; +			memset(&result, 0, sizeof(result)); +			dvbfe_get_info(params->fe, 0, &result, DVBFE_INFO_QUERYTYPE_IMMEDIATE, 0); +			switch(result.type) { +			case DVBFE_TYPE_DVBS: +				types = "DVB-S"; +				break; +			case DVBFE_TYPE_DVBC: +				types = "DVB-C"; +				break; +			case DVBFE_TYPE_DVBT: +				types = "DVB-T"; +				break; +			case DVBFE_TYPE_ATSC: +				types = "ATSC"; +				break; +			default: +				types = "Unknown"; +			} +			fprintf(stderr, "Using frontend \"%s\", type %s\n", result.name, types); + +			// do we have a valid SEC configuration? +			struct dvbsec_config *sec = NULL; +			if (params->valid_sec) +				sec = ¶ms->sec; + +			// tune! +			if (dvbsec_set(params->fe, +			    		  sec, +					  params->channel.polarization, +					  (params->channel.diseqc_switch & 0x01) ? DISEQC_SWITCH_B : DISEQC_SWITCH_A, +					  (params->channel.diseqc_switch & 0x02) ? DISEQC_SWITCH_B : DISEQC_SWITCH_A, +					  ¶ms->channel.fe_params, +					  0)) { +				fprintf(stderr, "Failed to set frontend\n"); +				exit(1); +			} + +			tune_state++; +		} else if (tune_state == 1) { +			struct dvbfe_info result; +			memset(&result, 0, sizeof(result)); +			if (dvbfe_get_info(params->fe, +					   FE_STATUS_PARAMS, +			    		   &result, +			    		   DVBFE_INFO_QUERYTYPE_IMMEDIATE, +			    		   0) != FE_STATUS_PARAMS) { +				fprintf(stderr, "Problem retrieving frontend information: %m\n"); +			} + +			fprintf(stderr, "status %c%c%c%c%c | signal %04x | snr %04x | ber %08x | unc %08x | %s\r", +				result.signal ? 'S' : ' ', +				result.carrier ? 'C' : ' ', +				result.viterbi ? 'V' : ' ', +				result.sync ? 'Y' : ' ', +				result.lock ? 'L' : ' ', +				result.signal_strength, +				result.snr, +				result.ber, +				result.ucblocks, +				result.lock ? "FE_HAS_LOCK" : ""); +			fflush(stderr); + +			if (result.lock) { +				tune_state++; +				fprintf(stderr, "\n"); +				fflush(stderr); +			} else { +				usleep(500000); +			} +		} + +		// is there SI data? +		int count = poll(pollfds, 3, 100); +		if (count < 0) { +			fprintf(stderr, "Poll error\n"); +			break; +		} +		if (count == 0) { +			continue; +		} + +		// PAT +		if (pollfds[0].revents & (POLLIN|POLLPRI)) { +			process_pat(pat_fd, params, &pmt_fd, &pollfds[2]); +		} + +		// TDT +		if (pollfds[1].revents & (POLLIN|POLLPRI)) { +			process_tdt(tdt_fd); +		} + +		//  PMT +		if (pollfds[2].revents & (POLLIN|POLLPRI)) { +			process_pmt(pmt_fd, params); +		} +	} + +	// close demuxers +	if (pat_fd != -1) +		close(pat_fd); +	if (pmt_fd != -1) +		close(pmt_fd); +	if (tdt_fd != -1) +		close(tdt_fd); + +	return 0; +} + +static void process_pat(int pat_fd, struct zap_dvb_params *params, int *pmt_fd, struct pollfd *pollfd) +{ +	int size; +	uint8_t sibuf[4096]; + +	// read the section +	if ((size = read(pat_fd, sibuf, sizeof(sibuf))) < 0) { +		return; +	} + +	// parse section +	struct section *section = section_codec(sibuf, size); +	if (section == NULL) { +		return; +	} + +	// parse section_ext +	struct section_ext *section_ext = section_ext_decode(section, 0); +	if (section_ext == NULL) { +		return; +	} +	if (pat_version == section_ext->version_number) { +		return; +	} + +	// parse PAT +	struct mpeg_pat_section *pat = mpeg_pat_section_codec(section_ext); +	if (pat == NULL) { +		return; +	} + +	// try and find the requested program +	struct mpeg_pat_program *cur_program; +	mpeg_pat_section_programs_for_each(pat, cur_program) { +		if (cur_program->program_number == params->channel.service_id) { +			// close old PMT fd +			if (*pmt_fd != -1) +				close(*pmt_fd); + +			// create PMT filter +			if ((*pmt_fd = create_section_filter(params->adapter_id, params->demux_id, +							     cur_program->pid, stag_mpeg_program_map)) < 0) { +				return; +			} +			pollfd->fd = *pmt_fd; +			pollfd->events = POLLIN|POLLPRI|POLLERR; + +			// we have a new PMT pid +			ca_pmt_version = -1; +			break; +		} +	} + +	// remember the PAT version +	pat_version = section_ext->version_number; +} + +static void process_tdt(int tdt_fd) +{ +	int size; +	uint8_t sibuf[4096]; + +	// read the section +	if ((size = read(tdt_fd, sibuf, sizeof(sibuf))) < 0) { +		return; +	} + +	// parse section +	struct section *section = section_codec(sibuf, size); +	if (section == NULL) { +		return; +	} + +	// parse TDT +	struct dvb_tdt_section *tdt = dvb_tdt_section_codec(section); +	if (tdt == NULL) { +		return; +	} + +	// done +	zap_ca_new_dvbtime(dvbdate_to_unixtime(tdt->utc_time)); +} + +static void process_pmt(int pmt_fd, struct zap_dvb_params *params) +{ +	int size; +	uint8_t sibuf[4096]; + +	// read the section +	if ((size = read(pmt_fd, sibuf, sizeof(sibuf))) < 0) { +		return; +	} + +	// parse section +	struct section *section = section_codec(sibuf, size); +	if (section == NULL) { +		return; +	} + +	// parse section_ext +	struct section_ext *section_ext = section_ext_decode(section, 0); +	if (section_ext == NULL) { +		return; +	} +	if ((section_ext->table_id_ext != params->channel.service_id) || +	    (section_ext->version_number == ca_pmt_version)) { +		return; +	} + +	// parse PMT +	struct mpeg_pmt_section *pmt = mpeg_pmt_section_codec(section_ext); +	if (pmt == NULL) { +		return; +	} + +	// do ca handling +	if (zap_ca_new_pmt(pmt) == 1) +		ca_pmt_version = pmt->head.version_number; +} + +static int create_section_filter(int adapter, int demux, uint16_t pid, uint8_t table_id) +{ +	int demux_fd = -1; +	uint8_t filter[18]; +	uint8_t mask[18]; + +	// open the demuxer +	if ((demux_fd = dvbdemux_open_demux(adapter, demux, 0)) < 0) { +		return -1; +	} + +	// create a section filter +	memset(filter, 0, sizeof(filter)); +	memset(mask, 0, sizeof(mask)); +	filter[0] = table_id; +	mask[0] = 0xFF; +	if (dvbdemux_set_section_filter(demux_fd, pid, filter, mask, 1, 1)) { +		close(demux_fd); +		return -1; +	} + +	// done +	return demux_fd; +} diff --git a/util/zap/zap_dvb.h b/util/zap/zap_dvb.h new file mode 100644 index 0000000..d2a219a --- /dev/null +++ b/util/zap/zap_dvb.h @@ -0,0 +1,41 @@ +/* +	ZAP utility DVB functions + +	Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com> +	Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net) + +	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 Lesser General Public License for more details. + +	You should have received a copy of the GNU Lesser General Public +	License along with this library; if not, write to the Free Software +	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA +*/ + +#ifndef ZAP_DVB_H +#define ZAP_DVB_H 1 + +#include <libdvbcfg/dvbcfg_zapchannel.h> +#include <libdvbsec/dvbsec_api.h> + +struct zap_dvb_params { +	int adapter_id; +	int frontend_id; +	int demux_id; +	struct dvbcfg_zapchannel channel; +	struct dvbsec_config sec; +	int valid_sec; +	struct dvbfe_handle *fe; +}; + +extern int zap_dvb_start(struct zap_dvb_params *params); +extern void zap_dvb_stop(void); + +#endif | 
