aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoretobi <git@e-tobi.net>2013-09-03 09:48:40 +0200
committeretobi <git@e-tobi.net>2013-09-03 09:48:40 +0200
commit6b350466c4902c5b137e0efaf1d189128a7f18f5 (patch)
treea7cf91f9896c0f8c9d8b291114e51f1373940c70
parent6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d (diff)
downloadlinux-dvb-apps-b1e95e2f20b330388550a933376b4c90cabb0740.tar.gz
Imported Upstream version 1.1.1upstream/1.1.1
-rw-r--r--README9
-rw-r--r--include/linux/dvb/frontend.h217
-rw-r--r--util/dvbnet/dvbnet.c2
-rw-r--r--util/scan/Makefile4
-rw-r--r--util/scan/atsc/us-ATSC-center-frequencies-8VSB71
-rw-r--r--util/scan/atsc/us-CA-SF-Bay-Area16
-rw-r--r--util/scan/atsc/us-Cable-EIA-542-HRC-center-frequencies-QAM256142
-rw-r--r--util/scan/atsc/us-Cable-EIA-542-IRC-center_frequencies-QAM256142
-rw-r--r--util/scan/atsc/us-Cable-HRC-center-frequencies-QAM256142
-rw-r--r--util/scan/atsc/us-Cable-IRC-center-frequencies-QAM256142
-rw-r--r--util/scan/atsc/us-Cable-Standard-center-frequencies-QAM256140
-rw-r--r--util/scan/atsc/us-ID-Boise8
-rw-r--r--util/scan/atsc/us-MA-Boston13
-rw-r--r--util/scan/atsc/us-MI-Lansing7
-rw-r--r--util/scan/atsc/us-NTSC-center-frequencies-8VSB71
-rw-r--r--util/scan/atsc/us-NY-TWC-NYC53
-rw-r--r--util/scan/atsc/us-PA-Philadelphia16
-rw-r--r--util/scan/atsc_psip_section.c62
-rw-r--r--util/scan/atsc_psip_section.h60
-rw-r--r--util/scan/diseqc.c2
-rw-r--r--util/scan/dump-vdr.c36
-rw-r--r--util/scan/dump-vdr.h1
-rw-r--r--util/scan/dump-zap.c11
-rw-r--r--util/scan/lnb.c108
-rw-r--r--util/scan/lnb.h24
-rw-r--r--util/scan/scan.c467
-rw-r--r--util/scan/section.c25
-rw-r--r--util/scan/section.h14
-rw-r--r--util/szap/Makefile4
-rw-r--r--util/szap/azap.c392
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@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@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@convergence.de>
- * Ralph Metzler <ralph@convergence.de>
- * Holger Waechtler <holger@convergence.de>
- * Andre Draszik <ad@convergence.de>
- * for convergence integrated media GmbH
+ * Ralph Metzler <ralph@convergence.de>
+ * Holger Waechtler <holger@convergence.de>
+ * Andre Draszik <ad@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;
+}
+