[linuxtv-dvb-apps] 09/30: Imported Upstream version 1.1.1

Tobias Grimm tiber-guest at alioth.debian.org
Tue Sep 3 07:51:57 UTC 2013


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to branch master
in repository linuxtv-dvb-apps.

commit 6b350466c4902c5b137e0efaf1d189128a7f18f5
Author: etobi <git at e-tobi.net>
Date:   Tue Sep 3 09:48:40 2013 +0200

    Imported Upstream version 1.1.1
---
 README                                             |    9 +-
 include/linux/dvb/frontend.h                       |  217 ++++-----
 util/dvbnet/dvbnet.c                               |    2 +-
 util/scan/Makefile                                 |    4 +-
 util/scan/atsc/us-ATSC-center-frequencies-8VSB     |   71 +++
 util/scan/atsc/us-CA-SF-Bay-Area                   |   16 +
 .../us-Cable-EIA-542-HRC-center-frequencies-QAM256 |  142 ++++++
 .../us-Cable-EIA-542-IRC-center_frequencies-QAM256 |  142 ++++++
 .../atsc/us-Cable-HRC-center-frequencies-QAM256    |  142 ++++++
 .../atsc/us-Cable-IRC-center-frequencies-QAM256    |  142 ++++++
 .../us-Cable-Standard-center-frequencies-QAM256    |  140 ++++++
 util/scan/atsc/us-ID-Boise                         |    8 +
 util/scan/atsc/us-MA-Boston                        |   13 +
 util/scan/atsc/us-MI-Lansing                       |    7 +
 util/scan/atsc/us-NTSC-center-frequencies-8VSB     |   71 +++
 util/scan/atsc/us-NY-TWC-NYC                       |   53 +++
 util/scan/atsc/us-PA-Philadelphia                  |   16 +
 util/scan/atsc_psip_section.c                      |   62 +++
 util/scan/atsc_psip_section.h                      |   60 +++
 util/scan/diseqc.c                                 |    2 +-
 util/scan/dump-vdr.c                               |   36 +-
 util/scan/dump-vdr.h                               |    1 +
 util/scan/dump-zap.c                               |   11 +-
 util/scan/lnb.c                                    |  108 +++++
 util/scan/lnb.h                                    |   24 +
 util/scan/scan.c                                   |  467 +++++++++++++++++---
 util/scan/section.c                                |   25 ++
 util/scan/section.h                                |   14 +
 util/szap/Makefile                                 |    4 +-
 util/szap/azap.c                                   |  392 ++++++++++++++++
 30 files changed, 2229 insertions(+), 172 deletions(-)

diff --git a/README b/README
index 190a4c4..aced028 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-linuxtv-dvb-apps-1.1.0
+linuxtv-dvb-apps-1.1.1
 ======================
 
 Linux DVB API test/demo applications and utilities.
@@ -19,3 +19,10 @@ the stuff in "DVB" is now unmaintained and out of date.
 
 
 Johannes Stezenbach <js at convergence.de>
+
+This is an interim point release adding support for ATSC to the 1.1.0 release.
+dvb-apps is currently being rewritten completely with new standardised DVB 
+libraries for all aspects of DVB, ca support etc, so expect a 1.2.0 release 
+at some point soon.
+
+Andrew de Quincey <adq_dvb at lidskialf.net>
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h
index 3fa118e..d41df70 100644
--- a/include/linux/dvb/frontend.h
+++ b/include/linux/dvb/frontend.h
@@ -2,10 +2,10 @@
  * frontend.h
  *
  * Copyright (C) 2000 Marcus Metzler <marcus at convergence.de>
- *                    Ralph  Metzler <ralph at convergence.de>
- *                    Holger Waechtler <holger at convergence.de>
- *                    Andre Draszik <ad at convergence.de>
- *                    for convergence integrated media GmbH
+ *		    Ralph  Metzler <ralph at convergence.de>
+ *		    Holger Waechtler <holger at convergence.de>
+ *		    Andre Draszik <ad at 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
@@ -30,52 +30,55 @@
 
 
 typedef enum fe_type {
-        FE_QPSK,
-        FE_QAM,
-        FE_OFDM
+	FE_QPSK,
+	FE_QAM,
+	FE_OFDM,
+	FE_ATSC
 } fe_type_t;
 
 
 typedef enum fe_caps {
-	FE_IS_STUPID                  = 0,
-	FE_CAN_INVERSION_AUTO         = 0x1,
-	FE_CAN_FEC_1_2                = 0x2,
-	FE_CAN_FEC_2_3                = 0x4,
-	FE_CAN_FEC_3_4                = 0x8,
-	FE_CAN_FEC_4_5                = 0x10,
-	FE_CAN_FEC_5_6                = 0x20,
-	FE_CAN_FEC_6_7                = 0x40,
-	FE_CAN_FEC_7_8                = 0x80,
-	FE_CAN_FEC_8_9                = 0x100,
-	FE_CAN_FEC_AUTO               = 0x200,
-	FE_CAN_QPSK                   = 0x400,
-	FE_CAN_QAM_16                 = 0x800,
-	FE_CAN_QAM_32                 = 0x1000,
-	FE_CAN_QAM_64                 = 0x2000,
-	FE_CAN_QAM_128                = 0x4000,
-	FE_CAN_QAM_256                = 0x8000,
-	FE_CAN_QAM_AUTO               = 0x10000,
-	FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000,
-	FE_CAN_BANDWIDTH_AUTO         = 0x40000,
-	FE_CAN_GUARD_INTERVAL_AUTO    = 0x80000,
-	FE_CAN_HIERARCHY_AUTO         = 0x100000,
-	FE_CAN_RECOVER                = 0x20000000,
-	FE_CAN_CLEAN_SETUP            = 0x40000000,
-	FE_CAN_MUTE_TS                = 0x80000000
+	FE_IS_STUPID			= 0,
+	FE_CAN_INVERSION_AUTO		= 0x1,
+	FE_CAN_FEC_1_2			= 0x2,
+	FE_CAN_FEC_2_3			= 0x4,
+	FE_CAN_FEC_3_4			= 0x8,
+	FE_CAN_FEC_4_5			= 0x10,
+	FE_CAN_FEC_5_6			= 0x20,
+	FE_CAN_FEC_6_7			= 0x40,
+	FE_CAN_FEC_7_8			= 0x80,
+	FE_CAN_FEC_8_9			= 0x100,
+	FE_CAN_FEC_AUTO			= 0x200,
+	FE_CAN_QPSK			= 0x400,
+	FE_CAN_QAM_16			= 0x800,
+	FE_CAN_QAM_32			= 0x1000,
+	FE_CAN_QAM_64			= 0x2000,
+	FE_CAN_QAM_128			= 0x4000,
+	FE_CAN_QAM_256			= 0x8000,
+	FE_CAN_QAM_AUTO			= 0x10000,
+	FE_CAN_TRANSMISSION_MODE_AUTO	= 0x20000,
+	FE_CAN_BANDWIDTH_AUTO		= 0x40000,
+	FE_CAN_GUARD_INTERVAL_AUTO	= 0x80000,
+	FE_CAN_HIERARCHY_AUTO		= 0x100000,
+	FE_CAN_8VSB			= 0x200000,
+	FE_CAN_16VSB			= 0x400000,
+	FE_NEEDS_BENDING		= 0x20000000, // not supported anymore, don't use (frontend requires frequency bending)
+	FE_CAN_RECOVER			= 0x40000000, // frontend can recover from a cable unplug automatically
+	FE_CAN_MUTE_TS			= 0x80000000  // frontend can stop spurious TS data output
 } fe_caps_t;
 
 
 struct dvb_frontend_info {
 	char       name[128];
-        fe_type_t  type;
-        __u32      frequency_min;
-        __u32      frequency_max;
+	fe_type_t  type;
+	__u32      frequency_min;
+	__u32      frequency_max;
 	__u32      frequency_stepsize;
 	__u32      frequency_tolerance;
 	__u32      symbol_rate_min;
-        __u32      symbol_rate_max;
-	__u32      symbol_rate_tolerance;     /* ppm */
-	__u32      notifier_delay;            /* ms */
+	__u32      symbol_rate_max;
+	__u32      symbol_rate_tolerance;	/* ppm */
+	__u32      notifier_delay;		/* DEPRECATED */
 	fe_caps_t  caps;
 };
 
@@ -85,80 +88,81 @@ struct dvb_frontend_info {
  *  the meaning of this struct...
  */
 struct dvb_diseqc_master_cmd {
-        __u8 msg [6];        /*  { framing, address, command, data [3] } */
-        __u8 msg_len;        /*  valid values are 3...6  */
+	__u8 msg [6];	/*  { framing, address, command, data [3] } */
+	__u8 msg_len;	/*  valid values are 3...6  */
 };
 
 
 struct dvb_diseqc_slave_reply {
-	__u8 msg [4];        /*  { framing, data [3] } */
-	__u8 msg_len;        /*  valid values are 0...4, 0 means no msg  */
-	int  timeout;        /*  return from ioctl after timeout ms with */
-};                           /*  errorcode when no message was received  */
+	__u8 msg [4];	/*  { framing, data [3] } */
+	__u8 msg_len;	/*  valid values are 0...4, 0 means no msg  */
+	int  timeout;	/*  return from ioctl after timeout ms with */
+};			/*  errorcode when no message was received  */
 
 
 typedef enum fe_sec_voltage {
-        SEC_VOLTAGE_13,
-        SEC_VOLTAGE_18,
+	SEC_VOLTAGE_13,
+	SEC_VOLTAGE_18,
 	SEC_VOLTAGE_OFF
 } fe_sec_voltage_t;
 
 
 typedef enum fe_sec_tone_mode {
-        SEC_TONE_ON,
-        SEC_TONE_OFF
+	SEC_TONE_ON,
+	SEC_TONE_OFF
 } fe_sec_tone_mode_t;
 
 
 typedef enum fe_sec_mini_cmd {
-        SEC_MINI_A,
-        SEC_MINI_B
+	SEC_MINI_A,
+	SEC_MINI_B
 } fe_sec_mini_cmd_t;
 
 
 typedef enum fe_status {
-	FE_HAS_SIGNAL     = 0x01,   /*  found something above the noise level */
-	FE_HAS_CARRIER    = 0x02,   /*  found a DVB signal  */
-	FE_HAS_VITERBI    = 0x04,   /*  FEC is stable  */
-	FE_HAS_SYNC       = 0x08,   /*  found sync bytes  */
-	FE_HAS_LOCK       = 0x10,   /*  everything's working... */
-	FE_TIMEDOUT       = 0x20,   /*  no lock within the last ~2 seconds */
-	FE_REINIT         = 0x40    /*  frontend was reinitialized,  */
-} fe_status_t;                      /*  application is recommended to reset */
-                                    /*  DiSEqC, tone and parameters */
+	FE_HAS_SIGNAL	= 0x01,   /*  found something above the noise level */
+	FE_HAS_CARRIER	= 0x02,   /*  found a DVB signal  */
+	FE_HAS_VITERBI	= 0x04,   /*  FEC is stable  */
+	FE_HAS_SYNC	= 0x08,   /*  found sync bytes  */
+	FE_HAS_LOCK	= 0x10,   /*  everything's working... */
+	FE_TIMEDOUT	= 0x20,   /*  no lock within the last ~2 seconds */
+	FE_REINIT	= 0x40    /*  frontend was reinitialized,  */
+} fe_status_t;			  /*  application is recommended to reset */
+				  /*  DiSEqC, tone and parameters */
 
 typedef enum fe_spectral_inversion {
-        INVERSION_OFF,
-        INVERSION_ON,
-        INVERSION_AUTO
+	INVERSION_OFF,
+	INVERSION_ON,
+	INVERSION_AUTO
 } fe_spectral_inversion_t;
 
 
 typedef enum fe_code_rate {
-        FEC_NONE = 0,
-        FEC_1_2,
-        FEC_2_3,
-        FEC_3_4,
-        FEC_4_5,
-        FEC_5_6,
-        FEC_6_7,
-        FEC_7_8,
-        FEC_8_9,
-        FEC_AUTO
+	FEC_NONE = 0,
+	FEC_1_2,
+	FEC_2_3,
+	FEC_3_4,
+	FEC_4_5,
+	FEC_5_6,
+	FEC_6_7,
+	FEC_7_8,
+	FEC_8_9,
+	FEC_AUTO
 } fe_code_rate_t;
 
 
 typedef enum fe_modulation {
-        QPSK,
-        QAM_16,
-        QAM_32,
-        QAM_64,
-        QAM_128,
-        QAM_256,
-	QAM_AUTO
+	QPSK,
+	QAM_16,
+	QAM_32,
+	QAM_64,
+	QAM_128,
+	QAM_256,
+	QAM_AUTO,
+	VSB_8,
+	VSB_16
 } fe_modulation_t;
 
-
 typedef enum fe_transmit_mode {
 	TRANSMISSION_MODE_2K,
 	TRANSMISSION_MODE_8K,
@@ -192,37 +196,40 @@ typedef enum fe_hierarchy {
 
 
 struct dvb_qpsk_parameters {
-        __u32           symbol_rate;  /* symbol rate in Symbols per second */
-        fe_code_rate_t  fec_inner;    /* forward error correction (see above) */
+	__u32		symbol_rate;  /* symbol rate in Symbols per second */
+	fe_code_rate_t	fec_inner;    /* forward error correction (see above) */
 };
 
-
 struct dvb_qam_parameters {
-        __u32            symbol_rate; /* symbol rate in Symbols per second */
-        fe_code_rate_t   fec_inner;   /* forward error correction (see above) */
-        fe_modulation_t  modulation;  /* modulation type (see above) */
+	__u32		symbol_rate; /* symbol rate in Symbols per second */
+	fe_code_rate_t	fec_inner;   /* forward error correction (see above) */
+	fe_modulation_t	modulation;  /* modulation type (see above) */
 };
 
+struct dvb_vsb_parameters {
+	fe_modulation_t	modulation;  /* modulation type (see above) */
+};
 
 struct dvb_ofdm_parameters {
-        fe_bandwidth_t      bandwidth;
-        fe_code_rate_t      code_rate_HP;  /* high priority stream code rate */
-        fe_code_rate_t      code_rate_LP;  /* low priority stream code rate */
-        fe_modulation_t     constellation; /* modulation type (see above) */
-        fe_transmit_mode_t  transmission_mode;
-        fe_guard_interval_t guard_interval;
-        fe_hierarchy_t      hierarchy_information;
+	fe_bandwidth_t      bandwidth;
+	fe_code_rate_t      code_rate_HP;  /* high priority stream code rate */
+	fe_code_rate_t      code_rate_LP;  /* low priority stream code rate */
+	fe_modulation_t     constellation; /* modulation type (see above) */
+	fe_transmit_mode_t  transmission_mode;
+	fe_guard_interval_t guard_interval;
+	fe_hierarchy_t      hierarchy_information;
 };
 
 
 struct dvb_frontend_parameters {
-        __u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM */
-                             /* intermediate frequency in kHz for QPSK */
+	__u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
+			     /* intermediate frequency in kHz for QPSK */
 	fe_spectral_inversion_t inversion;
 	union {
 		struct dvb_qpsk_parameters qpsk;
 		struct dvb_qam_parameters  qam;
 		struct dvb_ofdm_parameters ofdm;
+		struct dvb_vsb_parameters vsb;
 	} u;
 };
 
@@ -234,27 +241,27 @@ struct dvb_frontend_event {
 
 
 
-#define FE_GET_INFO                _IOR('o', 61, struct dvb_frontend_info)
+#define FE_GET_INFO		   _IOR('o', 61, struct dvb_frontend_info)
 
 #define FE_DISEQC_RESET_OVERLOAD   _IO('o', 62)
 #define FE_DISEQC_SEND_MASTER_CMD  _IOW('o', 63, struct dvb_diseqc_master_cmd)
 #define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply)
 #define FE_DISEQC_SEND_BURST       _IO('o', 65)  /* fe_sec_mini_cmd_t */
 
-#define FE_SET_TONE                _IO('o', 66)  /* fe_sec_tone_mode_t */
-#define FE_SET_VOLTAGE             _IO('o', 67)  /* fe_sec_voltage_t */
+#define FE_SET_TONE		   _IO('o', 66)  /* fe_sec_tone_mode_t */
+#define FE_SET_VOLTAGE		   _IO('o', 67)  /* fe_sec_voltage_t */
 #define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68)  /* int */
 
-#define FE_READ_STATUS             _IOR('o', 69, fe_status_t)
-#define FE_READ_BER                _IOR('o', 70, __u32)
+#define FE_READ_STATUS		   _IOR('o', 69, fe_status_t)
+#define FE_READ_BER		   _IOR('o', 70, __u32)
 #define FE_READ_SIGNAL_STRENGTH    _IOR('o', 71, __u16)
-#define FE_READ_SNR                _IOR('o', 72, __u16)
+#define FE_READ_SNR		   _IOR('o', 72, __u16)
 #define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
 
-#define FE_SET_FRONTEND            _IOW('o', 76, struct dvb_frontend_parameters)
-#define FE_GET_FRONTEND            _IOR('o', 77, struct dvb_frontend_parameters)
-#define FE_GET_EVENT               _IOR('o', 78, struct dvb_frontend_event)
+#define FE_SET_FRONTEND		   _IOW('o', 76, struct dvb_frontend_parameters)
+#define FE_GET_FRONTEND		   _IOR('o', 77, struct dvb_frontend_parameters)
+#define FE_GET_EVENT		   _IOR('o', 78, struct dvb_frontend_event)
 
+#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
 
 #endif /*_DVBFRONTEND_H_*/
-
diff --git a/util/dvbnet/dvbnet.c b/util/dvbnet/dvbnet.c
index 573fa59..a58f156 100644
--- a/util/dvbnet/dvbnet.c
+++ b/util/dvbnet/dvbnet.c
@@ -38,7 +38,7 @@
 #include <version.h>
 
 #ifndef VERSION_INFO
-#define VERSION_INFO "1.1.0"
+#define VERSION_INFO "1.1.1"
 #endif
 
 #define OK    0
diff --git a/util/scan/Makefile b/util/scan/Makefile
index a82d865..4b29842 100644
--- a/util/scan/Makefile
+++ b/util/scan/Makefile
@@ -1,9 +1,9 @@
 
 CC = gcc
-CFLAGS = -MD -g -Wall -O2 -I../../include -I../lib
+CFLAGS = -MD -g -Wall -O2 -I../../include
 LFLAGS = -g -Wall
 
-OBJS = diseqc.o dump-zap.o dump-vdr.o scan.o ../lib/lnb.o
+OBJS = diseqc.o dump-zap.o dump-vdr.o scan.o lnb.o section.o atsc_psip_section.o
 SRCS = $(OBJS:.o=.c)
 
 TARGET = scan
diff --git a/util/scan/atsc/us-ATSC-center-frequencies-8VSB b/util/scan/atsc/us-ATSC-center-frequencies-8VSB
new file mode 100644
index 0000000..ffd0b02
--- /dev/null
+++ b/util/scan/atsc/us-ATSC-center-frequencies-8VSB
@@ -0,0 +1,71 @@
+# US ATSC center frequencies, use if in doubt
+
+A  57028615 8VSB
+A  63028615 8VSB
+A  69028615 8VSB
+A  79028615 8VSB
+A  85028615 8VSB
+A 177028615 8VSB
+A 183028615 8VSB
+A 189028615 8VSB
+A 195028615 8VSB
+A 201028615 8VSB
+A 207028615 8VSB
+A 213028615 8VSB
+A 473028615 8VSB
+A 479028615 8VSB
+A 485028615 8VSB
+A 491028615 8VSB
+A 497028615 8VSB
+A 503028615 8VSB
+A 509028615 8VSB
+A 515028615 8VSB
+A 521028615 8VSB
+A 527028615 8VSB
+A 533028615 8VSB
+A 539028615 8VSB
+A 545028615 8VSB
+A 551028615 8VSB
+A 557028615 8VSB
+A 563028615 8VSB
+A 569028615 8VSB
+A 575028615 8VSB
+A 581028615 8VSB
+A 587028615 8VSB
+A 593028615 8VSB
+A 599028615 8VSB
+A 605028615 8VSB
+A 611028615 8VSB
+A 617028615 8VSB
+A 623028615 8VSB
+A 629028615 8VSB
+A 635028615 8VSB
+A 641028615 8VSB
+A 647028615 8VSB
+A 653028615 8VSB
+A 659028615 8VSB
+A 665028615 8VSB
+A 671028615 8VSB
+A 677028615 8VSB
+A 683028615 8VSB
+A 689028615 8VSB
+A 695028615 8VSB
+A 701028615 8VSB
+A 707028615 8VSB
+A 713028615 8VSB
+A 719028615 8VSB
+A 725028615 8VSB
+A 731028615 8VSB
+A 737028615 8VSB
+A 743028615 8VSB
+A 749028615 8VSB
+A 755028615 8VSB
+A 761028615 8VSB
+A 767028615 8VSB
+A 773028615 8VSB
+A 779028615 8VSB
+A 785028615 8VSB
+A 791028615 8VSB
+A 797028615 8VSB
+A 803028615 8VSB
+
diff --git a/util/scan/atsc/us-CA-SF-Bay-Area b/util/scan/atsc/us-CA-SF-Bay-Area
new file mode 100644
index 0000000..8cca4e0
--- /dev/null
+++ b/util/scan/atsc/us-CA-SF-Bay-Area
@@ -0,0 +1,16 @@
+# initial tuning data for some frequencies of for the San Francisco Bay Area
+# includes San Francisco, San Jose, Oakland...
+
+A 503000000 8VSB
+A 551000000 8VSB
+A 563000000 8VSB
+A 593000000 8VSB
+A 623000000 8VSB
+A 635000000 8VSB
+A 647000000 8VSB
+A 659000000 8VSB
+A 683000000 8VSB
+A 689000000 8VSB
+A 701000000 8VSB
+A 725000000 8VSB
+A 731000000 8VSB
diff --git a/util/scan/atsc/us-Cable-EIA-542-HRC-center-frequencies-QAM256 b/util/scan/atsc/us-Cable-EIA-542-HRC-center-frequencies-QAM256
new file mode 100644
index 0000000..c0afed9
--- /dev/null
+++ b/util/scan/atsc/us-Cable-EIA-542-HRC-center-frequencies-QAM256
@@ -0,0 +1,142 @@
+# US EIA-542 Cable center frequencies
+# Harmonically Related Carriers (HRC)
+# Channels 1 to 125 are in ascending EIA/NCTA channel designation order
+
+#1
+A  73753600 QAM256
+A  55752700 QAM256
+A  61753000 QAM256
+A  67753300 QAM256
+A  77753900 QAM256
+A  83754200 QAM256
+A 175758700 QAM256
+A 181759000 QAM256
+A 187759300 QAM256
+#10
+A 193759600 QAM256
+A 199759900 QAM256
+A 205760200 QAM256
+A 211760500 QAM256
+A 121756000 QAM256
+A 127756300 QAM256
+A 133756600 QAM256
+A 139756900 QAM256
+A 145757200 QAM256
+A 151757500 QAM256
+#20
+A 157757800 QAM256
+A 163758100 QAM256
+A 169758400 QAM256
+A 217760800 QAM256
+A 223761100 QAM256
+A 229761400 QAM256
+A 235761700 QAM256
+A 241762000 QAM256
+A 247762300 QAM256
+A 253762600 QAM256
+#30
+A 259762900 QAM256
+A 265763200 QAM256
+A 271763500 QAM256
+A 277763800 QAM256
+A 283764100 QAM256
+A 289764400 QAM256
+A 295764700 QAM256
+A 301765000 QAM256
+A 307765300 QAM256
+A 313765600 QAM256
+#40
+A 319765900 QAM256
+A 325766200 QAM256
+A 331766500 QAM256
+A 337766800 QAM256
+A 343767100 QAM256
+A 349767400 QAM256
+A 355767700 QAM256
+A 361768000 QAM256
+A 367768300 QAM256
+A 373768600 QAM256
+#50
+A 379768900 QAM256
+A 385769200 QAM256
+A 391769500 QAM256
+A 397769800 QAM256
+A 403770100 QAM256
+A 409770400 QAM256
+A 415770700 QAM256
+A 421771000 QAM256
+A 427771300 QAM256
+A 433771600 QAM256
+#60
+A 439771900 QAM256
+A 445772200 QAM256
+A 451772500 QAM256
+A 457772800 QAM256
+A 463773100 QAM256
+A 469773400 QAM256
+A 475773700 QAM256
+A 481774000 QAM256
+A 487774300 QAM256
+A 493774600 QAM256
+#70
+A 499774900 QAM256
+A 505775200 QAM256
+A 511775500 QAM256
+A 517775800 QAM256
+A 523776100 QAM256
+A 529776400 QAM256
+A 535776700 QAM256
+A 541777000 QAM256
+A 547777300 QAM256
+A 553777600 QAM256
+#80
+A 559777900 QAM256
+A 565778200 QAM256
+A 571778500 QAM256
+A 577778800 QAM256
+A 583779100 QAM256
+A 589779400 QAM256
+A 595779700 QAM256
+A 601780000 QAM256
+A 607780300 QAM256
+A 613780600 QAM256
+#90
+A 619780900 QAM256
+A 625781200 QAM256
+A 631781500 QAM256
+A 637781800 QAM256
+A 643782100 QAM256
+A  91754500 QAM256
+A  97754800 QAM256
+A 103755100 QAM256
+A 109775000 QAM256
+A 115775000 QAM256
+#100
+A 649782400 QAM256
+A 655782700 QAM256
+A 661783000 QAM256
+A 667783300 QAM256
+A 673783600 QAM256
+A 679783900 QAM256
+A 685784200 QAM256
+A 691784500 QAM256
+A 697784800 QAM256
+A 703785100 QAM256
+#110
+A 709785400 QAM256
+A 715785700 QAM256
+A 721786000 QAM256
+A 727786300 QAM256
+A 733786600 QAM256
+A 739786900 QAM256
+A 745787200 QAM256
+A 751787500 QAM256
+A 757787800 QAM256
+A 763788100 QAM256
+#120
+A 769788400 QAM256
+A 775788700 QAM256
+A 781789000 QAM256
+A 787789300 QAM256
+A 793789600 QAM256
+A 799789900 QAM256
diff --git a/util/scan/atsc/us-Cable-EIA-542-IRC-center_frequencies-QAM256 b/util/scan/atsc/us-Cable-EIA-542-IRC-center_frequencies-QAM256
new file mode 100644
index 0000000..f18d5e5
--- /dev/null
+++ b/util/scan/atsc/us-Cable-EIA-542-IRC-center_frequencies-QAM256
@@ -0,0 +1,142 @@
+# US Cable EIA-542 center frequencies
+# Incrementally Related Carriers (IRC)
+# Channels 1-125 are in ascending EIA/NCTA channel designation order
+
+#1
+A  75012500 QAM256
+A  57025000 QAM256
+A  63012500 QAM256
+A  69012500 QAM256
+A  79012500 QAM256
+A  85012500 QAM256
+A 177012500 QAM256
+A 183012500 QAM256
+A 189012500 QAM256
+#10
+A 195012500 QAM256
+A 201012500 QAM256
+A 207012500 QAM256
+A 213012500 QAM256
+A 123012500 QAM256
+A 129012500 QAM256
+A 135012500 QAM256
+A 141012500 QAM256
+A 147012500 QAM256
+A 153012500 QAM256
+#20
+A 159012500 QAM256
+A 165012500 QAM256
+A 171012500 QAM256
+A 219012500 QAM256
+A 225012500 QAM256
+A 231012500 QAM256
+A 237012500 QAM256
+A 243012500 QAM256
+A 249012500 QAM256
+A 255012500 QAM256
+#30
+A 261012500 QAM256
+A 267012500 QAM256
+A 273012500 QAM256
+A 279012500 QAM256
+A 285012500 QAM256
+A 291012500 QAM256
+A 297012500 QAM256
+A 303012500 QAM256
+A 309012500 QAM256
+A 315012500 QAM256
+#40
+A 321012500 QAM256
+A 327012500 QAM256
+A 333025000 QAM256
+A 339012500 QAM256
+A 345012500 QAM256
+A 351012500 QAM256
+A 357012500 QAM256
+A 363012500 QAM256
+A 369012500 QAM256
+A 375012500 QAM256
+#50
+A 381012500 QAM256
+A 387012500 QAM256
+A 393012500 QAM256
+A 399012500 QAM256
+A 405012500 QAM256
+A 411012500 QAM256
+A 417012500 QAM256
+A 423012500 QAM256
+A 429012500 QAM256
+A 435012500 QAM256
+#60
+A 441012500 QAM256
+A 447012500 QAM256
+A 453012500 QAM256
+A 459012500 QAM256
+A 465012500 QAM256
+A 471012500 QAM256
+A 477012500 QAM256
+A 483012500 QAM256
+A 489012500 QAM256
+A 495012500 QAM256
+#70
+A 501012500 QAM256
+A 507012500 QAM256
+A 513012500 QAM256
+A 519012500 QAM256
+A 525012500 QAM256
+A 531012500 QAM256
+A 537012500 QAM256
+A 543012500 QAM256
+A 549012500 QAM256
+A 555012500 QAM256
+#80
+A 561012500 QAM256
+A 567012500 QAM256
+A 573012500 QAM256
+A 579012500 QAM256
+A 585012500 QAM256
+A 591012500 QAM256
+A 597012500 QAM256
+A 603012500 QAM256
+A 609012500 QAM256
+A 615012500 QAM256
+#90
+A 621012500 QAM256
+A 627012500 QAM256
+A 633012500 QAM256
+A 639012500 QAM256
+A 645012500 QAM256
+A  93012500 QAM256
+A  99012500 QAM256
+A 105012500 QAM256
+A 111012500 QAM256
+A 117012500 QAM256
+#100
+A 651012500 QAM256
+A 657012500 QAM256
+A 663012500 QAM256
+A 669012500 QAM256
+A 675012500 QAM256
+A 681012500 QAM256
+A 687012500 QAM256
+A 693012500 QAM256
+A 699012500 QAM256
+A 705012500 QAM256
+#110
+A 711012500 QAM256
+A 717012500 QAM256
+A 723012500 QAM256
+A 729012500 QAM256
+A 735012500 QAM256
+A 741012500 QAM256
+A 747012500 QAM256
+A 753012500 QAM256
+A 759012500 QAM256
+A 765012500 QAM256
+#120
+A 771012500 QAM256
+A 777012500 QAM256
+A 783012500 QAM256
+A 789012500 QAM256
+A 795012500 QAM256
+A 801012500 QAM256
diff --git a/util/scan/atsc/us-Cable-HRC-center-frequencies-QAM256 b/util/scan/atsc/us-Cable-HRC-center-frequencies-QAM256
new file mode 100644
index 0000000..2bc3838
--- /dev/null
+++ b/util/scan/atsc/us-Cable-HRC-center-frequencies-QAM256
@@ -0,0 +1,142 @@
+# US Cable center frequencies
+# Harmonically Related Carriers (HRC)
+# Channels are in ascending EIA/NCTA channel designation order
+
+#1
+A  73753600 QAM256
+A  55752700 QAM256
+A  61753000 QAM256
+A  67753300 QAM256
+A  77753900 QAM256
+A  83754200 QAM256
+A 175758700 QAM256
+A 181759000 QAM256
+A 187759300 QAM256
+#10
+A 193759600 QAM256
+A 199759900 QAM256
+A 205760200 QAM256
+A 211760500 QAM256
+A 121756000 QAM256
+A 127756300 QAM256
+A 133756600 QAM256
+A 139756900 QAM256
+A 145757200 QAM256
+A 151757500 QAM256
+#20
+A 157757800 QAM256
+A 163758100 QAM256
+A 169758400 QAM256
+A 217760800 QAM256
+A 223761100 QAM256
+A 229761400 QAM256
+A 235761700 QAM256
+A 241762000 QAM256
+A 247762300 QAM256
+A 253762600 QAM256
+#30
+A 259762900 QAM256
+A 265763200 QAM256
+A 271763500 QAM256
+A 277763800 QAM256
+A 283764100 QAM256
+A 289764400 QAM256
+A 295764700 QAM256
+A 301765000 QAM256
+A 307765300 QAM256
+A 313765600 QAM256
+#40
+A 319765900 QAM256
+A 325766200 QAM256
+A 331766500 QAM256
+A 337766800 QAM256
+A 343767100 QAM256
+A 349767400 QAM256
+A 355767700 QAM256
+A 361768000 QAM256
+A 367768300 QAM256
+A 373768600 QAM256
+#50
+A 379768900 QAM256
+A 385769200 QAM256
+A 391769500 QAM256
+A 397769800 QAM256
+A 403770100 QAM256
+A 409770400 QAM256
+A 415770700 QAM256
+A 421771000 QAM256
+A 427771300 QAM256
+A 433771600 QAM256
+#60
+A 439771900 QAM256
+A 445772200 QAM256
+A 451772500 QAM256
+A 457772800 QAM256
+A 463773100 QAM256
+A 469773400 QAM256
+A 475773700 QAM256
+A 481774000 QAM256
+A 487774300 QAM256
+A 493774600 QAM256
+#70
+A 499774900 QAM256
+A 505775200 QAM256
+A 511775500 QAM256
+A 517775800 QAM256
+A 523776100 QAM256
+A 529776400 QAM256
+A 535776700 QAM256
+A 541777000 QAM256
+A 547777300 QAM256
+A 553777600 QAM256
+#80
+A 559777900 QAM256
+A 565778200 QAM256
+A 571778500 QAM256
+A 577778800 QAM256
+A 583779100 QAM256
+A 589779400 QAM256
+A 595779700 QAM256
+A 601780000 QAM256
+A 607780300 QAM256
+A 613780600 QAM256
+#90
+A 619780900 QAM256
+A 625781200 QAM256
+A 631781500 QAM256
+A 637781800 QAM256
+A 643782100 QAM256
+A  91754500 QAM256
+A  97754800 QAM256
+A 103755100 QAM256
+A 109755400 QAM256
+A 115755700 QAM256
+#100
+A 649782400 QAM256
+A 655782700 QAM256
+A 661783000 QAM256
+A 667783300 QAM256
+A 673783600 QAM256
+A 679783900 QAM256
+A 685784200 QAM256
+A 691784500 QAM256
+A 697784800 QAM256
+A 703785100 QAM256
+#110
+A 709785400 QAM256
+A 715785700 QAM256
+A 721786000 QAM256
+A 727786300 QAM256
+A 733786600 QAM256
+A 739786900 QAM256
+A 745787200 QAM256
+A 751787500 QAM256
+A 757787800 QAM256
+A 763788100 QAM256
+#120
+A 769788400 QAM256
+A 775788700 QAM256
+A 781789000 QAM256
+A 787789300 QAM256
+A 793789600 QAM256
+A 799789900 QAM256
diff --git a/util/scan/atsc/us-Cable-IRC-center-frequencies-QAM256 b/util/scan/atsc/us-Cable-IRC-center-frequencies-QAM256
new file mode 100644
index 0000000..72842e0
--- /dev/null
+++ b/util/scan/atsc/us-Cable-IRC-center-frequencies-QAM256
@@ -0,0 +1,142 @@
+# US Cable center frequencies
+# Incrementally Related Carriers (IRC)
+# Channels are in ascending EIA/NCTA channel designation order
+
+#1
+A  75000000 QAM256
+A  57000000 QAM256
+A  63000000 QAM256
+A  69000000 QAM256
+A  79000000 QAM256
+A  85000000 QAM256
+A 177000000 QAM256
+A 183000000 QAM256
+A 189000000 QAM256
+#10
+A 195000000 QAM256
+A 201000000 QAM256
+A 207000000 QAM256
+A 213000000 QAM256
+A 123000000 QAM256
+A 129000000 QAM256
+A 135000000 QAM256
+A 141000000 QAM256
+A 147000000 QAM256
+A 153000000 QAM256
+#20
+A 159000000 QAM256
+A 165000000 QAM256
+A 171000000 QAM256
+A 219000000 QAM256
+A 225000000 QAM256
+A 231000000 QAM256
+A 237000000 QAM256
+A 243000000 QAM256
+A 249000000 QAM256
+A 255000000 QAM256
+#30
+A 261000000 QAM256
+A 267000000 QAM256
+A 273000000 QAM256
+A 279000000 QAM256
+A 285000000 QAM256
+A 291000000 QAM256
+A 297000000 QAM256
+A 303000000 QAM256
+A 309000000 QAM256
+A 315000000 QAM256
+#40
+A 321000000 QAM256
+A 327000000 QAM256
+A 333000000 QAM256
+A 339000000 QAM256
+A 345000000 QAM256
+A 351000000 QAM256
+A 357000000 QAM256
+A 363000000 QAM256
+A 369000000 QAM256
+A 375000000 QAM256
+#50
+A 381000000 QAM256
+A 387000000 QAM256
+A 393000000 QAM256
+A 399000000 QAM256
+A 405000000 QAM256
+A 411000000 QAM256
+A 417000000 QAM256
+A 423000000 QAM256
+A 429000000 QAM256
+A 435000000 QAM256
+#60
+A 441000000 QAM256
+A 447000000 QAM256
+A 453000000 QAM256
+A 459000000 QAM256
+A 465000000 QAM256
+A 471000000 QAM256
+A 477000000 QAM256
+A 483000000 QAM256
+A 489000000 QAM256
+A 495000000 QAM256
+#70
+A 501000000 QAM256
+A 507000000 QAM256
+A 513000000 QAM256
+A 519000000 QAM256
+A 525000000 QAM256
+A 531000000 QAM256
+A 537000000 QAM256
+A 543000000 QAM256
+A 549000000 QAM256
+A 555000000 QAM256
+#80
+A 561000000 QAM256
+A 567000000 QAM256
+A 573000000 QAM256
+A 579000000 QAM256
+A 585000000 QAM256
+A 591000000 QAM256
+A 597000000 QAM256
+A 603000000 QAM256
+A 609000000 QAM256
+A 615000000 QAM256
+#90
+A 621000000 QAM256
+A 627000000 QAM256
+A 633000000 QAM256
+A 639000000 QAM256
+A 645000000 QAM256
+A  93000000 QAM256
+A  99000000 QAM256
+A 105000000 QAM256
+A 111000000 QAM256
+A 117000000 QAM256
+#100
+A 651000000 QAM256
+A 657000000 QAM256
+A 663000000 QAM256
+A 669000000 QAM256
+A 675000000 QAM256
+A 681000000 QAM256
+A 687000000 QAM256
+A 693000000 QAM256
+A 699000000 QAM256
+A 705000000 QAM256
+#110
+A 711000000 QAM256
+A 717000000 QAM256
+A 723000000 QAM256
+A 729000000 QAM256
+A 735000000 QAM256
+A 741000000 QAM256
+A 747000000 QAM256
+A 753000000 QAM256
+A 759000000 QAM256
+A 765000000 QAM256
+#120
+A 771000000 QAM256
+A 777000000 QAM256
+A 783000000 QAM256
+A 789000000 QAM256
+A 795000000 QAM256
+A 801000000 QAM256
diff --git a/util/scan/atsc/us-Cable-Standard-center-frequencies-QAM256 b/util/scan/atsc/us-Cable-Standard-center-frequencies-QAM256
new file mode 100644
index 0000000..4367e7a
--- /dev/null
+++ b/util/scan/atsc/us-Cable-Standard-center-frequencies-QAM256
@@ -0,0 +1,140 @@
+# US EIA/NCTA Standard Cable center frequencies
+# Channels are in ascending EIA/NCTA channel designation order
+
+#2
+A  57000000 QAM256
+A  63000000 QAM256
+A  69000000 QAM256
+A  79000000 QAM256
+A  85000000 QAM256
+A 177000000 QAM256
+A 183000000 QAM256
+A 189000000 QAM256
+#10
+A 195000000 QAM256
+A 201000000 QAM256
+A 207000000 QAM256
+A 213000000 QAM256
+A 123012500 QAM256
+A 129012500 QAM256
+A 135012500 QAM256
+A 141000000 QAM256
+A 147000000 QAM256
+A 153000000 QAM256
+#20
+A 159000000 QAM256
+A 165000000 QAM256
+A 171000000 QAM256
+A 219000000 QAM256
+A 225000000 QAM256
+A 231012500 QAM256
+A 237012500 QAM256
+A 243012500 QAM256
+A 249012500 QAM256
+A 255012500 QAM256
+#30
+A 261012500 QAM256
+A 267012500 QAM256
+A 273012500 QAM256
+A 279012500 QAM256
+A 285012500 QAM256
+A 291012500 QAM256
+A 297012500 QAM256
+A 303012500 QAM256
+A 309012500 QAM256
+A 315012500 QAM256
+#40
+A 321012500 QAM256
+A 327012500 QAM256
+A 333025000 QAM256
+A 339012500 QAM256
+A 345012500 QAM256
+A 351012500 QAM256
+A 357012500 QAM256
+A 363012500 QAM256
+A 369012500 QAM256
+A 375012500 QAM256
+#50
+A 381012500 QAM256
+A 387012500 QAM256
+A 393012500 QAM256
+A 399012500 QAM256
+A 405000000 QAM256
+A 411000000 QAM256
+A 417000000 QAM256
+A 423000000 QAM256
+A 429000000 QAM256
+A 435000000 QAM256
+#60
+A 441000000 QAM256
+A 447000000 QAM256
+A 453000000 QAM256
+A 459000000 QAM256
+A 465000000 QAM256
+A 471000000 QAM256
+A 477000000 QAM256
+A 483000000 QAM256
+A 489000000 QAM256
+A 495000000 QAM256
+#70
+A 501000000 QAM256
+A 507000000 QAM256
+A 513000000 QAM256
+A 519000000 QAM256
+A 525000000 QAM256
+A 531000000 QAM256
+A 537000000 QAM256
+A 543000000 QAM256
+A 549000000 QAM256
+A 555000000 QAM256
+#80
+A 561000000 QAM256
+A 567000000 QAM256
+A 573000000 QAM256
+A 579000000 QAM256
+A 585000000 QAM256
+A 591000000 QAM256
+A 597000000 QAM256
+A 603000000 QAM256
+A 609000000 QAM256
+A 615000000 QAM256
+#90
+A 621000000 QAM256
+A 627000000 QAM256
+A 633000000 QAM256
+A 639000000 QAM256
+A 645000000 QAM256
+A  93000000 QAM256
+A  99000000 QAM256
+A 105000000 QAM256
+A 111025000 QAM256
+A 117025000 QAM256
+#100
+A 651000000 QAM256
+A 657000000 QAM256
+A 663000000 QAM256
+A 669000000 QAM256
+A 675000000 QAM256
+A 681000000 QAM256
+A 687000000 QAM256
+A 693000000 QAM256
+A 699000000 QAM256
+A 705000000 QAM256
+#110
+A 711000000 QAM256
+A 717000000 QAM256
+A 723000000 QAM256
+A 729000000 QAM256
+A 735000000 QAM256
+A 741000000 QAM256
+A 747000000 QAM256
+A 753000000 QAM256
+A 759000000 QAM256
+A 765000000 QAM256
+#120
+A 771000000 QAM256
+A 777000000 QAM256
+A 783000000 QAM256
+A 789000000 QAM256
+A 795000000 QAM256
+A 801000000 QAM256
diff --git a/util/scan/atsc/us-ID-Boise b/util/scan/atsc/us-ID-Boise
new file mode 100644
index 0000000..9fe7cd2
--- /dev/null
+++ b/util/scan/atsc/us-ID-Boise
@@ -0,0 +1,8 @@
+# Boise, ID, USA
+# A freq mod
+A 195000000 8VSB
+A 213000000 8VSB
+A 515000000 8VSB
+A 533000000 8VSB
+A 545000000 8VSB
+A 557000000 8VSB
diff --git a/util/scan/atsc/us-MA-Boston b/util/scan/atsc/us-MA-Boston
new file mode 100644
index 0000000..05f170a
--- /dev/null
+++ b/util/scan/atsc/us-MA-Boston
@@ -0,0 +1,13 @@
+# initial tuning data for Boston, MA
+
+A 503000000 8VSB
+A 509000000 8VSB
+A 527000000 8VSB
+A 563000000 8VSB
+A 569000000 8VSB
+A 575000000 8VSB
+A 581000000 8VSB
+A 623000000 8VSB
+A 635000000 8VSB
+A 641000000 8VSB
+A 647000000 8VSB
diff --git a/util/scan/atsc/us-MI-Lansing b/util/scan/atsc/us-MI-Lansing
new file mode 100644
index 0000000..167555f
--- /dev/null
+++ b/util/scan/atsc/us-MI-Lansing
@@ -0,0 +1,7 @@
+# initial tuning data for Lansing, MI
+
+A 617000000 8VSB
+A 695000000 8VSB
+A 719000000 8VSB
+A 731000000 8VSB
+A 743000000 8VSB
diff --git a/util/scan/atsc/us-NTSC-center-frequencies-8VSB b/util/scan/atsc/us-NTSC-center-frequencies-8VSB
new file mode 100644
index 0000000..d21f9ae
--- /dev/null
+++ b/util/scan/atsc/us-NTSC-center-frequencies-8VSB
@@ -0,0 +1,71 @@
+# US NTSC center frequencies, use if in doubt
+
+A  57000000 8VSB
+A  63000000 8VSB
+A  69000000 8VSB
+A  79000000 8VSB
+A  85000000 8VSB
+A 177000000 8VSB
+A 183000000 8VSB
+A 189000000 8VSB
+A 195000000 8VSB
+A 201000000 8VSB
+A 207000000 8VSB
+A 213000000 8VSB
+A 473000000 8VSB
+A 479000000 8VSB
+A 485000000 8VSB
+A 491000000 8VSB
+A 497000000 8VSB
+A 503000000 8VSB
+A 509000000 8VSB
+A 515000000 8VSB
+A 521000000 8VSB
+A 527000000 8VSB
+A 533000000 8VSB
+A 539000000 8VSB
+A 545000000 8VSB
+A 551000000 8VSB
+A 557000000 8VSB
+A 563000000 8VSB
+A 569000000 8VSB
+A 575000000 8VSB
+A 581000000 8VSB
+A 587000000 8VSB
+A 593000000 8VSB
+A 599000000 8VSB
+A 605000000 8VSB
+A 611000000 8VSB
+A 617000000 8VSB
+A 623000000 8VSB
+A 629000000 8VSB
+A 635000000 8VSB
+A 641000000 8VSB
+A 647000000 8VSB
+A 653000000 8VSB
+A 659000000 8VSB
+A 665000000 8VSB
+A 671000000 8VSB
+A 677000000 8VSB
+A 683000000 8VSB
+A 689000000 8VSB
+A 695000000 8VSB
+A 701000000 8VSB
+A 707000000 8VSB
+A 713000000 8VSB
+A 719000000 8VSB
+A 725000000 8VSB
+A 731000000 8VSB
+A 737000000 8VSB
+A 743000000 8VSB
+A 749000000 8VSB
+A 755000000 8VSB
+A 761000000 8VSB
+A 767000000 8VSB
+A 773000000 8VSB
+A 779000000 8VSB
+A 785000000 8VSB
+A 791000000 8VSB
+A 797000000 8VSB
+A 803000000 8VSB
+
diff --git a/util/scan/atsc/us-NY-TWC-NYC b/util/scan/atsc/us-NY-TWC-NYC
new file mode 100644
index 0000000..0ad6e48
--- /dev/null
+++ b/util/scan/atsc/us-NY-TWC-NYC
@@ -0,0 +1,53 @@
+#initial tuning data for Time Warner Cable in New York City
+
+#80
+A 561000000 QAM256
+A 567000000 QAM256
+A 573000000 QAM256
+A 579000000 QAM256
+A 585000000 QAM256
+A 591000000 QAM256
+A 597000000 QAM256
+A 603000000 QAM256
+A 609000000 QAM256
+A 615000000 QAM256
+#90
+A 621000000 QAM256
+A 627000000 QAM256
+A 633000000 QAM256
+A 639000000 QAM256
+A 645000000 QAM256
+A  93000000 QAM256
+A  99000000 QAM256
+A 105000000 QAM256
+A 111025000 QAM256
+A 117025000 QAM256
+#100
+A 651000000 QAM256
+A 657000000 QAM256
+A 663000000 QAM256
+A 669000000 QAM256
+A 675000000 QAM256
+A 681000000 QAM256
+A 687000000 QAM256
+A 693000000 QAM256
+A 699000000 QAM256
+A 705000000 QAM256
+#110
+A 711000000 QAM256
+A 717000000 QAM256
+A 723000000 QAM256
+A 729000000 QAM256
+A 735000000 QAM256
+A 741000000 QAM256
+A 747000000 QAM256
+A 753000000 QAM256
+A 759000000 QAM256
+A 765000000 QAM256
+#120
+A 771000000 QAM256
+A 777000000 QAM256
+A 783000000 QAM256
+A 789000000 QAM256
+A 795000000 QAM256
+A 801000000 QAM256
diff --git a/util/scan/atsc/us-PA-Philadelphia b/util/scan/atsc/us-PA-Philadelphia
new file mode 100644
index 0000000..eea9685
--- /dev/null
+++ b/util/scan/atsc/us-PA-Philadelphia
@@ -0,0 +1,16 @@
+# US NY state
+
+#A 183000000 8VSB
+#A 515000000 8VSB
+#A 545000000 8VSB
+#A 551000000 8VSB
+A 575000000 8VSB
+A 581000000 8VSB
+A 593000000 8VSB
+#A 641000000 8VSB
+A 647000000 8VSB
+A 713000000 8VSB
+#A 719000000 8VSB
+A 773000000 8VSB
+A 785000000 8VSB
+A 791000000 8VSB
diff --git a/util/scan/atsc_psip_section.c b/util/scan/atsc_psip_section.c
new file mode 100644
index 0000000..0c50014
--- /dev/null
+++ b/util/scan/atsc_psip_section.c
@@ -0,0 +1,62 @@
+#include "atsc_psip_section.h"
+
+struct ATSC_extended_channel_name_descriptor read_ATSC_extended_channel_name_descriptor(const u8 *b)
+{
+	struct ATSC_extended_channel_name_descriptor v;
+	v.descriptor_tag            = getBits(b,  0, 8);
+	v.descriptor_length         = getBits(b,  8, 8);
+	v.TODO                      = getBits(b, 16, 1);
+	return v;
+}
+
+struct ATSC_service_location_descriptor read_ATSC_service_location_descriptor(const u8 *b)
+{
+	struct ATSC_service_location_descriptor v;
+	v.descriptor_tag            = getBits(b,  0, 8);
+	v.descriptor_length         = getBits(b,  8, 8);
+	v.reserved                  = getBits(b, 16, 3);
+	v.PCR_PID                   = getBits(b, 19,13);
+	v.number_elements           = getBits(b, 32, 8);
+	return v;
+}
+
+struct ATSC_service_location_element read_ATSC_service_location_element(const u8 *b)
+{
+	struct ATSC_service_location_element v;
+	v.stream_type               = getBits(b,  0, 8);
+	v.reserved                  = getBits(b,  8, 3);
+	v.elementary_PID            = getBits(b, 11,13);
+	v.ISO_639_language_code     = getBits(b, 24,24);
+	return v;
+}
+
+struct tvct_channel read_tvct_channel(const u8 *b)
+{
+	struct tvct_channel v;
+	v.short_name0               = getBits(b,  0,16);
+	v.short_name1               = getBits(b, 16,16);
+	v.short_name2               = getBits(b, 32,16);
+	v.short_name3               = getBits(b, 48,16);
+	v.short_name4               = getBits(b, 64,16);
+	v.short_name5               = getBits(b, 80,16);
+	v.short_name6               = getBits(b, 96,16);
+	v.reserved0                 = getBits(b,112, 4);
+	v.major_channel_number      = getBits(b,116,10);
+	v.minor_channel_number      = getBits(b,126,10);
+	v.modulation_mode           = getBits(b,136, 8);
+	v.carrier_frequency         = getBits(b,144,32);
+	v.channel_TSID              = getBits(b,176,16);
+	v.program_number            = getBits(b,192,16);
+	v.ETM_location              = getBits(b,208, 2);
+	v.access_controlled         = getBits(b,210, 1);
+	v.hidden                    = getBits(b,211, 1);
+	v.reserved1                 = getBits(b,212, 2);
+	v.hide_guide                = getBits(b,214, 1);
+	v.reserved2                 = getBits(b,215, 3);
+	v.service_type              = getBits(b,218, 6);
+	v.source_id                 = getBits(b,224,16);
+	v.reserved3                 = getBits(b,240, 6);
+	v.descriptors_length        = getBits(b,246,10);
+	return v;
+}
+
diff --git a/util/scan/atsc_psip_section.h b/util/scan/atsc_psip_section.h
new file mode 100644
index 0000000..c76bce7
--- /dev/null
+++ b/util/scan/atsc_psip_section.h
@@ -0,0 +1,60 @@
+#ifndef __ATSC_PSIP_SECTION_H_
+#define __ATSC_PSIP_SECTION_H_
+
+#include "section.h"
+
+#define ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR_ID 0xA0
+struct ATSC_extended_channel_name_descriptor {
+		u8  descriptor_tag            : 8;
+		u8  descriptor_length         : 8;
+		u8  TODO                      : 1;
+} PACKED;
+struct ATSC_extended_channel_name_descriptor read_ATSC_extended_channel_name_descriptor(const u8 *);
+
+#define ATSC_SERVICE_LOCATION_DESCRIPTOR_ID 0xA1
+struct ATSC_service_location_descriptor {
+		u8  descriptor_tag            : 8;
+		u8  descriptor_length         : 8;
+		u8  reserved                  : 3;
+		u16 PCR_PID                   :13;
+		u8  number_elements           : 8;
+} PACKED;
+struct ATSC_service_location_descriptor read_ATSC_service_location_descriptor(const u8 *);
+
+struct ATSC_service_location_element {
+		u8  stream_type               : 8;
+		u8  reserved                  : 3;
+		u16 elementary_PID            :13;
+		u32 ISO_639_language_code     :24;
+} PACKED;
+struct ATSC_service_location_element read_ATSC_service_location_element(const u8 *);
+
+struct tvct_channel {
+		u16 short_name0               :16;
+		u16 short_name1               :16;
+		u16 short_name2               :16;
+		u16 short_name3               :16;
+		u16 short_name4               :16;
+		u16 short_name5               :16;
+		u16 short_name6               :16;
+		u8  reserved0                 : 4;
+		u16 major_channel_number      :10;
+		u16 minor_channel_number      :10;
+		u8  modulation_mode           : 8;
+		u32 carrier_frequency         :32;
+		u16 channel_TSID              :16;
+		u16 program_number            :16;
+		u8  ETM_location              : 2;
+		u8  access_controlled         : 1;
+		u8  hidden                    : 1;
+		u8  reserved1                 : 2;
+		u8  hide_guide                : 1;
+		u8  reserved2                 : 3;
+		u8  service_type              : 6;
+		u16 source_id                 :16;
+		u8  reserved3                 : 6;
+		u16 descriptors_length        :10;
+} PACKED;
+struct tvct_channel read_tvct_channel(const u8 *);
+
+#endif
diff --git a/util/scan/diseqc.c b/util/scan/diseqc.c
index c763261..a337e0a 100644
--- a/util/scan/diseqc.c
+++ b/util/scan/diseqc.c
@@ -93,7 +93,7 @@ int setup_switch (int frontend_fd, int switch_pos, int voltage_18, int hiband)
 	verbose("DiSEqC: switch pos %i, %sV, %sband (index %d)\n",
 	    switch_pos, voltage_18 ? "18" : "13", hiband ? "hi" : "lo", i);
 
-	if (i < 0 || i >= sizeof(switch_cmds)/sizeof(struct diseqc_cmd))
+	if (i < 0 || i >= (int) (sizeof(switch_cmds)/sizeof(struct diseqc_cmd)))
 		return -EINVAL;
 
 	cmd[0] = &switch_cmds[i];
diff --git a/util/scan/dump-vdr.c b/util/scan/dump-vdr.c
index 8f86654..f030c93 100644
--- a/util/scan/dump-vdr.c
+++ b/util/scan/dump-vdr.c
@@ -101,6 +101,11 @@ void vdr_dump_dvb_parameters (FILE *f, fe_type_t type,
 		fprintf (f, ":T:27500:");
 		break;
 
+	case FE_ATSC:
+		fprintf (f, "%i:", p->frequency / 1000);
+		fprintf (f, "VDR does not support ATSC at this time");
+		break;
+
 	default:
 		;
 	};
@@ -115,6 +120,7 @@ void vdr_dump_service_parameter_set (FILE *f,
 				 int video_pid,
 				 int pcr_pid,
 				 uint16_t *audio_pid,
+				 char audio_lang[][4],
                                  int audio_num,
 				 int teletext_pid,
 				 int scrambled,
@@ -133,26 +139,42 @@ void vdr_dump_service_parameter_set (FILE *f,
         int i;
 
 	if ((video_pid || audio_pid[0]) && ((ca_select > 0) || ((ca_select == 0) && (scrambled == 0)))) {
+		if (vdr_version <= 2) {
+			audio_lang = NULL;
+			network_id = 0;
+			transport_stream_id = 0;
+		}
 		if ((dump_channum == 1) && (channel_num > 0))
 			fprintf(f, ":@%i\n", channel_num);
-		if (dump_provider == 1)
-			fprintf (f, "%s - ", provider_name);
-		fprintf (f, "%s:", service_name);
+		if (vdr_version >= 3)
+			fprintf (f, "%s;%s:", service_name, provider_name);
+		else
+		  {
+		    if (dump_provider == 1)
+		      fprintf (f, "%s - ", provider_name);
+		    fprintf (f, "%s:", service_name);
+		  }
 		vdr_dump_dvb_parameters (f, type, p, polarity, orbital_pos, we_flag);
 		if ((pcr_pid != video_pid) && (video_pid > 0))
 			fprintf (f, "%i+%i:", video_pid, pcr_pid);
 		else
 			fprintf (f, "%i:", video_pid);
 		fprintf (f, "%i", audio_pid[0]);
+		if (audio_lang && audio_lang[0][0])
+			fprintf (f, "=%.4s", audio_lang[0]);
 	        for (i = 1; i < audio_num; i++)
+	        {
 			fprintf (f, ",%i", audio_pid[i]);
+			if (audio_lang && audio_lang[i][0])
+				fprintf (f, "=%.4s", audio_lang[i]);
+		}
 		if (ac3_pid)
+	        {
 			fprintf (f, ";%i", ac3_pid);
+			if (audio_lang && audio_lang[0][0])
+				fprintf (f, "=%.4s", audio_lang[0]);
+ 		}
 		if (scrambled == 1) scrambled = ca_select;
-		if (vdr_version == 2) {
-			network_id = 0;
-			transport_stream_id = 0;
-		} 
 		fprintf (f, ":%d:%d:%d:%d:%d:0", teletext_pid, scrambled,
 				service_id, network_id, transport_stream_id);
 		fprintf (f, "\n");
diff --git a/util/scan/dump-vdr.h b/util/scan/dump-vdr.h
index 0602026..13bd05a 100644
--- a/util/scan/dump-vdr.h
+++ b/util/scan/dump-vdr.h
@@ -19,6 +19,7 @@ void vdr_dump_service_parameter_set (FILE *f,
 				 int video_pid,
 				 int pcr_pid,
 				 uint16_t *audio_pid,
+				 char audio_lang[][4],
                                  int audio_num,
 				 int teletext_pid,
 				 int scrambled,
diff --git a/util/scan/dump-zap.c b/util/scan/dump-zap.c
index fb46a2a..83505b9 100644
--- a/util/scan/dump-zap.c
+++ b/util/scan/dump-zap.c
@@ -29,7 +29,9 @@ static const char *qam_name [] = {
 	"QAM_64",
 	"QAM_128",
 	"QAM_256",
-	"QAM_AUTO"
+	"QAM_AUTO",
+	"8VSB",
+	"16VSB",
 };
 
 
@@ -96,12 +98,17 @@ void zap_dump_dvb_parameters (FILE *f, fe_type_t type, struct dvb_frontend_param
 		fprintf (f, "%s", hierarchy_name[p->u.ofdm.hierarchy_information]);
 		break;
 
+	case FE_ATSC:
+		fprintf (f, "%i:", p->frequency);
+		fprintf (f, "%s", qam_name[p->u.vsb.modulation]);
+		break;
+
 	default:
 		;
 	};
 }
 
-void zap_dump_service_parameter_set (FILE *f, 
+void zap_dump_service_parameter_set (FILE *f,
 				 const char *service_name,
 				 fe_type_t type,
 				 struct dvb_frontend_parameters *p,
diff --git a/util/scan/lnb.c b/util/scan/lnb.c
new file mode 100644
index 0000000..e30c1d6
--- /dev/null
+++ b/util/scan/lnb.c
@@ -0,0 +1,108 @@
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "lnb.h"
+
+static char *univ_desc[] = {
+		"Europe",
+		"10800 to 11800 MHz and 11600 to 12700 Mhz",
+		"Dual LO, loband 9750, hiband 10600 MHz",
+		(char *)NULL };
+
+static char *dbs_desc[] = {
+		"Expressvu, North America",
+		"12200 to 12700 MHz",
+		"Single LO, 11250 MHz",
+		(char *)NULL };
+
+static char *standard_desc[] = {
+		"10945 to 11450 Mhz",
+		"Single LO, 10000 Mhz",
+		(char *)NULL };
+
+static char *enhan_desc[] = {
+		"Astra",
+		"10700 to 11700 MHz",
+		"Single LO, 9750 MHz",
+		(char *)NULL };
+
+static char *cband_desc[] = {
+		"Big Dish - Monopoint LNBf",
+		"3700 to 4200 MHz",
+		"Single LO, 5150 Mhz",
+		(char *)NULL };
+
+static char *cmulti_desc[] = {
+		"Big Dish - Multipoint LNBf",
+		"3700 to 4200 MHz",
+		"Dual LO, 5150/5750 Mhz",
+		(char *)NULL };
+
+static struct lnb_types_st lnbs[] = {
+	{"UNIVERSAL",	univ_desc,		9750, 10600, 11700 },
+ 	{"DBS",		dbs_desc, 		11250, 0, 0 },
+	{"STANDARD",	standard_desc,		10000, 0, 0 },
+	{"ENHANCED",	enhan_desc,		9750, 0, 0 },
+	{"C-BAND",	cband_desc,		5150, 0, 0 },
+	{"C-MULTI",	cmulti_desc,		5150, 5750, 0 }
+};
+
+/* Enumerate through standard types of LNB's until NULL returned.
+ * Increment curno each time
+ */
+
+struct lnb_types_st *
+lnb_enum(int curno)
+{
+	if (curno >= (int) (sizeof(lnbs) / sizeof(lnbs[0])))
+		return (struct lnb_types_st *)NULL;
+	return &lnbs[curno];
+}
+
+/* Decode an lnb type, for example given on a command line
+ * If alpha and standard type, e.g. "Universal" then match that
+ * otherwise low[,high[,switch]]
+ */
+
+int
+lnb_decode(char *str, struct lnb_types_st *lnbp)
+{
+int i;
+char *cp, *np;
+
+	memset(lnbp, 0, sizeof(*lnbp));
+	cp = str;
+	while(*cp && isspace(*cp))
+		cp++;
+	if (isalpha(*cp)) {
+		for (i = 0; i < (int) (sizeof(lnbs) / sizeof(lnbs[0])); i++) {
+			if (!strcasecmp(lnbs[i].name, cp)) {
+				*lnbp = lnbs[i];
+				return 1;
+			}
+		}
+		return -1;
+	}
+	if (*cp == '\0' || !isdigit(*cp))
+		return -1;
+	lnbp->low_val = strtoul(cp, &np, 0);
+	if (lnbp->low_val == 0)
+		return -1;
+	cp = np;
+	while(*cp && (isspace(*cp) || *cp == ','))
+		cp++;
+	if (*cp == '\0')
+		return 1;
+	if (!isdigit(*cp))
+		return -1;
+	lnbp->high_val = strtoul(cp, &np, 0);
+	cp = np;
+	while(*cp && (isspace(*cp) || *cp == ','))
+		cp++;
+	if (*cp == '\0')
+		return 1;
+	if (!isdigit(*cp))
+		return -1;
+	lnbp->switch_val = strtoul(cp, NULL, 0);
+	return 1;
+}
diff --git a/util/scan/lnb.h b/util/scan/lnb.h
new file mode 100644
index 0000000..f78b7a6
--- /dev/null
+++ b/util/scan/lnb.h
@@ -0,0 +1,24 @@
+
+struct lnb_types_st {
+	char	*name;
+	char	**desc;
+	unsigned long	low_val;
+	unsigned long	high_val;	/* zero indicates no hiband */
+	unsigned long	switch_val;	/* zero indicates no hiband */
+};
+
+/* Enumerate through standard types of LNB's until NULL returned.
+ * Increment curno each time
+ */
+
+struct lnb_types_st *
+lnb_enum(int curno);
+
+/* Decode an lnb type, for example given on a command line
+ * If alpha and standard type, e.g. "Universal" then match that
+ * otherwise low[,high[,switch]]
+ */
+
+int
+lnb_decode(char *str, struct lnb_types_st *lnbp);
+
diff --git a/util/scan/scan.c b/util/scan/scan.c
index 30d77a5..350d9c9 100644
--- a/util/scan/scan.c
+++ b/util/scan/scan.c
@@ -1,4 +1,4 @@
-/**
+/*
  *  Simple MPEG parser to achieve network/service information.
  *
  *  refered standards:
@@ -7,6 +7,15 @@
  *    ETSI TR 101 211
  *    ETSI ETR 211
  *    ITU-T H.222.0
+ *
+ * 2005-05-10 - Basic ATSC PSIP parsing support added
+ *    ATSC Standard Revision B (A65/B)
+ *
+ * Thanks to Sean Device from Triveni for providing access to ATSC signals
+ *    and to Kevin Fowlks for his independent ATSC scanning tool.
+ *
+ * Please contribute: It is possible that some descriptors for ATSC are
+ *        not parsed yet and thus the result won't be complete.
  */
 
 #include <stdlib.h>
@@ -22,6 +31,8 @@
 #include <errno.h>
 #include <signal.h>
 #include <assert.h>
+#include <glob.h>
+#include <ctype.h>
 
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/dmx.h>
@@ -33,6 +44,7 @@
 #include "scan.h"
 #include "lnb.h"
 
+#include "atsc_psip_section.h"
 
 static char demux_devname[80];
 
@@ -47,10 +59,13 @@ static int current_tp_only;
 static int get_other_nits;
 static int vdr_dump_provider;
 static int vdr_dump_channum;
+static int no_ATSC_PSIP;
+static int ATSC_type=1;
 static int ca_select = 1;
 static int serv_select = 7;
 static int vdr_version = 2;
 static struct lnb_types_st lnb_type;
+static int unique_anon_services;
 
 static enum fe_spectral_inversion spectral_inversion = INVERSION_AUTO;
 
@@ -67,6 +82,7 @@ enum format {
 	OUTPUT_PIDS
 };
 static enum format output_format = OUTPUT_ZAP;
+static int output_format_set = 0;
 
 
 enum polarisation {
@@ -123,6 +139,7 @@ struct transponder {
 	unsigned int scan_done		  : 1;
 	unsigned int last_tuning_failed	  : 1;
 	unsigned int other_frequency_flag : 1;	/* DVB-T */
+	unsigned int wrong_frequency	  : 1;	/* DVB-T with other_frequency_flag */
 	int n_other_f;
 	uint32_t *other_f;			/* DVB-T freqeuency-list descriptor */
 };
@@ -157,14 +174,16 @@ static struct transponder *current_tp;
 static void dump_dvb_parameters (FILE *f, struct transponder *p);
 
 static void setup_filter (struct section_buf* s, const char *dmx_devname,
-		          int pid, int tid, int run_once, int segmented, int timeout);
+		          int pid, int tid, int tid_ext,
+			  int run_once, int segmented, int timeout);
 static void add_filter (struct section_buf *s);
 
+static const char * fe_type2str(fe_type_t t);
 
 /* According to the DVB standards, the combination of network_id and
  * transport_stream_id should be unique, but in real life the satellite
  * operators and broadcasters don't care enough to coordinate
- * the numbering. Thus we identify TPs by frequency (scan handles only
+ * the numbering. Thus we identify TPs by frequency (dvbscan handles only
  * one satellite at a time). Further complication: Different NITs on
  * one satellite sometimes list the same TP with slightly different
  * frequencies, so we have to search within some bandwidth.
@@ -201,6 +220,8 @@ static struct transponder *find_transponder(uint32_t frequency)
 
 	list_for_each(pos, &scanned_transponders) {
 		tp = list_entry(pos, struct transponder, list);
+		if (current_tp_only)
+			return tp;
 		if (is_same_transponder(tp->param.frequency, frequency))
 			return tp;
 	}
@@ -242,6 +263,7 @@ static struct service *alloc_service(struct transponder *tp, int service_id)
 	struct service *s = calloc(1, sizeof(*s));
 	INIT_LIST_HEAD(&s->list);
 	s->service_id = service_id;
+	s->transport_stream_id = tp->transport_stream_id;
 	list_add_tail(&s->list, &tp->services);
 	return s;
 }
@@ -264,7 +286,7 @@ static void parse_ca_identifier_descriptor (const unsigned char *buf,
 				     struct service *s)
 {
 	unsigned char len = buf [1];
-	int i;
+	unsigned int i;
 
 	buf += 2;
 
@@ -302,6 +324,8 @@ static void parse_iso639_language_descriptor (const unsigned char *buf, struct s
 
 static void parse_network_name_descriptor (const unsigned char *buf, void *dummy)
 {
+	(void)dummy;
+
 	unsigned char len = buf [1];
 
 	info("Network Name '%.*s'\n", len, buf + 2);
@@ -309,6 +333,8 @@ static void parse_network_name_descriptor (const unsigned char *buf, void *dummy
 
 static void parse_terrestrial_uk_channel_number (const unsigned char *buf, void *dummy)
 {
+	(void)dummy;
+
 	int i, n, channel_num, service_id;
 	struct list_head *p1, *p2;
 	struct transponder *t;
@@ -323,7 +349,7 @@ static void parse_terrestrial_uk_channel_number (const unsigned char *buf, void
 	buf += 2;
 	for (i = 0; i < n; i++) {
 		service_id = (buf[0]<<8)|(buf[1]&0xff);
-		channel_num = (buf[2]&0x03<<8)|(buf[3]&0xff);
+		channel_num = ((buf[2]&0x03)<<8)|(buf[3]&0xff);
 		debug("Service ID 0x%x has channel number %d ", service_id, channel_num);
 		list_for_each(p1, &scanned_transponders) {
 			t = list_entry(p1, struct transponder, list);
@@ -381,7 +407,7 @@ static void parse_cable_delivery_system_descriptor (const unsigned char *buf,
 	t->param.inversion = spectral_inversion;
 
 	if (verbosity >= 5) {
-		debug("0x%#04x/0x%#04x ", t->network_id, t->transport_stream_id);
+		debug("%#04x/%#04x ", t->network_id, t->transport_stream_id);
 		dump_dvb_parameters (stderr, t);
 		if (t->scan_done)
 			dprintf(5, " (done)");
@@ -413,7 +439,7 @@ static void parse_satellite_delivery_system_descriptor (const unsigned char *buf
 	t->we_flag = buf[8] >> 7;
 
 	if (verbosity >= 5) {
-		debug("0x%#04x/0x%#04x ", t->network_id, t->transport_stream_id);
+		debug("%#04x/%#04x ", t->network_id, t->transport_stream_id);
 		dump_dvb_parameters (stderr, t);
 		if (t->scan_done)
 			dprintf(5, " (done)");
@@ -467,7 +493,7 @@ static void parse_terrestrial_delivery_system_descriptor (const unsigned char *b
 	t->other_frequency_flag = (buf[8] & 0x01);
 
 	if (verbosity >= 5) {
-		debug("0x%#04x/0x%#04x ", t->network_id, t->transport_stream_id);
+		debug("%#04x/%#04x ", t->network_id, t->transport_stream_id);
 		dump_dvb_parameters (stderr, t);
 		if (t->scan_done)
 			dprintf(5, " (done)");
@@ -525,7 +551,7 @@ static void parse_service_descriptor (const unsigned char *buf, struct service *
 	/* remove control characters (FIXME: handle short/long name) */
 	/* FIXME: handle character set correctly (e.g. via iconv)
 	 * c.f. EN 300 468 annex A */
-	for (src = dest = s->provider_name; *src; src++)
+	for (src = dest = (unsigned char *) s->provider_name; *src; src++)
 		if (*src >= 0x20 && (*src < 0x80 || *src > 0x9f))
 			*dest++ = *src;
 	*dest = '\0';
@@ -549,7 +575,7 @@ static void parse_service_descriptor (const unsigned char *buf, struct service *
 	/* remove control characters (FIXME: handle short/long name) */
 	/* FIXME: handle character set correctly (e.g. via iconv)
 	 * c.f. EN 300 468 annex A */
-	for (src = dest = s->service_name; *src; src++)
+	for (src = dest = (unsigned char *) s->service_name; *src; src++)
 		if (*src >= 0x20 && (*src < 0x80 || *src > 0x9f))
 			*dest++ = *src;
 	*dest = '\0';
@@ -672,15 +698,15 @@ static void parse_descriptors(enum table_type t, const unsigned char *buf,
 static void parse_pat(const unsigned char *buf, int section_length,
 		      int transport_stream_id)
 {
+	(void)transport_stream_id;
+
 	while (section_length > 0) {
 		struct service *s;
 		int service_id = (buf[0] << 8) | buf[1];
 
-		if (service_id == 0) {
-			buf += 4;		/*  skip nit pid entry... */
-			section_length -= 4;
-			continue;
-		}
+		if (service_id == 0)
+			goto skip;	/* nit pid entry */
+
 		/* SDT might have been parsed first... */
 		s = find_service(current_tp, service_id);
 		if (!s)
@@ -689,11 +715,12 @@ static void parse_pat(const unsigned char *buf, int section_length,
 		if (!s->priv && s->pmt_pid) {
 			s->priv = malloc(sizeof(struct section_buf));
 			setup_filter(s->priv, demux_devname,
-				     s->pmt_pid, 0x02, 1, 0, 5);
+				     s->pmt_pid, 0x02, s->service_id, 1, 0, 5);
 
 			add_filter (s->priv);
 		}
 
+skip:
 		buf += 4;
 		section_length -= 4;
 	};
@@ -721,7 +748,7 @@ static void parse_pmt (const unsigned char *buf, int section_length, int service
 	buf += program_info_len + 4;
 	section_length -= program_info_len + 4;
 
-	while (section_length > 0) {
+	while (section_length >= 5) {
 		int ES_info_len = ((buf[3] & 0x0f) << 8) | buf[4];
 		int elementary_pid = ((buf[1] & 0x1f) << 8) | buf[2];
 
@@ -733,6 +760,7 @@ static void parse_pmt (const unsigned char *buf, int section_length, int service
 				s->video_pid = elementary_pid;
 			break;
 		case 0x03:
+		case 0x81: /* Audio per ATSC A/53B [2] Annex B */
 		case 0x04:
 			moreverbose("  AUDIO     : PID 0x%04x\n", elementary_pid);
 			if (s->audio_num < AUDIO_CHAN_MAX) {
@@ -775,8 +803,8 @@ static void parse_pmt (const unsigned char *buf, int section_length, int service
 	};
 
 
-        tmp = msg_buf;
-        tmp += sprintf(tmp, "0x%04x (%.4s)", s->audio_pid[0], s->audio_lang[0]);
+	tmp = msg_buf;
+	tmp += sprintf(tmp, "0x%04x (%.4s)", s->audio_pid[0], s->audio_lang[0]);
 
 	if (s->audio_num > AUDIO_CHAN_MAX) {
 		warning("more than %i audio channels: %i, truncating to %i\n",
@@ -846,16 +874,18 @@ static void parse_nit (const unsigned char *buf, int section_length, int network
 
 		section_length -= descriptors_loop_len + 6;
 		buf += descriptors_loop_len + 6;
-	};
+	}
 }
 
 
 static void parse_sdt (const unsigned char *buf, int section_length,
 		int transport_stream_id)
 {
+	(void)transport_stream_id;
+
 	buf += 3;	       /*  skip original network id + reserved field */
 
-	while (section_length > 4) {
+	while (section_length >= 5) {
 		int service_id = (buf[0] << 8) | buf[1];
 		int descriptors_loop_len = ((buf[3] & 0x0f) << 8) | buf[4];
 		struct service *s;
@@ -884,6 +914,159 @@ static void parse_sdt (const unsigned char *buf, int section_length,
 	};
 }
 
+/* ATSC PSIP VCT */
+static void parse_atsc_service_loc_desc(struct service *s,const unsigned char *buf)
+{
+	struct ATSC_service_location_descriptor d = read_ATSC_service_location_descriptor(buf);
+	int i;
+	unsigned char *b = (unsigned char *) buf+5;
+
+	s->pcr_pid = d.PCR_PID;
+	for (i=0; i < d.number_elements; i++) {
+		struct ATSC_service_location_element e = read_ATSC_service_location_element(b);
+		switch (e.stream_type) {
+			case 0x02: /* video */
+				s->video_pid = e.elementary_PID;
+				moreverbose("  VIDEO     : PID 0x%04x\n", e.elementary_PID);
+				break;
+			case 0x81: /* ATSC audio */
+				if (s->audio_num < AUDIO_CHAN_MAX) {
+					s->audio_pid[s->audio_num] = e.elementary_PID;
+					s->audio_lang[s->audio_num][0] = (e.ISO_639_language_code >> 16) & 0xff;
+					s->audio_lang[s->audio_num][1] = (e.ISO_639_language_code >> 8)  & 0xff;
+					s->audio_lang[s->audio_num][2] =  e.ISO_639_language_code        & 0xff;
+					s->audio_num++;
+				}
+				moreverbose("  AUDIO     : PID 0x%04x lang: %s\n",e.elementary_PID,s->audio_lang[s->audio_num-1]);
+
+				break;
+			default:
+				warning("unhandled stream_type: %x\n",e.stream_type);
+				break;
+		};
+		b += 6;
+	}
+}
+
+static void parse_atsc_ext_chan_name_desc(struct service *s,const unsigned char *buf)
+{
+	unsigned char *b = (unsigned char *) buf+2;
+	int i,j;
+	int num_str = b[0];
+
+	b++;
+	for (i = 0; i < num_str; i++) {
+		int num_seg = b[3];
+		b += 4; /* skip lang code */
+		for (j = 0; j < num_seg; j++) {
+			int comp_type = b[0],/* mode = b[1],*/ num_bytes = b[2];
+
+			switch (comp_type) {
+				case 0x00:
+					if (s->service_name)
+						free(s->service_name);
+					s->service_name = malloc(num_bytes * sizeof(char) + 1);
+					memcpy(s->service_name,&b[3],num_bytes);
+					s->service_name[num_bytes] = '\0';
+					break;
+				default:
+					warning("compressed strings are not supported yet\n");
+					break;
+			}
+			b += 3 + num_bytes;
+		}
+	}
+}
+
+static void parse_psip_descriptors(struct service *s,const unsigned char *buf,int len)
+{
+	unsigned char *b = (unsigned char *) buf;
+	int desc_len;
+	while (len > 0) {
+		desc_len = b[1];
+		switch (b[0]) {
+			case ATSC_SERVICE_LOCATION_DESCRIPTOR_ID:
+				parse_atsc_service_loc_desc(s,b);
+				break;
+			case ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR_ID:
+				parse_atsc_ext_chan_name_desc(s,b);
+				break;
+			default:
+				warning("unhandled psip descriptor: %02x\n",b[0]);
+				break;
+		}
+		b += 2 + desc_len;
+		len -= 2 + desc_len;
+	}
+}
+
+static void parse_psip_vct (const unsigned char *buf, int section_length,
+		int table_id, int transport_stream_id)
+{
+	(void)section_length;
+	(void)table_id;
+	(void)transport_stream_id;
+
+/*	int protocol_version = buf[0];*/
+	int num_channels_in_section = buf[1];
+	int i;
+	int pseudo_id = 0xffff;
+	unsigned char *b = (unsigned char *) buf + 2;
+
+	for (i = 0; i < num_channels_in_section; i++) {
+		struct service *s;
+		struct tvct_channel ch = read_tvct_channel(b);
+
+		switch (ch.service_type) {
+			case 0x01:
+				info("analog channels won't be put info channels.conf\n");
+				break;
+			case 0x02: /* ATSC TV */
+			case 0x03: /* ATSC Radio */
+				break;
+			case 0x04: /* ATSC Data */
+			default:
+				continue;
+		}
+
+		if (ch.program_number == 0)
+			ch.program_number = --pseudo_id;
+
+		s = find_service(current_tp, ch.program_number);
+		if (!s)
+			s = alloc_service(current_tp, ch.program_number);
+
+		if (s->service_name)
+			free(s->service_name);
+
+		s->service_name = malloc(7*sizeof(unsigned char));
+		/* TODO find a better solution to convert UTF-16 */
+		s->service_name[0] = ch.short_name0;
+		s->service_name[1] = ch.short_name1;
+		s->service_name[2] = ch.short_name2;
+		s->service_name[3] = ch.short_name3;
+		s->service_name[4] = ch.short_name4;
+		s->service_name[5] = ch.short_name5;
+		s->service_name[6] = ch.short_name6;
+
+		parse_psip_descriptors(s,&b[32],ch.descriptors_length);
+
+		s->channel_num = ch.major_channel_number << 10 | ch.minor_channel_number;
+
+		if (ch.hidden) {
+			s->running = RM_NOT_RUNNING;
+			info("service is not running, pseudo program_number.");
+		} else {
+			s->running = RM_RUNNING;
+			info("service is running.");
+		}
+
+		info(" Channel number: %d:%d. Name: '%s'\n",
+			ch.major_channel_number, ch.minor_channel_number,s->service_name);
+
+		b += 32 + ch.descriptors_length;
+	}
+}
 
 static int get_bit (uint8_t *bitfield, int bit)
 {
@@ -917,7 +1100,7 @@ static int parse_section (struct section_buf *s)
 	if (s->table_id != table_id)
 		return -1;
 
-	section_length = (((buf[1] & 0x0f) << 8) | buf[2]) - 11;
+	section_length = ((buf[1] & 0x0f) << 8) | buf[2];
 
 	table_id_ext = (buf[3] << 8) | buf[4];
 	section_version_number = (buf[5] >> 1) & 0x1f;
@@ -960,7 +1143,13 @@ static int parse_section (struct section_buf *s)
 		s->next_seg = next_seg;
 	}
 
-	buf += 8;
+	buf += 8;			/* past generic table header */
+	section_length -= 5 + 4;	/* header + crc */
+	if (section_length < 0) {
+		warning("truncated section (PID 0x%04x, lenght %d)",
+			s->pid, section_length + 9);
+		return 0;
+	}
 
 	if (!get_bit(s->section_done, section_number)) {
 		set_bit (s->section_done, section_number);
@@ -994,6 +1183,11 @@ static int parse_section (struct section_buf *s)
 			parse_sdt (buf, section_length, table_id_ext);
 			break;
 
+		case 0xc8:
+		case 0xc9:
+			verbose("ATSC VCT\n");
+			parse_psip_vct(buf, section_length, table_id, table_id_ext);
+			break;
 		default:
 			;
 		};
@@ -1054,13 +1248,14 @@ static int read_sections (struct section_buf *s)
 static LIST_HEAD(running_filters);
 static LIST_HEAD(waiting_filters);
 static int n_running;
-#define MAX_RUNNING 32
+#define MAX_RUNNING 27
 static struct pollfd poll_fds[MAX_RUNNING];
 static struct section_buf* poll_section_bufs[MAX_RUNNING];
 
 
 static void setup_filter (struct section_buf* s, const char *dmx_devname,
-			  int pid, int tid, int run_once, int segmented, int timeout)
+			  int pid, int tid, int tid_ext,
+			  int run_once, int segmented, int timeout)
 {
 	memset (s, 0, sizeof(struct section_buf));
 
@@ -1077,7 +1272,7 @@ static void setup_filter (struct section_buf* s, const char *dmx_devname,
 	else
 		s->timeout = timeout;
 
-	s->table_id_ext = -1;
+	s->table_id_ext = tid_ext;
 	s->section_version_number = -1;
 
 	INIT_LIST_HEAD (&s->list);
@@ -1129,6 +1324,12 @@ static int start_filter (struct section_buf* s)
 		f.filter.filter[0] = (uint8_t) s->table_id;
 		f.filter.mask[0]   = 0xff;
 	}
+	if (s->table_id_ext < 0x10000 && s->table_id_ext > 0) {
+		f.filter.filter[1] = (uint8_t) ((s->table_id_ext >> 8) & 0xff);
+		f.filter.filter[2] = (uint8_t) (s->table_id_ext & 0xff);
+		f.filter.mask[1] = 0xff;
+		f.filter.mask[2] = 0xff;
+	}
 
 	f.timeout = 0;
 	f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
@@ -1226,7 +1427,7 @@ static void read_filters (void)
 static int mem_is_zero (const void *mem, int size)
 {
 	const char *p = mem;
-	unsigned long i;
+	int i;
 
 	for (i=0; i<size; i++) {
 		if (p[i] != 0x00)
@@ -1314,6 +1515,8 @@ static int tune_to_transponder (int frontend_fd, struct transponder *t)
 	t->scan_done = 1;
 
 	if (t->type != fe_info.type) {
+		warning("frontend type (%s) is not compatible with requested tuning type (%s)\n",
+				fe_type2str(fe_info.type),fe_type2str(t->type));
 		/* ignore cable descriptors in sat NIT and vice versa */
 		t->last_tuning_failed = 1;
 		return -1;
@@ -1329,18 +1532,32 @@ static int tune_to_transponder (int frontend_fd, struct transponder *t)
 static int tune_to_next_transponder (int frontend_fd)
 {
 	struct list_head *pos, *tmp;
-	struct transponder *t;
+	struct transponder *t, *to;
+	uint32_t freq;
 
 	list_for_each_safe(pos, tmp, &new_transponders) {
 		t = list_entry (pos, struct transponder, list);
 retry:
 		if (tune_to_transponder (frontend_fd, t) == 0)
 			return 0;
-		if (t->other_frequency_flag &&
-				t->other_f &&
-				t->n_other_f) {
-			t->param.frequency = t->other_f[t->n_other_f - 1];
+next:
+		if (t->other_frequency_flag && t->other_f && t->n_other_f) {
+			/* check if the alternate freqeuncy is really new to us */
+			freq = t->other_f[t->n_other_f - 1];
 			t->n_other_f--;
+			if (find_transponder(freq))
+				goto next;
+
+			/* remember tuning to the old frequency failed */
+			to = calloc(1, sizeof(*to));
+			to->param.frequency = t->param.frequency;
+			to->wrong_frequency = 1;
+			INIT_LIST_HEAD(&to->list);
+			INIT_LIST_HEAD(&to->services);
+			list_add_tail(&to->list, &scanned_transponders);
+			copy_transponder(to, t);
+
+			t->param.frequency = freq;
 			info("retrying with f=%d\n", t->param.frequency);
 			goto retry;
 		}
@@ -1363,6 +1580,17 @@ static int str2enum(const char *str, const struct strtab *tab, int deflt)
 	return deflt;
 }
 
+static const char * enum2str(int v, const struct strtab *tab, const char *deflt)
+{
+	while (tab->str) {
+		if (v == tab->val)
+			return tab->str;
+		tab++;
+	}
+	error("invalid enum value '%d'\n", v);
+	return deflt;
+}
+
 static enum fe_code_rate str2fec(const char *fec)
 {
 	struct strtab fectab[] = {
@@ -1391,6 +1619,8 @@ static enum fe_modulation str2qam(const char *qam)
 		{ "QAM128", QAM_128 },
 		{ "QAM256", QAM_256 },
 		{ "AUTO",   QAM_AUTO },
+		{ "8VSB",   VSB_8 },
+		{ "16VSB",  VSB_16 },
 		{ NULL, 0 }
 	};
 	return str2enum(qam, qamtab, QAM_AUTO);
@@ -1445,6 +1675,19 @@ static enum fe_hierarchy str2hier(const char *hier)
 	return str2enum(hier, hiertab, HIERARCHY_AUTO);
 }
 
+static const char * fe_type2str(fe_type_t t)
+{
+	struct strtab typetab[] = {
+		{ "QPSK", FE_QPSK,},
+		{ "QAM",  FE_QAM, },
+		{ "OFDM", FE_OFDM,},
+		{ "ATSC", FE_ATSC,},
+		{ NULL, 0 }
+	};
+
+	return enum2str(t, typetab, "UNK");
+}
+
 static int tune_initial (int frontend_fd, const char *initial)
 {
 	FILE *inif;
@@ -1501,7 +1744,11 @@ static int tune_initial (int frontend_fd, const char *initial)
 			t->param.inversion = spectral_inversion;
 			t->param.u.ofdm.bandwidth = str2bandwidth(bw);
 			t->param.u.ofdm.code_rate_HP = str2fec(fec);
+			if (t->param.u.ofdm.code_rate_HP == FEC_NONE)
+				t->param.u.ofdm.code_rate_HP = FEC_AUTO;
 			t->param.u.ofdm.code_rate_LP = str2fec(fec2);
+			if (t->param.u.ofdm.code_rate_LP == FEC_NONE)
+				t->param.u.ofdm.code_rate_LP = FEC_AUTO;
 			t->param.u.ofdm.constellation = str2qam(qam);
 			t->param.u.ofdm.transmission_mode = str2mode(mode);
 			t->param.u.ofdm.guard_interval = str2guard(guard);
@@ -1516,7 +1763,12 @@ static int tune_initial (int frontend_fd, const char *initial)
 					t->param.u.ofdm.guard_interval,
 					t->param.u.ofdm.hierarchy_information);
 		}
-		else
+		else if (sscanf(buf, "A %u %7s\n",
+					&f,qam) == 2) {
+			t = alloc_transponder(f);
+			t->type = FE_ATSC;
+			t->param.u.vsb.modulation = str2qam(qam);
+		} else
 			error("cannot parse'%s'\n", buf);
 	}
 
@@ -1526,7 +1778,33 @@ static int tune_initial (int frontend_fd, const char *initial)
 }
 
 
-static void scan_tp (void)
+static void scan_tp_atsc(void)
+{
+	struct section_buf s0,s1,s2;
+
+	if (no_ATSC_PSIP) {
+		setup_filter(&s0, demux_devname, 0x00, 0x00, -1, 1, 0, 5); /* PAT */
+		add_filter(&s0);
+	} else {
+		if (ATSC_type & 0x1) {
+			setup_filter(&s0, demux_devname, 0x1ffb, 0xc8, -1, 1, 0, 5); /* terrestrial VCT */
+			add_filter(&s0);
+		}
+		if (ATSC_type & 0x2) {
+			setup_filter(&s1, demux_devname, 0x1ffb, 0xc9, -1, 1, 0, 5); /* cable VCT */
+			add_filter(&s1);
+		}
+		setup_filter(&s2, demux_devname, 0x00, 0x00, -1, 1, 0, 5); /* PAT */
+		add_filter(&s2);
+	}
+
+	do {
+		read_filters ();
+	} while (!(list_empty(&running_filters) &&
+		   list_empty(&waiting_filters)));
+}
+
+static void scan_tp_dvb (void)
 {
 	struct section_buf s0;
 	struct section_buf s1;
@@ -1536,21 +1814,21 @@ static void scan_tp (void)
 	/**
 	 *  filter timeouts > min repetition rates specified in ETR211
 	 */
-	setup_filter (&s0, demux_devname, 0x00, 0x00, 1, 0, 5); /* PAT */
-	setup_filter (&s1, demux_devname, 0x11, 0x42, 1, 0, 5); /* SDT */
+	setup_filter (&s0, demux_devname, 0x00, 0x00, -1, 1, 0, 5); /* PAT */
+	setup_filter (&s1, demux_devname, 0x11, 0x42, -1, 1, 0, 5); /* SDT */
 
 	add_filter (&s0);
 	add_filter (&s1);
 
 	if (!current_tp_only || output_format != OUTPUT_PIDS) {
-		setup_filter (&s2, demux_devname, 0x10, 0x40, 1, 0, 15); /* NIT */
+		setup_filter (&s2, demux_devname, 0x10, 0x40, -1, 1, 0, 15); /* NIT */
 		add_filter (&s2);
 		if (get_other_nits) {
 			/* get NIT-others
 			 * Note: There is more than one NIT-other: one per
 			 * network, separated by the network_id.
 			 */
-			setup_filter (&s3, demux_devname, 0x10, 0x41, 1, 1, 15);
+			setup_filter (&s3, demux_devname, 0x10, 0x41, -1, 1, 1, 15);
 			add_filter (&s3);
 		}
 	}
@@ -1561,6 +1839,22 @@ static void scan_tp (void)
 		   list_empty(&waiting_filters)));
 }
 
+static void scan_tp(void)
+{
+	switch(fe_info.type) {
+		case FE_QPSK:
+		case FE_QAM:
+		case FE_OFDM:
+			scan_tp_dvb();
+			break;
+		case FE_ATSC:
+			scan_tp_atsc();
+			break;
+		default:
+			break;
+	}
+}
+
 static void scan_network (int frontend_fd, const char *initial)
 {
 	if (tune_initial (frontend_fd, initial) < 0) {
@@ -1616,6 +1910,8 @@ static char sat_polarisation (struct transponder *t)
 
 static int sat_number (struct transponder *t)
 {
+	(void) t;
+
 	return switch_pos;
 }
 
@@ -1626,9 +1922,12 @@ static void dump_lists (void)
 	struct service *s;
 	int n = 0, i;
 	char sn[20];
+        int anon_services = 0;
 
 	list_for_each(p1, &scanned_transponders) {
 		t = list_entry(p1, struct transponder, list);
+		if (t->wrong_frequency)
+			continue;
 		list_for_each(p2, &t->services) {
 			n++;
 		}
@@ -1637,13 +1936,21 @@ static void dump_lists (void)
 
 	list_for_each(p1, &scanned_transponders) {
 		t = list_entry(p1, struct transponder, list);
+		if (t->wrong_frequency)
+			continue;
 		list_for_each(p2, &t->services) {
 			s = list_entry(p2, struct service, list);
 
 			if (!s->service_name) {
 				/* not in SDT */
-				snprintf(sn, sizeof(sn), "[%04x]", s->service_id);
+				if (unique_anon_services)
+					snprintf(sn, sizeof(sn), "[%03x-%04x]",
+						 anon_services, s->service_id);
+				else
+					snprintf(sn, sizeof(sn), "[%04x]",
+						 s->service_id);
 				s->service_name = strdup(sn);
+				anon_services++;
 			}
 			/* ':' is field separator in szap and vdr service lists */
 			for (i = 0; s->service_name[i]; i++) {
@@ -1677,7 +1984,7 @@ static void dump_lists (void)
 						    s->video_pid,
 						    s->pcr_pid,
 						    s->audio_pid,
-						    //FIXME: s->audio_lang
+						    s->audio_lang,
 						    s->audio_num,
 						    s->teletext_pid,
 						    s->scrambled,
@@ -1712,8 +2019,32 @@ static void dump_lists (void)
 	info("Done.\n");
 }
 
+static void show_existing_tuning_data_files(void)
+{
+#ifndef DATADIR
+#define DATADIR "/usr/local/share"
+#endif
+	static const char* prefixlist[] = { DATADIR "/dvb", "/etc/dvb",
+					    DATADIR "/doc/packages/dvb", 0 };
+	unsigned int i;
+	const char **prefix;
+	fprintf(stderr, "initial tuning data files:\n");
+	for (prefix = prefixlist; *prefix; prefix++) {
+		glob_t globbuf;
+		char* globspec = malloc (strlen(*prefix)+9);
+		strcpy (globspec, *prefix); strcat (globspec, "/dvb-?/*");
+		if (! glob (globspec, 0, 0, &globbuf)) {
+			for (i=0; i < globbuf.gl_pathc; i++)
+				fprintf(stderr, " file: %s\n", globbuf.gl_pathv[i]);
+		}
+		free (globspec);
+		globfree (&globbuf);
+	}
+}
+
 static void handle_sigint(int sig)
 {
+	(void)sig;
 	error("interrupted by SIGINT, dumping partial result...\n");
 	dump_lists();
 	exit(2);
@@ -1721,7 +2052,7 @@ static void handle_sigint(int sig)
 
 static const char *usage = "\n"
 	"usage: %s [options...] [-c | initial-tuning-data-file]\n"
-	"	scan doesn't do frequency scans, hence it needs initial\n"
+	"	atsc/dvbscan doesn't do frequency scans, hence it needs initial\n"
 	"	tuning data for at least one transponder/channel.\n"
 	"	-c	scan on currently tuned transponder only\n"
 	"	-v 	verbose (repeat for more)\n"
@@ -1743,22 +2074,31 @@ static const char *usage = "\n"
 	"	-p	for vdr output format: dump provider name\n"
 	"	-e N	VDR version, default 2 for VDR-1.2.x\n"
 	"		ANYTHING ELSE GIVES NONZERO NIT and TID\n"
+	"		Vdr version 1.3.x and up implies -p.\n"
 	"	-l lnb-type (DVB-S Only) (use -l help to print types) or \n"
 	"	-l low[,high[,switch]] in Mhz\n"
-	"	-u      UK DVB-T Freeview channel numbering for VDR\n";
+	"	-u      UK DVB-T Freeview channel numbering for VDR\n\n"
+	"	-P do not use ATSC PSIP tables for scanning\n"
+	"	    (but only PAT and PMT) (applies for ATSC only)\n"
+	"	-A N	check for ATSC 1=Terrestrial [default], 2=Cable or 3=both\n"
+	"	-U	Uniquely name unknown services\n";
 
 void
-bad_usage(char *pname, int prlnb)
+bad_usage(char *pname, int problem)
 {
-int i;
-struct lnb_types_st *lnbp;
-char **cp;
+	int i;
+	struct lnb_types_st *lnbp;
+	char **cp;
 
-	if (!prlnb) {
+	switch (problem) {
+	default:
+	case 0:
 		fprintf (stderr, usage, pname);
-	} else {
+		break;
+	case 1:
 		i = 0;
-		fprintf(stderr, "-l <lnb-type> or -l low[,high[,switch]] in Mhz\nwhere <lnb-type> is:\n");
+		fprintf(stderr, "-l <lnb-type> or -l low[,high[,switch]] in Mhz\n"
+			"where <lnb-type> is:\n");
 		while(NULL != (lnbp = lnb_enum(i))) {
 			fprintf (stderr, "%s\n", lnbp->name);
 			for (cp = lnbp->desc; *cp ; cp++) {
@@ -1766,6 +2106,10 @@ char **cp;
 			}
 			i++;
 		}
+		break;
+	case 2:
+		show_existing_tuning_data_files();
+		fprintf (stderr, usage, pname);
 	}
 }
 
@@ -1778,16 +2122,22 @@ int main (int argc, char **argv)
 	int fe_open_mode;
 	const char *initial = NULL;
 
+	if (argc <= 1) {
+	    bad_usage(argv[0], 2);
+	    return -1;
+	}
+
 	/* start with default lnb type */
 	lnb_type = *lnb_enum(0);
-	while ((opt = getopt(argc, argv, "5cnpa:f:d:s:o:x:e:t:i:l:vq:u")) != -1) {
+	while ((opt = getopt(argc, argv, "5cnpa:f:d:s:o:x:e:t:i:l:vquPA:U")) != -1) {
 		switch (opt) {
 		case 'a':
 			adapter = strtoul(optarg, NULL, 0);
 			break;
 		case 'c':
 			current_tp_only = 1;
-			output_format = OUTPUT_PIDS;
+			if (!output_format_set)
+				output_format = OUTPUT_PIDS;
 			break;
 		case 'n':
 			get_other_nits = 1;
@@ -1812,6 +2162,7 @@ int main (int argc, char **argv)
 				bad_usage(argv[0], 0);
 				return -1;
 			}
+			output_format_set = 1;
 			break;
 		case '5':
 			long_timeout = 1;
@@ -1844,6 +2195,20 @@ int main (int argc, char **argv)
 		case 'u':
 			vdr_dump_channum = 1;
 			break;
+		case 'P':
+			no_ATSC_PSIP = 1;
+			break;
+		case 'A':
+			ATSC_type = strtoul(optarg,NULL,0);
+			if (ATSC_type == 0 || ATSC_type > 3) {
+				bad_usage(argv[0], 1);
+				return -1;
+			}
+
+			break;
+		case 'U':
+			unique_anon_services = 1;
+			break;
 		default:
 			bad_usage(argv[0], 0);
 			return -1;
diff --git a/util/scan/section.c b/util/scan/section.c
new file mode 100644
index 0000000..8e49947
--- /dev/null
+++ b/util/scan/section.c
@@ -0,0 +1,25 @@
+#include "section.h"
+
+/* shamelessly stolen from dvbsnoop, but modified */
+u32 getBits (const u8 *buf, int startbit, int bitlen)
+{
+	const u8 *b;
+	u32 mask,tmp_long;
+	int bitHigh,i;
+
+	b = &buf[startbit / 8];
+	startbit %= 8;
+
+	bitHigh = 8;
+	tmp_long = b[0];
+	for (i = 0; i < ((bitlen-1) >> 3); i++) {
+		tmp_long <<= 8;
+		tmp_long  |= b[i+1];
+		bitHigh   += 8;
+	}
+
+	startbit = bitHigh - startbit - bitlen;
+	tmp_long = tmp_long >> startbit;
+	mask     = (1ULL << bitlen) - 1;
+	return tmp_long & mask;
+}
diff --git a/util/scan/section.h b/util/scan/section.h
new file mode 100644
index 0000000..88e9570
--- /dev/null
+++ b/util/scan/section.h
@@ -0,0 +1,14 @@
+#ifndef __SECTION_H__
+#define __SECTION_H__
+
+#include <stdio.h>
+
+#define u8  unsigned char
+#define u16 unsigned short
+#define u32 unsigned int
+
+#define PACKED __attribute((packed))
+
+u32 getBits (const u8 *buf, int startbit, int bitlen);
+
+#endif
diff --git a/util/szap/Makefile b/util/szap/Makefile
index 688c5d7..680793c 100644
--- a/util/szap/Makefile
+++ b/util/szap/Makefile
@@ -3,8 +3,8 @@ CFLAGS = -MD -Wall -g -O2 -I../../include -I../lib
 LFLAGS = -Wall -g -O2
 RM = rm -f
 
-TARGETS = szap tzap czap femon
-OBJS = szap.o tzap.o czap.o femon.o
+TARGETS = szap tzap czap azap femon
+OBJS = szap.o tzap.o czap.o azap.o femon.o
 
 all: $(OBJS) $(TARGETS)
 	@echo
diff --git a/util/szap/azap.c b/util/szap/azap.c
new file mode 100644
index 0000000..14a1c6a
--- /dev/null
+++ b/util/szap/azap.c
@@ -0,0 +1,392 @@
+#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 <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+
+static char FRONTEND_DEV [80];
+static char DEMUX_DEV [80];
+
+#define CHANNEL_FILE "/.azap/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 modulation_list [] = {
+	{ "8VSB", VSB_8 },
+	{ "16VSB", VSB_16 },
+	{ "QAM_64", QAM_64 },
+	{ "QAM_256", QAM_256 },
+};
+
+#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 */
+	};
+
+	*val = strtol(number, NULL, 10);
+
+	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 (c == ':' && channel[character] == '\0')
+			break;
+
+		if (toupper(c) == toupper(channel[character]))
+			character++;
+		else
+			character = 0;
+	};
+
+	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;
+}
+
+
+int parse(const char *fname, const char *channel,
+	  struct dvb_frontend_parameters *frontend, int *vpid, int *apid)
+{
+	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,
+				   modulation_list, LIST_SIZE(modulation_list),
+				   (int *) &frontend->u.vsb.modulation,
+				   "modulation")))
+		return -4;
+
+	if ((err = try_parse_int(fd, vpid, "Video PID")))
+		return -5;
+
+	if ((err = try_parse_int(fd, apid, "Audio PID")))
+		return -6;
+
+	close(fd);
+
+	return 0;
+}
+
+
+static
+int set_pesfilter (int fd, int pid, dmx_pes_type_t type, int dvr)
+{
+        struct dmx_pes_filter_params pesfilter;
+
+        if (pid <= 0 || pid >= 0x1fff)
+                return 0;
+
+        pesfilter.pid = pid;
+        pesfilter.input = DMX_IN_FRONTEND;
+        pesfilter.output = dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER;
+        pesfilter.pes_type = type;
+        pesfilter.flags = DMX_IMMEDIATE_START;
+
+        if (ioctl(fd, DMX_SET_PES_FILTER, &pesfilter) < 0) {
+                PERROR ("ioctl(DMX_SET_PES_FILTER) for %s PID failed",
+                        type == DMX_PES_AUDIO ? "Audio" :
+                        type == DMX_PES_VIDEO ? "Video" : "??");
+                return -1;
+        }
+
+        return 0;
+}
+
+
+static
+int setup_frontend (int fe_fd, struct dvb_frontend_parameters *frontend)
+{
+	struct dvb_frontend_info fe_info;
+
+	if (ioctl(fe_fd, FE_GET_INFO, &fe_info) < 0) {
+		PERROR("ioctl FE_GET_INFO failed");
+		return -1;
+	}
+
+	if (fe_info.type != FE_ATSC) {
+		ERROR ("frontend device is not an ATSC (VSB/QAM) device");
+		return -1;
+	}
+
+	printf ("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
+int check_frontend (int fe_fd)
+{
+	fe_status_t status;
+	uint16_t snr, signal;
+	uint32_t ber, uncorrected_blocks;
+
+	do {
+		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);
+
+		printf ("status %02x | signal %04x | snr %04x | "
+			"ber %08x | unc %08x | ",
+			status, signal, snr, ber, uncorrected_blocks);
+
+		if (status & FE_HAS_LOCK)
+			printf("FE_HAS_LOCK");
+
+		usleep(1000000);
+
+		printf("\n");
+	} while (1);
+
+	return 0;
+}
+
+
+static const char *usage = "\nusage: %s [-a adapter_num] [-f frontend_id] [-d demux_id] [-c conf_file] [-r] <channel name>\n\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;
+	int frontend_fd, audio_fd, video_fd;
+	int opt;
+
+	while ((opt = getopt(argc, argv, "hrn:a:f:d:c:")) != -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 'r':
+			dvr = 1;
+			break;
+		case 'c':
+			confname = optarg;
+			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);
+
+	printf ("using '%s' and '%s'\n", FRONTEND_DEV, DEMUX_DEV);
+
+	if (!confname)
+	{
+		if (!homedir)
+			ERROR ("$HOME not set");
+		confname = malloc (strlen(homedir) + strlen(CHANNEL_FILE) + 1);
+		memcpy (confname, homedir, strlen(homedir));
+		memcpy (confname + strlen(homedir), CHANNEL_FILE,
+	        	strlen(CHANNEL_FILE) + 1);
+	}
+
+	memset(&frontend_param, 0, sizeof(struct dvb_frontend_parameters));
+
+	if (parse (confname, channel, &frontend_param, &vpid, &apid))
+		return -1;
+
+	if ((frontend_fd = open(FRONTEND_DEV, O_RDWR)) < 0) {
+		PERROR ("failed opening '%s'", FRONTEND_DEV);
+		return -1;
+	}
+
+	if (setup_frontend (frontend_fd, &frontend_param) < 0)
+		return -1;
+
+        if ((video_fd = open(DEMUX_DEV, O_RDWR)) < 0) {
+                PERROR("failed opening '%s'", DEMUX_DEV);
+                return -1;
+        }
+
+	printf ("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;
+
+	check_frontend (frontend_fd);
+
+	close (audio_fd);
+	close (video_fd);
+	close (frontend_fd);
+
+	return 0;
+}
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/linuxtv-dvb-apps.git



More information about the pkg-vdr-dvb-changes mailing list