diff options
author | etobi <git@e-tobi.net> | 2013-09-03 09:48:40 +0200 |
---|---|---|
committer | etobi <git@e-tobi.net> | 2013-09-03 09:48:40 +0200 |
commit | 6b350466c4902c5b137e0efaf1d189128a7f18f5 (patch) | |
tree | a7cf91f9896c0f8c9d8b291114e51f1373940c70 | |
parent | 6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d (diff) | |
download | linux-dvb-apps-b1e95e2f20b330388550a933376b4c90cabb0740.tar.gz |
Imported Upstream version 1.1.1upstream/1.1.1
30 files changed, 2229 insertions, 172 deletions
@@ -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; +} + |