diff options
Diffstat (limited to 'util/zap')
-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 |