├── driver ├── etc │ └── 99-pt1.rules ├── dkms.conf ├── dkms.install ├── dkms.uninstall ├── pt1_com.h ├── pt1_ioctl.h ├── pt1_pci.h ├── Makefile ├── pt1_i2c.h ├── pt1_tuner_data.h ├── pt1_tuner.h ├── pt1_i2c.c ├── pt1_tuner.c ├── pt1_tuner_data.c └── pt1_pci.c ├── recpt1 ├── mkpath.h ├── channels │ ├── sample.recpt1-channels-kanazawa │ ├── sample.recpt1-channels-nagoya │ ├── sample.recpt1-channels-tokyo │ └── sample.recpt1-channels-chiba ├── configure.ac ├── decoder.h ├── mkpath.c ├── recpt1.h ├── Makefile.in ├── autogen.sh ├── tssplitter_lite.h ├── recpt1core.h ├── decoder.c ├── recpt1ctl.c ├── checksignal.c ├── pt1_dev.h ├── recpt1core.c └── tssplitter_lite.c ├── .gitignore └── README /driver/etc/99-pt1.rules: -------------------------------------------------------------------------------- 1 | KERNEL=="pt1video*" GROUP="video", MODE="0666" 2 | -------------------------------------------------------------------------------- /recpt1/mkpath.h: -------------------------------------------------------------------------------- 1 | #ifndef _MKPATH_H_ 2 | #define _MKPATH_H_ 3 | 4 | int mkpath(const char *path, mode_t mode); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /recpt1/channels/sample.recpt1-channels-kanazawa: -------------------------------------------------------------------------------- 1 | 13ch: NHK Educational 2 | 14ch: MRO 3 | 15ch: NHK General 4 | 16ch: Ishikawa TV 5 | 17ch: TV Kanazawa 6 | 23ch: Hokuriku Asahi 7 | -------------------------------------------------------------------------------- /recpt1/channels/sample.recpt1-channels-nagoya: -------------------------------------------------------------------------------- 1 | 13ch: NHK Educational 2 | 18ch: CBC 3 | 19ch: Chukyo TV 4 | 20ch: NHK Gemeral 5 | 21ch: Tokai TV 6 | 22ch: Nagoya TV (mei tere) 7 | 23ch: TV Aichi 8 | 27ch: Mie TV 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | *.o 3 | autom4te.cache 4 | recpt1/config* 5 | recpt1/checksignal 6 | recpt1/configure 7 | recpt1/configure~ 8 | recpt1/Makefile 9 | recpt1/recpt1 10 | recpt1/recpt1ctl 11 | recpt1/version.h 12 | -------------------------------------------------------------------------------- /recpt1/channels/sample.recpt1-channels-tokyo: -------------------------------------------------------------------------------- 1 | 20ch: Tokyo MX TV 2 | 21ch: Fuji TV 3 | 22ch: TBS 4 | 23ch: TV Tokyo 5 | 24ch: TV Asahi 6 | 25ch: Nihon TV 7 | 26ch: NHK Educational 8 | 27ch: NHK General 9 | 28ch: Housou Daigaku 10 | -------------------------------------------------------------------------------- /driver/dkms.conf: -------------------------------------------------------------------------------- 1 | PACKAGE_NAME="pt1_drv" 2 | PACKAGE_VERSION="d56831676696" 3 | PACKAGE_RELDATE="2018-04-16" 4 | MAKE="make KVER=${kernelver} dkms" 5 | BUILT_MODULE_NAME[0]="pt1_drv" 6 | DEST_MODULE_LOCATION[0]="/kernel/drivers/video/" 7 | AUTOINSTALL="YES" 8 | -------------------------------------------------------------------------------- /recpt1/channels/sample.recpt1-channels-chiba: -------------------------------------------------------------------------------- 1 | 20ch: Tokyo MX TV 2 | 21ch: Fuji TV 3 | 22ch: TBS 4 | 23ch: TV Tokyo 5 | 24ch: TV Asahi 6 | 25ch: Nihon TV 7 | 26ch: NHK Educational 8 | 27ch: NHK General 9 | 28ch: Housou Daigaku 10 | 30ch: CTC Chiba TV 11 | -------------------------------------------------------------------------------- /driver/dkms.install: -------------------------------------------------------------------------------- 1 | . ./dkms.uninstall 2 | 3 | su -c " 4 | cp -a `pwd` /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION; 5 | dkms add -m $PACKAGE_NAME -v $PACKAGE_VERSION; 6 | dkms build -m $PACKAGE_NAME -v $PACKAGE_VERSION; 7 | dkms install -m $PACKAGE_NAME -v $PACKAGE_VERSION" 8 | -------------------------------------------------------------------------------- /driver/dkms.uninstall: -------------------------------------------------------------------------------- 1 | if [ "$ZSH_NAME" = "zsh" ];then 2 | setopt localoptions ksharrays 3 | fi 4 | . ./dkms.conf 5 | 6 | su -c " 7 | #dkms uninstall -m $PACKAGE_NAME -v $PACKAGE_VERSION; 8 | #dkms remove -m $PACKAGE_NAME -v $PACKAGE_VERSION -k `uname -r`; 9 | dkms remove -m $PACKAGE_NAME -v $PACKAGE_VERSION --all; 10 | make uninstall; 11 | rm -vrf /usr/src/$PACKAGE_NAME-$PACKAGE_VERSION" 12 | -------------------------------------------------------------------------------- /recpt1/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.59) 5 | AC_INIT([recpt1], [1.2.0], yaz@honeyplanet.jp) 6 | AC_CONFIG_SRCDIR([recpt1.c]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | # Checks for programs. 10 | AC_PROG_CC 11 | 12 | # Checks for b25 support. 13 | AC_ARG_ENABLE(b25, 14 | [AS_HELP_STRING([--enable-b25],[enable b25 support])], 15 | [AC_CHECK_LIB([aribb25], [create_arib_std_b25], , [AC_MSG_WARN(libaribb25 is not available.)], [-lpcsclite])] 16 | ) 17 | 18 | # Checks for libraries. 19 | AC_CHECK_LIB([m], [log10]) 20 | AC_CHECK_LIB([pthread], [pthread_kill]) 21 | 22 | AC_CONFIG_FILES([Makefile]) 23 | AC_OUTPUT 24 | -------------------------------------------------------------------------------- /driver/pt1_com.h: -------------------------------------------------------------------------------- 1 | #ifndef __PT1_COM_H__ 2 | #define __PT1_COM_H__ 3 | /***************************************************************************/ 4 | /* I2Cデータ位置定義 */ 5 | /***************************************************************************/ 6 | #define MAX_CHANNEL 4 // チャネル数 7 | #define FALSE 0 8 | #define TRUE 1 9 | #define MAX_TUNER 2 //チューナ数 10 | enum{ 11 | CHANNEL_TYPE_ISDB_S, 12 | CHANNEL_TYPE_ISDB_T, 13 | CHANNEL_TYPE_MAX 14 | }; 15 | /***************************************************************************/ 16 | /* 状態 */ 17 | /***************************************************************************/ 18 | enum{ 19 | STATE_STOP, // 初期化直後 20 | STATE_START, // 通常 21 | STATE_FULL // ストッパー 22 | }; 23 | #endif 24 | -------------------------------------------------------------------------------- /driver/pt1_ioctl.h: -------------------------------------------------------------------------------- 1 | #ifndef __PT1_IOCTL_H__ 2 | #define __PT1_IOCTL_H__ 3 | /***************************************************************************/ 4 | /* チャンネル周波数情報構造体定義 */ 5 | /***************************************************************************/ 6 | typedef struct _frequency{ 7 | int frequencyno ; // 周波数テーブル番号 8 | int slot ; // スロット番号/加算する周波数 9 | }FREQUENCY; 10 | 11 | /***************************************************************************/ 12 | /* IOCTL定義 */ 13 | /***************************************************************************/ 14 | #define SET_CHANNEL _IOW(0x8D, 0x01, FREQUENCY) 15 | #define START_REC _IO(0x8D, 0x02) 16 | #define STOP_REC _IO(0x8D, 0x03) 17 | #define GET_SIGNAL_STRENGTH _IOR(0x8D, 0x04, int *) 18 | #define LNB_ENABLE _IOW(0x8D, 0x05, int) 19 | #define LNB_DISABLE _IO(0x8D, 0x06) 20 | #endif 21 | -------------------------------------------------------------------------------- /recpt1/decoder.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _DECODER_H_ 3 | #define _DECODER_H_ 4 | 5 | #include 6 | #include "config.h" 7 | 8 | #ifdef HAVE_LIBARIBB25 9 | 10 | #include 11 | #include 12 | 13 | typedef struct { 14 | ARIB_STD_B25 *b25; 15 | B_CAS_CARD *bcas; 16 | } decoder; 17 | 18 | typedef struct { 19 | int round; 20 | int strip; 21 | int emm; 22 | } decoder_options; 23 | 24 | #else 25 | 26 | typedef struct { 27 | uint8_t *data; 28 | int32_t size; 29 | } ARIB_STD_B25_BUFFER; 30 | 31 | typedef struct { 32 | void *dummy; 33 | } decoder; 34 | 35 | typedef struct { 36 | int round; 37 | int strip; 38 | int emm; 39 | } decoder_options; 40 | 41 | #endif 42 | 43 | /* prototypes */ 44 | decoder *b25_startup(decoder_options *opt); 45 | int b25_shutdown(decoder *dec); 46 | int b25_decode(decoder *dec, 47 | ARIB_STD_B25_BUFFER *sbuf, 48 | ARIB_STD_B25_BUFFER *dbuf); 49 | int b25_finish(decoder *dec, 50 | ARIB_STD_B25_BUFFER *sbuf, 51 | ARIB_STD_B25_BUFFER *dbuf); 52 | 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 【recpt1 HTTPサーバ版RC4 + α(STZ版)】 2 | Linux用PT1/PT2/PT3録画プログラムです。 3 | こちらは亜流版ですのでご注意下さい。 4 | 5 | 本家はこちら→ http://hg.honeyplanet.jp/pt1/ 6 | ※ドライバー部分は本家やその他分家(↓)のものをお使い下さい。 7 |  PT1/PT2:http://sourceforge.jp/projects/pt1dvr/ 8 |  PT3:https://github.com/m-tsudo/pt3 9 | ※libaribb25はこちら→ https://github.com/tsukumijima/libaribb25 10 | 11 | cd recpt1/recpt1 12 | ./autogen.sh 13 | ./configure --enable-b25 14 | make 15 | でビルドした後、 16 | ./recpt1 録画するチャンネル 録画秒数 出力先ファイル名 17 | で録画されます。 18 | 詳しいオプションはrecpt1 --helpをご覧下さい。 19 | 20 | チャンネル番号は以下の通りです。引数なしで実行すると同じリストが出力されます。 21 | 13-62: Terrestrial Channels 22 | BS01_0: BS朝日 23 | BS01_1: BS-TBS 24 | BS01_2: BSテレ東 25 | BS03_0: WOWOWプライム 26 | BS03_1: NHKBSプレミアム 27 | BS05_0: WOWOWライブ 28 | BS05_1: WOWOWシネマ 29 | BS09_0: BS11イレブン 30 | BS09_1: スターチャンネル1 31 | BS09_2: BS12トゥエルビ 32 | BS11_0: 放送大学 33 | BS11_1: BS釣りビジョン 34 | BS13_0: BS日テレ 35 | BS13_1: BSフジ 36 | BS13_2: BSアニマックス 37 | BS15_0: NHKBS1 38 | BS15_1: スターチャンネル2/3 39 | BS19_0: J SPORTS 4 40 | BS19_1: J SPORTS 1 41 | BS19_2: J SPORTS 2 42 | BS19_3: J SPORTS 3 43 | BS21_0: WOWOWプラス 44 | BS21_1: 日本映画専門ch 45 | BS21_2: グリーンチャンネル 46 | BS23_0: ディズニーch 47 | BS23_1: BSよしもと 48 | BS23_2: BSJapanext 49 | BS23_3: BS松竹東急 50 | C13-C63: CATV Channels 51 | CS2-CS24: CS Channels 52 | 53 | Special Thanks: 54 | ・2chの「Linuxでテレビ総合」スレッドの皆様 55 | 56 | 動作確認環境: 57 | CentOS 6.3 GNU/Linux 58 | Linux 2.6.32 SMP i686 59 | -------------------------------------------------------------------------------- /driver/pt1_pci.h: -------------------------------------------------------------------------------- 1 | #ifndef __PT1_PCI_H__ 2 | #define __PT1_PCI_H__ 3 | /***************************************************************************/ 4 | /* PCIアドレス定義 */ 5 | /***************************************************************************/ 6 | #define FIFO_GO 0x04 // FIFO実行 7 | #define FIFO_DONE 0x80 // FIFO 実行中ビット 8 | /***************************************************************************/ 9 | /* PCIアドレス定義 */ 10 | /***************************************************************************/ 11 | #define FIFO_GO_ADDR 0x00 // FIFO 実行アドレス 12 | #define FIFO_RESULT_ADDR 0x00 // FIFO 結果情報 13 | #define CFG_REGS_ADDR 0x04 14 | #define I2C_RESULT_ADDR 0x08 // I2C処理結果 15 | #define FIFO_ADDR 0x10 // FIFOに書くアドレス 16 | #define DMA_ADDR 0x14 // DMA設定に書くアドレス 17 | #define TS_TEST_ENABLE_ADDR 0x08 // 18 | 19 | /***************************************************************************/ 20 | /* DMAエラー定義 */ 21 | /***************************************************************************/ 22 | #define MICROPACKET_ERROR 1 // Micro Packetエラー 23 | #define BIT_RAM_OVERFLOW (1 << 3) // 24 | #define BIT_INITIATOR_ERROR (1 << 4) // 25 | #define BIT_INITIATOR_WARNING (1 << 5) // 26 | #endif 27 | -------------------------------------------------------------------------------- /recpt1/mkpath.c: -------------------------------------------------------------------------------- 1 | /* mkpath is originally written by Jonathan Leffler. 2 | * see "http://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux" for detail. 3 | * copyright: (C) JLSS 1990-91,1997-98,2001,2005,2008 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static int 13 | do_mkdir(const char *path, mode_t mode) 14 | { 15 | struct stat st; 16 | int status = 0; 17 | 18 | if (stat(path, &st) != 0) { 19 | /* Directory does not exist */ 20 | if (mkdir(path, mode) != 0) 21 | status = -1; 22 | } 23 | else if (!S_ISDIR(st.st_mode)) { 24 | errno = ENOTDIR; 25 | status = -1; 26 | } 27 | 28 | return(status); 29 | } 30 | 31 | int 32 | mkpath(const char *path, mode_t mode) 33 | { 34 | char *pp; 35 | char *sp; 36 | int status; 37 | char *copypath = strdup(path); 38 | 39 | status = 0; 40 | pp = copypath; 41 | while (status == 0 && (sp = strchr(pp, '/')) != 0) { 42 | if (sp != pp) { 43 | /* Neither root nor double slash in path */ 44 | *sp = '\0'; 45 | status = do_mkdir(copypath, mode); 46 | *sp = '/'; 47 | } 48 | pp = sp + 1; 49 | } 50 | if (status == 0) 51 | status = do_mkdir(path, mode); 52 | free(copypath); 53 | return (status); 54 | } 55 | -------------------------------------------------------------------------------- /recpt1/recpt1.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _RECPT1_H_ 3 | #define _RECPT1_H_ 4 | 5 | #define NUM_BSDEV 128 6 | #define NUM_ISDB_T_DEV 128 7 | #define CHTYPE_SATELLITE 0 /* satellite digital */ 8 | #define CHTYPE_GROUND 1 /* terrestrial digital */ 9 | #define MAX_QUEUE 8192 10 | #define MAX_READ_SIZE (188 * 87) /* 188*87=16356 splitterが188アライメントを期待しているのでこの数字とする*/ 11 | #define WRITE_SIZE (1024 * 1024 * 2) 12 | #define TRUE 1 13 | #define FALSE 0 14 | 15 | #define ISDB_T_NODE_LIMIT 24 // 32:ARIB limit 24:program maximum 16 | #define ISDB_T_SLOT_LIMIT 8 17 | 18 | typedef struct { 19 | int size; 20 | u_char buffer[MAX_READ_SIZE]; 21 | } BUFSZ; 22 | 23 | typedef struct { 24 | unsigned int in; // 次に入れるインデックス 25 | unsigned int out; // 次に出すインデックス 26 | unsigned int size; // キューのサイズ 27 | unsigned int num_avail; // 満タンになると 0 になる 28 | unsigned int num_used; // 空っぽになると 0 になる 29 | pthread_mutex_t mutex; 30 | pthread_cond_t cond_avail; // データが満タンのときに待つための cond 31 | pthread_cond_t cond_used; // データが空のときに待つための cond 32 | BUFSZ *buffer[1]; // バッファポインタ 33 | } QUEUE_T; 34 | 35 | typedef struct { 36 | int set_freq; // 実際にioctl()を行う値 37 | int type; // チャンネルタイプ 38 | int add_freq; // 追加する周波数(BS/CSの場合はスロット番号) 39 | char *parm_freq; // パラメータで受ける値 40 | } ISDB_T_FREQ_CONV_TABLE; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /driver/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := pt1_drv.ko 2 | VERBOSITY = 0 3 | EXTRA_CFLAGS += -Wformat=2 4 | KVER ?= `uname -r` 5 | 6 | KBUILD = /lib/modules/$(KVER)/build 7 | INSTALL_DIR = /lib/modules/$(KVER)/kernel/drivers/video 8 | 9 | all: ${TARGET} 10 | 11 | pt1_drv.ko: pt1_pci.c pt1_i2c.c pt1_tuner.c pt1_tuner_data.c version.h 12 | make -C $(KBUILD) M=`pwd` V=$(VERBOSITY) modules 13 | 14 | clean: 15 | make -C $(KBUILD) M=`pwd` V=$(VERBOSITY) clean 16 | 17 | obj-m := pt1_drv.o 18 | 19 | pt1_drv-objs := pt1_pci.o pt1_i2c.o pt1_tuner.o pt1_tuner_data.o 20 | 21 | clean-files := *.o *.ko *.mod.[co] *~ version.h 22 | 23 | version.h: 24 | eval `sed -e "s/\[0\]//" ./dkms.conf`; \ 25 | printf "#define DRV_VERSION \"$${PACKAGE_VERSION}\"\n#define DRV_RELDATE \"$$PACKAGE_RELDATE\"\n#define DRV_NAME \"$${BUILT_MODULE_NAME}\"\n" > $@; 26 | 27 | uninstall: 28 | rm -vf $(INSTALL_DIR)/$(TARGET)* /etc/udev/rules.d/99-pt1.rules 29 | 30 | dkms: $(TARGET) 31 | if [ -d /etc/udev/rules.d -a ! -f /etc/udev/rules.d/99-pt1.rules ] ; then \ 32 | install -m 644 etc/99-pt1.rules /etc/udev/rules.d ; \ 33 | fi 34 | 35 | install: uninstall dkms 36 | install -d $(INSTALL_DIR) 37 | install -m 644 $(TARGET) $(INSTALL_DIR) 38 | depmod -a $(KVER) 39 | 40 | install_compress: install 41 | . $(KBUILD)/.config ; \ 42 | if [ $$CONFIG_DECOMPRESS_XZ = "y" ] ; then \ 43 | xz -9e $(INSTALL_DIR)/$(TARGET); \ 44 | elif [ $$CONFIG_DECOMPRESS_BZIP2 = "y" ] ; then \ 45 | bzip2 -9 $(INSTALL_DIR)/$(TARGET); \ 46 | elif [ $$CONFIG_DECOMPRESS_GZIP = "y" ] ; then \ 47 | gzip -9 $(INSTALL_DIR)/$(TARGET); \ 48 | fi 49 | depmod -a $(KVER) 50 | -------------------------------------------------------------------------------- /recpt1/Makefile.in: -------------------------------------------------------------------------------- 1 | DESTDIR = 2 | prefix = @prefix@ 3 | exec_prefix = @exec_prefix@ 4 | bindir = @bindir@ 5 | CC = @CC@ 6 | 7 | TARGET = recpt1 8 | TARGET2 = recpt1ctl 9 | TARGET3 = checksignal 10 | TARGETS = $(TARGET) $(TARGET2) $(TARGET3) 11 | RELEASE_VERSION = "c8688d7d6382_with_http_server_RC4 by stz2012" 12 | 13 | CPPFLAGS = -I../driver -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 14 | CFLAGS = -O2 -g -pthread 15 | 16 | LIBS = @LIBS@ 17 | LIBS2 = -lm 18 | LIBS3 = -lpthread -lm 19 | LDFLAGS = 20 | 21 | OBJS = recpt1.o decoder.o mkpath.o tssplitter_lite.o recpt1core.o 22 | OBJS2 = recpt1ctl.o recpt1core.o 23 | OBJS3 = checksignal.o recpt1core.o 24 | OBJALL = $(OBJS) $(OBJS2) $(OBJS3) 25 | DEPEND = .deps 26 | 27 | all: $(TARGETS) 28 | 29 | clean: 30 | rm -f $(OBJALL) $(TARGETS) $(DEPEND) version.h 31 | 32 | distclean: clean 33 | rm -f Makefile config.h config.log config.status 34 | 35 | maintainer-clean: distclean 36 | rm -fr configure config.h.in aclocal.m4 autom4te.cache *~ 37 | 38 | $(TARGET): $(OBJS) 39 | $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) 40 | 41 | $(TARGET2): $(OBJS2) 42 | $(CC) $(LDFLAGS) -o $@ $(OBJS2) $(LIBS2) 43 | 44 | $(TARGET3): $(OBJS3) 45 | $(CC) $(LDFLAGS) -o $@ $(OBJS3) $(LIBS3) 46 | 47 | $(DEPEND): version.h 48 | $(CC) -MM $(OBJS:.o=.c) $(OBJS2:.o=.c) $(CPPFLAGS) > $@ 49 | 50 | version.h: 51 | revh="`git rev-list HEAD | wc -l 2> /dev/null`"; \ 52 | if [ -n "$$revh" ] && [ "$$revh" != "0" ] ; then \ 53 | echo "const char *version = \"rev.$$revh by stz2012\";" > $@; \ 54 | else \ 55 | echo "const char *version = \"$(RELEASE_VERSION)\";" > $@; \ 56 | fi 57 | 58 | install: $(TARGET) 59 | install -m 755 $(TARGETS) $(DESTDIR)$(bindir) 60 | 61 | -include .deps 62 | -------------------------------------------------------------------------------- /recpt1/autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | [ -f configure.ac ] || { 4 | echo "autogen.sh: run this command only at the top of a recpt1 source tree." 5 | exit 1 6 | } 7 | 8 | DIE=0 9 | 10 | (autoconf --version) < /dev/null > /dev/null 2>&1 || { 11 | echo 12 | echo "You must have autoconf installed to compile recpt1." 13 | echo "Get ftp://ftp.gnu.org/pub/gnu/autoconf/autoconf-2.62.tar.gz" 14 | echo "(or a newer version if it is available)" 15 | DIE=1 16 | NO_AUTOCONF=yes 17 | } 18 | 19 | (automake --version) < /dev/null > /dev/null 2>&1 || { 20 | echo 21 | echo "You must have automake installed to compile recpt1." 22 | echo "Get ftp://ftp.gnu.org/pub/gnu/automake/automake-1.10.1.tar.gz" 23 | echo "(or a newer version if it is available)" 24 | DIE=1 25 | NO_AUTOMAKE=yes 26 | } 27 | 28 | # if no automake, don't bother testing for aclocal 29 | test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { 30 | echo 31 | echo "**Error**: Missing \`aclocal'. The version of \`automake'" 32 | echo "installed doesn't appear recent enough." 33 | echo "Get ftp://ftp.gnu.org/pub/gnu/automake/automake-1.10.1.tar.gz" 34 | echo "(or a newer version if it is available)" 35 | DIE=1 36 | } 37 | 38 | # if no autoconf, don't bother testing for autoheader 39 | test -n "$NO_AUTOCONF" || (autoheader --version) < /dev/null > /dev/null 2>&1 || { 40 | echo 41 | echo "**Error**: Missing \`autoheader'. The version of \`autoheader'" 42 | echo "installed doesn't appear recent enough." 43 | echo "Get ftp://ftp.gnu.org/pub/gnu/autoconf/autoconf-2.62.tar.gz" 44 | echo "(or a newer version if it is available)" 45 | DIE=1 46 | } 47 | 48 | if test "$DIE" -eq 1; then 49 | exit 1 50 | fi 51 | 52 | echo "Generating configure script and Makefiles for recpt1." 53 | 54 | echo "Running aclocal ..." 55 | aclocal -I . 56 | echo "Running autoheader ..." 57 | autoheader 58 | echo "Running autoconf ..." 59 | autoconf 60 | -------------------------------------------------------------------------------- /recpt1/tssplitter_lite.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: t -*- */ 2 | /* tssplitter_lite.h -- split TS stream program's header. 3 | 4 | Copyright 2009 querulous 5 | Copyright 2010 Naoya OYAMA 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | #ifndef _TS_SPLITTER_LITE_H_ 20 | #define _TS_SPLITTER_LITE_H_ 21 | 22 | #define __STDC_FORMAT_MACROS 23 | #include 24 | #include 25 | 26 | #define LENGTH_PACKET (188) 27 | #define MAX_PID (8192) 28 | #define MAX_SERVICES (50) 29 | #define LENGTH_CRC_DATA (176) 30 | #define false (0) 31 | #define true (1) 32 | 33 | #define TSS_SUCCESS (0) 34 | #define TSS_ERROR (-1) 35 | #define TSS_NULL (-2) 36 | #define LENGTH_PAT_HEADER (12) 37 | #define C_CHAR_COMMA ',' 38 | #define SECTION_CONTINUE (1) 39 | 40 | typedef struct pmt_version { 41 | int pid; 42 | int version; 43 | int packet; 44 | } pmt_version; 45 | 46 | /** 47 | * splitter構造体 48 | */ 49 | typedef struct splitter { 50 | unsigned char pids[MAX_PID]; 51 | unsigned char pmt_pids[MAX_PID]; 52 | unsigned char* pat; 53 | char** sid_list; 54 | unsigned char pat_count; 55 | int pmt_retain; 56 | int pmt_counter; 57 | int avail_pmts[MAX_SERVICES]; 58 | pmt_version pmt_version[MAX_SERVICES]; 59 | int num_pmts; 60 | uint16_t section_remain[MAX_PID]; // セクション残りバイト数 61 | uint8_t packet_seq[MAX_PID]; // 巡回カウンタ 62 | } splitter; 63 | 64 | /* b25 decoder would hoard up large chank */ 65 | typedef struct _splitbuf_t 66 | { 67 | u_char* buffer; 68 | int buffer_size; 69 | int buffer_filled; 70 | } splitbuf_t; 71 | 72 | splitter* split_startup(char *sid); 73 | int split_select(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); 74 | void split_shutdown(splitter *sp); 75 | int split_ts(splitter *splitter, ARIB_STD_B25_BUFFER *sbuf, splitbuf_t *dbuf); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /recpt1/recpt1core.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _RECPT1_UTIL_H_ 3 | #define _RECPT1_UTIL_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "pt1_ioctl.h" 33 | #include "config.h" 34 | #include "decoder.h" 35 | #include "recpt1.h" 36 | #include "mkpath.h" 37 | #include "tssplitter_lite.h" 38 | 39 | /* ipc message size */ 40 | #define MSGSZ 255 41 | 42 | /* used in checksigna.c */ 43 | #define MAX_RETRY (2) 44 | 45 | /* type definitions */ 46 | typedef int boolean; 47 | 48 | typedef struct { 49 | int sfd; /* socket fd */ 50 | struct sockaddr_in addr; 51 | } sock_data; 52 | 53 | typedef struct { 54 | long mtype; 55 | char mtext[MSGSZ]; 56 | } message_buf; 57 | 58 | typedef struct { 59 | int tfd; /* tuner fd */ //xxx variable 60 | 61 | int wfd; /* output file fd */ //invariable 62 | int lnb; /* LNB voltage */ //invariable 63 | int msqid; //invariable 64 | time_t start_time; //invariable 65 | 66 | int recsec; //xxx variable 67 | 68 | boolean indefinite; //invaliable 69 | boolean tune_persistent; //invaliable 70 | 71 | QUEUE_T *queue; //invariable 72 | ISDB_T_FREQ_CONV_TABLE *table; //invariable 73 | sock_data *sock_data; //invariable 74 | pthread_t signal_thread; //invariable 75 | decoder *decoder; //invariable 76 | decoder_options *dopt; //invariable 77 | splitter *splitter; //invariable 78 | } thread_data; 79 | 80 | extern const char *version; 81 | extern char *bsdev[]; 82 | extern char *isdb_t_dev[]; 83 | 84 | extern boolean f_exit; 85 | 86 | /* prototypes */ 87 | int tune(char *channel, thread_data *tdata, char *device); 88 | int close_tuner(thread_data *tdata); 89 | void show_channels(void); 90 | ISDB_T_FREQ_CONV_TABLE *searchrecoff(char *channel); 91 | void calc_cn(int fd, int type, boolean use_bell); 92 | int parse_time(char *rectimestr, int *recsec); 93 | void do_bell(int bell); 94 | 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /recpt1/decoder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "decoder.h" 5 | 6 | #ifdef HAVE_LIBARIBB25 7 | 8 | decoder * 9 | b25_startup(decoder_options *opt) 10 | { 11 | decoder *dec = calloc(1, sizeof(decoder)); 12 | int code; 13 | const char *err = NULL; 14 | 15 | dec->b25 = create_arib_std_b25(); 16 | if(!dec->b25) { 17 | err = "create_arib_std_b25 failed"; 18 | goto error; 19 | } 20 | 21 | code = dec->b25->set_multi2_round(dec->b25, opt->round); 22 | if(code < 0) { 23 | err = "set_multi2_round failed"; 24 | goto error; 25 | } 26 | 27 | code = dec->b25->set_strip(dec->b25, opt->strip); 28 | if(code < 0) { 29 | err = "set_strip failed"; 30 | goto error; 31 | } 32 | 33 | code = dec->b25->set_emm_proc(dec->b25, opt->emm); 34 | if(code < 0) { 35 | err = "set_emm_proc failed"; 36 | goto error; 37 | } 38 | 39 | dec->bcas = create_b_cas_card(); 40 | if(!dec->bcas) { 41 | err = "create_b_cas_card failed"; 42 | goto error; 43 | } 44 | code = dec->bcas->init(dec->bcas); 45 | if(code < 0) { 46 | err = "bcas->init failed"; 47 | goto error; 48 | } 49 | 50 | code = dec->b25->set_b_cas_card(dec->b25, dec->bcas); 51 | if(code < 0) { 52 | err = "set_b_cas_card failed"; 53 | goto error; 54 | } 55 | 56 | return dec; 57 | 58 | error: 59 | fprintf(stderr, "%s\n", err); 60 | free(dec); 61 | return NULL; 62 | } 63 | 64 | int 65 | b25_shutdown(decoder *dec) 66 | { 67 | dec->b25->release(dec->b25); 68 | dec->bcas->release(dec->bcas); 69 | free(dec); 70 | 71 | return 0; 72 | } 73 | 74 | int 75 | b25_decode(decoder *dec, ARIB_STD_B25_BUFFER *sbuf, ARIB_STD_B25_BUFFER *dbuf) 76 | { 77 | int code; 78 | 79 | code = dec->b25->put(dec->b25, sbuf); 80 | if(code < 0) { 81 | fprintf(stderr, "b25->put failed\n"); 82 | return code; 83 | } 84 | 85 | code = dec->b25->get(dec->b25, dbuf); 86 | if(code < 0) { 87 | fprintf(stderr, "b25->get failed\n"); 88 | return code; 89 | } 90 | 91 | return code; 92 | } 93 | 94 | int 95 | b25_finish(decoder *dec, ARIB_STD_B25_BUFFER *sbuf, ARIB_STD_B25_BUFFER *dbuf) 96 | { 97 | int code; 98 | 99 | code = dec->b25->flush(dec->b25); 100 | if(code < 0) { 101 | fprintf(stderr, "b25->flush failed\n"); 102 | return code; 103 | } 104 | 105 | code = dec->b25->get(dec->b25, dbuf); 106 | if(code < 0) { 107 | fprintf(stderr, "b25->get failed\n"); 108 | return code; 109 | } 110 | 111 | return code; 112 | } 113 | 114 | #else 115 | 116 | /* functions */ 117 | decoder *b25_startup(decoder_options *opt) 118 | { 119 | return NULL; 120 | } 121 | 122 | int b25_shutdown(decoder *dec) 123 | { 124 | return 0; 125 | } 126 | 127 | int b25_decode(decoder *dec, 128 | ARIB_STD_B25_BUFFER *sbuf, 129 | ARIB_STD_B25_BUFFER *dbuf) 130 | { 131 | return 0; 132 | } 133 | 134 | int b25_finish(decoder *dec, 135 | ARIB_STD_B25_BUFFER *sbuf, 136 | ARIB_STD_B25_BUFFER *dbuf) 137 | { 138 | return 0; 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /driver/pt1_i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef __PT1_I2C_H__ 2 | #define __PT1_I2C_H__ 3 | #include 4 | /***************************************************************************/ 5 | /* I2Cデータ位置定義 */ 6 | /***************************************************************************/ 7 | #define MAX_CHANNEL 4 // チャネル数 8 | 9 | #define FALSE 0 10 | #define TRUE 1 11 | 12 | /***************************************************************************/ 13 | /* I2Cデータ位置定義 */ 14 | /***************************************************************************/ 15 | #define I2C_ADDRESS 10 // I2Cアドレス(10ビット) 16 | 17 | #define I2C_DATA_EN 10 18 | #define I2C_CLOCK 11 19 | #define I2C_WRIET_MODE 12 // I2C書き込み/読み込み 20 | #define I2C_BUSY 13 21 | #define I2C_DATA 18 // I2Cデータ(18ビット) 22 | /***************************************************************************/ 23 | /* I2C定義 */ 24 | /***************************************************************************/ 25 | #define WRITE_EN 1 // 書き込み 26 | #define READ_EN 0 // 読み込み 27 | #define DATA_EN 1 // データあり 28 | #define DATA_DIS 0 // データなし 29 | #define CLOCK_EN 1 // CLOCKあり 30 | #define CLOCK_DIS 0 // CLOCKなし 31 | #define BUSY_EN 1 // BUSYあり 32 | #define BUSY_DIS 0 // BUSYなし 33 | 34 | /***************************************************************************/ 35 | /* */ 36 | /***************************************************************************/ 37 | #define PCI_LOCKED 1 38 | #define RAM_LOCKED 2 39 | #define RAM_SHIFT 4 40 | /***************************************************************************/ 41 | /* ビット */ 42 | /***************************************************************************/ 43 | #define WRITE_PCI_RESET (1 << 16) 44 | #define WRITE_PCI_RESET_ (1 << 24) 45 | #define WRITE_RAM_RESET (1 << 17) 46 | #define WRITE_RAM_RESET_ (1 << 25) 47 | #define WRITE_RAM_ENABLE (1 << 1) 48 | 49 | #define WRITE_PULSE (1 << 3) 50 | #define I2C_READ_SYNC (1 << 29) 51 | #define READ_DATA (1 << 30) 52 | #define READ_UNLOCK (1 << 31) 53 | 54 | #define XC3S_PCI_CLOCK (512 / 4) 55 | #define XC3S_PCI_CLOCK_PT2 (166) 56 | /***************************************************************************/ 57 | /* I2Cアドレス定義 */ 58 | /***************************************************************************/ 59 | #define T0_ISDB_S 0X1B // チューナ0 ISDB-S 60 | #define T1_ISDB_S 0X19 // チューナ1 ISDB-S 61 | 62 | #define T0_ISDB_T 0X1A // チューナ0 ISDB-T 63 | #define T1_ISDB_T 0X18 // チューナ1 ISDB-T 64 | 65 | /***************************************************************************/ 66 | /* I2C書き込みデータ定義 */ 67 | /***************************************************************************/ 68 | typedef struct _WBLOCK{ 69 | __u8 addr ; // I2Cデバイスアドレス 70 | __u32 count ; // 転送個数 71 | __u8 value[16]; // 書き込み値 72 | }WBLOCK; 73 | 74 | /***************************************************************************/ 75 | /* 関数定義 */ 76 | /***************************************************************************/ 77 | //extern __u32 makei2c(void __iomem *, __u32, __u32, __u32, __u32, __u32, __u32); 78 | extern int xc3s_init(void __iomem *, int); 79 | extern void SetStream(void __iomem *, __u32, __u32); 80 | extern void blockwrite(void __iomem *, WBLOCK *); 81 | extern void i2c_write(void __iomem *, struct mutex *, WBLOCK *); 82 | extern __u32 i2c_read(void __iomem *, struct mutex *, WBLOCK *, int); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /driver/pt1_tuner_data.h: -------------------------------------------------------------------------------- 1 | #ifndef __PT1_TUNER_DATA_H__ 2 | #define __PT1_TUNER_DATA_H__ 3 | /***************************************************************************/ 4 | /* */ 5 | /***************************************************************************/ 6 | #define PT1_MAX_ISDB_S_INIT 19 // ISDB-S 初期化データ数 7 | #define PT1_MAX_ISDB_T_INIT 16 // ISDB-T 初期化データ数 8 | #define PT2_MAX_ISDB_S_INIT 18 // ISDB-S 初期化データ数 9 | #define PT2_MAX_ISDB_T_INIT 12 // ISDB-T 初期化データ数 10 | 11 | #define MAX_BS_CHANNEL 36 // 周波数テーブル数 12 | #define MAX_ISDB_T_CHANNEL 113 // 周波数テーブル数(地デジタル) 13 | #define MAX_BS_CHANNEL_PLL_COMMAND 3 // PLLロックするためのコマンド数 14 | /***************************************************************************/ 15 | /* */ 16 | /***************************************************************************/ 17 | 18 | /***************************************************************************/ 19 | /* */ 20 | /***************************************************************************/ 21 | typedef struct _WBLOCK_BS_PLL{ 22 | WBLOCK *wblock[MAX_BS_CHANNEL_PLL_COMMAND] ; 23 | }WBLOCK_BS_PLL; 24 | 25 | /***************************************************************************/ 26 | /* */ 27 | /***************************************************************************/ 28 | extern WBLOCK com_initdata; //初期化(共通) 29 | extern WBLOCK isdb_s_init1; //ISDB-S先頭 30 | extern WBLOCK isdb_s_init21; //ISDB-S最終 31 | extern WBLOCK isdb_t_init17; //ISDB-T最終 32 | extern WBLOCK bs_pll_lock; //ISDB-S PLLロック確認 33 | extern WBLOCK *isdb_s_initial_pt1[PT1_MAX_ISDB_S_INIT]; 34 | extern WBLOCK *isdb_t_initial_pt1[PT1_MAX_ISDB_T_INIT]; 35 | extern WBLOCK *isdb_s_initial_pt2[PT2_MAX_ISDB_S_INIT]; 36 | extern WBLOCK *isdb_t_initial_pt2[PT2_MAX_ISDB_T_INIT]; 37 | /***************************************************************************/ 38 | /* BS用データ定義 */ 39 | /***************************************************************************/ 40 | extern WBLOCK_BS_PLL bs_pll[MAX_BS_CHANNEL] ; // 周波数テーブル 41 | extern WBLOCK *bs_get_ts_id[(MAX_BS_TS_ID / 2)] ; // TS-ID取得テーブル 42 | extern WBLOCK bs_tmcc_get_1; // TMCC取得テーブル 43 | extern WBLOCK bs_tmcc_get_2; // TMCC取得テーブル 44 | extern WBLOCK bs_get_ts_lock; 45 | extern WBLOCK bs_set_ts_lock; 46 | extern WBLOCK bs_get_slot; 47 | extern WBLOCK bs_get_clock; 48 | extern WBLOCK bs_get_carrir; 49 | extern WBLOCK bs_get_signal1; 50 | extern WBLOCK bs_get_signal2; 51 | extern WBLOCK bs_get_agc; 52 | /***************************************************************************/ 53 | /* 地デジ用データ定義 */ 54 | /***************************************************************************/ 55 | extern WBLOCK isdb_t_pll_base; // 地デジ用周波数テーブルbase 56 | extern WBLOCK isdb_t_pll_lock; 57 | extern WBLOCK_BS_PLL isdb_t_info[MAX_ISDB_T_INFO_LEN]; 58 | extern WBLOCK isdb_t_check_tune; 59 | extern WBLOCK isdb_t_tune_read; 60 | extern WBLOCK isdb_t_tmcc_read_1; 61 | extern WBLOCK isdb_t_tmcc_read_1; 62 | extern WBLOCK isdb_t_signal1; 63 | extern WBLOCK isdb_t_signal2; 64 | extern WBLOCK isdb_t_agc2; 65 | 66 | extern WBLOCK isdb_t_get_clock; 67 | extern WBLOCK isdb_t_get_carrir; 68 | 69 | /***************************************************************************/ 70 | /* 省電力用データ定義 */ 71 | /***************************************************************************/ 72 | extern WBLOCK isdb_s_wake; 73 | extern WBLOCK isdb_t_wake; 74 | extern WBLOCK isdb_s_wake2; 75 | extern WBLOCK isdb_t_wake2; 76 | 77 | extern WBLOCK isdb_s_sleep; 78 | extern WBLOCK isdb_t_sleep; 79 | 80 | extern ISDB_S_CH_TABLE isdb_t_table[11]; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /recpt1/recpt1ctl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include "recpt1core.h" 11 | 12 | #define MSGSZ 255 13 | 14 | void 15 | show_usage(char *cmd) 16 | { 17 | fprintf(stderr, "Usage: \n%s --pid pid [--channel channel] [--sid SID1,SID2] [--extend time_to_extend] [--time recording_time]\n", cmd); 18 | fprintf(stderr, "\n"); 19 | } 20 | 21 | void 22 | show_options(void) 23 | { 24 | fprintf(stderr, "Options:\n"); 25 | fprintf(stderr, "--pid: Process id of recpt1 to control\n"); 26 | fprintf(stderr, "--channel: Tune to specified channel\n"); 27 | fprintf(stderr, "--sid SID1,SID2,...: Specify SID number in CSV format (101,102,...)\n"); 28 | fprintf(stderr, "--extend: Extend recording time\n"); 29 | fprintf(stderr, "--time: Set total recording time\n"); 30 | fprintf(stderr, "--help: Show this help\n"); 31 | fprintf(stderr, "--version: Show version\n"); 32 | fprintf(stderr, "--list: Show channel list\n"); 33 | } 34 | 35 | int 36 | main(int argc, char **argv) 37 | { 38 | int msqid; 39 | int msgflg = IPC_CREAT | 0666; 40 | key_t key = 0; 41 | int recsec = 0, extsec=0; 42 | char *channel = NULL; 43 | message_buf sbuf; 44 | size_t buf_length; 45 | char *sid_list = NULL; 46 | 47 | int result; 48 | int option_index; 49 | struct option long_options[] = { 50 | { "pid", 1, NULL, 'p'}, 51 | { "channel", 1, NULL, 'c'}, 52 | { "sid", 1, NULL, 'i'}, 53 | { "extend", 1, NULL, 'e'}, 54 | { "time", 1, NULL, 't'}, 55 | { "help", 0, NULL, 'h'}, 56 | { "version", 0, NULL, 'v'}, 57 | { "list", 0, NULL, 'l'}, 58 | {0, 0, NULL, 0} /* terminate */ 59 | }; 60 | 61 | while((result = getopt_long(argc, argv, "p:c:i:e:t:hvl", 62 | long_options, &option_index)) != -1) { 63 | switch(result) { 64 | case 'h': 65 | fprintf(stderr, "\n"); 66 | show_usage(argv[0]); 67 | fprintf(stderr, "\n"); 68 | show_options(); 69 | fprintf(stderr, "\n"); 70 | show_channels(); 71 | fprintf(stderr, "\n"); 72 | exit(0); 73 | break; 74 | case 'v': 75 | fprintf(stderr, "%s %s\n", argv[0], version); 76 | fprintf(stderr, "control command for recpt1.\n"); 77 | exit(0); 78 | break; 79 | case 'l': 80 | show_channels(); 81 | exit(0); 82 | break; 83 | /* following options require argument */ 84 | case 'p': 85 | key = (key_t)atoi(optarg); 86 | fprintf(stderr, "Pid = %d\n", key); 87 | break; 88 | case 'c': 89 | channel = optarg; 90 | fprintf(stderr, "Channel = %s\n", channel); 91 | break; 92 | case 'e': 93 | parse_time(optarg, &extsec); 94 | fprintf(stderr, "Extend %d sec\n", extsec); 95 | break; 96 | case 't': 97 | parse_time(optarg, &recsec); 98 | fprintf(stderr, "Total recording time = %d sec\n", recsec); 99 | break; 100 | case 'i': 101 | sid_list = optarg; 102 | fprintf(stderr, "Service ID = %s\n", sid_list); 103 | break; 104 | } 105 | } 106 | 107 | if(!key) { 108 | fprintf(stderr, "Arguments are necessary!\n"); 109 | fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); 110 | exit(1); 111 | } 112 | 113 | if ((msqid = msgget(key, msgflg )) < 0) { 114 | perror("msgget"); 115 | exit(1); 116 | } 117 | 118 | sbuf.mtype = 1; 119 | sprintf(sbuf.mtext, "ch=%s t=%d e=%d sid=%s", channel, recsec, extsec, sid_list); 120 | 121 | buf_length = strlen(sbuf.mtext) + 1 ; 122 | 123 | if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0) { 124 | perror("msgsnd"); 125 | exit(1); 126 | } 127 | 128 | exit(0); 129 | } 130 | -------------------------------------------------------------------------------- /driver/pt1_tuner.h: -------------------------------------------------------------------------------- 1 | #ifndef __PT1_TUNER_H__ 2 | #define __PT1_TUNER_H__ 3 | /***************************************************************************/ 4 | /* チューナ状態定義 */ 5 | /***************************************************************************/ 6 | // SLEEPモード設定 7 | enum { 8 | TYPE_SLEEP, 9 | TYPE_WAKEUP 10 | }; 11 | 12 | // チューナパワーモード設定 13 | enum { 14 | BIT_TUNER, 15 | BIT_LNB_UP, 16 | BIT_LNB_DOWN, 17 | BIT_RESET, 18 | BIT_33A1, 19 | BIT_33A2, 20 | BIT_5A_, 21 | BIT_5A1, 22 | BIT_5A2 23 | }; 24 | 25 | // LNBパワー設定 26 | enum{ 27 | LNB_OFF, // LNB OFF 28 | LNB_11V, // +11 V 29 | LNB_15V // +15 V 30 | }; 31 | 32 | enum{ // 電源/ハードウェアリセット 33 | TUNER_POWER_OFF, // オフ/イネーブル 34 | TUNER_POWER_ON_RESET_ENABLE, // オン/イネーブル 35 | TUNER_POWER_ON_RESET_DISABLE // オン/ディセーブル 36 | }; 37 | 38 | enum { 39 | PT1 = 0, 40 | PT2, 41 | }; 42 | 43 | /***************************************************************************/ 44 | /* チューナ状態定義 */ 45 | /***************************************************************************/ 46 | #define MAX_BS_TS_ID 8 // TS-ID取得最大値 47 | #define MAX_ISDB_T_INFO 3 // 地デジ階層情報数 48 | #define MAX_ISDB_T_INFO_LEN 2 // 地デジ階層情報数 49 | /***************************************************************************/ 50 | /* ISDB-S状態定義 */ 51 | /***************************************************************************/ 52 | typedef struct _ISDB_S_CH_TABLE{ 53 | int channel ; // 入力チャンネル番号 54 | int real_chno ; // 実際のテーブル番号 55 | int slotno ; // スロット番号 56 | }ISDB_S_CH_TABLE ; 57 | 58 | /***************************************************************************/ 59 | /* ISDB-S状態定義 */ 60 | /***************************************************************************/ 61 | typedef struct _ISDB_S_TS_ID{ 62 | __u16 ts_id ; // TS-ID 63 | __u16 dmy ; // PAD 64 | __u8 low_mode ; // 低階層 モード 65 | __u8 low_slot ; // 低階層 スロット数 66 | __u8 high_mode ; // 高階層 モード 67 | __u8 high_slot ; // 高階層 スロット数 68 | }ISDB_S_TS_ID; 69 | typedef struct _ISDB_S_TMCC{ 70 | ISDB_S_TS_ID ts_id[MAX_BS_TS_ID]; // 相対TS番号nに対するTS ID情報 71 | #if 0 72 | __u32 indicator; // 変更指示 (5ビット) 73 | __u32 emergency; // 起動制御信号 (1ビット) 74 | __u32 uplink; // アップリンク制御情報 (4ビット) 75 | __u32 ext; // 拡張フラグ (1ビット) 76 | __u32 extdata[2]; // 拡張領域 (61ビット) 77 | #endif 78 | __u32 agc ; // AGC 79 | __u32 clockmargin ; // クロック周波数誤差 80 | __u32 carriermargin ; // キャリア周波数誤差 81 | }ISDB_S_TMCC; 82 | 83 | // 階層情報 84 | typedef struct _ISDB_T_INFO{ 85 | __u32 mode; // キャリア変調方式 (3ビット) 86 | __u32 rate; // 畳込み符号化率 (3ビット) 87 | __u32 interleave; // インターリーブ長 (3ビット) 88 | __u32 segment; // セグメント数 (4ビット) 89 | }ISDB_T_INFO; 90 | 91 | typedef struct _ISDB_T_TMCC { 92 | #if 0 93 | __u32 sysid; // システム識別 (2ビット) 94 | __u32 indicator; // 伝送パラメータ切り替え指標 (4ビット) 95 | __u32 emergency; // 緊急警報放送用起動フラグ (1ビット) 96 | #endif 97 | ISDB_T_INFO info[MAX_ISDB_T_INFO]; 98 | #if 0 99 | // カレント情報 100 | __u32 partial; // 部分受信フラグ (1ビット) 101 | __u32 Phase; // 連結送信位相補正量 (3ビット) 102 | __u32 Reserved; // リザーブ (12ビット) 103 | #endif 104 | __u32 cn[2] ; // CN 105 | __u32 agc ; // AGC 106 | __u32 clockmargin ; // クロック周波数誤差 107 | __u32 carriermargin ; // キャリア周波数誤差 108 | }ISDB_T_TMCC; 109 | /***************************************************************************/ 110 | /* チューナ状態定義 */ 111 | /***************************************************************************/ 112 | extern void settuner_reset(void __iomem *, int, __u32, __u32); 113 | extern int tuner_init(void __iomem *, int, struct mutex *, int); 114 | extern void set_sleepmode(void __iomem *, struct mutex *, int, int, int); 115 | 116 | extern int bs_tune(void __iomem *, struct mutex *, int, int, ISDB_S_TMCC *); 117 | extern int ts_lock(void __iomem *, struct mutex *, int, __u16); 118 | 119 | extern int isdb_t_tune(void __iomem *, struct mutex *, int, int, ISDB_T_TMCC *); 120 | extern int isdb_t_frequency(void __iomem *, struct mutex *, int, int, int); 121 | extern int isdb_s_read_signal_strength(void __iomem *, struct mutex *, int); 122 | extern int isdb_t_read_signal_strength(void __iomem *, struct mutex *, int); 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /recpt1/checksignal.c: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include "pt1_ioctl.h" 25 | 26 | #include "config.h" 27 | #include "decoder.h" 28 | #include "recpt1core.h" 29 | #include "mkpath.h" 30 | 31 | #include 32 | #include 33 | #include "tssplitter_lite.h" 34 | 35 | /* prototypes */ 36 | int tune(char *channel, thread_data *tdata, char *device); 37 | int close_tuner(thread_data *tdata); 38 | 39 | void 40 | cleanup(thread_data *tdata) 41 | { 42 | f_exit = TRUE; 43 | } 44 | 45 | /* will be signal handler thread */ 46 | void * 47 | process_signals(void *data) 48 | { 49 | sigset_t waitset; 50 | int sig; 51 | thread_data *tdata = (thread_data *)data; 52 | 53 | sigemptyset(&waitset); 54 | sigaddset(&waitset, SIGINT); 55 | sigaddset(&waitset, SIGTERM); 56 | sigaddset(&waitset, SIGUSR1); 57 | 58 | sigwait(&waitset, &sig); 59 | 60 | switch(sig) { 61 | case SIGINT: 62 | fprintf(stderr, "\nSIGINT received. cleaning up...\n"); 63 | cleanup(tdata); 64 | break; 65 | case SIGTERM: 66 | fprintf(stderr, "\nSIGTERM received. cleaning up...\n"); 67 | cleanup(tdata); 68 | break; 69 | case SIGUSR1: /* normal exit*/ 70 | cleanup(tdata); 71 | break; 72 | } 73 | 74 | return NULL; /* dummy */ 75 | } 76 | 77 | void 78 | init_signal_handlers(pthread_t *signal_thread, thread_data *tdata) 79 | { 80 | sigset_t blockset; 81 | 82 | sigemptyset(&blockset); 83 | sigaddset(&blockset, SIGINT); 84 | sigaddset(&blockset, SIGTERM); 85 | sigaddset(&blockset, SIGUSR1); 86 | 87 | if(pthread_sigmask(SIG_BLOCK, &blockset, NULL)) 88 | fprintf(stderr, "pthread_sigmask() failed.\n"); 89 | 90 | pthread_create(signal_thread, NULL, process_signals, tdata); 91 | } 92 | 93 | void 94 | show_usage(char *cmd) 95 | { 96 | fprintf(stderr, "Usage: \n%s [--device devicefile] [--lnb voltage] [--bell] channel\n", cmd); 97 | fprintf(stderr, "\n"); 98 | } 99 | 100 | void 101 | show_options(void) 102 | { 103 | fprintf(stderr, "Options:\n"); 104 | fprintf(stderr, "--device devicefile: Specify devicefile to use\n"); 105 | fprintf(stderr, "--lnb voltage: Specify LNB voltage (0, 11, 15)\n"); 106 | fprintf(stderr, "--bell: Notify signal quality by bell\n"); 107 | fprintf(stderr, "--help: Show this help\n"); 108 | fprintf(stderr, "--version: Show version\n"); 109 | fprintf(stderr, "--list: Show channel list\n"); 110 | } 111 | 112 | int 113 | main(int argc, char **argv) 114 | { 115 | pthread_t signal_thread; 116 | static thread_data tdata; 117 | int result; 118 | int option_index; 119 | struct option long_options[] = { 120 | { "bell", 0, NULL, 'b'}, 121 | { "help", 0, NULL, 'h'}, 122 | { "version", 0, NULL, 'v'}, 123 | { "list", 0, NULL, 'l'}, 124 | { "LNB", 1, NULL, 'n'}, 125 | { "lnb", 1, NULL, 'n'}, 126 | { "device", 1, NULL, 'd'}, 127 | {0, 0, NULL, 0} /* terminate */ 128 | }; 129 | 130 | char *device = NULL; 131 | int val; 132 | char *voltage[] = {"0V", "11V", "15V"}; 133 | boolean use_bell = FALSE; 134 | 135 | while((result = getopt_long(argc, argv, "bhvln:d:", 136 | long_options, &option_index)) != -1) { 137 | switch(result) { 138 | case 'b': 139 | use_bell = TRUE; 140 | break; 141 | case 'h': 142 | fprintf(stderr, "\n"); 143 | show_usage(argv[0]); 144 | fprintf(stderr, "\n"); 145 | show_options(); 146 | fprintf(stderr, "\n"); 147 | show_channels(); 148 | fprintf(stderr, "\n"); 149 | exit(0); 150 | break; 151 | case 'v': 152 | fprintf(stderr, "%s %s\n", argv[0], version); 153 | fprintf(stderr, "signal check utility for PT1/2/3 digital tuner.\n"); 154 | exit(0); 155 | break; 156 | case 'l': 157 | show_channels(); 158 | exit(0); 159 | break; 160 | /* following options require argument */ 161 | case 'n': 162 | val = atoi(optarg); 163 | switch(val) { 164 | case 11: 165 | tdata.lnb = 1; 166 | break; 167 | case 15: 168 | tdata.lnb = 2; 169 | break; 170 | default: 171 | tdata.lnb = 0; 172 | break; 173 | } 174 | fprintf(stderr, "LNB = %s\n", voltage[tdata.lnb]); 175 | break; 176 | case 'd': 177 | device = optarg; 178 | break; 179 | } 180 | } 181 | 182 | if(argc - optind < 1) { 183 | fprintf(stderr, "channel must be specified!\n"); 184 | fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]); 185 | return 1; 186 | } 187 | 188 | /* set tune_persistent flag */ 189 | tdata.tune_persistent = TRUE; 190 | 191 | /* spawn signal handler thread */ 192 | init_signal_handlers(&signal_thread, &tdata); 193 | 194 | /* tune */ 195 | if(tune(argv[optind], &tdata, device) != 0) 196 | return 1; 197 | 198 | while(1) { 199 | if(f_exit) 200 | break; 201 | /* show signal strength */ 202 | calc_cn(tdata.tfd, tdata.table->type, use_bell); 203 | sleep(1); 204 | } 205 | 206 | /* wait for signal thread */ 207 | pthread_kill(signal_thread, SIGUSR1); 208 | pthread_join(signal_thread, NULL); 209 | 210 | /* close tuner */ 211 | if(close_tuner(&tdata) != 0) 212 | return 1; 213 | 214 | return 0; 215 | } 216 | -------------------------------------------------------------------------------- /driver/pt1_i2c.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************/ 2 | /* I2C情報作成 */ 3 | /***************************************************************************/ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) 15 | #include 16 | #endif 17 | #include 18 | #include 19 | #include 20 | 21 | #include "pt1_com.h" 22 | #include "pt1_i2c.h" 23 | #include "pt1_pci.h" 24 | #include "pt1_tuner.h" 25 | 26 | #define PROGRAM_ADDRESS 1024 27 | static int state = STATE_STOP ; 28 | static int i2c_lock(void __iomem *, __u32, __u32, __u32); 29 | static int i2c_lock_one(void __iomem *, __u32, __u32); 30 | static int i2c_unlock(void __iomem *, int); 31 | static void writebits(void __iomem *, __u32 *, __u32, __u32); 32 | static void begin_i2c(void __iomem *, __u32 *, __u32 *); 33 | static void start_i2c(void __iomem *, __u32 *, __u32 *, __u32); 34 | static void stop_i2c(void __iomem *, __u32 *, __u32 *, __u32, __u32); 35 | 36 | 37 | // PCIに書き込むI2Cデータ生成 38 | void makei2c(void __iomem *regs, __u32 base_addr, __u32 i2caddr, __u32 writemode, __u32 data_en, __u32 clock, __u32 busy) 39 | { 40 | 41 | __u32 val ; 42 | val = ((base_addr << I2C_DATA) | (writemode << I2C_WRIET_MODE) | 43 | ( data_en << I2C_DATA_EN) | 44 | (clock << I2C_CLOCK) | (busy << I2C_BUSY) | i2caddr) ; 45 | writel(val, regs + FIFO_ADDR); 46 | } 47 | 48 | int xc3s_init(void __iomem *regs, int cardtype) 49 | { 50 | 51 | __u32 val ; 52 | int lp ; 53 | int rc ; 54 | int phase = XC3S_PCI_CLOCK; 55 | 56 | /* 57 | val = (1 << 19) | (1 << 27) | (1 << 16) | (1 << 24) | (1 << 17) | (1 << 25); 58 | writel(WRITE_PULSE, regs); 59 | BIT 19, 19+8 ON 60 | BIT 16, 16+8 ON 61 | BIT 17, 17+8 ON 62 | */ 63 | // XC3S初期化 64 | for(lp = 0 ; lp < PROGRAM_ADDRESS ; lp++){ 65 | makei2c(regs, lp, 0, READ_EN, DATA_DIS, CLOCK_DIS, BUSY_DIS); 66 | } 67 | // XC3S 初期化待ち (512 PCI Clocks) 68 | for(lp = 0 ; lp < XC3S_PCI_CLOCK ; lp++){ 69 | makei2c(regs, 0, 0, READ_EN, DATA_DIS, CLOCK_DIS, BUSY_DIS); 70 | } 71 | // プロテクト解除 72 | // これは何を意図しているんだろう? 73 | // 元コードが良く判らない 74 | for(lp = 0 ; lp < 57 ; lp++){ 75 | val = readl(regs); 76 | if(val & I2C_READ_SYNC){ 77 | break ; 78 | } 79 | writel(WRITE_PULSE, regs); 80 | } 81 | 82 | for(lp = 0 ; lp < 57 ; lp++){ 83 | val = readl(regs); 84 | if(val & READ_DATA){ 85 | break ; 86 | } 87 | writel(WRITE_PULSE, regs); 88 | } 89 | 90 | // UNLOCK 91 | rc = i2c_unlock(regs, READ_UNLOCK); 92 | if(rc < 0){ 93 | return rc ; 94 | } 95 | 96 | // Enable PCI 97 | rc =i2c_lock(regs, (WRITE_PCI_RESET | WRITE_PCI_RESET_), WRITE_PCI_RESET_, PCI_LOCKED); 98 | if(rc < 0){ 99 | return -EIO ; 100 | } 101 | 102 | // Enable RAM 103 | rc =i2c_lock(regs, (WRITE_RAM_RESET | WRITE_RAM_RESET_), WRITE_RAM_RESET_, RAM_LOCKED); 104 | if(rc){ 105 | return -EIO ; 106 | } 107 | switch(cardtype) { 108 | case PT1: 109 | phase = XC3S_PCI_CLOCK; 110 | break; 111 | case PT2: 112 | phase = XC3S_PCI_CLOCK_PT2; 113 | break; 114 | } 115 | for(lp = 0; lp < phase; lp++){ 116 | rc = i2c_lock_one(regs, WRITE_RAM_ENABLE, RAM_SHIFT); 117 | if(rc < 0){ 118 | printk(KERN_ERR "PT1:LOCK FALUT\n"); 119 | return rc ; 120 | } 121 | } 122 | 123 | // ストリームごとの転送制御(OFF) 124 | for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ 125 | SetStream(regs, lp, 0); 126 | SetStream(regs, lp, 0); 127 | } 128 | return 0 ; 129 | } 130 | // 131 | // 132 | //BIT 0. 1 : Tuner番号 (Enable/Disable) 133 | //BIT 8. 9 : Tuner番号 134 | // 135 | // 136 | void SetStream(void __iomem *regs, __u32 channel, __u32 enable) 137 | { 138 | __u32 val ; 139 | 140 | val = (1 << (8 + channel)); 141 | if(enable){ 142 | val |= (1 << channel); 143 | } 144 | writel(val, regs + TS_TEST_ENABLE_ADDR); 145 | } 146 | 147 | static int i2c_lock(void __iomem *regs, __u32 firstval, __u32 secondval, __u32 lockval) 148 | { 149 | 150 | __u32 val ; 151 | int lp ; 152 | 153 | writel(firstval, regs); 154 | writel(secondval, regs); 155 | 156 | // RAMがロックされた? 157 | for(lp = 0 ; lp < XC3S_PCI_CLOCK ; lp++){ 158 | val = readl(regs); 159 | if((val & lockval)){ 160 | return 0 ; 161 | } 162 | schedule_timeout_interruptible(msecs_to_jiffies(1)); 163 | } 164 | return -EIO ; 165 | } 166 | 167 | static int i2c_lock_one(void __iomem *regs, __u32 firstval, __u32 lockval) 168 | { 169 | 170 | __u32 val ; 171 | __u32 val2 ; 172 | int lp ; 173 | 174 | val = (readl(regs) & lockval); 175 | writel(firstval, regs); 176 | 177 | // RAMがロックされた? 178 | for(lp = 0 ; lp < 10 ; lp++){ 179 | for(lp = 0 ; lp < 1024 ; lp++){ 180 | val2 = readl(regs); 181 | // 最初に取得したデータと逆になればOK 182 | if(((val2 & lockval) != val)){ 183 | return 0 ; 184 | } 185 | } 186 | schedule_timeout_interruptible(msecs_to_jiffies(1)); 187 | } 188 | printk(KERN_INFO "PT1:Lock Fault(%x:%x)\n", val, val2); 189 | return -EIO ; 190 | } 191 | static int i2c_unlock(void __iomem *regs, int lockval) 192 | { 193 | int lp ; 194 | __u32 val ; 195 | 196 | writel(WRITE_PULSE, regs); 197 | 198 | for(lp = 0 ; lp < 3 ; lp++){ 199 | val = readl(regs); 200 | if((val &lockval)){ 201 | return 0 ; 202 | } 203 | schedule_timeout_interruptible(msecs_to_jiffies(1)); 204 | } 205 | return -EIO ; 206 | } 207 | void blockwrite(void __iomem *regs, WBLOCK *wblock) 208 | { 209 | int lp ; 210 | int bitpos ; 211 | __u32 bits ; 212 | __u32 old_bits = 1 ; 213 | __u32 address = 0; 214 | __u32 clock = 0; 215 | 216 | begin_i2c(regs, &address, &clock); 217 | if(state == STATE_STOP){ 218 | start_i2c(regs, &address, &clock, old_bits); 219 | old_bits = 0 ; 220 | stop_i2c(regs, &address, &clock, old_bits, FALSE); 221 | state = STATE_START ; 222 | } 223 | old_bits = 1 ; 224 | start_i2c(regs, &address, &clock, old_bits); 225 | old_bits = 0 ; 226 | 227 | // まずアドレスを書く 228 | for(bitpos = 0 ; bitpos < 7 ; bitpos++){ 229 | bits = ((wblock->addr >> (6 - bitpos)) & 1); 230 | writebits(regs, &address, old_bits, bits); 231 | old_bits = bits ; 232 | } 233 | // タイプ:WRT 234 | writebits(regs, &address, old_bits, 0); 235 | // ACK/NACK用(必ず1) 236 | writebits(regs, &address, 0, 1); 237 | 238 | old_bits = 1 ; 239 | // 実際のデータを書く 240 | for (lp = 0 ; lp < wblock->count ; lp++){ 241 | for(bitpos = 0 ; bitpos < 8 ; bitpos++){ 242 | bits = ((wblock->value[lp] >> (7 - bitpos)) & 1); 243 | writebits(regs, &address, old_bits, bits); 244 | old_bits = bits ; 245 | } 246 | // ACK/NACK用(必ず1) 247 | writebits(regs, &address, old_bits, 1); 248 | old_bits = 1 ; 249 | } 250 | 251 | // Clock negedge 252 | makei2c(regs, address, address + 1, 0, (old_bits ^ 1), 1, 1); 253 | clock = TRUE ; 254 | address += 1 ; 255 | stop_i2c(regs, &address, &clock, old_bits, TRUE); 256 | 257 | } 258 | 259 | void blockread(void __iomem *regs, WBLOCK *wblock, int count) 260 | { 261 | int lp ; 262 | int bitpos ; 263 | __u32 bits ; 264 | __u32 old_bits = 1 ; 265 | __u32 address = 0; 266 | __u32 clock = 0; 267 | 268 | begin_i2c(regs, &address, &clock); 269 | if(state == STATE_STOP){ 270 | start_i2c(regs, &address, &clock, old_bits); 271 | old_bits = 0 ; 272 | stop_i2c(regs, &address, &clock, old_bits, FALSE); 273 | state = STATE_START ; 274 | } 275 | old_bits = 1 ; 276 | start_i2c(regs, &address, &clock, old_bits); 277 | old_bits = 0 ; 278 | 279 | // まずアドレスを書く 280 | for(bitpos = 0 ; bitpos < 7 ; bitpos++){ 281 | bits = ((wblock->addr >> (6 - bitpos)) & 1); 282 | writebits(regs, &address, old_bits, bits); 283 | old_bits = bits ; 284 | } 285 | // タイプ:WRT 286 | writebits(regs, &address, old_bits, 0); 287 | // ACK/NACK用(必ず1) 288 | writebits(regs, &address, 0, 1); 289 | 290 | old_bits = 1 ; 291 | // 実際のデータを書く 292 | for (lp = 0 ; lp < wblock->count ; lp++){ 293 | for(bitpos = 0 ; bitpos < 8 ; bitpos++){ 294 | bits = ((wblock->value[lp] >> (7 - bitpos)) & 1); 295 | writebits(regs, &address, old_bits, bits); 296 | old_bits = bits ; 297 | } 298 | // ACK/NACK用(必ず1) 299 | writebits(regs, &address, old_bits, 1); 300 | old_bits = 1 ; 301 | } 302 | 303 | // Clock negedge 304 | makei2c(regs, address, address + 1, 0, (old_bits ^ 1), 1, 1); 305 | clock = TRUE ; 306 | address += 1 ; 307 | 308 | // ここから Read 309 | start_i2c(regs, &address, &clock, old_bits); 310 | old_bits = 0 ; 311 | // まずアドレスを書く 312 | for(bitpos = 0 ; bitpos < 7 ; bitpos++){ 313 | bits = ((wblock->addr >> (6 - bitpos)) & 1); 314 | writebits(regs, &address, old_bits, bits); 315 | old_bits = bits ; 316 | } 317 | // タイプ:RD 318 | writebits(regs, &address, old_bits, 1); 319 | // ACK/NACK用(必ず1) 320 | writebits(regs, &address, 1, 1); 321 | 322 | old_bits = 1 ; 323 | // 実際のデータを書く 324 | for (lp = 0 ; lp < count ; lp++){ 325 | for(bitpos = 0 ; bitpos < 8 ; bitpos++){ 326 | writebits(regs, &address, old_bits, 1); 327 | // Read Mode Set 328 | makei2c(regs, address, address + 1, 1, 0, 0, 1); 329 | address += 1 ; 330 | old_bits = 1 ; 331 | } 332 | if(lp >= (count - 1)){ 333 | // ACK/NACK用(必ず1) 334 | writebits(regs, &address, old_bits, 1); 335 | old_bits = 0 ; 336 | }else{ 337 | // ACK/NACK用(必ず1) 338 | writebits(regs, &address, old_bits, 0); 339 | old_bits = 1 ; 340 | } 341 | } 342 | 343 | // Clock negedge 344 | makei2c(regs, address, address + 1, 0, 0, 1, 1); 345 | clock = TRUE ; 346 | address += 1 ; 347 | old_bits = 1 ; 348 | stop_i2c(regs, &address, &clock, old_bits, TRUE); 349 | 350 | } 351 | static void writebits(void __iomem *regs, __u32 *address, __u32 old_bits, __u32 bits) 352 | { 353 | // CLOCK UP 354 | makei2c(regs, *address, *address + 1, 0, (old_bits ^ 1), 1, 1); 355 | *address += 1 ; 356 | 357 | // CLOCK UP 358 | makei2c(regs, *address, *address + 1, 0, (bits ^ 1), 1, 1); 359 | *address += 1 ; 360 | 361 | // CLOCK DOWN 362 | makei2c(regs, *address, *address + 1, 0, (bits ^ 1), 0, 1); 363 | *address += 1 ; 364 | 365 | } 366 | static void begin_i2c(void __iomem *regs, __u32 *address, __u32 *clock) 367 | { 368 | // bus FREE 369 | makei2c(regs, *address, *address, 0, 0, 0, 0); 370 | *address += 1 ; 371 | 372 | // bus busy 373 | makei2c(regs, *address, *address + 1, 0, 0, 0, 1); 374 | *address += 1 ; 375 | *clock = FALSE ; 376 | } 377 | 378 | static void start_i2c(void __iomem *regs, __u32 *address, __u32 *clock, __u32 data) 379 | { 380 | // データが残っていなければデータを下げる 381 | if(!data){ 382 | // CLOCKがあればCLOCKを下げる 383 | if(*clock != TRUE){ 384 | *clock = TRUE ; 385 | makei2c(regs, *address, *address + 1, 0, 1, 1, 1); 386 | *address += 1 ; 387 | } 388 | makei2c(regs, *address, *address + 1, 0, 0, 1, 1); 389 | *address += 1 ; 390 | } 391 | 392 | if(*clock != FALSE){ 393 | *clock = FALSE ; 394 | makei2c(regs, *address, *address + 1, 0, 0, 0, 1); 395 | *address += 1; 396 | } 397 | makei2c(regs, *address, *address + 1, 0, 1, 0, 1); 398 | *address += 1; 399 | *clock = FALSE ; 400 | } 401 | 402 | static void stop_i2c(void __iomem *regs, __u32 *address, __u32 *clock, __u32 data, __u32 end) 403 | { 404 | // データが残っていて 405 | if(data){ 406 | // クロックがあれば 407 | if(*clock != TRUE){ 408 | *clock = TRUE ; 409 | makei2c(regs, *address, *address + 1, 0, 0, 1, 1); 410 | *address += 1; 411 | } 412 | makei2c(regs, *address, *address + 1, 0, 1, 1, 1); 413 | *address += 1 ; 414 | } 415 | // クロックが落ちていれば 416 | if(*clock){ 417 | *clock = FALSE ; 418 | makei2c(regs, *address, *address + 1, 0, 1, 0, 1); 419 | *address += 1 ; 420 | } 421 | 422 | if(end){ 423 | makei2c(regs, *address, 0, 0, 0, 0, 1); 424 | }else{ 425 | makei2c(regs, *address, *address + 1, 0, 0, 0, 1); 426 | *address += 1 ; 427 | } 428 | } 429 | 430 | void i2c_write(void __iomem *regs, struct mutex *lock, WBLOCK *wblock) 431 | { 432 | 433 | int lp; 434 | __u32 val ; 435 | 436 | // ロックする 437 | mutex_lock(lock); 438 | #if 0 439 | printk(KERN_INFO "Addr=%x(%d)\n", wblock->addr, wblock->count); 440 | for(lp = 0 ; lp < wblock->count ; lp++){ 441 | printk(KERN_INFO "%x\n", wblock->value[lp]); 442 | } 443 | printk(KERN_INFO "\n"); 444 | #endif 445 | 446 | blockwrite(regs, wblock); 447 | writel(FIFO_GO, regs + FIFO_GO_ADDR); 448 | //とりあえずロックしないように。 449 | for(lp = 0 ; lp < 100 ; lp++){ 450 | val = readl(regs + FIFO_RESULT_ADDR); 451 | if(!(val & FIFO_DONE)){ 452 | break ; 453 | } 454 | schedule_timeout_interruptible(msecs_to_jiffies(1)); 455 | } 456 | mutex_unlock(lock); 457 | } 458 | 459 | __u32 i2c_read(void __iomem *regs, struct mutex *lock, WBLOCK *wblock, int size) 460 | { 461 | 462 | int lp; 463 | __u32 val ; 464 | 465 | // ロックする 466 | mutex_lock(lock); 467 | #if 0 468 | printk(KERN_INFO "Addr=%x:%d:%d\n", wblock->addr, wblock->count, size); 469 | for(lp = 0 ; lp < wblock->count ; lp++){ 470 | printk(KERN_INFO "%x\n", wblock->value[lp]); 471 | } 472 | printk(KERN_INFO "\n"); 473 | #endif 474 | blockread(regs, wblock, size); 475 | 476 | writel(FIFO_GO, regs + FIFO_GO_ADDR); 477 | 478 | for(lp = 0 ; lp < 100 ; lp++){ 479 | schedule_timeout_interruptible(msecs_to_jiffies(1)); 480 | val = readl(regs + FIFO_RESULT_ADDR); 481 | if(!(val & FIFO_DONE)){ 482 | break ; 483 | } 484 | } 485 | 486 | val = readl(regs + I2C_RESULT_ADDR); 487 | mutex_unlock(lock); 488 | return val ; 489 | } 490 | -------------------------------------------------------------------------------- /driver/pt1_tuner.c: -------------------------------------------------------------------------------- 1 | /* pt1-tuner.c: A PT1 on Tuner driver for Linux. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) 13 | #include 14 | #endif 15 | #include 16 | #include 17 | #include 18 | 19 | #include "pt1_com.h" 20 | #include "pt1_pci.h" 21 | #include "pt1_i2c.h" 22 | #include "pt1_tuner.h" 23 | #include "pt1_tuner_data.h" 24 | 25 | typedef struct _TUNER_INFO{ 26 | int isdb_s ; 27 | int isdb_t ; 28 | }TUNER_INFO; 29 | 30 | TUNER_INFO tuner_info[2] = { 31 | {T0_ISDB_S, T0_ISDB_T}, 32 | {T1_ISDB_S, T1_ISDB_T} 33 | }; 34 | 35 | typedef struct _isdb_t_freq_add_table{ 36 | __u16 pos ; // 追加するチャンネルポジション 37 | __u16 add_freq ; // 追加する値 38 | }isdb_t_freq_add_table; 39 | 40 | isdb_t_freq_add_table isdb_t_freq_add[10] = { 41 | { 7, 0x8081}, // 0~7迄 42 | { 12, 0x80A1}, // 8~12迄 43 | { 21, 0x8062}, // 13~21迄 44 | { 39, 0x80A2}, // 22~39迄 45 | { 51, 0x80E2}, // 40~51迄 46 | { 59, 0x8064}, // 52~59迄 47 | { 75, 0x8084}, // 60~75迄 48 | { 84, 0x80a4}, // 76~84迄 49 | {100, 0x80C4}, // 85~100迄 50 | {112, 0x80E4} // 101~112迄 51 | }; 52 | 53 | void settuner_reset(void __iomem *regs, int cardtype, __u32 lnb, __u32 tuner) 54 | { 55 | __u32 val = TUNER_POWER_OFF; 56 | switch(lnb){ 57 | case LNB_11V: 58 | val = (1 << BIT_LNB_DOWN); 59 | break ; 60 | case LNB_15V: 61 | val = (1 << BIT_LNB_UP) | (1 << BIT_LNB_DOWN); 62 | break ; 63 | } 64 | 65 | if(cardtype == PT1) { 66 | switch(tuner){ 67 | case TUNER_POWER_ON_RESET_ENABLE: 68 | val |= (1 << BIT_TUNER); 69 | break; 70 | case TUNER_POWER_ON_RESET_DISABLE: 71 | val |= (1 << BIT_TUNER) | (1 << BIT_RESET); 72 | break ; 73 | } 74 | } 75 | else if(cardtype == PT2) { 76 | switch(tuner){ 77 | case TUNER_POWER_ON_RESET_ENABLE: 78 | val |= (1 << BIT_TUNER) 79 | | (1 << BIT_33A1) 80 | | (1 << BIT_33A2) 81 | | (1 << BIT_5A_) 82 | | (1 << BIT_5A1) 83 | | (1 << BIT_5A2); 84 | break; 85 | case TUNER_POWER_ON_RESET_DISABLE: 86 | val |= (1 << BIT_TUNER) 87 | | (1 << BIT_RESET) 88 | | (1 << BIT_33A1) 89 | | (1 << BIT_33A2) 90 | | (1 << BIT_5A_) 91 | | (1 << BIT_5A1) 92 | | (1 << BIT_5A2); 93 | break ; 94 | } 95 | } 96 | writel(val, (regs + CFG_REGS_ADDR)); 97 | } 98 | static int init_isdb_s(void __iomem *regs, int cardtype, struct mutex *lock, __u32 addr) 99 | { 100 | 101 | WBLOCK wk; 102 | int lp ; 103 | __u32 val ; 104 | 105 | // ISDB-S/T初期化 106 | memcpy(&wk, &com_initdata, sizeof(WBLOCK)); 107 | 108 | // 初期化1(なぜかREADなので) 109 | memcpy(&wk, &isdb_s_init1, sizeof(WBLOCK)); 110 | wk.addr = addr; 111 | val = i2c_read(regs, lock, &wk, 1); 112 | 113 | if(cardtype == PT1) { 114 | if((val & 0xff) != 0x4c) { 115 | printk(KERN_INFO "PT1:ISDB-S Read(%x)\n", val); 116 | return -EIO ; 117 | } 118 | for(lp = 0 ; lp < PT1_MAX_ISDB_S_INIT ; lp++) { 119 | memcpy(&wk, isdb_s_initial_pt1[lp], sizeof(WBLOCK)); 120 | wk.addr = addr; 121 | i2c_write(regs, lock, &wk); 122 | } 123 | } 124 | else if(cardtype == PT2) { 125 | if((val & 0xff) != 0x52) { 126 | printk(KERN_INFO "PT2:ISDB-S Read(%x)\n", val); 127 | return -EIO ; 128 | } 129 | for(lp = 0 ; lp < PT2_MAX_ISDB_S_INIT ; lp++) { 130 | memcpy(&wk, isdb_s_initial_pt2[lp], sizeof(WBLOCK)); 131 | wk.addr = addr; 132 | i2c_write(regs, lock, &wk); 133 | } 134 | } 135 | 136 | return 0 ; 137 | } 138 | static void init_isdb_t(void __iomem *regs, int cardtype, struct mutex *lock, __u32 addr) 139 | { 140 | int lp ; 141 | WBLOCK wk; 142 | 143 | // ISDB-S/T初期化 144 | if(cardtype == PT1) { 145 | for(lp = 0 ; lp < PT1_MAX_ISDB_T_INIT ; lp++){ 146 | memcpy(&wk, isdb_t_initial_pt1[lp], sizeof(WBLOCK)); 147 | wk.addr = addr; 148 | i2c_write(regs, lock, &wk); 149 | } 150 | } 151 | else if(cardtype == PT2) { 152 | for(lp = 0 ; lp < PT2_MAX_ISDB_T_INIT ; lp++){ 153 | memcpy(&wk, isdb_t_initial_pt2[lp], sizeof(WBLOCK)); 154 | wk.addr = addr; 155 | i2c_write(regs, lock, &wk); 156 | } 157 | } 158 | } 159 | 160 | int tuner_init(void __iomem *regs, int cardtype, struct mutex *lock, int tuner_no) 161 | { 162 | 163 | int rc ; 164 | WBLOCK wk; 165 | 166 | // ISDB-S/T初期化 167 | memcpy(&wk, &com_initdata, sizeof(WBLOCK)); 168 | 169 | // 初期化(共通) 170 | wk.addr = tuner_info[tuner_no].isdb_t ; 171 | i2c_write(regs, lock, &wk); 172 | wk.addr = tuner_info[tuner_no].isdb_s ; 173 | i2c_write(regs, lock, &wk); 174 | 175 | rc = init_isdb_s(regs, cardtype, lock, tuner_info[tuner_no].isdb_s); 176 | if(rc < 0){ 177 | return rc ; 178 | } 179 | init_isdb_t(regs, cardtype, lock, tuner_info[tuner_no].isdb_t); 180 | 181 | memcpy(&wk, &isdb_s_init21, sizeof(WBLOCK)); 182 | wk.addr = tuner_info[tuner_no].isdb_s ; 183 | i2c_write(regs, lock, &wk); 184 | 185 | memcpy(&wk, &isdb_t_init17, sizeof(WBLOCK)); 186 | wk.addr = tuner_info[tuner_no].isdb_t ; 187 | i2c_write(regs, lock, &wk); 188 | 189 | return 0 ; 190 | } 191 | void set_sleepmode(void __iomem *regs, struct mutex *lock, int address, int tuner_type, int type) 192 | { 193 | WBLOCK wk; 194 | 195 | if(type == TYPE_WAKEUP){ 196 | switch(tuner_type){ 197 | case CHANNEL_TYPE_ISDB_S: 198 | printk(KERN_INFO "PT1:ISDB-S Wakeup\n"); 199 | memcpy(&wk, &isdb_s_wake, sizeof(WBLOCK)); 200 | wk.addr = address; 201 | i2c_write(regs, lock, &wk); 202 | 203 | memcpy(&wk, &isdb_s_wake2, sizeof(WBLOCK)); 204 | wk.addr = address; 205 | i2c_write(regs, lock, &wk); 206 | break ; 207 | case CHANNEL_TYPE_ISDB_T: 208 | printk(KERN_INFO "PT1:ISDB-T Wakeup\n"); 209 | memcpy(&wk, &isdb_t_wake, sizeof(WBLOCK)); 210 | wk.addr = address; 211 | i2c_write(regs, lock, &wk); 212 | 213 | memcpy(&wk, &isdb_t_wake2, sizeof(WBLOCK)); 214 | wk.addr = address; 215 | i2c_write(regs, lock, &wk); 216 | break ; 217 | } 218 | } 219 | if(type == TYPE_SLEEP){ 220 | switch(tuner_type){ 221 | case CHANNEL_TYPE_ISDB_S: 222 | printk(KERN_INFO "PT1:ISDB-S Sleep\n"); 223 | memcpy(&wk, &isdb_s_sleep, sizeof(WBLOCK)); 224 | wk.addr = address; 225 | i2c_write(regs, lock, &wk); 226 | break ; 227 | case CHANNEL_TYPE_ISDB_T: 228 | printk(KERN_INFO "PT1:ISDB-T Sleep\n"); 229 | memcpy(&wk, &isdb_t_sleep, sizeof(WBLOCK)); 230 | wk.addr = address; 231 | i2c_write(regs, lock, &wk); 232 | break ; 233 | } 234 | } 235 | } 236 | 237 | int bs_frequency(void __iomem *regs, struct mutex *lock, int addr, int channel) 238 | { 239 | int lp ; 240 | int tmcclock = FALSE ; 241 | WBLOCK wk; 242 | __u32 val ; 243 | 244 | if(channel >= MAX_BS_CHANNEL){ 245 | return -EIO ; 246 | } 247 | // ISDB-S PLLロック 248 | for(lp = 0 ; lp < MAX_BS_CHANNEL_PLL_COMMAND ; lp++){ 249 | memcpy(&wk, bs_pll[channel].wblock[lp], sizeof(WBLOCK)); 250 | wk.addr = addr ; 251 | i2c_write(regs, lock, &wk); 252 | } 253 | 254 | // PLLロック確認 255 | // チェック用 256 | for(lp = 0 ; lp < 200 ; lp++){ 257 | memcpy(&wk, &bs_pll_lock, sizeof(WBLOCK)); 258 | wk.addr = addr; 259 | val = i2c_read(regs, lock, &wk, 1); 260 | if(((val & 0xFF) != 0) && ((val & 0XFF) != 0XFF)){ 261 | tmcclock = TRUE ; 262 | break ; 263 | } 264 | } 265 | 266 | if(tmcclock == FALSE){ 267 | printk(KERN_INFO "PLL LOCK ERROR\n"); 268 | return -EIO; 269 | } 270 | 271 | memcpy(&wk, &bs_tmcc_get_1, sizeof(WBLOCK)); 272 | wk.addr = addr; 273 | i2c_write(regs, lock, &wk); 274 | 275 | tmcclock = FALSE ; 276 | 277 | for(lp = 0 ; lp < 200 ; lp++){ 278 | memcpy(&wk, &bs_tmcc_get_2, sizeof(WBLOCK)); 279 | wk.addr = addr; 280 | 281 | val = i2c_read(regs, lock, &wk, 1); 282 | if(((val & 0XFF) != 0XFF) && (!(val & 0x10))){ 283 | tmcclock = TRUE ; 284 | break ; 285 | } 286 | } 287 | 288 | if(tmcclock == FALSE){ 289 | printk(KERN_INFO "TMCC LOCK ERROR\n"); 290 | return -EIO; 291 | } 292 | 293 | return 0 ; 294 | } 295 | int ts_lock(void __iomem *regs, struct mutex *lock, int addr, __u16 ts_id) 296 | { 297 | 298 | int lp ; 299 | WBLOCK wk; 300 | __u32 val ; 301 | union{ 302 | __u8 ts[2]; 303 | __u16 tsid; 304 | }uts_id ; 305 | 306 | uts_id.tsid = ts_id ; 307 | memcpy(&wk, &bs_set_ts_lock, sizeof(WBLOCK)); 308 | wk.addr = addr; 309 | // TS-ID設定 310 | wk.value[1] = uts_id.ts[1]; 311 | wk.value[2] = uts_id.ts[0]; 312 | i2c_write(regs, lock, &wk); 313 | 314 | for(lp = 0 ; lp < 100 ; lp++){ 315 | memcpy(&wk, &bs_get_ts_lock, sizeof(WBLOCK)); 316 | wk.addr = addr; 317 | val = i2c_read(regs, lock, &wk, 2); 318 | if((val & 0xFFFF) == ts_id){ 319 | return 0 ; 320 | } 321 | } 322 | printk(KERN_INFO "PT1:ERROR TS-LOCK(%x)\n", ts_id); 323 | return -EIO ; 324 | } 325 | int bs_tune(void __iomem *regs, struct mutex *lock, int addr, int channel, ISDB_S_TMCC *tmcc) 326 | { 327 | 328 | int lp ; 329 | int lp2; 330 | WBLOCK wk; 331 | __u32 val ; 332 | ISDB_S_TS_ID *tsid ; 333 | union{ 334 | __u8 slot[4]; 335 | __u32 u32slot; 336 | }ts_slot ; 337 | union{ 338 | __u16 ts[2]; 339 | __u32 tsid; 340 | }ts_id ; 341 | 342 | if(channel >= MAX_BS_CHANNEL){ 343 | printk(KERN_INFO "Invalid Channel(%d)\n", channel); 344 | return -EIO ; 345 | } 346 | val = bs_frequency(regs, lock, addr, channel); 347 | if(val == -EIO){ 348 | return val ; 349 | } 350 | 351 | tsid = &tmcc->ts_id[0] ; 352 | // 該当周波数のTS-IDを取得 353 | for(lp = 0 ; lp < (MAX_BS_TS_ID / 2) ; lp++){ 354 | for(lp2 = 0 ; lp2 < 100 ; lp2++){ 355 | memcpy(&wk, bs_get_ts_id[lp], sizeof(WBLOCK)); 356 | wk.addr = addr; 357 | ts_id.tsid = i2c_read(regs, lock, &wk, 4); 358 | // TS-IDが0の場合は再取得する 359 | if((ts_id.ts[0] != 0) && (ts_id.ts[1] != 0)){ 360 | break ; 361 | } 362 | } 363 | tsid->ts_id = ts_id.ts[1] ; 364 | tsid += 1; 365 | tsid->ts_id = ts_id.ts[0] ; 366 | tsid += 1; 367 | } 368 | 369 | memcpy(&wk, &bs_get_agc, sizeof(WBLOCK)); 370 | wk.addr = addr; 371 | tmcc->agc = i2c_read(regs, lock, &wk, 1); 372 | 373 | // TS-ID別の情報を取得 374 | tsid = &tmcc->ts_id[0] ; 375 | for(lp = 0 ; lp < MAX_BS_TS_ID ; lp++, tsid += 1){ 376 | // TS-IDなし=0XFFFF 377 | if(tsid->ts_id == 0xFFFF){ 378 | continue ; 379 | } 380 | ts_lock(regs, lock, addr, tsid->ts_id); 381 | 382 | //スロット取得 383 | memcpy(&wk, &bs_get_slot, sizeof(WBLOCK)); 384 | wk.addr = addr; 385 | ts_slot.u32slot = i2c_read(regs, lock, &wk, 3); 386 | tsid->high_mode = 0; 387 | tsid->low_slot = ts_slot.slot[0] ; 388 | tsid->high_slot = ts_slot.slot[1] ; 389 | tsid->low_mode = ts_slot.slot[2] ; 390 | } 391 | 392 | memcpy(&wk, &bs_get_clock, sizeof(WBLOCK)); 393 | wk.addr = addr; 394 | tmcc->clockmargin = i2c_read(regs, lock, &wk, 1); 395 | 396 | memcpy(&wk, &bs_get_carrir, sizeof(WBLOCK)); 397 | wk.addr = addr; 398 | tmcc->carriermargin = i2c_read(regs, lock, &wk, 1); 399 | return 0 ; 400 | } 401 | int isdb_s_read_signal_strength(void __iomem *regs, struct mutex *lock, int addr) 402 | { 403 | WBLOCK wk; 404 | __u32 val ; 405 | __u32 val2; 406 | int val3 ; 407 | 408 | memcpy(&wk, &bs_get_signal1, sizeof(WBLOCK)); 409 | wk.addr = addr; 410 | val = i2c_read(regs, lock, &wk, 1); 411 | 412 | memcpy(&wk, &bs_get_signal2, sizeof(WBLOCK)); 413 | wk.addr = addr; 414 | val2 = i2c_read(regs, lock, &wk, 1); 415 | val3 = (((val << 8) & 0XFF00) | (val2 & 0XFF)); 416 | 417 | return val3 ; 418 | } 419 | 420 | __u32 getfrequency_add(__u32 channel) 421 | { 422 | int lp ; 423 | 424 | for(lp = 0 ; lp < 10 ; lp++){ 425 | if(channel <= isdb_t_freq_add[lp].pos){ 426 | return isdb_t_freq_add[lp].add_freq ; 427 | } 428 | } 429 | return 0 ; 430 | } 431 | __u32 getfrequency(__u32 channel, int addfreq) 432 | { 433 | __u32 frequencyoffset = 0; 434 | __u32 frequencyOffset = 0; 435 | 436 | if (12 <= channel) 437 | frequencyoffset += 2; 438 | if (17 <= channel) 439 | frequencyoffset -= 2; 440 | if (63 <= channel){ 441 | frequencyoffset += 2; 442 | } 443 | #if 0 444 | return (((93 + channel * 6 + frequencyOffset) + addfreq) * 7) + 400; 445 | #endif 446 | frequencyOffset = 93 + channel * 6 + frequencyoffset; 447 | frequencyOffset = 7 * (frequencyOffset + addfreq); 448 | return frequencyOffset + 400; 449 | 450 | } 451 | int isdb_t_frequency(void __iomem *regs, struct mutex *lock, int addr, int channel, int addfreq) 452 | { 453 | 454 | int lp ; 455 | WBLOCK wk; 456 | __u32 val ; 457 | int tmcclock = FALSE ; 458 | union{ 459 | __u8 charfreq[2]; 460 | __u16 freq; 461 | }freq[2] ; 462 | 463 | if(channel >= MAX_ISDB_T_CHANNEL){ 464 | return -EIO ; 465 | } 466 | 467 | freq[0].freq = getfrequency(channel, addfreq); 468 | freq[1].freq = getfrequency_add(channel); 469 | //指定周波数 470 | memcpy(&wk, &isdb_t_pll_base, sizeof(WBLOCK)); 471 | wk.addr = addr ; 472 | // 計算した周波数を設定 473 | wk.value[wk.count] = freq[0].charfreq[1]; 474 | wk.count += 1 ; 475 | wk.value[wk.count] = freq[0].charfreq[0]; 476 | wk.count += 1 ; 477 | 478 | // 計算した周波数付加情報を設定 479 | wk.value[wk.count] = freq[1].charfreq[1]; 480 | wk.count += 1 ; 481 | wk.value[wk.count] = freq[1].charfreq[0]; 482 | wk.count += 1 ; 483 | 484 | i2c_write(regs, lock, &wk); 485 | 486 | for(lp = 0 ; lp < 100 ; lp++){ 487 | memcpy(&wk, &isdb_t_pll_lock, sizeof(WBLOCK)); 488 | wk.addr = addr; 489 | val = i2c_read(regs, lock, &wk, 1); 490 | if(((val & 0xFF) != 0XFF) && ((val & 0X50) == 0x50)){ 491 | tmcclock = TRUE ; 492 | break ; 493 | } 494 | } 495 | if(tmcclock != TRUE){ 496 | printk(KERN_INFO "PT1:ISDB-T LOCK NG(%08x)\n", val); 497 | return -EIO ; 498 | } 499 | 500 | memcpy(&wk, &isdb_t_check_tune, sizeof(WBLOCK)); 501 | wk.addr = addr ; 502 | i2c_write(regs, lock, &wk); 503 | 504 | tmcclock = FALSE ; 505 | for(lp = 0 ; lp < 1000 ; lp++){ 506 | memcpy(&wk, &isdb_t_tune_read, sizeof(WBLOCK)); 507 | wk.addr = addr; 508 | val = i2c_read(regs, lock, &wk, 1); 509 | if(((val & 0xFF) != 0XFF) && ((val & 0X8) != 8)){ 510 | tmcclock = TRUE ; 511 | break ; 512 | } 513 | } 514 | if(tmcclock != TRUE){ 515 | return -EIO ; 516 | } 517 | return 0 ; 518 | } 519 | int isdb_t_read_signal_strength(void __iomem *regs, struct mutex *lock, int addr) 520 | { 521 | __u32 val ; 522 | __u32 val2; 523 | __u32 val3; 524 | WBLOCK wk; 525 | 526 | memcpy(&wk, &isdb_t_signal1, sizeof(WBLOCK)); 527 | wk.addr = addr; 528 | val = i2c_read(regs, lock, &wk, 1); 529 | printk(KERN_INFO "CN(1)Val(%x)\n", val); 530 | 531 | memcpy(&wk, &isdb_t_signal2, sizeof(WBLOCK)); 532 | wk.addr = addr; 533 | val2 = i2c_read(regs, lock, &wk, 1); 534 | val3 = (((val << 8) & 0XFF00) | (val2 & 0XFF)); 535 | return val3 ; 536 | } 537 | #if 0 538 | int isdb_t_tune(void __iomem *regs, struct mutex *lock, int addr, int channel, ISDB_T_TMCC *tmcc) 539 | { 540 | 541 | int lp ; 542 | int rc ; 543 | int lp2 ; 544 | WBLOCK wk; 545 | __u32 val ; 546 | 547 | printk(KERN_INFO "Channel(%d) Start\n", channel); 548 | if(channel >= MAX_ISDB_T_CHANNEL){ 549 | return -EIO ; 550 | } 551 | rc = isdb_t_frequency(regs, lock, addr, channel); 552 | if(rc < 0){ 553 | return -EIO ; 554 | } 555 | for(lp = 0 ; lp < 100 ; lp++){ 556 | memcpy(&wk, &isdb_t_tmcc_read_1, sizeof(WBLOCK)); 557 | wk.addr = addr; 558 | val = i2c_read(regs, lock, &wk, 4); 559 | if((val & 0xFF) != 0){ 560 | break ; 561 | } 562 | } 563 | printk(KERN_INFO "TMCC(1)Val(%x)\n", val); 564 | 565 | for(lp = 0 ; lp < 100 ; lp++){ 566 | memcpy(&wk, &isdb_t_tmcc_read_2, sizeof(WBLOCK)); 567 | wk.addr = addr; 568 | val = i2c_read(regs, lock, &wk, 4); 569 | if((val & 0xFF) != 0){ 570 | break ; 571 | } 572 | } 573 | printk(KERN_INFO "TMCC(2)Val(%x)\n", val); 574 | 575 | memcpy(&wk, &isdb_t_cn_1, sizeof(WBLOCK)); 576 | wk.addr = addr; 577 | val = i2c_read(regs, lock, &wk, 1); 578 | printk(KERN_INFO "CN(1)Val(%x)\n", val); 579 | 580 | memcpy(&wk, &isdb_t_cn_2, sizeof(WBLOCK)); 581 | wk.addr = addr; 582 | val = i2c_read(regs, lock, &wk, 1); 583 | printk(KERN_INFO "CN(2)Val(%x)\n", val); 584 | 585 | memcpy(&wk, &isdb_t_agc_1, sizeof(WBLOCK)); 586 | wk.addr = addr; 587 | val = i2c_read(regs, lock, &wk, 1); 588 | printk(KERN_INFO "AGC(1)Val(%x)\n", val); 589 | 590 | memcpy(&wk, &isdb_t_agc_2, sizeof(WBLOCK)); 591 | wk.addr = addr; 592 | val = i2c_read(regs, lock, &wk, 1); 593 | printk(KERN_INFO "AGC(2)Val(%x)\n", val); 594 | return 0; 595 | } 596 | #endif 597 | -------------------------------------------------------------------------------- /recpt1/pt1_dev.h: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: nil -*- */ 2 | #ifndef _PT1_DEV_H_ 3 | #define _PT1_DEV_H_ 4 | 5 | char *bsdev[NUM_BSDEV] = { 6 | "/dev/pt1video1", 7 | "/dev/pt1video0", 8 | "/dev/pt1video5", 9 | "/dev/pt1video4", 10 | "/dev/pt1video9", 11 | "/dev/pt1video8", 12 | "/dev/pt1video13", 13 | "/dev/pt1video12", 14 | "/dev/pt3video1", 15 | "/dev/pt3video0", 16 | "/dev/pt3video5", 17 | "/dev/pt3video4", 18 | "/dev/pt3video9", 19 | "/dev/pt3video8", 20 | "/dev/pt3video13", 21 | "/dev/pt3video12", 22 | "/dev/px4video0", 23 | "/dev/px4video1", 24 | "/dev/px4video4", 25 | "/dev/px4video5", 26 | "/dev/asv52201", 27 | "/dev/asv52200", 28 | "/dev/asv52205", 29 | "/dev/asv52204", 30 | "/dev/asv52209", 31 | "/dev/asv52208", 32 | "/dev/asv522013", 33 | "/dev/asv522012", 34 | "/dev/pxq3pe0", 35 | "/dev/pxq3pe1", 36 | "/dev/pxq3pe4", 37 | "/dev/pxq3pe5", 38 | "/dev/pxq3pe8", 39 | "/dev/pxq3pe9", 40 | "/dev/pxq3pe12", 41 | "/dev/pxq3pe13", 42 | "/dev/pxw3u30", 43 | "/dev/pxw3u32", 44 | "/dev/pxs3u20", 45 | "/dev/pxs3u0", 46 | 47 | "/dev/px4-DTV0", 48 | "/dev/px4-DTV1", 49 | "/dev/px4-DTV4", 50 | "/dev/px4-DTV5", 51 | "/dev/px4-DTV8", 52 | "/dev/px4-DTV9", 53 | "/dev/px4-DTV12", 54 | "/dev/px4-DTV13", 55 | "/dev/px4-DTV16", 56 | "/dev/px4-DTV17", 57 | "/dev/px4-DTV20", 58 | "/dev/px4-DTV21", 59 | "/dev/px4-DTV24", 60 | "/dev/px4-DTV25", 61 | "/dev/px4-DTV28", 62 | "/dev/px4-DTV29", 63 | 64 | "/dev/px5-DTV0", 65 | "/dev/px5-DTV1", 66 | "/dev/px5-DTV2", 67 | "/dev/px5-DTV3", 68 | "/dev/px5-DTV4", 69 | "/dev/px5-DTV5", 70 | "/dev/px5-DTV6", 71 | "/dev/px5-DTV7", 72 | "/dev/px5-DTV8", 73 | "/dev/px5-DTV9", 74 | "/dev/px5-DTV10", 75 | "/dev/px5-DTV11", 76 | "/dev/px5-DTV12", 77 | "/dev/px5-DTV13", 78 | "/dev/px5-DTV14", 79 | "/dev/px5-DTV15", 80 | "/dev/px5-DTV16", 81 | "/dev/px5-DTV17", 82 | "/dev/px5-DTV18", 83 | "/dev/px5-DTV19", 84 | "/dev/px5-DTV20", 85 | "/dev/px5-DTV21", 86 | "/dev/px5-DTV22", 87 | "/dev/px5-DTV23", 88 | "/dev/px5-DTV24", 89 | "/dev/px5-DTV25", 90 | "/dev/px5-DTV26", 91 | "/dev/px5-DTV27", 92 | "/dev/px5-DTV28", 93 | "/dev/px5-DTV29", 94 | "/dev/px5-DTV30", 95 | "/dev/px5-DTV31" 96 | }; 97 | char *isdb_t_dev[NUM_ISDB_T_DEV] = { 98 | "/dev/pt1video2", 99 | "/dev/pt1video3", 100 | "/dev/pt1video6", 101 | "/dev/pt1video7", 102 | "/dev/pt1video10", 103 | "/dev/pt1video11", 104 | "/dev/pt1video14", 105 | "/dev/pt1video15", 106 | "/dev/pt3video2", 107 | "/dev/pt3video3", 108 | "/dev/pt3video6", 109 | "/dev/pt3video7", 110 | "/dev/pt3video10", 111 | "/dev/pt3video11", 112 | "/dev/pt3video14", 113 | "/dev/pt3video15", 114 | "/dev/px4video2", 115 | "/dev/px4video3", 116 | "/dev/px4video6", 117 | "/dev/px4video7", 118 | "/dev/asv52202", 119 | "/dev/asv52203", 120 | "/dev/asv52206", 121 | "/dev/asv52207", 122 | "/dev/asv522010", 123 | "/dev/asv522011", 124 | "/dev/asv522014", 125 | "/dev/asv522015", 126 | "/dev/pxq3pe2", 127 | "/dev/pxq3pe3", 128 | "/dev/pxq3pe6", 129 | "/dev/pxq3pe7", 130 | "/dev/pxq3pe10", 131 | "/dev/pxq3pe11", 132 | "/dev/pxq3pe14", 133 | "/dev/pxq3pe15", 134 | "/dev/pxw3u31", 135 | "/dev/pxw3u33", 136 | "/dev/pxs3u21", 137 | "/dev/pxs3u1", 138 | 139 | "/dev/px4-DTV2", 140 | "/dev/px4-DTV3", 141 | "/dev/px4-DTV6", 142 | "/dev/px4-DTV7", 143 | "/dev/px4-DTV10", 144 | "/dev/px4-DTV11", 145 | "/dev/px4-DTV14", 146 | "/dev/px4-DTV15", 147 | "/dev/px4-DTV18", 148 | "/dev/px4-DTV19", 149 | "/dev/px4-DTV22", 150 | "/dev/px4-DTV23", 151 | "/dev/px4-DTV26", 152 | "/dev/px4-DTV27", 153 | "/dev/px4-DTV30", 154 | "/dev/px4-DTV31", 155 | 156 | "/dev/px5-DTV0", 157 | "/dev/px5-DTV1", 158 | "/dev/px5-DTV2", 159 | "/dev/px5-DTV3", 160 | "/dev/px5-DTV4", 161 | "/dev/px5-DTV5", 162 | "/dev/px5-DTV6", 163 | "/dev/px5-DTV7", 164 | "/dev/px5-DTV8", 165 | "/dev/px5-DTV9", 166 | "/dev/px5-DTV10", 167 | "/dev/px5-DTV11", 168 | "/dev/px5-DTV12", 169 | "/dev/px5-DTV13", 170 | "/dev/px5-DTV14", 171 | "/dev/px5-DTV15", 172 | "/dev/px5-DTV16", 173 | "/dev/px5-DTV17", 174 | "/dev/px5-DTV18", 175 | "/dev/px5-DTV19", 176 | "/dev/px5-DTV20", 177 | "/dev/px5-DTV21", 178 | "/dev/px5-DTV22", 179 | "/dev/px5-DTV23", 180 | "/dev/px5-DTV24", 181 | "/dev/px5-DTV25", 182 | "/dev/px5-DTV26", 183 | "/dev/px5-DTV27", 184 | "/dev/px5-DTV28", 185 | "/dev/px5-DTV29", 186 | "/dev/px5-DTV30", 187 | "/dev/px5-DTV31" 188 | }; 189 | 190 | // 変換テーブル(ISDB-T用) 191 | // 実際にioctl()を行う値の部分はREADMEを参照の事。 192 | // BS/CSの設定値およびスロット番号は 193 | // http://www5e.biglobe.ne.jp/~kazu_f/digital-sat/index.htmlより取得。 194 | // 195 | 196 | ISDB_T_FREQ_CONV_TABLE isdb_t_conv_table[] = { 197 | { 0, CHTYPE_SATELLITE, 0, "151"}, /* 151ch:BS朝日 */ 198 | { 0, CHTYPE_SATELLITE, 1, "161"}, /* 161ch:BS-TBS */ 199 | { 0, CHTYPE_SATELLITE, 2, "171"}, /* 171ch:BSテレ東 */ 200 | { 1, CHTYPE_SATELLITE, 0, "191"}, /* 191ch:WOWOWプライム */ 201 | { 1, CHTYPE_SATELLITE, 1, "103"}, /* 103ch:NHKBSプレミアム*/ 202 | { 2, CHTYPE_SATELLITE, 0, "192"}, /* 192ch:WOWOWライブ */ 203 | { 2, CHTYPE_SATELLITE, 1, "193"}, /* 193ch:WOWOWシネマ */ 204 | { 4, CHTYPE_SATELLITE, 0, "211"}, /* 211ch:BS11イレブン */ 205 | { 4, CHTYPE_SATELLITE, 1, "200"}, /* 200ch:スター・チャンネル1 */ 206 | { 4, CHTYPE_SATELLITE, 2, "222"}, /* 222ch:BS12トゥエルビ */ 207 | { 5, CHTYPE_SATELLITE, 0, "231"}, /* 231ch:放送大学ex */ 208 | { 5, CHTYPE_SATELLITE, 0, "232"}, /* 232ch:放送大学on */ 209 | { 5, CHTYPE_SATELLITE, 0, "531"}, /* 531ch:放送大学ラジオ */ 210 | { 5, CHTYPE_SATELLITE, 1, "251"}, /* 251ch:BS釣りビジョン */ 211 | { 6, CHTYPE_SATELLITE, 0, "141"}, /* 141ch:BS日テレ */ 212 | { 6, CHTYPE_SATELLITE, 1, "181"}, /* 181ch:BSフジ */ 213 | { 6, CHTYPE_SATELLITE, 2, "236"}, /* 236ch:BSアニマックス */ 214 | { 7, CHTYPE_SATELLITE, 0, "101"}, /* 101ch:NHKBS1 */ 215 | { 7, CHTYPE_SATELLITE, 0, "102"}, /* 102ch:NHKBS1 */ 216 | { 7, CHTYPE_SATELLITE, 1, "201"}, /* 201ch:スター・チャンネル2 */ 217 | { 7, CHTYPE_SATELLITE, 1, "202"}, /* 202ch:スター・チャンネル3 */ 218 | { 9, CHTYPE_SATELLITE, 0, "245"}, /* 245ch:J SPORTS 4 */ 219 | { 9, CHTYPE_SATELLITE, 1, "242"}, /* 242ch:J SPORTS 1 */ 220 | { 9, CHTYPE_SATELLITE, 2, "243"}, /* 243ch:J SPORTS 2 */ 221 | { 9, CHTYPE_SATELLITE, 3, "244"}, /* 244ch:J SPORTS 3 */ 222 | { 10, CHTYPE_SATELLITE, 0, "252"}, /* 252ch:WOWOWプラス */ 223 | { 10, CHTYPE_SATELLITE, 1, "255"}, /* 255ch:日本映画専門ch */ 224 | { 10, CHTYPE_SATELLITE, 2, "234"}, /* 234ch:グリーンチャンネル */ 225 | { 11, CHTYPE_SATELLITE, 0, "256"}, /* 256ch:ディズニーch */ 226 | { 11, CHTYPE_SATELLITE, 1, "265"}, /* 265ch:BSよしもと */ 227 | { 11, CHTYPE_SATELLITE, 2, "263"}, /* 263ch:BSJapanext */ 228 | { 11, CHTYPE_SATELLITE, 3, "260"}, /* 260ch:BS松竹東急 */ 229 | { 12, CHTYPE_SATELLITE, 0, "CS2"}, /* ND2: 230 | * 237ch:スター・チャンネル プラス 231 | * 239ch:日本映画専門チャンネルHD 232 | * 306ch:フジテレビNEXT */ 233 | { 13, CHTYPE_SATELLITE, 0, "CS4"}, /* ND4: 234 | * 100ch:e2プロモ 235 | * 256ch:J sports ESPN 236 | * 312ch:FOX 237 | * 322ch:スペースシャワーTV 238 | * 331ch:カートゥーンネットワーク 239 | * 294ch:ホームドラマチャンネル 240 | * 334ch:トゥーン・ディズニー */ 241 | { 14, CHTYPE_SATELLITE, 0, "CS6"}, /* ND6: 242 | * 221ch:東映チャンネル 243 | * 222ch:衛星劇場 244 | * 223ch:チャンネルNECO 245 | * 224ch:洋画★シネフィル・イマジカ 246 | * 292ch:時代劇専門チャンネル 247 | * 238ch:スター・チャンネル クラシック 248 | * 310ch:スーパー!ドラマTV 249 | * 311ch:AXN 250 | * 250ch:スカイ・Asports+ */ 251 | { 15, CHTYPE_SATELLITE, 0, "CS8"}, /* ND8: 252 | * 055ch:ショップ チャンネル 253 | * 335ch:キッズステーションHD */ 254 | { 16, CHTYPE_SATELLITE, 0, "CS10"}, /* ND10: 255 | * 228ch:ザ・シネマ 256 | * 800ch:スカチャンHD800 257 | * 801ch:スカチャン801 258 | * 802ch:スカチャン802 */ 259 | { 17, CHTYPE_SATELLITE, 0, "CS12"}, /* ND12: 260 | * 260ch:ザ・ゴルフ・チャンネル 261 | * 303ch:テレ朝チャンネル 262 | * 323ch:MTV 324ch:大人の音楽専門TV◆ミュージック・エア 263 | * 352ch:朝日ニュースター 264 | * 353ch:BBCワールドニュース 265 | * 354ch:CNNj 266 | * 110ch:ワンテンポータル */ 267 | { 18, CHTYPE_SATELLITE, 0, "CS14"}, /* ND14: 268 | * 251ch:J sports 1 269 | * 252ch:J sports 2 270 | * 253ch:J sports Plus 271 | * 254ch:GAORA */ 272 | { 19, CHTYPE_SATELLITE, 0, "CS16"}, /* ND16: 273 | * 305ch:チャンネル銀河 274 | * 333ch:アニメシアターX(AT-X) 275 | * 342ch:ヒストリーチャンネル 276 | * 290ch:TAKARAZUKA SKYSTAGE 277 | * 803ch:スカチャン803 278 | * 804ch:スカチャン804 */ 279 | { 20, CHTYPE_SATELLITE, 0, "CS18"}, /* ND18: 280 | * 240ch:ムービープラスHD 281 | * 262ch:ゴルフネットワーク 282 | * 314ch:LaLa HDHV */ 283 | { 21, CHTYPE_SATELLITE, 0, "CS20"}, /* ND20: 284 | * 258ch:フジテレビONE 285 | * 302ch:フジテレビTWO 286 | * 332ch:アニマックス 287 | * 340ch:ディスカバリーチャンネル 288 | * 341ch:アニマルプラネット */ 289 | { 22, CHTYPE_SATELLITE, 0, "CS22"}, /* ND22: 290 | * 160ch:C-TBSウェルカムチャンネル 291 | * 161ch:QVC 292 | * 185ch:プライム365.TV 293 | * 293ch:ファミリー劇場 294 | * 301ch:TBSチャンネル 295 | * 304ch:ディズニー・チャンネル 296 | * 325ch:MUSIC ON! TV 297 | * 351ch:TBSニュースバード 298 | * 343ch:ナショナルジオグラフィックチャンネル */ 299 | { 23, CHTYPE_SATELLITE, 0, "CS24"}, /* ND24: 300 | * 257ch:日テレG+ HD 301 | * 291ch:fashiontv 302 | * 300ch:日テレプラス 303 | * 315ch:FOXプラス 304 | * 321ch:MusicJapan TV 305 | * 350ch:日テレNEWS24 306 | * 362ch:旅チャンネル*/ 307 | { 0, CHTYPE_GROUND, 0, "1"}, { 1, CHTYPE_GROUND, 0, "2"}, 308 | { 2, CHTYPE_GROUND, 0, "3"}, { 3, CHTYPE_GROUND, 0, "C13"}, 309 | { 4, CHTYPE_GROUND, 0, "C14"}, { 5, CHTYPE_GROUND, 0, "C15"}, 310 | { 6, CHTYPE_GROUND, 0, "C16"}, { 7, CHTYPE_GROUND, 0, "C17"}, 311 | { 8, CHTYPE_GROUND, 0, "C18"}, { 9, CHTYPE_GROUND, 0, "C19"}, 312 | { 10, CHTYPE_GROUND, 0, "C20"}, { 11, CHTYPE_GROUND, 0, "C21"}, 313 | { 12, CHTYPE_GROUND, 0, "C22"}, { 13, CHTYPE_GROUND, 0, "4"}, 314 | { 14, CHTYPE_GROUND, 0, "5"}, { 15, CHTYPE_GROUND, 0, "6"}, 315 | { 16, CHTYPE_GROUND, 0, "7"}, { 17, CHTYPE_GROUND, 0, "8"}, 316 | { 18, CHTYPE_GROUND, 0, "9"}, { 19, CHTYPE_GROUND, 0, "10"}, 317 | { 20, CHTYPE_GROUND, 0, "11"}, { 21, CHTYPE_GROUND, 0, "12"}, 318 | { 22, CHTYPE_GROUND, 0, "C23"}, { 23, CHTYPE_GROUND, 0, "C24"}, 319 | { 24, CHTYPE_GROUND, 0, "C25"}, { 25, CHTYPE_GROUND, 0, "C26"}, 320 | { 26, CHTYPE_GROUND, 0, "C27"}, { 27, CHTYPE_GROUND, 0, "C28"}, 321 | { 28, CHTYPE_GROUND, 0, "C29"}, { 29, CHTYPE_GROUND, 0, "C30"}, 322 | { 30, CHTYPE_GROUND, 0, "C31"}, { 31, CHTYPE_GROUND, 0, "C32"}, 323 | { 32, CHTYPE_GROUND, 0, "C33"}, { 33, CHTYPE_GROUND, 0, "C34"}, 324 | { 34, CHTYPE_GROUND, 0, "C35"}, { 35, CHTYPE_GROUND, 0, "C36"}, 325 | { 36, CHTYPE_GROUND, 0, "C37"}, { 37, CHTYPE_GROUND, 0, "C38"}, 326 | { 38, CHTYPE_GROUND, 0, "C39"}, { 39, CHTYPE_GROUND, 0, "C40"}, 327 | { 40, CHTYPE_GROUND, 0, "C41"}, { 41, CHTYPE_GROUND, 0, "C42"}, 328 | { 42, CHTYPE_GROUND, 0, "C43"}, { 43, CHTYPE_GROUND, 0, "C44"}, 329 | { 44, CHTYPE_GROUND, 0, "C45"}, { 45, CHTYPE_GROUND, 0, "C46"}, 330 | { 46, CHTYPE_GROUND, 0, "C47"}, { 47, CHTYPE_GROUND, 0, "C48"}, 331 | { 48, CHTYPE_GROUND, 0, "C49"}, { 49, CHTYPE_GROUND, 0, "C50"}, 332 | { 50, CHTYPE_GROUND, 0, "C51"}, { 51, CHTYPE_GROUND, 0, "C52"}, 333 | { 52, CHTYPE_GROUND, 0, "C53"}, { 53, CHTYPE_GROUND, 0, "C54"}, 334 | { 54, CHTYPE_GROUND, 0, "C55"}, { 55, CHTYPE_GROUND, 0, "C56"}, 335 | { 56, CHTYPE_GROUND, 0, "C57"}, { 57, CHTYPE_GROUND, 0, "C58"}, 336 | { 58, CHTYPE_GROUND, 0, "C59"}, { 59, CHTYPE_GROUND, 0, "C60"}, 337 | { 60, CHTYPE_GROUND, 0, "C61"}, { 61, CHTYPE_GROUND, 0, "C62"}, 338 | { 62, CHTYPE_GROUND, 0, "C63"}, { 63, CHTYPE_GROUND, 0, "13"}, 339 | { 64, CHTYPE_GROUND, 0, "14"}, { 65, CHTYPE_GROUND, 0, "15"}, 340 | { 66, CHTYPE_GROUND, 0, "16"}, { 67, CHTYPE_GROUND, 0, "17"}, 341 | { 68, CHTYPE_GROUND, 0, "18"}, { 69, CHTYPE_GROUND, 0, "19"}, 342 | { 70, CHTYPE_GROUND, 0, "20"}, { 71, CHTYPE_GROUND, 0, "21"}, 343 | { 72, CHTYPE_GROUND, 0, "22"}, { 73, CHTYPE_GROUND, 0, "23"}, 344 | { 74, CHTYPE_GROUND, 0, "24"}, { 75, CHTYPE_GROUND, 0, "25"}, 345 | { 76, CHTYPE_GROUND, 0, "26"}, { 77, CHTYPE_GROUND, 0, "27"}, 346 | { 78, CHTYPE_GROUND, 0, "28"}, { 79, CHTYPE_GROUND, 0, "29"}, 347 | { 80, CHTYPE_GROUND, 0, "30"}, { 81, CHTYPE_GROUND, 0, "31"}, 348 | { 82, CHTYPE_GROUND, 0, "32"}, { 83, CHTYPE_GROUND, 0, "33"}, 349 | { 84, CHTYPE_GROUND, 0, "34"}, { 85, CHTYPE_GROUND, 0, "35"}, 350 | { 86, CHTYPE_GROUND, 0, "36"}, { 87, CHTYPE_GROUND, 0, "37"}, 351 | { 88, CHTYPE_GROUND, 0, "38"}, { 89, CHTYPE_GROUND, 0, "39"}, 352 | { 90, CHTYPE_GROUND, 0, "40"}, { 91, CHTYPE_GROUND, 0, "41"}, 353 | { 92, CHTYPE_GROUND, 0, "42"}, { 93, CHTYPE_GROUND, 0, "43"}, 354 | { 94, CHTYPE_GROUND, 0, "44"}, { 95, CHTYPE_GROUND, 0, "45"}, 355 | { 96, CHTYPE_GROUND, 0, "46"}, { 97, CHTYPE_GROUND, 0, "47"}, 356 | { 98, CHTYPE_GROUND, 0, "48"}, { 99, CHTYPE_GROUND, 0, "49"}, 357 | { 100, CHTYPE_GROUND, 0, "50"}, { 101, CHTYPE_GROUND, 0, "51"}, 358 | { 102, CHTYPE_GROUND, 0, "52"}, { 103, CHTYPE_GROUND, 0, "53"}, 359 | { 104, CHTYPE_GROUND, 0, "54"}, { 105, CHTYPE_GROUND, 0, "55"}, 360 | { 106, CHTYPE_GROUND, 0, "56"}, { 107, CHTYPE_GROUND, 0, "57"}, 361 | { 108, CHTYPE_GROUND, 0, "58"}, { 109, CHTYPE_GROUND, 0, "59"}, 362 | { 110, CHTYPE_GROUND, 0, "60"}, { 111, CHTYPE_GROUND, 0, "61"}, 363 | { 112, CHTYPE_GROUND, 0, "62"}, 364 | { 0, 0, 0, NULL} /* terminate */ 365 | }; 366 | #endif 367 | -------------------------------------------------------------------------------- /recpt1/recpt1core.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "recpt1core.h" 4 | #include "version.h" 5 | #include "pt1_dev.h" 6 | 7 | #define ISDB_T_NODE_LIMIT 24 // 32:ARIB limit 24:program maximum 8 | #define ISDB_T_SLOT_LIMIT 8 9 | 10 | /* globals */ 11 | boolean f_exit = FALSE; 12 | char bs_channel_buf[8]; 13 | ISDB_T_FREQ_CONV_TABLE isdb_t_conv_set = { 0, CHTYPE_SATELLITE, 0, bs_channel_buf }; 14 | 15 | 16 | #if 0 17 | /* lookup frequency conversion table*/ 18 | ISDB_T_FREQ_CONV_TABLE * 19 | searchrecoff(char *channel) 20 | { 21 | int lp; 22 | 23 | for(lp = 0; isdb_t_conv_table[lp].parm_freq != NULL; lp++) { 24 | /* return entry number in the table when strings match and 25 | * lengths are same. */ 26 | if((memcmp(isdb_t_conv_table[lp].parm_freq, channel, 27 | strlen(channel)) == 0) && 28 | (strlen(channel) == strlen(isdb_t_conv_table[lp].parm_freq))) { 29 | return &isdb_t_conv_table[lp]; 30 | } 31 | } 32 | return NULL; 33 | } 34 | #endif 35 | 36 | /* lookup frequency conversion table*/ 37 | ISDB_T_FREQ_CONV_TABLE * 38 | searchrecoff(char *channel) 39 | { 40 | int lp; 41 | 42 | if(channel[0] == 'B' && channel[1] == 'S') { 43 | int node = 0; 44 | int slot = 0; 45 | char *bs_ch; 46 | 47 | bs_ch = channel + 2; 48 | while(isdigit(*bs_ch)) { 49 | node *= 10; 50 | node += *bs_ch++ - '0'; 51 | } 52 | if(*bs_ch == '_' && (node&0x01) && node < ISDB_T_NODE_LIMIT) { 53 | if(isdigit(*++bs_ch)) { 54 | slot = *bs_ch - '0'; 55 | if(*++bs_ch == '\0' && slot < ISDB_T_SLOT_LIMIT) { 56 | isdb_t_conv_set.set_freq = node / 2; 57 | isdb_t_conv_set.add_freq = slot; 58 | sprintf(bs_channel_buf, "BS%d_%d", node, slot); 59 | return &isdb_t_conv_set; 60 | } 61 | } 62 | } 63 | return NULL; 64 | } 65 | for(lp = 0; isdb_t_conv_table[lp].parm_freq != NULL; lp++) { 66 | /* return entry number in the table when strings match and 67 | * lengths are same. */ 68 | if((memcmp(isdb_t_conv_table[lp].parm_freq, channel, 69 | strlen(channel)) == 0) && 70 | (strlen(channel) == strlen(isdb_t_conv_table[lp].parm_freq))) { 71 | return &isdb_t_conv_table[lp]; 72 | } 73 | } 74 | return NULL; 75 | } 76 | 77 | int 78 | close_tuner(thread_data *tdata) 79 | { 80 | int rv = 0; 81 | 82 | if(tdata->tfd == -1) 83 | return rv; 84 | 85 | if(tdata->table->type == CHTYPE_SATELLITE) { 86 | if(ioctl(tdata->tfd, LNB_DISABLE, 0) < 0) { 87 | rv = 1; 88 | } 89 | } 90 | close(tdata->tfd); 91 | tdata->tfd = -1; 92 | 93 | return rv; 94 | } 95 | 96 | float 97 | getsignal_isdb_s(int signal) 98 | { 99 | /* apply linear interpolation */ 100 | static const float afLevelTable[] = { 101 | 24.07f, // 00 00 0 24.07dB 102 | 24.07f, // 10 00 4096 24.07dB 103 | 18.61f, // 20 00 8192 18.61dB 104 | 15.21f, // 30 00 12288 15.21dB 105 | 12.50f, // 40 00 16384 12.50dB 106 | 10.19f, // 50 00 20480 10.19dB 107 | 8.140f, // 60 00 24576 8.140dB 108 | 6.270f, // 70 00 28672 6.270dB 109 | 4.550f, // 80 00 32768 4.550dB 110 | 3.730f, // 88 00 34816 3.730dB 111 | 3.630f, // 88 FF 35071 3.630dB 112 | 2.940f, // 90 00 36864 2.940dB 113 | 1.420f, // A0 00 40960 1.420dB 114 | 0.000f // B0 00 45056 -0.01dB 115 | }; 116 | 117 | unsigned char sigbuf[4]; 118 | memset(sigbuf, '\0', sizeof(sigbuf)); 119 | sigbuf[0] = (((signal & 0xFF00) >> 8) & 0XFF); 120 | sigbuf[1] = (signal & 0xFF); 121 | 122 | /* calculate signal level */ 123 | if(sigbuf[0] <= 0x10U) { 124 | /* clipped maximum */ 125 | return 24.07f; 126 | } 127 | else if (sigbuf[0] >= 0xB0U) { 128 | /* clipped minimum */ 129 | return 0.0f; 130 | } 131 | else { 132 | /* linear interpolation */ 133 | const float fMixRate = 134 | (float)(((unsigned short)(sigbuf[0] & 0x0FU) << 8) | 135 | (unsigned short)sigbuf[0]) / 4096.0f; 136 | return afLevelTable[sigbuf[0] >> 4] * (1.0f - fMixRate) + 137 | afLevelTable[(sigbuf[0] >> 4) + 0x01U] * fMixRate; 138 | } 139 | } 140 | 141 | void 142 | calc_cn(int fd, int type, boolean use_bell) 143 | { 144 | int rc; 145 | double P; 146 | double CNR; 147 | int bell = 0; 148 | 149 | if(ioctl(fd, GET_SIGNAL_STRENGTH, &rc) < 0) { 150 | fprintf(stderr, "Tuner Select Error\n"); 151 | return ; 152 | } 153 | 154 | if(type == CHTYPE_GROUND) { 155 | P = log10(5505024/(double)rc) * 10; 156 | CNR = (0.000024 * P * P * P * P) - (0.0016 * P * P * P) + 157 | (0.0398 * P * P) + (0.5491 * P)+3.0965; 158 | } 159 | else { 160 | CNR = getsignal_isdb_s(rc); 161 | } 162 | 163 | if(use_bell) { 164 | if(CNR >= 30.0) 165 | bell = 3; 166 | else if(CNR >= 15.0 && CNR < 30.0) 167 | bell = 2; 168 | else if(CNR < 15.0) 169 | bell = 1; 170 | fprintf(stderr, "\rC/N = %fdB ", CNR); 171 | do_bell(bell); 172 | } 173 | else { 174 | fprintf(stderr, "\rC/N = %fdB", CNR); 175 | } 176 | } 177 | 178 | void 179 | show_channels(void) 180 | { 181 | FILE *f; 182 | char *home; 183 | char buf[255], filename[255]; 184 | 185 | fprintf(stderr, "Available Channels:\n"); 186 | 187 | home = getenv("HOME"); 188 | sprintf(filename, "%s/.recpt1-channels", home); 189 | f = fopen(filename, "r"); 190 | if(f) { 191 | while(fgets(buf, 255, f)) 192 | fprintf(stderr, "%s", buf); 193 | fclose(f); 194 | } 195 | else 196 | fprintf(stderr, "13-62: Terrestrial Channels\n"); 197 | 198 | fprintf(stderr, "BS01_0: BS朝日\n"); 199 | fprintf(stderr, "BS01_1: BS-TBS\n"); 200 | fprintf(stderr, "BS01_2: BSテレ東\n"); 201 | fprintf(stderr, "BS03_0: WOWOWプライム\n"); 202 | fprintf(stderr, "BS03_1: NHKBSプレミアム\n"); 203 | fprintf(stderr, "BS05_0: WOWOWライブ\n"); 204 | fprintf(stderr, "BS05_1: WOWOWシネマ\n"); 205 | fprintf(stderr, "BS09_0: BS11イレブン\n"); 206 | fprintf(stderr, "BS09_1: スターチャンネル1\n"); 207 | fprintf(stderr, "BS09_2: BS12トゥエルビ\n"); 208 | fprintf(stderr, "BS11_0: 放送大学\n"); 209 | fprintf(stderr, "BS11_1: BS釣りビジョン\n"); 210 | fprintf(stderr, "BS13_0: BS日テレ\n"); 211 | fprintf(stderr, "BS13_1: BSフジ\n"); 212 | fprintf(stderr, "BS13_2: BSアニマックス\n"); 213 | fprintf(stderr, "BS15_0: NHKBS1\n"); 214 | fprintf(stderr, "BS15_1: スターチャンネル2/3\n"); 215 | fprintf(stderr, "BS19_0: J SPORTS 4\n"); 216 | fprintf(stderr, "BS19_1: J SPORTS 1\n"); 217 | fprintf(stderr, "BS19_2: J SPORTS 2\n"); 218 | fprintf(stderr, "BS19_3: J SPORTS 3\n"); 219 | fprintf(stderr, "BS21_0: WOWOWプラス\n"); 220 | fprintf(stderr, "BS21_1: 日本映画専門ch\n"); 221 | fprintf(stderr, "BS21_2: グリーンチャンネル\n"); 222 | fprintf(stderr, "BS23_0: ディズニーch\n"); 223 | fprintf(stderr, "BS23_1: BSよしもと\n"); 224 | fprintf(stderr, "BS23_2: BSJapanext\n"); 225 | fprintf(stderr, "BS23_3: BS松竹東急\n"); 226 | fprintf(stderr, "C13-C63: CATV Channels\n"); 227 | fprintf(stderr, "CS2-CS24: CS Channels\n"); 228 | } 229 | 230 | 231 | #if 0 232 | int 233 | parse_time(char *rectimestr, thread_data *tdata) 234 | { 235 | /* indefinite */ 236 | if(!strcmp("-", rectimestr)) { 237 | tdata->indefinite = TRUE; 238 | tdata->recsec = -1; 239 | return 0; 240 | } 241 | /* colon */ 242 | else if(strchr(rectimestr, ':')) { 243 | int n1, n2, n3; 244 | if(sscanf(rectimestr, "%d:%d:%d", &n1, &n2, &n3) == 3) 245 | tdata->recsec = n1 * 3600 + n2 * 60 + n3; 246 | else if(sscanf(rectimestr, "%d:%d", &n1, &n2) == 2) 247 | tdata->recsec = n1 * 3600 + n2 * 60; 248 | else 249 | return 1; 250 | return 0; 251 | } 252 | /* HMS */ 253 | else { 254 | char *tmpstr; 255 | char *p1, *p2; 256 | int flag; 257 | 258 | if( *rectimestr == '-' ){ 259 | rectimestr++; 260 | flag = 1; 261 | }else 262 | flag = 0; 263 | tmpstr = strdup(rectimestr); 264 | p1 = tmpstr; 265 | while(*p1 && !isdigit(*p1)) 266 | p1++; 267 | 268 | /* hour */ 269 | if((p2 = strchr(p1, 'H')) || (p2 = strchr(p1, 'h'))) { 270 | *p2 = '\0'; 271 | tdata->recsec += atoi(p1) * 3600; 272 | p1 = p2 + 1; 273 | while(*p1 && !isdigit(*p1)) 274 | p1++; 275 | } 276 | 277 | /* minute */ 278 | if((p2 = strchr(p1, 'M')) || (p2 = strchr(p1, 'm'))) { 279 | *p2 = '\0'; 280 | tdata->recsec += atoi(p1) * 60; 281 | p1 = p2 + 1; 282 | while(*p1 && !isdigit(*p1)) 283 | p1++; 284 | } 285 | 286 | /* second */ 287 | tdata->recsec += atoi(p1); 288 | if( flag ) 289 | *recsec *= -1; 290 | 291 | free(tmpstr); 292 | return 0; 293 | } /* else */ 294 | 295 | return 1; /* unsuccessful */ 296 | } 297 | #endif 298 | 299 | int 300 | parse_time(char *rectimestr, int *recsec) 301 | { 302 | /* indefinite */ 303 | if(!strcmp("-", rectimestr)) { 304 | *recsec = -1; 305 | return 0; 306 | } 307 | /* colon */ 308 | else if(strchr(rectimestr, ':')) { 309 | int n1, n2, n3; 310 | if(sscanf(rectimestr, "%d:%d:%d", &n1, &n2, &n3) == 3) 311 | *recsec = n1 * 3600 + n2 * 60 + n3; 312 | else if(sscanf(rectimestr, "%d:%d", &n1, &n2) == 2) 313 | *recsec = n1 * 3600 + n2 * 60; 314 | else 315 | return 1; /* unsuccessful */ 316 | 317 | return 0; 318 | } 319 | /* HMS */ 320 | else { 321 | char *tmpstr; 322 | char *p1, *p2; 323 | int flag; 324 | 325 | if( *rectimestr == '-' ){ 326 | rectimestr++; 327 | flag = 1; 328 | }else 329 | flag = 0; 330 | tmpstr = strdup(rectimestr); 331 | p1 = tmpstr; 332 | while(*p1 && !isdigit(*p1)) 333 | p1++; 334 | 335 | /* hour */ 336 | if((p2 = strchr(p1, 'H')) || (p2 = strchr(p1, 'h'))) { 337 | *p2 = '\0'; 338 | *recsec += atoi(p1) * 3600; 339 | p1 = p2 + 1; 340 | while(*p1 && !isdigit(*p1)) 341 | p1++; 342 | } 343 | 344 | /* minute */ 345 | if((p2 = strchr(p1, 'M')) || (p2 = strchr(p1, 'm'))) { 346 | *p2 = '\0'; 347 | *recsec += atoi(p1) * 60; 348 | p1 = p2 + 1; 349 | while(*p1 && !isdigit(*p1)) 350 | p1++; 351 | } 352 | 353 | /* second */ 354 | *recsec += atoi(p1); 355 | if( flag ) 356 | *recsec *= -1; 357 | 358 | free(tmpstr); 359 | 360 | return 0; 361 | } /* else */ 362 | 363 | return 1; /* unsuccessful */ 364 | } 365 | 366 | void 367 | do_bell(int bell) 368 | { 369 | int i; 370 | for(i=0; i < bell; i++) { 371 | fprintf(stderr, "\a"); 372 | usleep(400000); 373 | } 374 | } 375 | 376 | /* from checksignal.c */ 377 | int 378 | tune(char *channel, thread_data *tdata, char *device) 379 | { 380 | char **tuner; 381 | int num_devs; 382 | int lp; 383 | FREQUENCY freq; 384 | 385 | /* get channel */ 386 | tdata->table = searchrecoff(channel); 387 | if(tdata->table == NULL) { 388 | fprintf(stderr, "Invalid Channel: %s\n", channel); 389 | return 1; 390 | } 391 | 392 | freq.frequencyno = tdata->table->set_freq; 393 | freq.slot = tdata->table->add_freq; 394 | 395 | /* open tuner */ 396 | /* case 1: specified tuner device */ 397 | if(device) { 398 | tdata->tfd = open(device, O_RDONLY); 399 | if(tdata->tfd < 0) { 400 | fprintf(stderr, "Cannot open tuner device: %s\n", device); 401 | return 1; 402 | } 403 | 404 | /* power on LNB */ 405 | if(tdata->table->type == CHTYPE_SATELLITE) { 406 | if(ioctl(tdata->tfd, LNB_ENABLE, tdata->lnb) < 0) { 407 | fprintf(stderr, "Power on LNB failed: %s\n", device); 408 | } 409 | } 410 | 411 | /* tune to specified channel */ 412 | while(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) { 413 | if(tdata->tune_persistent) { 414 | if(f_exit) { 415 | close_tuner(tdata); 416 | return 1; 417 | } 418 | fprintf(stderr, "No signal. Still trying: %s\n", device); 419 | } 420 | else { 421 | close(tdata->tfd); 422 | fprintf(stderr, "Cannot tune to the specified channel: %s\n", device); 423 | return 1; 424 | } 425 | } 426 | 427 | fprintf(stderr, "device = %s\n", device); 428 | } 429 | else { 430 | /* case 2: loop around available devices */ 431 | if(tdata->table->type == CHTYPE_SATELLITE) { 432 | tuner = bsdev; 433 | num_devs = NUM_BSDEV; 434 | } 435 | else { 436 | tuner = isdb_t_dev; 437 | num_devs = NUM_ISDB_T_DEV; 438 | } 439 | 440 | for(lp = 0; lp < num_devs; lp++) { 441 | int count = 0; 442 | 443 | tdata->tfd = open(tuner[lp], O_RDONLY); 444 | if(tdata->tfd >= 0) { 445 | /* power on LNB */ 446 | if(tdata->table->type == CHTYPE_SATELLITE) { 447 | if(ioctl(tdata->tfd, LNB_ENABLE, tdata->lnb) < 0) { 448 | fprintf(stderr, "Warning: Power on LNB failed: %s\n", tuner[lp]); 449 | } 450 | } 451 | 452 | /* tune to specified channel */ 453 | if(tdata->tune_persistent) { 454 | while(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0 && 455 | count < MAX_RETRY) { 456 | if(f_exit) { 457 | close_tuner(tdata); 458 | return 1; 459 | } 460 | fprintf(stderr, "No signal. Still trying: %s\n", tuner[lp]); 461 | count++; 462 | } 463 | 464 | if(count >= MAX_RETRY) { 465 | close_tuner(tdata); 466 | count = 0; 467 | continue; 468 | } 469 | } /* tune_persistent */ 470 | else { 471 | if(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) { 472 | close(tdata->tfd); 473 | tdata->tfd = -1; 474 | continue; 475 | } 476 | } 477 | 478 | if(tdata->tune_persistent) 479 | fprintf(stderr, "device = %s\n", tuner[lp]); 480 | break; /* found suitable tuner */ 481 | } 482 | } 483 | 484 | /* all tuners cannot be used */ 485 | if(tdata->tfd < 0) { 486 | fprintf(stderr, "Cannot tune to the specified channel\n"); 487 | return 1; 488 | } 489 | } 490 | 491 | if(!tdata->tune_persistent) { 492 | /* show signal strength */ 493 | calc_cn(tdata->tfd, tdata->table->type, FALSE); 494 | } 495 | 496 | return 0; /* success */ 497 | } 498 | 499 | 500 | #if 0 501 | /* from recpt1.c */ 502 | int 503 | tune(char *channel, thread_data *tdata, char *device) 504 | { 505 | char **tuner; 506 | int num_devs; 507 | int lp; 508 | FREQUENCY freq; 509 | 510 | /* get channel */ 511 | tdata->table = searchrecoff(channel); 512 | if(tdata->table == NULL) { 513 | fprintf(stderr, "Invalid Channel: %s\n", channel); 514 | return 1; 515 | } 516 | 517 | freq.frequencyno = tdata->table->set_freq; 518 | freq.slot = tdata->table->add_freq; 519 | 520 | /* open tuner */ 521 | /* case 1: specified tuner device */ 522 | if(device) { 523 | tdata->tfd = open(device, O_RDONLY); 524 | if(tdata->tfd < 0) { 525 | fprintf(stderr, "Cannot open tuner device: %s\n", device); 526 | return 1; 527 | } 528 | 529 | /* power on LNB */ 530 | if(tdata->table->type == CHTYPE_SATELLITE) { 531 | if(ioctl(tdata->tfd, LNB_ENABLE, tdata->lnb) < 0) { 532 | fprintf(stderr, "Power on LNB failed: %s\n", device); 533 | } 534 | } 535 | 536 | /* tune to specified channel */ 537 | if(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) { 538 | close(tdata->tfd); 539 | fprintf(stderr, "Cannot tune to the specified channel: %s\n", device); 540 | return 1; 541 | } 542 | } 543 | else { 544 | /* case 2: loop around available devices */ 545 | if(tdata->table->type == CHTYPE_SATELLITE) { 546 | tuner = bsdev; 547 | num_devs = NUM_BSDEV; 548 | } 549 | else { 550 | tuner = isdb_t_dev; 551 | num_devs = NUM_ISDB_T_DEV; 552 | } 553 | 554 | for(lp = 0; lp < num_devs; lp++) { 555 | tdata->tfd = open(tuner[lp], O_RDONLY); 556 | if(tdata->tfd >= 0) { 557 | /* power on LNB */ 558 | if(tdata->table->type == CHTYPE_SATELLITE) { 559 | if(ioctl(tdata->tfd, LNB_ENABLE, tdata->lnb) < 0) { 560 | fprintf(stderr, "Warning: Power on LNB failed: %s\n", tuner[lp]); 561 | } 562 | } 563 | 564 | /* tune to specified channel */ 565 | if(ioctl(tdata->tfd, SET_CHANNEL, &freq) < 0) { 566 | close(tdata->tfd); 567 | tdata->tfd = -1; 568 | continue; 569 | } 570 | 571 | break; /* found suitable tuner */ 572 | } 573 | } 574 | 575 | /* all tuners cannot be used */ 576 | if(tdata->tfd < 0) { 577 | fprintf(stderr, "Cannot tune to the specified channel\n"); 578 | return 1; 579 | } 580 | } 581 | 582 | /* show signal strength */ 583 | calc_cn(tdata->tfd, tdata->table->type, FALSE); 584 | 585 | return 0; /* success */ 586 | } 587 | #endif 588 | -------------------------------------------------------------------------------- /recpt1/tssplitter_lite.c: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: t -*- */ 2 | /* tssplitter_lite.c -- split TS stream. 3 | 4 | Copyright 2009 querulous 5 | Copyright 2010 Naoya OYAMA 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include "decoder.h" 29 | #include "recpt1.h" 30 | #include "tssplitter_lite.h" 31 | 32 | /* prototypes */ 33 | static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf); 34 | static int AnalyzePat(splitter *sp, unsigned char *buf); 35 | static int RecreatePat(splitter *sp, unsigned char *buf, int *pos); 36 | static char** AnalyzeSid(char *sid); 37 | static int AnalyzePmt(splitter *sp, unsigned char *buf, unsigned char mark); 38 | static int GetCrc32(unsigned char *data, int len); 39 | static int GetPid(unsigned char *data); 40 | 41 | /** 42 | * サービスID解析 43 | */ 44 | static char** AnalyzeSid( 45 | char* sid) // [in] サービスID(カンマ区切りテキスト) 46 | { 47 | int i = 0; 48 | char** sid_list = NULL; 49 | char* p; 50 | int CommaNum = 0; 51 | 52 | /* sid は次の形式の引数を許容する */ 53 | /* 指定無し */ 54 | /* SID[0] */ 55 | /* SID[0],SID[1],...,SID[N-1],SID[N] */ 56 | 57 | /*カンマの数を数える*/ 58 | p = sid; 59 | while(*p != '\0') 60 | { 61 | if( *p == C_CHAR_COMMA ){ 62 | CommaNum++; 63 | } 64 | p++; 65 | } 66 | 67 | /* sid_listの数はカンマの数+2(NULL止めするから) */ 68 | sid_list = malloc(sizeof(char*)*(CommaNum+2)); 69 | if ( sid_list == NULL ) 70 | { 71 | fprintf(stderr, "AnalyzeSid() malloc error.\n"); 72 | return NULL; 73 | } 74 | 75 | /* sidが空である場合 */ 76 | p = sid; 77 | if ( strlen(p) == 0 ) 78 | { 79 | sid_list[0] = NULL; 80 | return sid_list; 81 | } 82 | 83 | /* カンマ無し */ 84 | if ( CommaNum == 0 ) 85 | { 86 | sid_list[0] = sid; 87 | sid_list[1] = NULL; 88 | return sid_list; 89 | } 90 | 91 | /* カンマ区切りで複数指定時 */ 92 | i=0; 93 | p = sid; 94 | /* 文字列端に到達するか、カンマ数が数えた数に達したら終了 */ 95 | while((*p != '\0') || i < CommaNum) 96 | { 97 | /* 現在の処理位置をsid_list[i]にセット */ 98 | /* このタイミングの p は 99 | * ・sid先頭 100 | * ・[,]の次の文字 101 | * いずれかであるので p を sid_list[i] に代入してよい 102 | */ 103 | sid_list[i] = p; 104 | i++; 105 | 106 | /* 最初に現れる[,]をNULL文字で置換する */ 107 | p = strchr(p, C_CHAR_COMMA); 108 | if ( p == NULL ) 109 | { 110 | /* カンマが見つからない場合は最後の処理対象なので終了 */ 111 | break; 112 | } 113 | *p = '\0'; 114 | /* 処理位置をNULLで置換した文字の次の位置に設定する */ 115 | p++; 116 | } 117 | 118 | /* 最後のsid_list[n]はNULLポインタで止める */ 119 | sid_list[i] = NULL; 120 | 121 | i=0; 122 | while( sid_list[i] != NULL ) 123 | { 124 | i++; 125 | } 126 | #if 0 127 | for(i=0; sid_list[i] != NULL; i++) 128 | { 129 | printf("sid_list[%d]=[%s].\n",i, sid_list[i]); 130 | } 131 | #endif 132 | return sid_list; 133 | } 134 | 135 | /** 136 | * 初期化処理 137 | */ 138 | splitter* split_startup( 139 | char *sid // [in] サービスID(引数で指定した文字列) 140 | ) 141 | { 142 | splitter* sp; 143 | sp = malloc(sizeof(splitter)); 144 | if ( sp == NULL ) 145 | { 146 | fprintf(stderr, "split_startup malloc error.\n"); 147 | return NULL; 148 | } 149 | memset(sp->pids, 0, sizeof(sp->pids)); 150 | memset(sp->pmt_pids, 0, sizeof(sp->pmt_pids)); 151 | 152 | sp->sid_list = NULL; 153 | sp->pat = NULL; 154 | sp->sid_list = AnalyzeSid(sid); 155 | if ( sp->sid_list == NULL ) 156 | { 157 | free(sp); 158 | return NULL; 159 | } 160 | sp->pat_count = 0xFF; 161 | sp->pmt_retain = -1; 162 | sp->pmt_counter = 0; 163 | 164 | memset(sp->section_remain, 0U, sizeof(sp->section_remain)); 165 | memset(sp->packet_seq, 0U, sizeof(sp->packet_seq)); 166 | 167 | return sp; 168 | } 169 | 170 | /** 171 | * 落とすPIDを確定させる 172 | */ 173 | int split_select( 174 | splitter *sp, // [in/out] splitter構造体 175 | ARIB_STD_B25_BUFFER *sbuf // [in] 入力TS 176 | ) 177 | { 178 | int result; 179 | // TS解析 180 | result = ReadTs(sp, sbuf); 181 | 182 | return result; 183 | } 184 | 185 | /** 186 | * 終了処理 187 | */ 188 | void split_shutdown(splitter* sp) 189 | { 190 | if ( sp != NULL ) { 191 | if ( sp->pat != NULL ) 192 | { 193 | free(sp->pat); 194 | sp->pat = NULL; 195 | } 196 | if ( sp->sid_list != NULL ) 197 | { 198 | free(sp->sid_list); 199 | sp->sid_list = NULL; 200 | } 201 | free(sp); 202 | sp = NULL; 203 | } 204 | } 205 | 206 | /** 207 | * TS 解析処理 208 | * 209 | * 対象のチャンネル番号のみの PAT の再構築と出力対象 PID の抽出を行う 210 | */ 211 | static int ReadTs(splitter *sp, ARIB_STD_B25_BUFFER *sbuf) 212 | #if 0 213 | unsigned char **pat, // [out] PAT 情報(再構築後) 214 | unsigned char* pids, // [out] 出力対象 PID 情報 215 | char** sid_list, // [in] 出力対象サービス ID のリスト 216 | unsigned char* pmt_pids, // [in] 出力対象PIDのPMT PID 217 | , // [in] pt1_drvの入力TS 218 | int* pmt_retain, // [in] 残すべきPMTの数 219 | int* pmt_counter // [out] 残したPMTの数 220 | #endif 221 | { 222 | int length = sbuf->size; 223 | int pid; 224 | int result = TSS_ERROR; 225 | int index; 226 | int analyze_result = 0; 227 | 228 | index = 0; 229 | while(length - index - LENGTH_PACKET > 0) { 230 | pid = GetPid(sbuf->data + index + 1); 231 | // PAT 232 | if(0x0000 == pid) { 233 | result = AnalyzePat(sp, sbuf->data + index); 234 | if(result != TSS_SUCCESS) { 235 | /* 下位の関数内部でmalloc error発生 */ 236 | return result; 237 | } 238 | } 239 | 240 | // PMT 241 | /* 残すpmt_pidである場合には、pmtに書かれている 242 | * 残すべきPCR/AUDIO/VIDEO PIDを取得する */ 243 | if(sp->pmt_pids[pid] == 1) { 244 | /* この中にはPMT毎に一度しか入らないようにしておく */ 245 | analyze_result = AnalyzePmt(sp, sbuf->data + index, 1); 246 | if(TSS_SUCCESS == analyze_result) { 247 | sp->pmt_pids[pid]++; 248 | sp->pmt_counter += 1; 249 | *(sbuf->data + index + 1) = 0xff; 250 | *(sbuf->data + index + 2) = 0xff; 251 | } 252 | } 253 | /* 録画する全てのPMTについて、中にあるPCR/AUDIO/VIDEOのPIDを 254 | * 得る */ 255 | /* pmt_counter と pmt_retain が一致する場合に条件は満たされる */ 256 | if(sp->pmt_counter == sp->pmt_retain) { 257 | result = TSS_SUCCESS; 258 | break; 259 | } 260 | else { 261 | result = TSS_ERROR; 262 | } 263 | index += LENGTH_PACKET; 264 | } 265 | 266 | return(result); 267 | } 268 | 269 | static int RescanPID(splitter *splitter, unsigned char *buf) 270 | { 271 | int result = TSS_NULL; 272 | int i; 273 | 274 | // clear 275 | if (splitter->pmt_counter == splitter->pmt_retain) { 276 | memcpy(splitter->pids, splitter->pmt_pids, sizeof(splitter->pids)); 277 | splitter->pmt_counter = 0; 278 | memset(splitter->section_remain, 0U, sizeof(splitter->section_remain)); 279 | memset(splitter->packet_seq, 0U, sizeof(splitter->packet_seq)); 280 | 281 | fprintf(stderr, "Rescan PID \n"); 282 | } 283 | 284 | if (TSS_SUCCESS == AnalyzePmt(splitter, buf, 2)) { 285 | splitter->pmt_counter += 1; 286 | } 287 | 288 | if (splitter->pmt_retain == splitter->pmt_counter) { 289 | result = TSS_SUCCESS; 290 | for (i = 0; MAX_PID > i; i++) { 291 | if (splitter->pids[i] > 0) { 292 | splitter->pids[i] -= 1; 293 | } 294 | } 295 | fprintf(stderr, "Rescan PID End\n"); 296 | } 297 | 298 | return result; 299 | } 300 | /** 301 | * TS 分離処理 302 | */ 303 | int split_ts( 304 | splitter *splitter, // [in] splitterパラメータ 305 | ARIB_STD_B25_BUFFER *sbuf, // [in] 入力TS 306 | splitbuf_t *dbuf // [out] 出力TS 307 | ) 308 | { 309 | int pid; 310 | unsigned char *sptr, *dptr; 311 | int s_offset = 0; 312 | int d_offset = 0; 313 | int result = TSS_SUCCESS; 314 | int pmts = 0; 315 | int version = 0; 316 | 317 | /* 初期化 */ 318 | dbuf->buffer_filled = 0; 319 | if (sbuf->size < 0) { 320 | return TSS_ERROR; 321 | } 322 | 323 | sptr = sbuf->data; 324 | dptr = dbuf->buffer; 325 | 326 | while(sbuf->size > s_offset) { 327 | pid = GetPid(sptr + s_offset + 1); 328 | switch(pid) { 329 | 330 | // PAT 331 | case 0x0000: 332 | // 巡回カウンタカウントアップ 333 | if(0xFF == splitter->pat_count) { 334 | splitter->pat_count = splitter->pat[3]; 335 | } 336 | else { 337 | splitter->pat_count += 1; 338 | if(0 == splitter->pat_count % 0x10) { 339 | splitter->pat_count -= 0x10; 340 | } 341 | } 342 | splitter->pat[3] = splitter->pat_count; 343 | 344 | memcpy(dptr + d_offset, splitter->pat, LENGTH_PACKET); 345 | d_offset += LENGTH_PACKET; 346 | dbuf->buffer_filled += LENGTH_PACKET; 347 | break; 348 | default: 349 | if(0 != splitter->pmt_pids[pid]) { 350 | //PMT 351 | if ((sptr + s_offset)[1] & 0x40) { // PES開始インジケータ 352 | // バージョンチェック 353 | for(pmts = 0; splitter->pmt_retain > pmts; pmts++) { 354 | if (splitter->pmt_version[pmts].pid == pid) { 355 | version = splitter->pmt_version[pmts].version; 356 | break; 357 | } 358 | } 359 | if((version != ((sptr + s_offset)[10] & 0x3e)) 360 | ||(splitter->pmt_retain != splitter->pmt_counter)) { 361 | // 再チェック 362 | result = RescanPID(splitter, sptr + s_offset); 363 | } 364 | } 365 | else { 366 | if (splitter->pmt_retain != splitter->pmt_counter) { 367 | // 再チェック 368 | result = RescanPID(splitter, sptr + s_offset); 369 | } 370 | } 371 | } 372 | /* pids[pid] が 1 は残すパケットなので書き込む */ 373 | if(0 != splitter->pids[pid]) { 374 | memcpy(dptr + d_offset, sptr + s_offset, LENGTH_PACKET); 375 | d_offset += LENGTH_PACKET; 376 | dbuf->buffer_filled += LENGTH_PACKET; 377 | } 378 | break; 379 | } /* switch */ 380 | 381 | s_offset += LENGTH_PACKET; 382 | } 383 | 384 | return result; 385 | } 386 | 387 | /** 388 | * PAT 解析処理 389 | * 390 | * PAT を解析し、出力対象チャンネルが含まれているかチェックを行い、PAT を再構築する 391 | */ 392 | static int AnalyzePat(splitter *sp, unsigned char *buf) 393 | #if 0 394 | splitter *sp 395 | unsigned char** pat, // [out] PAT 情報(再構築後) 396 | unsigned char* pids, // [out] 出力対象 PID 情報 397 | char** sid_list, // [in] 出力対象サービス ID のリスト 398 | unsigned char* pmt_pids, // [out] サービス ID に対応する PMT の PID 399 | int* pmt_retain // [out] 残すPMTの数 400 | 401 | unsigned char* buf, // [in] 読み込んだバッファ 402 | #endif 403 | { 404 | int pos[MAX_PID]; 405 | int service_id; 406 | int i, j, k; 407 | int size = 0; 408 | int pid; 409 | int result = TSS_SUCCESS; 410 | char **p; 411 | int sid_found = FALSE; 412 | int avail_sids[MAX_SERVICES]; 413 | 414 | unsigned char *pat = sp->pat; 415 | unsigned char *pids = sp->pids; 416 | char **sid_list = sp->sid_list; 417 | unsigned char *pmt_pids = sp->pmt_pids; 418 | 419 | char chosen_sid[512]; 420 | chosen_sid[0] = '\0'; 421 | 422 | if(pat == NULL) { 423 | /* 初期化 */ 424 | sp->pmt_retain = 0; 425 | memset(pos, 0, sizeof(pos)); 426 | size = buf[7]; 427 | 428 | /* prescan SID/PMT */ 429 | for(i = 13, j = 0; i < (size + 8) - 4; i = i + 4) { 430 | 431 | pid = GetPid(&buf[i+2]); 432 | if(pid == 0x0010) 433 | continue; 434 | 435 | avail_sids[j] = (buf[i] << 8) + buf[i+1]; 436 | sp->avail_pmts[j] = pid; 437 | j++; 438 | } 439 | sp->num_pmts = j; 440 | 441 | // 対象チャンネル判定 442 | /* size + 8 = パケット全長 */ 443 | /* 最終 4 バイトはCRCなので飛ばす */ 444 | for(i = 13; i < (size + 8) - 4; i = i + 4) { 445 | 446 | pid = GetPid(&buf[i+2]); 447 | if(pid == 0x0010) 448 | continue; 449 | 450 | service_id = (buf[i] << 8) + buf[i+1]; 451 | p = sid_list; 452 | 453 | while(*p) { 454 | if(service_id == atoi(*p)) { 455 | /* 録画対象の pmt_pids は 1 とする */ 456 | /* 録画対象の pmt の pids は 1 とする */ 457 | pid = GetPid(&buf[i + 2]); 458 | *(pmt_pids+pid) = 1; 459 | *(pids+pid) = 1; 460 | pos[pid] = i; 461 | sid_found = TRUE; 462 | sp->pmt_version[sp->pmt_retain].pid = pid; 463 | sp->pmt_retain += 1; 464 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 465 | } 466 | else if(!strcasecmp(*p, "hd") || !strcasecmp(*p, "sd1")) { 467 | /* hd/sd1 指定時には1番目のサービスを保存する */ 468 | if(service_id == avail_sids[0]) { 469 | pid = GetPid(&buf[i + 2]); 470 | *(pmt_pids+pid) = 1; 471 | *(pids+pid) = 1; 472 | pos[pid] = i; 473 | sid_found = TRUE; 474 | sp->pmt_version[sp->pmt_retain].pid = pid; 475 | sp->pmt_retain += 1; 476 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 477 | } 478 | } 479 | else if(!strcasecmp(*p, "sd2")) { 480 | /* sd2 指定時には2番目のサービスを保存する */ 481 | if(service_id == avail_sids[1]) { 482 | pid = GetPid(&buf[i + 2]); 483 | *(pmt_pids+pid) = 1; 484 | *(pids+pid) = 1; 485 | pos[pid] = i; 486 | sid_found = TRUE; 487 | sp->pmt_version[sp->pmt_retain].pid = pid; 488 | sp->pmt_retain += 1; 489 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 490 | } 491 | } 492 | else if(!strcasecmp(*p, "sd3")) { 493 | /* sd3 指定時には3番目のサービスを保存する */ 494 | if(service_id == avail_sids[2]) { 495 | pid = GetPid(&buf[i + 2]); 496 | *(pmt_pids+pid) = 1; 497 | *(pids+pid) = 1; 498 | pos[pid] = i; 499 | sid_found = TRUE; 500 | sp->pmt_version[sp->pmt_retain].pid = pid; 501 | sp->pmt_retain += 1; 502 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 503 | } 504 | } 505 | else if(!strcasecmp(*p, "1seg")) { 506 | /* 1seg 指定時には PMTPID=0x1FC8 のサービスを保存する */ 507 | pid = GetPid(&buf[i + 2]); 508 | if(pid == 0x1FC8) { 509 | *(pmt_pids+pid) = 1; 510 | *(pids+pid) = 1; 511 | pos[pid] = i; 512 | sid_found = TRUE; 513 | sp->pmt_version[sp->pmt_retain].pid = pid; 514 | sp->pmt_retain += 1; 515 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 516 | } 517 | } 518 | else if(!strcasecmp(*p, "all")) { 519 | /* all指定時には全保存する */ 520 | pid = GetPid(&buf[i + 2]); 521 | *(pmt_pids+pid) = 1; 522 | *(pids+pid) = 1; 523 | pos[pid] = i; 524 | sid_found = TRUE; 525 | sp->pmt_version[sp->pmt_retain].pid = pid; 526 | sp->pmt_retain += 1; 527 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 528 | break; 529 | } 530 | else if(!strcasecmp(*p, "epg")) { 531 | /* epg抽出に必要なPIDのみを保存する */ 532 | sid_found = TRUE; 533 | *(pids+0x11) = 1; 534 | *(pids+0x12) = 1; 535 | *(pids+0x23) = 1; // SDTT 536 | *(pids+0x29) = 1; // CDT 537 | } 538 | else if(!strcasecmp(*p, "epg1seg")) { 539 | /* ワンセグ用epg抽出に必要なPIDのみを保存する */ 540 | sid_found = TRUE; 541 | *(pids+0x11) = 1; 542 | // *(pids+0x26) = 1; // 車載用epg 規格のみで未送出のもよう 543 | *(pids+0x27) = 1; 544 | } 545 | 546 | p++; 547 | } /* while */ 548 | } 549 | 550 | /* if sid has been specified but no sid found, fall back to all */ 551 | if(*sid_list && !sid_found) { 552 | for(i = 13; i < (size + 8) - 4; i = i + 4) { 553 | 554 | pid = GetPid(&buf[i+2]); 555 | if(pid==0x0010) 556 | continue; 557 | 558 | service_id = (buf[i] << 8) + buf[i+1]; 559 | pid = GetPid(&buf[i + 2]); 560 | *(pmt_pids+pid) = 1; 561 | *(pids+pid) = 1; 562 | pos[pid] = i; 563 | sid_found = TRUE; 564 | sp->pmt_version[sp->pmt_retain].pid = pid; 565 | sp->pmt_retain += 1; 566 | sprintf(chosen_sid, "%s %d", *chosen_sid ? chosen_sid : "", service_id); 567 | } 568 | } 569 | 570 | /* print SIDs */ 571 | fprintf(stderr, "Available sid = "); 572 | for(k=0; k < sp->num_pmts; k++) 573 | fprintf(stderr, "%d ", avail_sids[k]); 574 | fprintf(stderr, "\n"); 575 | fprintf(stderr, "Chosen sid =%s\n", chosen_sid); 576 | 577 | #if 1 578 | /* print PMTs */ 579 | fprintf(stderr, "Available PMT = "); 580 | for(k=0; k < sp->num_pmts; k++) 581 | fprintf(stderr, "0x%x ", sp->avail_pmts[k]); 582 | fprintf(stderr, "\n"); 583 | #endif 584 | 585 | // PAT 再構築 586 | result = RecreatePat(sp, buf, pos); 587 | #if 0 588 | int tc; 589 | for(tc=0; tc<188; tc++) 590 | fprintf(stderr, "%02x ", *(sp->pat+tc)); 591 | #endif 592 | } 593 | 594 | return(result); 595 | } 596 | 597 | /** 598 | * PAT 再構築処理 599 | * 600 | * PMT から出力対象チャンネル以外のチャンネル情報を削除し、PAT を再構築する 601 | */ 602 | static int RecreatePat(splitter *sp, unsigned char *buf, int *pos) 603 | #if 0 604 | splitter *sp // [in/out] 605 | unsigned char** pat, // [out] PAT 情報(再構築後) 606 | unsigned char* pids, // [out] 出力対象 PID 情報 607 | 608 | unsigned char* buf, // [in] 読み込んだバッファ 609 | int *pos // [in] 取得対象 PMT のバッファ中の位置 610 | #endif 611 | { 612 | unsigned char y[LENGTH_CRC_DATA]; 613 | int crc; 614 | int i; 615 | int j; 616 | int pos_i; 617 | int pid_num = 0; 618 | 619 | // CRC 計算のためのデータ 620 | { 621 | // チャンネルによって変わらない部分 622 | for (i = 0; i < LENGTH_PAT_HEADER - 4; i++) 623 | { 624 | y[i] = buf[i + 5]; 625 | } 626 | 627 | // NIT 628 | y[LENGTH_PAT_HEADER-4] = 0x00; 629 | y[LENGTH_PAT_HEADER-3] = 0x00; 630 | y[LENGTH_PAT_HEADER-2] = 0xe0; 631 | y[LENGTH_PAT_HEADER-1] = 0x10; 632 | 633 | // チャンネルによって変わる部分 634 | for (i = 0; i < MAX_PID; i++) 635 | { 636 | if(pos[i] != 0) 637 | { 638 | /* buf[pos_i] を y にコピー(抽出したPIDの数) */ 639 | pos_i = pos[i]; 640 | for (j = 0; j < 4; j++) 641 | { 642 | y[LENGTH_PAT_HEADER + ((4*pid_num) + j)] = buf[pos_i + j]; 643 | } 644 | pid_num++; 645 | } 646 | } 647 | } 648 | /* パケットサイズ計算 */ 649 | y[2] = pid_num * 4 + 0x0d; 650 | // CRC 計算 651 | crc = GetCrc32(y, LENGTH_PAT_HEADER + pid_num*4); 652 | 653 | // PAT 再構成 654 | sp->pat = (unsigned char*)malloc(LENGTH_PACKET); 655 | if(sp->pat == NULL) 656 | { 657 | fprintf(stderr, "RecreatePat() malloc error.\n"); 658 | return(TSS_NULL); 659 | } 660 | memset(sp->pat, 0xFF, LENGTH_PACKET); 661 | for (i = 0; i < 5; i++) 662 | { 663 | (sp->pat)[i] = buf[i]; 664 | } 665 | for (i = 0; i < LENGTH_PAT_HEADER + pid_num*4; i++) 666 | { 667 | (sp->pat)[i + 5] = y[i]; 668 | } 669 | (sp->pat)[5 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 24) & 0xFF; 670 | (sp->pat)[6 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 16) & 0xFF; 671 | (sp->pat)[7 + LENGTH_PAT_HEADER + pid_num*4] = (crc >> 8) & 0xFF; 672 | (sp->pat)[8 + LENGTH_PAT_HEADER + pid_num*4] = (crc ) & 0xFF; 673 | 674 | return(TSS_SUCCESS); 675 | } 676 | 677 | /** 678 | * PMT 解析処理 679 | * 680 | * PMT を解析し、保存対象の PID を特定する 681 | */ 682 | static int AnalyzePmt(splitter *sp, unsigned char *buf, unsigned char mark) 683 | #if 0 684 | unsigned char* buf, // [in] 読み込んだバッファ 685 | unsigned char* pids // [out] 出力対象 PID 情報 686 | #endif 687 | { 688 | uint16_t Nall; 689 | uint16_t N; 690 | int pcr; 691 | int epid; 692 | int pid; 693 | int retry_count = 0; 694 | int count; 695 | int payload_offset; // offset to payload 696 | 697 | pid = GetPid(&buf[1]); 698 | if (buf[1] & 0x40) { // PES開始インジケータ 699 | sp->section_remain[pid] = ((buf[6] & 0x0F) << 8) + buf[7] + 3; // セクションサイズ取得(ヘッダ込) 700 | payload_offset = 5; 701 | 702 | for (count = 0; sp->pmt_retain > count; count++) { 703 | if (sp->pmt_version[count].pid == pid) { 704 | sp->pmt_version[count].version = buf[10] & 0x3e; 705 | } 706 | } 707 | // PCR, 番組情報が先頭からはみ出ることはないだろう 708 | 709 | // PCR 710 | pcr = GetPid(&buf[payload_offset + 8]); 711 | sp->pids[pcr] = mark; 712 | 713 | // ECM 714 | N = ((buf[payload_offset + 10] & 0x0F) << 8) + buf[payload_offset + 11] + payload_offset + 12; // ES情報開始点 715 | int p = payload_offset + 12; 716 | 717 | while(p < N) { 718 | uint32_t ca_pid; 719 | uint32_t tag; 720 | uint32_t len; 721 | 722 | tag = buf[p]; 723 | len = buf[p+1]; 724 | p += 2; 725 | 726 | if(tag == 0x09 && len >= 4 && p+len <= N) { 727 | ca_pid = ((buf[p+2] << 8) | buf[p+3]) & 0x1fff; 728 | sp->pids[ca_pid] = mark; 729 | } 730 | p += len; 731 | } 732 | } 733 | else { 734 | if (sp->section_remain[pid] == 0) return TSS_ERROR; // セクション先頭が飛んでいる 735 | if ((buf[3] & 0x0F) != ((sp->packet_seq[pid] + 1) & 0x0F)) return TSS_ERROR; // パケットカウンタが飛んだ 736 | payload_offset = 4; 737 | N = payload_offset; 738 | } 739 | sp->packet_seq[pid] = buf[3] & 0x0F; // 巡回カウンタ 740 | 741 | Nall = sp->section_remain[pid]; 742 | if(Nall > LENGTH_PACKET - payload_offset) 743 | Nall = LENGTH_PACKET - payload_offset; 744 | 745 | // ES PID 746 | while (N <= Nall + payload_offset - 5) 747 | { 748 | // ストリーム種別が 0x0D(type D)は出力対象外 749 | if (0x0D != buf[N]) 750 | { 751 | epid = GetPid(&buf[N + 1]); 752 | 753 | sp->pids[epid] = mark; 754 | } 755 | N += 4 + (((buf[N + 3]) & 0x0F) << 8) + buf[N + 4] + 1; 756 | retry_count++; 757 | if(retry_count > Nall) { 758 | return TSS_ERROR; 759 | } 760 | } 761 | sp->section_remain[pid] -= Nall; 762 | 763 | if (sp->section_remain[pid] > 0) 764 | return SECTION_CONTINUE; 765 | else 766 | return TSS_SUCCESS; 767 | } 768 | 769 | /** 770 | * CRC 計算 771 | */ 772 | static int GetCrc32( 773 | unsigned char* data, // [in] CRC 計算対象データ 774 | int len) // [in] CRC 計算対象データ長 775 | { 776 | int crc; 777 | int i, j; 778 | int c; 779 | int bit; 780 | 781 | crc = 0xFFFFFFFF; 782 | for (i = 0; i < len; i++) 783 | { 784 | char x; 785 | x = data[i]; 786 | 787 | for (j = 0; j < 8; j++) 788 | { 789 | 790 | bit = (x >> (7 - j)) & 0x1; 791 | 792 | c = 0; 793 | if (crc & 0x80000000) 794 | { 795 | c = 1; 796 | } 797 | 798 | crc = crc << 1; 799 | 800 | if (c ^ bit) 801 | { 802 | crc ^= 0x04C11DB7; 803 | } 804 | 805 | crc &= 0xFFFFFFFF; 806 | } 807 | } 808 | 809 | return crc; 810 | } 811 | 812 | /** 813 | * PID 取得 814 | */ 815 | static int GetPid( 816 | unsigned char* data) // [in] 取得対象データのポインタ 817 | { 818 | return ((data[0] & 0x1F) << 8) + data[1]; 819 | } 820 | -------------------------------------------------------------------------------- /driver/pt1_tuner_data.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) 11 | #include 12 | #endif 13 | #include 14 | #include 15 | #include 16 | 17 | #include "pt1_com.h" 18 | #include "pt1_pci.h" 19 | #include "pt1_i2c.h" 20 | #include "pt1_tuner.h" 21 | #include "pt1_tuner_data.h" 22 | 23 | /***************************************************************************/ 24 | /* 省電力テーブル */ 25 | /***************************************************************************/ 26 | /* 27 | ISDB-S省電力 28 | 送信:7Bit Address Mode(1b):17:01 29 | 30 | ISDB-S省電力OFF 31 | 送信:7Bit Address Mode(1b):fe:c0:e4:fe:c0:f4:d6 32 | 送信:7Bit Address Mode(1b):17:00 33 | */ 34 | WBLOCK isdb_s_sleep = { 35 | 0, 36 | 2, 37 | {0x17, 0x01} 38 | }; 39 | WBLOCK isdb_s_wake = { 40 | 0, 41 | 7, 42 | {0xFE, 0xC0, 0xE4, 0xFE, 0xC0, 0xF4, 0xD6} 43 | }; 44 | WBLOCK isdb_s_wake2 = { 45 | 0, 46 | 2, 47 | {0x17, 0x00} 48 | }; 49 | 50 | /* 51 | ISDB-T省電力 52 | 送信:7Bit Address Mode(1a):03:90 53 | 54 | ISDB-T省電力OFF 55 | 送信:7Bit Address Mode(1a):fe:c2:0e:7f:c1:84:80 56 | 送信:7Bit Address Mode(1a):03:80 57 | */ 58 | WBLOCK isdb_t_sleep = { 59 | 0, 60 | 2, 61 | {0x03, 0x90} 62 | }; 63 | WBLOCK isdb_t_wake = { 64 | 0, 65 | 7, 66 | {0xFE, 0xC2, 0x0E, 0x7F, 0xC1, 0x84, 0x80} 67 | }; 68 | WBLOCK isdb_t_wake2 = { 69 | 0, 70 | 2, 71 | {0x03, 0x80} 72 | }; 73 | 74 | /***************************************************************************/ 75 | /* 初期化データ定義(共通) */ 76 | /***************************************************************************/ 77 | WBLOCK com_initdata = { 78 | 0, 79 | 2, 80 | {0x01, 0x80} 81 | }; 82 | 83 | /***************************************************************************/ 84 | /* 初期化データ定義(ISDB-S) */ 85 | /***************************************************************************/ 86 | // ISDB-S初期化値1 87 | WBLOCK isdb_s_init1 ={ 88 | 0, 89 | 1, 90 | {0x0f} 91 | }; 92 | // ISDB-S初期化値2 93 | WBLOCK isdb_s_init2 ={ 94 | 0, 95 | 2, 96 | {0x04, 0x02} 97 | }; 98 | // ISDB-S初期化値3 99 | WBLOCK isdb_s_init3 ={ 100 | 0, 101 | 2, 102 | {0x0D, 0x55} //pt1 only 103 | }; 104 | // ISDB-S初期化値4 105 | WBLOCK isdb_s_init4 ={ 106 | 0, 107 | 2, 108 | {0x11, 0x40} 109 | }; 110 | // ISDB-S初期化値5 111 | WBLOCK isdb_s_init5 ={ 112 | 0, 113 | 2, 114 | {0x13, 0x80} 115 | }; 116 | // ISDB-S初期化値6 117 | WBLOCK isdb_s_init6 ={ 118 | 0, 119 | 2, 120 | {0x17, 0x01} 121 | }; 122 | // ISDB-S初期化値7 123 | WBLOCK isdb_s_init7 ={ 124 | 0, 125 | 2, 126 | {0x1C, 0x0A} 127 | }; 128 | // ISDB-S初期化値8 129 | WBLOCK isdb_s_init8 ={ 130 | 0, 131 | 2, 132 | {0x1D, 0xAA} 133 | }; 134 | // ISDB-S初期化値9 135 | WBLOCK isdb_s_init9 ={ 136 | 0, 137 | 2, 138 | {0x1E, 0x20} 139 | }; 140 | // ISDB-S初期化値10 141 | WBLOCK isdb_s_init10 ={ 142 | 0, 143 | 2, 144 | {0x1F, 0x88} 145 | }; 146 | // ISDB-S初期化値11 147 | WBLOCK isdb_s_init11 ={ 148 | 0, 149 | 2, 150 | {0x51, 0xB0} 151 | }; 152 | // ISDB-S初期化値12 153 | WBLOCK isdb_s_init12 ={ 154 | 0, 155 | 2, 156 | {0x52, 0x89} 157 | }; 158 | // ISDB-S初期化値13 159 | WBLOCK isdb_s_init13 ={ 160 | 0, 161 | 2, 162 | {0x53, 0xB3} 163 | }; 164 | // ISDB-S初期化値14 165 | WBLOCK isdb_s_init14 ={ 166 | 0, 167 | 2, 168 | {0x5A, 0x2D} 169 | }; 170 | // ISDB-S初期化値15 171 | WBLOCK isdb_s_init15 ={ 172 | 0, 173 | 2, 174 | {0x5B, 0xD3} 175 | }; 176 | // ISDB-S初期化値16 177 | WBLOCK isdb_s_init16 ={ 178 | 0, 179 | 2, 180 | {0x85, 0x69} 181 | }; 182 | // ISDB-S初期化値17 183 | WBLOCK isdb_s_init17 ={ 184 | 0, 185 | 2, 186 | {0x87, 0x04} 187 | }; 188 | // ISDB-S初期化値18 189 | WBLOCK isdb_s_init18 ={ 190 | 0, 191 | 2, 192 | {0x8E, 0x26} 193 | }; 194 | // ISDB-S初期化値19 195 | WBLOCK isdb_s_init19 ={ 196 | 0, 197 | 2, 198 | {0xA3, 0xF7} 199 | }; 200 | // ISDB-S初期化値20 201 | WBLOCK isdb_s_init20 ={ 202 | 0, 203 | 2, 204 | {0xA5, 0xC0} 205 | }; 206 | // ISDB-S初期化値21 207 | WBLOCK isdb_s_init21 ={ 208 | 0, 209 | 4, 210 | {0xFE, 0xC0, 0xF0, 0x04} 211 | }; 212 | /***************************************************************************/ 213 | /* 初期化データ定義(ISDB-T) */ 214 | /***************************************************************************/ 215 | // ISDB-T初期化値1 216 | WBLOCK isdb_t_init1 ={ 217 | 0, 218 | 2, 219 | {0x03, 0x90} 220 | }; 221 | // ISDB-T初期化値2 222 | WBLOCK isdb_t_init2 ={ 223 | 0, 224 | 2, 225 | {0x14, 0x8F} //pt1 only 226 | }; 227 | // ISDB-T初期化値3 228 | WBLOCK isdb_t_init3 ={ 229 | 0, 230 | 2, 231 | {0x1C, 0x2A} 232 | }; 233 | // ISDB-T初期化値4 234 | WBLOCK isdb_t_init4 ={ 235 | 0, 236 | 2, 237 | {0x1D, 0xA8} 238 | }; 239 | // ISDB-T初期化値5 240 | WBLOCK isdb_t_init5 ={ 241 | 0, 242 | 2, 243 | {0x1E, 0xA2} 244 | }; 245 | // ISDB-T初期化値6 246 | WBLOCK isdb_t_init6 ={ 247 | 0, 248 | 2, 249 | {0x22, 0x83} 250 | }; 251 | // ISDB-T初期化値7 252 | WBLOCK isdb_t_init7 ={ 253 | 0, 254 | 2, 255 | {0x31, 0x0D} //pt1 256 | }; 257 | // ISDB-T初期化値8 258 | WBLOCK isdb_t_init8 ={ 259 | 0, 260 | 2, 261 | {0x32, 0xE0} //pt1 262 | }; 263 | // ISDB-T初期化値9 264 | WBLOCK isdb_t_init9 ={ 265 | 0, 266 | 2, 267 | {0x39, 0xD3} //pt1 268 | }; 269 | // ISDB-T初期化値10 270 | WBLOCK isdb_t_init10 ={ 271 | 0, 272 | 2, 273 | {0x3A, 0x00} 274 | }; 275 | // ISDB-T初期化値11 276 | WBLOCK isdb_t_init11 ={ 277 | 0, 278 | 2, 279 | {0x5C, 0x40} 280 | }; 281 | // ISDB-T初期化値12 282 | WBLOCK isdb_t_init12 ={ 283 | 0, 284 | 2, 285 | {0x5F, 0x80} 286 | }; 287 | // ISDB-T初期化値13 288 | WBLOCK isdb_t_init13 ={ 289 | 0, 290 | 2, 291 | {0x75, 0x0a} 292 | }; 293 | // ISDB-T初期化値14 294 | WBLOCK isdb_t_init14 ={ 295 | 0, 296 | 2, 297 | {0x76, 0x4c} 298 | }; 299 | // ISDB-T初期化値15 300 | WBLOCK isdb_t_init15 ={ 301 | 0, 302 | 2, 303 | {0x77, 0x03} 304 | }; 305 | // ISDB-T初期化値16 306 | WBLOCK isdb_t_init16 ={ 307 | 0, 308 | 2, 309 | {0xEF, 0x01} 310 | }; 311 | // ISDB-T初期化値17 312 | WBLOCK isdb_t_init17 ={ 313 | 0, 314 | 7, 315 | {0xFE, 0xC2, 0x01, 0x8F, 0xC1, 0x80, 0x80} 316 | }; 317 | /***************************************************************************/ 318 | /* 初期化データブロック定義(ISDB-S) */ 319 | /***************************************************************************/ 320 | WBLOCK *isdb_s_initial_pt1[PT1_MAX_ISDB_S_INIT] = 321 | { 322 | &isdb_s_init2, &isdb_s_init3, &isdb_s_init4, &isdb_s_init5, 323 | &isdb_s_init6, &isdb_s_init7, &isdb_s_init8, &isdb_s_init9, 324 | &isdb_s_init10, &isdb_s_init11, &isdb_s_init12, &isdb_s_init13, 325 | &isdb_s_init14, &isdb_s_init15, &isdb_s_init16, &isdb_s_init17, 326 | &isdb_s_init18, &isdb_s_init19, &isdb_s_init20 327 | }; 328 | WBLOCK *isdb_s_initial_pt2[PT2_MAX_ISDB_S_INIT] = 329 | { 330 | &isdb_s_init2, &isdb_s_init4, &isdb_s_init5, 331 | &isdb_s_init6, &isdb_s_init7, &isdb_s_init8, &isdb_s_init9, 332 | &isdb_s_init10, &isdb_s_init11, &isdb_s_init12, &isdb_s_init13, 333 | &isdb_s_init14, &isdb_s_init15, &isdb_s_init16, &isdb_s_init17, 334 | &isdb_s_init18, &isdb_s_init19, &isdb_s_init20 335 | }; 336 | /***************************************************************************/ 337 | /* 初期化データブロック定義(ISDB-T) */ 338 | /***************************************************************************/ 339 | WBLOCK *isdb_t_initial_pt1[PT1_MAX_ISDB_T_INIT] = 340 | { 341 | &isdb_t_init1, &isdb_t_init2, &isdb_t_init3, &isdb_t_init4, 342 | &isdb_t_init5, &isdb_t_init6, &isdb_t_init7, &isdb_t_init8, 343 | &isdb_t_init9, &isdb_t_init10, &isdb_t_init11, &isdb_t_init12, 344 | &isdb_t_init13, &isdb_t_init14, &isdb_t_init15, &isdb_t_init16 345 | }; 346 | WBLOCK *isdb_t_initial_pt2[PT2_MAX_ISDB_T_INIT] = 347 | { 348 | &isdb_t_init1, &isdb_t_init3, &isdb_t_init4, 349 | &isdb_t_init5, &isdb_t_init6, 350 | &isdb_t_init10, &isdb_t_init11, &isdb_t_init12, 351 | &isdb_t_init13, &isdb_t_init14, &isdb_t_init15, &isdb_t_init16 352 | }; 353 | /***************************************************************************/ 354 | /* 地上デジタル用データ */ 355 | /***************************************************************************/ 356 | /***************************************************************************/ 357 | /* 周波数設定基本テーブル */ 358 | /* 0~1: 固定 */ 359 | /* 2~3: 計算結果 */ 360 | /* 4~5: 追加計算結果 */ 361 | /***************************************************************************/ 362 | 363 | WBLOCK isdb_t_pll_base = { 364 | 0, 365 | 2, 366 | {0xFE, 0xC2, 0, 0, 0, 0, 0, 0} 367 | }; 368 | /***************************************************************************/ 369 | /* 地デジ周波数ロックチェック */ 370 | /***************************************************************************/ 371 | WBLOCK isdb_t_pll_lock = { 372 | 0, 373 | 2, 374 | {0xFE, 0xC3} 375 | }; 376 | 377 | WBLOCK isdb_t_check_tune = { 378 | 0, 379 | 2, 380 | {0x01, 0x40} 381 | }; 382 | 383 | WBLOCK isdb_t_tune_read = { 384 | 0, 385 | 1, 386 | {0x80} 387 | }; 388 | WBLOCK isdb_t_tmcc_read_1 = { 389 | 0, 390 | 1, 391 | {0xB2} 392 | }; 393 | WBLOCK isdb_t_tmcc_read_2 = { 394 | 0, 395 | 1, 396 | {0xB6} 397 | }; 398 | /***************************************************************************/ 399 | /* 地デジ周波数ロックチェック */ 400 | /***************************************************************************/ 401 | WBLOCK isdb_t_signal1 = { 402 | 0, 403 | 1, 404 | {0x8C} 405 | }; 406 | WBLOCK isdb_t_signal2 = { 407 | 0, 408 | 1, 409 | {0x8D} 410 | }; 411 | WBLOCK isdb_t_agc2 = { 412 | 0, 413 | 1, 414 | {0x82} 415 | }; 416 | WBLOCK isdb_t_lockedt1 = { 417 | 0, 418 | 1, 419 | {0x96} 420 | }; 421 | WBLOCK isdb_t_lockedt2 = { 422 | 0, 423 | 1, 424 | {0xB0} 425 | }; 426 | WBLOCK isdb_t_get_clock = { 427 | 0, 428 | 1, 429 | {0x86} 430 | }; 431 | WBLOCK isdb_t_get_carrir = { 432 | 0, 433 | 1, 434 | {0x84} 435 | }; 436 | 437 | /***************************************************************************/ 438 | /* 地デジ用データ */ 439 | /***************************************************************************/ 440 | 441 | /***************************************************************************/ 442 | /* BS用データ */ 443 | /***************************************************************************/ 444 | /***************************************************************************/ 445 | /* BS周波数ロックチェック */ 446 | /***************************************************************************/ 447 | WBLOCK bs_pll_lock = { 448 | 0, 449 | 2, 450 | {0xFE, 0xC1} 451 | }; 452 | /***************************************************************************/ 453 | /* TMCC取得 */ 454 | /***************************************************************************/ 455 | WBLOCK bs_tmcc_get_1 = { 456 | 0, 457 | 2, 458 | {0x03, 0x01} 459 | }; 460 | WBLOCK bs_tmcc_get_2 = { 461 | 0, 462 | 1, 463 | {0xC3} 464 | }; 465 | /***************************************************************************/ 466 | /* TMCC取得 */ 467 | /***************************************************************************/ 468 | WBLOCK bs_get_slot_ts_id_1 = { 469 | 0, 470 | 1, 471 | {0xCE} 472 | }; 473 | WBLOCK bs_get_slot_ts_id_2 = { 474 | 0, 475 | 1, 476 | {0xD2} 477 | }; 478 | WBLOCK bs_get_slot_ts_id_3 = { 479 | 0, 480 | 1, 481 | {0xD6} 482 | }; 483 | WBLOCK bs_get_slot_ts_id_4 = { 484 | 0, 485 | 1, 486 | {0xDA} 487 | }; 488 | /***************************************************************************/ 489 | /* TS-IDロック */ 490 | /***************************************************************************/ 491 | WBLOCK bs_set_ts_lock = { 492 | 0, 493 | 3, 494 | {0x8F, 0x00, 0x00} 495 | }; 496 | /***************************************************************************/ 497 | /* TS-ID取得 */ 498 | /***************************************************************************/ 499 | WBLOCK bs_get_ts_lock = { 500 | 0, 501 | 1, 502 | {0xE6} 503 | }; 504 | /***************************************************************************/ 505 | /* スロット取得 */ 506 | /***************************************************************************/ 507 | WBLOCK bs_get_slot = { 508 | 0, 509 | 1, 510 | {0xE8} 511 | }; 512 | /***************************************************************************/ 513 | /* CN/AGC/MAXAGC取得 */ 514 | /***************************************************************************/ 515 | WBLOCK bs_get_signal1 = { 516 | 0, 517 | 1, 518 | {0xBC} 519 | }; 520 | WBLOCK bs_get_signal2 = { 521 | 0, 522 | 1, 523 | {0xBD} 524 | }; 525 | WBLOCK bs_get_agc = { 526 | 0, 527 | 1, 528 | {0xBA} 529 | }; 530 | /***************************************************************************/ 531 | /* クロック周波数誤差取得 */ 532 | /***************************************************************************/ 533 | WBLOCK bs_get_clock = { 534 | 0, 535 | 1, 536 | {0xBE} 537 | }; 538 | /***************************************************************************/ 539 | /* キャリア周波数誤差取得 */ 540 | /***************************************************************************/ 541 | WBLOCK bs_get_carrir = { 542 | 0, 543 | 1, 544 | {0xBB} 545 | }; 546 | /***************************************************************************/ 547 | /* 周波数設定テーブル */ 548 | /* BSに関してのみ。とりあえずテーブルとしたが、計算で算出出来るなら */ 549 | /* 計算で算出させる。 */ 550 | /***************************************************************************/ 551 | /***************************************************************************/ 552 | /* BS共通テーブル */ 553 | /***************************************************************************/ 554 | WBLOCK bs_com_step2 = { 555 | 0, 556 | 3, 557 | {0xFE, 0xC0, 0xE4} 558 | }; 559 | /***************************************************************************/ 560 | /* BS-1 */ 561 | /***************************************************************************/ 562 | WBLOCK bs_1_step1 = { 563 | 0, 564 | 6, 565 | {0xFE, 0xC0, 0x48, 0x29, 0xE0, 0xD2} 566 | }; 567 | WBLOCK bs_1_step3 = { 568 | 0, 569 | 4, 570 | {0xFE, 0xC0, 0xF4, 0xD6} 571 | }; 572 | /***************************************************************************/ 573 | /* BS-3 */ 574 | /***************************************************************************/ 575 | WBLOCK bs_3_step1 = { 576 | 0, 577 | 6, 578 | {0xFE, 0xC0, 0x44, 0x40, 0xE0, 0xE2} 579 | }; 580 | WBLOCK bs_3_step3 = { 581 | 0, 582 | 4, 583 | {0xFE, 0xC0, 0xF4, 0xE6} 584 | }; 585 | /***************************************************************************/ 586 | /* BS-5 */ 587 | /***************************************************************************/ 588 | WBLOCK bs_5_step1 = { 589 | 0, 590 | 6, 591 | {0xFE, 0xC0, 0x44, 0x66, 0xE0, 0xE2} 592 | }; 593 | WBLOCK bs_5_step3 = { 594 | 0, 595 | 4, 596 | {0xFE, 0xC0, 0xF4, 0xE6} 597 | }; 598 | /***************************************************************************/ 599 | /* BS-7 */ 600 | /***************************************************************************/ 601 | WBLOCK bs_7_step1 = { 602 | 0, 603 | 6, 604 | {0xFE, 0xC0, 0x44, 0x8D, 0xE0, 0x20} 605 | }; 606 | WBLOCK bs_7_step3 = { 607 | 0, 608 | 4, 609 | {0xFE, 0xC0, 0xF4, 0x24} 610 | }; 611 | /***************************************************************************/ 612 | /* BS-9 */ 613 | /***************************************************************************/ 614 | WBLOCK bs_9_step1 = { 615 | 0, 616 | 6, 617 | {0xFE, 0xC0, 0x44, 0xB3, 0xE0, 0x20} 618 | }; 619 | WBLOCK bs_9_step3 = { 620 | 0, 621 | 4, 622 | {0xFE, 0xC0, 0xF4, 0x24} 623 | }; 624 | /***************************************************************************/ 625 | /* BS-11 */ 626 | /***************************************************************************/ 627 | WBLOCK bs_11_step1 = { 628 | 0, 629 | 6, 630 | {0xFE, 0xC0, 0x44, 0xD9, 0xE0, 0x20} 631 | }; 632 | WBLOCK bs_11_step3 = { 633 | 0, 634 | 4, 635 | {0xFE, 0xC0, 0xF4, 0x24} 636 | }; 637 | /***************************************************************************/ 638 | /* BS-13 */ 639 | /***************************************************************************/ 640 | WBLOCK bs_13_step1 = { 641 | 0, 642 | 6, 643 | {0xFE, 0xC0, 0x45, 0x00, 0xE0, 0x20} 644 | }; 645 | WBLOCK bs_13_step3 = { 646 | 0, 647 | 4, 648 | {0xFE, 0xC0, 0xF4, 0x24} 649 | }; 650 | /***************************************************************************/ 651 | /* BS-15 */ 652 | /***************************************************************************/ 653 | WBLOCK bs_15_step1 = { 654 | 0, 655 | 6, 656 | {0xFE, 0xC0, 0x45, 0x26, 0xE0, 0x40} 657 | }; 658 | WBLOCK bs_15_step3 = { 659 | 0, 660 | 4, 661 | {0xFE, 0xC0, 0xF4, 0x44} 662 | }; 663 | /***************************************************************************/ 664 | /* BS-17 */ 665 | /***************************************************************************/ 666 | WBLOCK bs_17_step1 = { 667 | 0, 668 | 6, 669 | {0xFE, 0xC0, 0x45, 0x4C, 0xE0, 0x40} 670 | }; 671 | WBLOCK bs_17_step3 = { 672 | 0, 673 | 4, 674 | {0xFE, 0xC0, 0xF4, 0X44} 675 | }; 676 | /***************************************************************************/ 677 | /* BS-19 */ 678 | /***************************************************************************/ 679 | WBLOCK bs_19_step1 = { 680 | 0, 681 | 6, 682 | {0xFE, 0xC0, 0x45, 0x73, 0xE0, 0x40} 683 | }; 684 | WBLOCK bs_19_step3 = { 685 | 0, 686 | 4, 687 | {0xFE, 0xC0, 0xF4, 0x44} 688 | }; 689 | /***************************************************************************/ 690 | /* BS-21 */ 691 | /***************************************************************************/ 692 | WBLOCK bs_21_step1 = { 693 | 0, 694 | 6, 695 | {0xFE, 0xC0, 0x45, 0x99, 0xE0, 0x40} 696 | }; 697 | WBLOCK bs_21_step3 = { 698 | 0, 699 | 4, 700 | {0xFE, 0xC0, 0xF4, 0x44} 701 | }; 702 | /***************************************************************************/ 703 | /* BS-23 */ 704 | /***************************************************************************/ 705 | WBLOCK bs_23_step1 = { 706 | 0, 707 | 6, 708 | {0xFE, 0xC0, 0x45, 0xBF, 0xE0, 0x60} 709 | }; 710 | WBLOCK bs_23_step3 = { 711 | 0, 712 | 4, 713 | {0xFE, 0xC0, 0xF4, 0x64} 714 | }; 715 | 716 | /***************************************************************************/ 717 | /* ND 2 */ 718 | /***************************************************************************/ 719 | WBLOCK nd_2_step1 = { 720 | 0, 721 | 6, 722 | {0xFE, 0xC0, 0x46, 0x4D, 0xE0, 0x60} 723 | }; 724 | WBLOCK nd_2_step3 = { 725 | 0, 726 | 4, 727 | {0xFE, 0xC0, 0xF4, 0x64} 728 | }; 729 | 730 | /***************************************************************************/ 731 | /* ND 4 */ 732 | /***************************************************************************/ 733 | WBLOCK nd_4_step1 = { 734 | 0, 735 | 6, 736 | {0xFE, 0xC0, 0x46, 0x75, 0xE0, 0x80} 737 | }; 738 | WBLOCK nd_4_step3 = { 739 | 0, 740 | 4, 741 | {0xFE, 0xC0, 0xF4, 0x84} 742 | }; 743 | 744 | /***************************************************************************/ 745 | /* ND 6 */ 746 | /***************************************************************************/ 747 | WBLOCK nd_6_step1 = { 748 | 0, 749 | 6, 750 | {0xFE, 0xC0, 0x46, 0x9D, 0xE0, 0x80} 751 | }; 752 | WBLOCK nd_6_step3 = { 753 | 0, 754 | 4, 755 | {0xFE, 0xC0, 0xF4, 0x84} 756 | }; 757 | 758 | /***************************************************************************/ 759 | /* ND 8 */ 760 | /***************************************************************************/ 761 | WBLOCK nd_8_step1 = { 762 | 0, 763 | 6, 764 | {0xFE, 0xC0, 0x46, 0xC5, 0xE0, 0x80} 765 | }; 766 | WBLOCK nd_8_step3 = { 767 | 0, 768 | 4, 769 | {0xFE, 0xC0, 0xF4, 0x84} 770 | }; 771 | 772 | /***************************************************************************/ 773 | /* ND 10 */ 774 | /***************************************************************************/ 775 | WBLOCK nd_10_step1 = { 776 | 0, 777 | 6, 778 | {0xFE, 0xC0, 0x46, 0xED, 0xE0, 0x80} 779 | }; 780 | WBLOCK nd_10_step3 = { 781 | 0, 782 | 4, 783 | {0xFE, 0xC0, 0xF4, 0x84} 784 | }; 785 | 786 | /***************************************************************************/ 787 | /* ND 12 */ 788 | /***************************************************************************/ 789 | WBLOCK nd_12_step1 = { 790 | 0, 791 | 6, 792 | {0xFE, 0xC0, 0x47, 0x15, 0xE0, 0xA0} 793 | }; 794 | WBLOCK nd_12_step3 = { 795 | 0, 796 | 4, 797 | {0xFE, 0xC0, 0xF4, 0xA4} 798 | }; 799 | 800 | /***************************************************************************/ 801 | /* ND 14 */ 802 | /***************************************************************************/ 803 | WBLOCK nd_14_step1 = { 804 | 0, 805 | 6, 806 | {0xFE, 0xC0, 0x47, 0x3D, 0xE0, 0xA0} 807 | }; 808 | WBLOCK nd_14_step3 = { 809 | 0, 810 | 4, 811 | {0xFE, 0xC0, 0xF4, 0xA4} 812 | }; 813 | 814 | /***************************************************************************/ 815 | /* ND 16 */ 816 | /***************************************************************************/ 817 | WBLOCK nd_16_step1 = { 818 | 0, 819 | 6, 820 | {0xFE, 0xC0, 0x47, 0x65, 0xE0, 0xA0} 821 | }; 822 | WBLOCK nd_16_step3 = { 823 | 0, 824 | 4, 825 | {0xFE, 0xC0, 0xF4, 0xA4} 826 | }; 827 | 828 | /***************************************************************************/ 829 | /* ND 18 */ 830 | /***************************************************************************/ 831 | WBLOCK nd_18_step1 = { 832 | 0, 833 | 6, 834 | {0xFE, 0xC0, 0x47, 0x8D, 0xE0, 0xA0} 835 | }; 836 | WBLOCK nd_18_step3 = { 837 | 0, 838 | 4, 839 | {0xFE, 0xC0, 0xF4, 0xA4} 840 | }; 841 | 842 | /***************************************************************************/ 843 | /* ND 20 */ 844 | /***************************************************************************/ 845 | WBLOCK nd_20_step1 = { 846 | 0, 847 | 6, 848 | {0xFE, 0xC0, 0x47, 0xB5, 0xE0, 0xC0} 849 | }; 850 | WBLOCK nd_20_step3 = { 851 | 0, 852 | 4, 853 | {0xFE, 0xC0, 0xF4, 0xC4} 854 | }; 855 | 856 | /***************************************************************************/ 857 | /* ND 22 */ 858 | /***************************************************************************/ 859 | WBLOCK nd_22_step1 = { 860 | 0, 861 | 6, 862 | {0xFE, 0xC0, 0x47, 0xDD, 0xE0, 0xC0} 863 | }; 864 | WBLOCK nd_22_step3 = { 865 | 0, 866 | 4, 867 | {0xFE, 0xC0, 0xF4, 0xC4} 868 | }; 869 | 870 | /***************************************************************************/ 871 | /* ND 24 */ 872 | /***************************************************************************/ 873 | WBLOCK nd_24_step1 = { 874 | 0, 875 | 6, 876 | {0xFE, 0xC0, 0x48, 0x05, 0xE0, 0xC0} 877 | }; 878 | WBLOCK nd_24_step3 = { 879 | 0, 880 | 4, 881 | {0xFE, 0xC0, 0xF4, 0xC4} 882 | }; 883 | 884 | /***************************************************************************/ 885 | /* ND 1 */ 886 | /***************************************************************************/ 887 | WBLOCK nd_1_step1 = { 888 | 0, 889 | 6, 890 | {0xFE, 0xC0, 0x46, 0x39, 0xE0, 0x60} 891 | }; 892 | WBLOCK nd_1_step3 = { 893 | 0, 894 | 4, 895 | {0xFE, 0xC0, 0xF4, 0x64} 896 | }; 897 | 898 | /***************************************************************************/ 899 | /* ND 3 */ 900 | /***************************************************************************/ 901 | WBLOCK nd_3_step1 = { 902 | 0, 903 | 6, 904 | {0xFE, 0xC0, 0x46, 0x61, 0xE0, 0x80} 905 | }; 906 | WBLOCK nd_3_step3 = { 907 | 0, 908 | 4, 909 | {0xFE, 0xC0, 0xF4, 0x84} 910 | }; 911 | 912 | /***************************************************************************/ 913 | /* ND 5 */ 914 | /***************************************************************************/ 915 | WBLOCK nd_5_step1 = { 916 | 0, 917 | 6, 918 | {0xFE, 0xC0, 0x46, 0x89, 0xE0, 0x80} 919 | }; 920 | WBLOCK nd_5_step3 = { 921 | 0, 922 | 4, 923 | {0xFE, 0xC0, 0xF4, 0x84} 924 | }; 925 | 926 | /***************************************************************************/ 927 | /* ND 7 */ 928 | /***************************************************************************/ 929 | WBLOCK nd_7_step1 = { 930 | 0, 931 | 6, 932 | {0xFE, 0xC0, 0x46, 0xB1, 0xE0, 0x80} 933 | }; 934 | WBLOCK nd_7_step3 = { 935 | 0, 936 | 4, 937 | {0xFE, 0xC0, 0xF4, 0x84} 938 | }; 939 | 940 | /***************************************************************************/ 941 | /* ND 9 */ 942 | /***************************************************************************/ 943 | WBLOCK nd_9_step1 = { 944 | 0, 945 | 6, 946 | {0xFE, 0xC0, 0x46, 0xD9, 0xE0, 0x80} 947 | }; 948 | WBLOCK nd_9_step3 = { 949 | 0, 950 | 4, 951 | {0xFE, 0xC0, 0xF4, 0x84} 952 | }; 953 | 954 | /***************************************************************************/ 955 | /* ND 11 */ 956 | /***************************************************************************/ 957 | WBLOCK nd_11_step1 = { 958 | 0, 959 | 6, 960 | {0xFE, 0xC0, 0x47, 0x01, 0xE0, 0xA0} 961 | }; 962 | WBLOCK nd_11_step3 = { 963 | 0, 964 | 4, 965 | {0xFE, 0xC0, 0xF4, 0xA4} 966 | }; 967 | 968 | /***************************************************************************/ 969 | /* ND 13 */ 970 | /***************************************************************************/ 971 | WBLOCK nd_13_step1 = { 972 | 0, 973 | 6, 974 | {0xFE, 0xC0, 0x47, 0x29, 0xE0, 0xA0} 975 | }; 976 | WBLOCK nd_13_step3 = { 977 | 0, 978 | 4, 979 | {0xFE, 0xC0, 0xF4, 0xA4} 980 | }; 981 | 982 | /***************************************************************************/ 983 | /* ND 15 */ 984 | /***************************************************************************/ 985 | WBLOCK nd_15_step1 = { 986 | 0, 987 | 6, 988 | {0xFE, 0xC0, 0x47, 0x51, 0xE0, 0xA0} 989 | }; 990 | WBLOCK nd_15_step3 = { 991 | 0, 992 | 4, 993 | {0xFE, 0xC0, 0xF4, 0xA4} 994 | }; 995 | 996 | /***************************************************************************/ 997 | /* ND 17 */ 998 | /***************************************************************************/ 999 | WBLOCK nd_17_step1 = { 1000 | 0, 1001 | 6, 1002 | {0xFE, 0xC0, 0x47, 0x79, 0xE0, 0xA0} 1003 | }; 1004 | WBLOCK nd_17_step3 = { 1005 | 0, 1006 | 4, 1007 | {0xFE, 0xC0, 0xF4, 0xA4} 1008 | }; 1009 | 1010 | /***************************************************************************/ 1011 | /* ND 19 */ 1012 | /***************************************************************************/ 1013 | WBLOCK nd_19_step1 = { 1014 | 0, 1015 | 6, 1016 | {0xFE, 0xC0, 0x47, 0xA1, 0xE0, 0xA0} 1017 | }; 1018 | WBLOCK nd_19_step3 = { 1019 | 0, 1020 | 4, 1021 | {0xFE, 0xC0, 0xF4, 0xA4} 1022 | }; 1023 | 1024 | /***************************************************************************/ 1025 | /* ND 21 */ 1026 | /***************************************************************************/ 1027 | WBLOCK nd_21_step1 = { 1028 | 0, 1029 | 6, 1030 | {0xFE, 0xC0, 0x47, 0xC9, 0xE0, 0xC0} 1031 | }; 1032 | WBLOCK nd_21_step3 = { 1033 | 0, 1034 | 4, 1035 | {0xFE, 0xC0, 0xF4, 0xC4} 1036 | }; 1037 | 1038 | /***************************************************************************/ 1039 | /* ND 23 */ 1040 | /***************************************************************************/ 1041 | WBLOCK nd_23_step1 = { 1042 | 0, 1043 | 6, 1044 | {0xFE, 0xC0, 0x47, 0xF1, 0xE0, 0xC0} 1045 | }; 1046 | WBLOCK nd_23_step3 = { 1047 | 0, 1048 | 4, 1049 | {0xFE, 0xC0, 0xF4, 0xC4} 1050 | }; 1051 | 1052 | /***************************************************************************/ 1053 | /* BS-周波数テーブル */ 1054 | /***************************************************************************/ 1055 | WBLOCK_BS_PLL bs_pll[MAX_BS_CHANNEL] = { 1056 | {{&bs_1_step1, &bs_com_step2, &bs_1_step3}}, 1057 | {{&bs_3_step1, &bs_com_step2, &bs_3_step3}}, 1058 | {{&bs_5_step1, &bs_com_step2, &bs_5_step3}}, 1059 | {{&bs_7_step1, &bs_com_step2, &bs_7_step3}}, 1060 | {{&bs_9_step1, &bs_com_step2, &bs_9_step3}}, 1061 | {{&bs_11_step1, &bs_com_step2, &bs_11_step3}}, 1062 | {{&bs_13_step1, &bs_com_step2, &bs_13_step3}}, 1063 | {{&bs_15_step1, &bs_com_step2, &bs_15_step3}}, 1064 | {{&bs_17_step1, &bs_com_step2, &bs_17_step3}}, 1065 | {{&bs_19_step1, &bs_com_step2, &bs_19_step3}}, 1066 | {{&bs_21_step1, &bs_com_step2, &bs_21_step3}}, 1067 | {{&bs_23_step1, &bs_com_step2, &bs_23_step3}}, 1068 | {{&nd_2_step1, &bs_com_step2, &nd_2_step3}}, 1069 | {{&nd_4_step1, &bs_com_step2, &nd_4_step3}}, 1070 | {{&nd_6_step1, &bs_com_step2, &nd_6_step3}}, 1071 | {{&nd_8_step1, &bs_com_step2, &nd_8_step3}}, 1072 | {{&nd_10_step1, &bs_com_step2, &nd_10_step3}}, 1073 | {{&nd_12_step1, &bs_com_step2, &nd_12_step3}}, 1074 | {{&nd_14_step1, &bs_com_step2, &nd_14_step3}}, 1075 | {{&nd_16_step1, &bs_com_step2, &nd_16_step3}}, 1076 | {{&nd_18_step1, &bs_com_step2, &nd_18_step3}}, 1077 | {{&nd_20_step1, &bs_com_step2, &nd_20_step3}}, 1078 | {{&nd_22_step1, &bs_com_step2, &nd_22_step3}}, 1079 | {{&nd_24_step1, &bs_com_step2, &nd_24_step3}}, 1080 | {{&nd_1_step1, &bs_com_step2, &nd_1_step3}}, 1081 | {{&nd_3_step1, &bs_com_step2, &nd_3_step3}}, 1082 | {{&nd_5_step1, &bs_com_step2, &nd_5_step3}}, 1083 | {{&nd_7_step1, &bs_com_step2, &nd_7_step3}}, 1084 | {{&nd_9_step1, &bs_com_step2, &nd_9_step3}}, 1085 | {{&nd_11_step1, &bs_com_step2, &nd_11_step3}}, 1086 | {{&nd_13_step1, &bs_com_step2, &nd_13_step3}}, 1087 | {{&nd_15_step1, &bs_com_step2, &nd_15_step3}}, 1088 | {{&nd_17_step1, &bs_com_step2, &nd_17_step3}}, 1089 | {{&nd_19_step1, &bs_com_step2, &nd_19_step3}}, 1090 | {{&nd_21_step1, &bs_com_step2, &nd_21_step3}}, 1091 | {{&nd_23_step1, &bs_com_step2, &nd_23_step3}} 1092 | }; 1093 | WBLOCK *bs_get_ts_id[(MAX_BS_TS_ID / 2)] = { 1094 | &bs_get_slot_ts_id_1, 1095 | &bs_get_slot_ts_id_2, 1096 | &bs_get_slot_ts_id_3, 1097 | &bs_get_slot_ts_id_4 1098 | }; 1099 | -------------------------------------------------------------------------------- /driver/pt1_pci.c: -------------------------------------------------------------------------------- 1 | /* -*- tab-width: 4; indent-tabs-mode: t -*- */ 2 | /* pt1-pci.c: A PT1 on PCI bus driver for Linux. */ 3 | #include "version.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0) 22 | #include 23 | #endif 24 | 25 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) 26 | #include 27 | #else 28 | #define set_freezable() 29 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) 30 | typedef struct pm_message { 31 | int event; 32 | } pm_message_t; 33 | #endif 34 | #endif 35 | 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | 42 | #include 43 | 44 | #include "pt1_com.h" 45 | #include "pt1_pci.h" 46 | #include "pt1_tuner.h" 47 | #include "pt1_i2c.h" 48 | #include "pt1_tuner_data.h" 49 | #include "pt1_ioctl.h" 50 | 51 | #if LINUX_VERSION_CODE > KERNEL_VERSION(3,8,0) 52 | #define __devinit 53 | #define __devinitdata 54 | #define __devexit 55 | #define __devexit_p 56 | #endif 57 | 58 | #if LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0) 59 | #include 60 | #endif 61 | 62 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,18,0) 63 | static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) 64 | { 65 | return dma_alloc_coherent(&hwdev->dev, size, dma_handle, GFP_KERNEL); 66 | } 67 | 68 | static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) 69 | { 70 | dma_free_coherent(&hwdev->dev, size, vaddr, dma_handle); 71 | } 72 | 73 | static inline int pci_set_dma_mask(struct pci_dev *hwdev, u64 mask) 74 | { 75 | return dma_set_mask(&hwdev->dev, mask); 76 | } 77 | #endif 78 | 79 | /* These identify the driver base version and may not be removed. */ 80 | static char version[] __devinitdata = 81 | DRV_NAME ".c: " DRV_VERSION " " DRV_RELDATE " \n"; 82 | 83 | MODULE_AUTHOR("Tomoaki Ishikawa tomy@users.sourceforge.jp and Yoshiki Yazawa yaz@honeyplanet.jp"); 84 | #define DRIVER_DESC "PCI earthsoft PT1/2 driver" 85 | MODULE_DESCRIPTION(DRIVER_DESC); 86 | MODULE_LICENSE("GPL"); 87 | 88 | static int debug = 7; /* 1 normal messages, 0 quiet .. 7 verbose. */ 89 | static int lnb = 0; /* LNB OFF:0 +11V:1 +15V:2 */ 90 | 91 | module_param(debug, int, 0); 92 | module_param(lnb, int, 0); 93 | MODULE_PARM_DESC(debug, "debug level (1-2)"); 94 | MODULE_PARM_DESC(debug, "LNB level (0:OFF 1:+11V 2:+15V)"); 95 | 96 | #define VENDOR_EARTHSOFT 0x10ee 97 | #define PCI_PT1_ID 0x211a 98 | #define PCI_PT2_ID 0x222a 99 | 100 | static struct pci_device_id pt1_pci_tbl[] = { 101 | { VENDOR_EARTHSOFT, PCI_PT1_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 102 | { VENDOR_EARTHSOFT, PCI_PT2_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 103 | { 0, } 104 | }; 105 | MODULE_DEVICE_TABLE(pci, pt1_pci_tbl); 106 | #define DEV_NAME "pt1video" 107 | 108 | #define PACKET_SIZE 188 // 1パケット長 109 | #define MAX_READ_BLOCK 4 // 1度に読み出す最大DMAバッファ数 110 | #define MAX_PCI_DEVICE 128 // 最大64枚 111 | #define DMA_SIZE 4096 // DMAバッファサイズ 112 | #define DMA_RING_SIZE 128 // number of DMA RINGS 113 | #define DMA_RING_MAX 511 // number of DMA entries in a RING(1023はNGで511まで) 114 | #define CHANNEL_DMA_SIZE (2*1024*1024) // 地デジ用(16Mbps) 115 | #define BS_CHANNEL_DMA_SIZE (4*1024*1024) // BS用(32Mbps) 116 | #define READ_SIZE (16*DMA_SIZE) 117 | 118 | typedef struct _DMA_CONTROL{ 119 | dma_addr_t ring_dma[DMA_RING_MAX] ; // DMA情報 120 | __u32 *data[DMA_RING_MAX]; 121 | }DMA_CONTROL; 122 | 123 | typedef struct _PT1_CHANNEL PT1_CHANNEL; 124 | 125 | typedef struct _pt1_device{ 126 | unsigned long mmio_start ; 127 | __u32 mmio_len ; 128 | void __iomem *regs; 129 | struct mutex lock ; 130 | dma_addr_t ring_dma[DMA_RING_SIZE] ; // DMA情報 131 | void *dmaptr[DMA_RING_SIZE] ; 132 | struct task_struct *kthread; 133 | dev_t dev ; 134 | int card_number; 135 | __u32 base_minor ; 136 | struct cdev cdev[MAX_CHANNEL]; 137 | wait_queue_head_t dma_wait_q ;// for poll on reading 138 | DMA_CONTROL *dmactl[DMA_RING_SIZE]; 139 | PT1_CHANNEL *channel[MAX_CHANNEL]; 140 | int cardtype; 141 | } PT1_DEVICE; 142 | 143 | typedef struct _MICRO_PACKET{ 144 | char data[3]; 145 | char head ; 146 | }MICRO_PACKET; 147 | 148 | struct _PT1_CHANNEL{ 149 | __u32 valid ; // 使用中フラグ 150 | __u32 address ; // I2Cアドレス 151 | __u32 channel ; // チャネル番号 152 | int type ; // チャネルタイプ 153 | __u32 packet_size ; // パケットサイズ 154 | __u32 drop ; // パケットドロップ数 155 | struct mutex lock ; // CH別mutex_lock用 156 | __u32 size ; // DMAされたサイズ 157 | __u32 maxsize ; // DMA用バッファサイズ 158 | __u32 bufsize ; // チャネルに割り振られたサイズ 159 | __u32 overflow ; // オーバーフローエラー発生 160 | __u32 counetererr ; // 転送カウンタ1エラー 161 | __u32 transerr ; // 転送エラー 162 | __u32 minor ; // マイナー番号 163 | __u8 *buf; // CH別受信メモリ 164 | __u32 pointer; 165 | __u8 req_dma ; // 溢れたチャネル 166 | __u8 packet_buf[PACKET_SIZE] ; // 溢れたチャネル 167 | PT1_DEVICE *ptr ; // カード別情報 168 | wait_queue_head_t wait_q ; // for poll on reading 169 | }; 170 | 171 | // I2Cアドレス(video0, 1 = ISDB-S) (video2, 3 = ISDB-T) 172 | int i2c_address[MAX_CHANNEL] = {T0_ISDB_S, T1_ISDB_S, T0_ISDB_T, T1_ISDB_T}; 173 | int real_channel[MAX_CHANNEL] = {0, 2, 1, 3}; 174 | int channeltype[MAX_CHANNEL] = {CHANNEL_TYPE_ISDB_S, CHANNEL_TYPE_ISDB_S, 175 | CHANNEL_TYPE_ISDB_T, CHANNEL_TYPE_ISDB_T}; 176 | 177 | static PT1_DEVICE *device[MAX_PCI_DEVICE]; 178 | static struct class *pt1video_class; 179 | 180 | #define PT1MAJOR 251 181 | #define DRIVERNAME "pt1video" 182 | 183 | static void reset_dma(PT1_DEVICE *dev_conf) 184 | { 185 | 186 | int lp ; 187 | __u32 addr ; 188 | int ring_pos = 0; 189 | int data_pos = 0 ; 190 | __u32 *dataptr ; 191 | 192 | // データ初期化 193 | for(ring_pos = 0 ; ring_pos < DMA_RING_SIZE ; ring_pos++){ 194 | for(data_pos = 0 ; data_pos < DMA_RING_MAX ; data_pos++){ 195 | dataptr = (dev_conf->dmactl[ring_pos])->data[data_pos]; 196 | dataptr[(DMA_SIZE / sizeof(__u32)) - 2] = 0; 197 | } 198 | } 199 | // 転送カウンタをリセット 200 | writel(0x00000010, dev_conf->regs); 201 | // 転送カウンタをインクリメント 202 | for(lp = 0 ; lp < DMA_RING_SIZE ; lp++){ 203 | writel(0x00000020, dev_conf->regs); 204 | } 205 | 206 | addr = (int)dev_conf->ring_dma[0] ; 207 | addr >>= 12 ; 208 | // DMAバッファ設定 209 | writel(addr, dev_conf->regs + DMA_ADDR); 210 | // DMA開始 211 | writel(0x0c000040, dev_conf->regs); 212 | 213 | } 214 | static int pt1_thread(void *data) 215 | { 216 | PT1_DEVICE *dev_conf = data ; 217 | PT1_CHANNEL *channel ; 218 | int ring_pos = 0; 219 | int data_pos = 0 ; 220 | int lp ; 221 | int chno ; 222 | int dma_channel ; 223 | int packet_pos ; 224 | __u32 *dataptr ; 225 | __u32 *curdataptr ; 226 | __u32 val ; 227 | union mpacket{ 228 | __u32 val ; 229 | MICRO_PACKET packet ; 230 | }micro; 231 | 232 | set_freezable(); 233 | reset_dma(dev_conf); 234 | printk(KERN_INFO "pt1_thread run\n"); 235 | 236 | for(;;){ 237 | if(kthread_should_stop()){ 238 | break ; 239 | } 240 | 241 | for(;;){ 242 | dataptr = (dev_conf->dmactl[ring_pos])->data[data_pos]; 243 | // データあり? 244 | if(dataptr[(DMA_SIZE / sizeof(__u32)) - 2] == 0){ 245 | break ; 246 | } 247 | micro.val = *dataptr ; 248 | curdataptr = dataptr ; 249 | data_pos += 1 ; 250 | for(lp = 0 ; lp < (DMA_SIZE / sizeof(__u32)) ; lp++, dataptr++){ 251 | micro.val = *dataptr ; 252 | dma_channel = ((micro.packet.head >> 5) & 0x07); 253 | //チャネル情報不正 254 | if(dma_channel > MAX_CHANNEL){ 255 | printk(KERN_ERR "DMA Channel Number Error(%d)\n", dma_channel); 256 | continue ; 257 | } 258 | chno = real_channel[(((micro.packet.head >> 5) & 0x07) - 1)]; 259 | packet_pos = ((micro.packet.head >> 2) & 0x07); 260 | channel = dev_conf->channel[chno] ; 261 | // エラーチェック 262 | if((micro.packet.head & MICROPACKET_ERROR)){ 263 | val = readl(dev_conf->regs); 264 | if((val & BIT_RAM_OVERFLOW)){ 265 | channel->overflow += 1 ; 266 | } 267 | if((val & BIT_INITIATOR_ERROR)){ 268 | channel->counetererr += 1 ; 269 | } 270 | if((val & BIT_INITIATOR_WARNING)){ 271 | channel->transerr += 1 ; 272 | } 273 | // 初期化して先頭から 274 | reset_dma(dev_conf); 275 | ring_pos = data_pos = 0 ; 276 | break ; 277 | } 278 | // 未使用チャネルは捨てる 279 | if(channel->valid == FALSE){ 280 | continue ; 281 | } 282 | mutex_lock(&channel->lock); 283 | // あふれたら読み出すまで待つ 284 | while(1){ 285 | if(channel->size >= (channel->maxsize - PACKET_SIZE - 4)){ 286 | // 該当チャンネルのDMA読みだし待ちにする 287 | wake_up(&channel->wait_q); 288 | channel->req_dma = TRUE ; 289 | mutex_unlock(&channel->lock); 290 | // タスクに時間を渡す為中断 291 | wait_event_timeout(dev_conf->dma_wait_q, (channel->req_dma == FALSE), 292 | msecs_to_jiffies(500)); 293 | mutex_lock(&channel->lock); 294 | channel->drop += 1 ; 295 | }else{ 296 | break ; 297 | } 298 | } 299 | // 先頭で、一時バッファに残っている場合 300 | if((micro.packet.head & 0x02) && (channel->packet_size != 0)){ 301 | channel->packet_size = 0 ; 302 | } 303 | // データコピー 304 | channel->packet_buf[channel->packet_size] = micro.packet.data[2]; 305 | channel->packet_buf[channel->packet_size+1] = micro.packet.data[1]; 306 | channel->packet_buf[channel->packet_size+2] = micro.packet.data[0]; 307 | channel->packet_size += 3; 308 | 309 | // パケットが出来たらコピーする 310 | if(channel->packet_size >= PACKET_SIZE){ 311 | if (channel->pointer + channel->size >= channel->maxsize) { 312 | // リングバッファの境界を越えていてリングバッファの先頭に戻っている場合 313 | // channel->pointer + channel->size - channel->maxsize でリングバッファ先頭からのアドレスになる 314 | memcpy(&channel->buf[channel->pointer + channel->size - channel->maxsize], channel->packet_buf, PACKET_SIZE); 315 | } else if (channel->pointer + channel->size + PACKET_SIZE > channel->maxsize) { 316 | // リングバッファの境界をまたぐように書き込まれる場合 317 | // リングバッファの境界まで書き込み 318 | __u32 tmp_size = channel->maxsize - (channel->pointer + channel->size); 319 | memcpy(&channel->buf[channel->pointer + channel->size], channel->packet_buf, tmp_size); 320 | // 先頭に戻って書き込み 321 | memcpy(channel->buf, &channel->packet_buf[tmp_size], PACKET_SIZE - tmp_size); 322 | } else { 323 | // リングバッファ内で収まる場合 324 | // 通常の書き込み 325 | memcpy(&channel->buf[channel->pointer + channel->size], channel->packet_buf, PACKET_SIZE); 326 | } 327 | channel->size += PACKET_SIZE ; 328 | channel->packet_size = 0 ; 329 | } 330 | mutex_unlock(&channel->lock); 331 | } 332 | curdataptr[(DMA_SIZE / sizeof(__u32)) - 2] = 0; 333 | 334 | if(data_pos >= DMA_RING_MAX){ 335 | data_pos = 0; 336 | ring_pos += 1 ; 337 | // DMAリングが変わった場合はインクリメント 338 | writel(0x00000020, dev_conf->regs); 339 | if(ring_pos >= DMA_RING_SIZE){ 340 | ring_pos = 0 ; 341 | } 342 | } 343 | 344 | // 頻度を落す(wait until READ_SIZE) 345 | for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ 346 | channel = dev_conf->channel[real_channel[lp]] ; 347 | if((channel->size >= READ_SIZE) && (channel->valid == TRUE)){ 348 | wake_up(&channel->wait_q); 349 | } 350 | } 351 | } 352 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 353 | } 354 | return 0 ; 355 | } 356 | static int pt1_open(struct inode *inode, struct file *file) 357 | { 358 | int major = imajor(inode); 359 | int minor = iminor(inode); 360 | int lp ; 361 | int lp2 ; 362 | PT1_CHANNEL *channel ; 363 | 364 | for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ 365 | if(device[lp] == NULL){ 366 | return -EIO ; 367 | } 368 | 369 | if(MAJOR(device[lp]->dev) == major && 370 | device[lp]->base_minor <= minor && 371 | device[lp]->base_minor + MAX_CHANNEL > minor) { 372 | 373 | mutex_lock(&device[lp]->lock); 374 | for(lp2 = 0 ; lp2 < MAX_CHANNEL ; lp2++){ 375 | channel = device[lp]->channel[lp2] ; 376 | if(channel->minor == minor){ 377 | if(channel->valid == TRUE){ 378 | mutex_unlock(&device[lp]->lock); 379 | return -EIO ; 380 | } 381 | 382 | /* wake tuner up */ 383 | set_sleepmode(channel->ptr->regs, &channel->lock, 384 | channel->address, channel->type, 385 | TYPE_WAKEUP); 386 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 387 | 388 | channel->drop = 0 ; 389 | channel->valid = TRUE ; 390 | channel->overflow = 0 ; 391 | channel->counetererr = 0 ; 392 | channel->transerr = 0 ; 393 | channel->packet_size = 0 ; 394 | file->private_data = channel; 395 | mutex_lock(&channel->lock); 396 | // データ初期化 397 | channel->size = 0 ; 398 | mutex_unlock(&channel->lock); 399 | mutex_unlock(&device[lp]->lock); 400 | return 0 ; 401 | } 402 | } 403 | } 404 | } 405 | return -EIO; 406 | } 407 | static int pt1_release(struct inode *inode, struct file *file) 408 | { 409 | PT1_CHANNEL *channel = file->private_data; 410 | 411 | mutex_lock(&channel->ptr->lock); 412 | SetStream(channel->ptr->regs, channel->channel, FALSE); 413 | channel->valid = FALSE ; 414 | printk(KERN_INFO "(%d:%d)Drop=%08d:%08d:%08d:%08d\n", imajor(inode), iminor(inode), channel->drop, 415 | channel->overflow, channel->counetererr, channel->transerr); 416 | channel->overflow = 0 ; 417 | channel->counetererr = 0 ; 418 | channel->transerr = 0 ; 419 | channel->drop = 0 ; 420 | // 停止している場合は起こす 421 | if(channel->req_dma == TRUE){ 422 | channel->req_dma = FALSE ; 423 | wake_up(&channel->ptr->dma_wait_q); 424 | } 425 | 426 | /* send tuner to sleep */ 427 | set_sleepmode(channel->ptr->regs, &channel->lock, 428 | channel->address, channel->type, TYPE_SLEEP); 429 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 430 | 431 | mutex_unlock(&channel->ptr->lock); 432 | 433 | return 0; 434 | } 435 | 436 | static ssize_t pt1_read(struct file *file, char __user *buf, size_t cnt, loff_t * ppos) 437 | { 438 | PT1_CHANNEL *channel = file->private_data; 439 | __u32 size ; 440 | unsigned long dummy; 441 | 442 | // READ_SIZE単位で起こされるのを待つ(CPU負荷対策) 443 | if(channel->size < READ_SIZE){ 444 | wait_event_timeout(channel->wait_q, (channel->size >= READ_SIZE), 445 | msecs_to_jiffies(500)); 446 | } 447 | mutex_lock(&channel->lock); 448 | if(!channel->size){ 449 | size = 0 ; 450 | }else{ 451 | __u32 tmp_size = 0; 452 | if (cnt < channel->size) { 453 | // バッファにあるデータより小さい読み込みの場合 454 | size = cnt; 455 | } else { 456 | // バッファにあるデータ以上の読み込みの場合 457 | size = channel->size; 458 | } 459 | if (channel->maxsize <= size + channel->pointer) { 460 | // リングバッファの境界を越える場合 461 | tmp_size = channel->maxsize - channel->pointer; 462 | // 境界までコピー 463 | dummy = copy_to_user(buf, &channel->buf[channel->pointer], tmp_size); 464 | // 残りをコピー 465 | dummy = copy_to_user(&buf[tmp_size], channel->buf, size - tmp_size); 466 | channel->pointer = size - tmp_size; 467 | } else { 468 | // 普通にコピー 469 | dummy = copy_to_user(buf, &channel->buf[channel->pointer], size); 470 | channel->pointer += size; 471 | } 472 | channel->size -= size; 473 | } 474 | // 読み終わったかつ使用しているのがが4K以下 475 | if(channel->req_dma == TRUE){ 476 | channel->req_dma = FALSE ; 477 | wake_up(&channel->ptr->dma_wait_q); 478 | } 479 | mutex_unlock(&channel->lock); 480 | return size ; 481 | } 482 | static int SetFreq(PT1_CHANNEL *channel, FREQUENCY *freq) 483 | { 484 | 485 | switch(channel->type){ 486 | case CHANNEL_TYPE_ISDB_S: 487 | { 488 | ISDB_S_TMCC tmcc ; 489 | if(bs_tune(channel->ptr->regs, 490 | &channel->ptr->lock, 491 | channel->address, 492 | freq->frequencyno, 493 | &tmcc) < 0){ 494 | return -EIO ; 495 | } 496 | 497 | #if 0 498 | printk(KERN_INFO "clockmargin = (%x)\n", (tmcc.clockmargin & 0xFF)); 499 | printk(KERN_INFO "carriermargin = (%x)\n", (tmcc.carriermargin & 0xFF)); 500 | { 501 | int lp; 502 | for(lp = 0 ; lp < MAX_BS_TS_ID ; lp++){ 503 | if(tmcc.ts_id[lp].ts_id == 0xFFFF){ 504 | continue ; 505 | } 506 | printk(KERN_INFO "Slot(%d:%x)\n", lp, tmcc.ts_id[lp].ts_id); 507 | printk(KERN_INFO "mode (low/high) = (%x:%x)\n", 508 | tmcc.ts_id[lp].low_mode, tmcc.ts_id[lp].high_mode); 509 | printk(KERN_INFO "slot (low/high) = (%x:%x)\n", 510 | tmcc.ts_id[lp].low_slot, 511 | tmcc.ts_id[lp].high_slot); 512 | } 513 | } 514 | #endif 515 | ts_lock(channel->ptr->regs, 516 | &channel->ptr->lock, 517 | channel->address, 518 | tmcc.ts_id[freq->slot].ts_id); 519 | } 520 | break ; 521 | case CHANNEL_TYPE_ISDB_T: 522 | { 523 | if(isdb_t_frequency(channel->ptr->regs, 524 | &channel->ptr->lock, 525 | channel->address, 526 | freq->frequencyno, freq->slot) < 0){ 527 | return -EINVAL ; 528 | } 529 | } 530 | } 531 | return 0 ; 532 | } 533 | 534 | static int count_used_bs_tuners(PT1_DEVICE *device) 535 | { 536 | int count = 0; 537 | int i; 538 | 539 | for(i=0; ichannel[i] && 541 | device->channel[i]->type == CHANNEL_TYPE_ISDB_S && 542 | device->channel[i]->valid) 543 | count++; 544 | } 545 | 546 | printk(KERN_INFO "used bs tuners on %p = %d\n", device, count); 547 | return count; 548 | } 549 | 550 | static long pt1_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg0) 551 | { 552 | PT1_CHANNEL *channel = file->private_data; 553 | int signal = 0; 554 | unsigned long dummy; 555 | void *arg = (void *)arg0; 556 | int lnb_eff, lnb_usr; 557 | char *voltage[] = {"0V", "11V", "15V"}; 558 | int count; 559 | 560 | switch(cmd){ 561 | case SET_CHANNEL: 562 | { 563 | FREQUENCY freq ; 564 | dummy = copy_from_user(&freq, arg, sizeof(FREQUENCY)); 565 | return SetFreq(channel, &freq); 566 | } 567 | case START_REC: 568 | SetStream(channel->ptr->regs, channel->channel, TRUE); 569 | return 0 ; 570 | case STOP_REC: 571 | SetStream(channel->ptr->regs, channel->channel, FALSE); 572 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 573 | return 0 ; 574 | case GET_SIGNAL_STRENGTH: 575 | switch(channel->type){ 576 | case CHANNEL_TYPE_ISDB_S: 577 | signal = isdb_s_read_signal_strength(channel->ptr->regs, 578 | &channel->ptr->lock, 579 | channel->address); 580 | break ; 581 | case CHANNEL_TYPE_ISDB_T: 582 | signal = isdb_t_read_signal_strength(channel->ptr->regs, 583 | &channel->ptr->lock, channel->address); 584 | break ; 585 | } 586 | dummy = copy_to_user(arg, &signal, sizeof(int)); 587 | return 0 ; 588 | case LNB_ENABLE: 589 | count = count_used_bs_tuners(channel->ptr); 590 | if(count <= 1) { 591 | lnb_usr = (int)arg0; 592 | lnb_eff = lnb_usr ? lnb_usr : lnb; 593 | settuner_reset(channel->ptr->regs, channel->ptr->cardtype, lnb_eff, TUNER_POWER_ON_RESET_DISABLE); 594 | printk(KERN_INFO "PT1:LNB on %s\n", voltage[lnb_eff]); 595 | } 596 | return 0 ; 597 | case LNB_DISABLE: 598 | count = count_used_bs_tuners(channel->ptr); 599 | if(count <= 1) { 600 | settuner_reset(channel->ptr->regs, channel->ptr->cardtype, LNB_OFF, TUNER_POWER_ON_RESET_DISABLE); 601 | printk(KERN_INFO "PT1:LNB off\n"); 602 | } 603 | return 0 ; 604 | } 605 | return -EINVAL; 606 | } 607 | 608 | static long pt1_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg0) 609 | { 610 | PT1_CHANNEL *channel = file->private_data; 611 | long ret; 612 | 613 | mutex_lock(&channel->lock); 614 | ret = pt1_do_ioctl(file, cmd, arg0); 615 | mutex_unlock(&channel->lock); 616 | 617 | return ret; 618 | } 619 | 620 | static long pt1_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg0) 621 | { 622 | long ret; 623 | /* should do 32bit <-> 64bit conversion here? --yaz */ 624 | ret = pt1_unlocked_ioctl(file, cmd, arg0); 625 | 626 | return ret; 627 | } 628 | 629 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 630 | static int pt1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg0) 631 | { 632 | int ret; 633 | ret = (int)pt1_do_ioctl(file, cmd, arg0); 634 | return ret; 635 | } 636 | #endif 637 | 638 | /* 639 | */ 640 | static const struct file_operations pt1_fops = { 641 | .owner = THIS_MODULE, 642 | .open = pt1_open, 643 | .release = pt1_release, 644 | .read = pt1_read, 645 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) 646 | .ioctl = pt1_ioctl, 647 | #else 648 | .unlocked_ioctl = pt1_unlocked_ioctl, 649 | .compat_ioctl = pt1_compat_ioctl, 650 | #endif 651 | .llseek = no_llseek, 652 | }; 653 | 654 | int pt1_makering(struct pci_dev *pdev, PT1_DEVICE *dev_conf) 655 | { 656 | int lp ; 657 | int lp2 ; 658 | DMA_CONTROL *dmactl; 659 | __u32 *dmaptr ; 660 | __u32 addr ; 661 | __u32 *ptr ; 662 | 663 | //DMAリング作成 664 | for(lp = 0 ; lp < DMA_RING_SIZE ; lp++){ 665 | ptr = dev_conf->dmaptr[lp]; 666 | if(lp == (DMA_RING_SIZE - 1)){ 667 | addr = (__u32)dev_conf->ring_dma[0]; 668 | }else{ 669 | addr = (__u32)dev_conf->ring_dma[(lp + 1)]; 670 | } 671 | addr >>= 12 ; 672 | memcpy(ptr, &addr, sizeof(__u32)); 673 | ptr += 1 ; 674 | 675 | dmactl = dev_conf->dmactl[lp]; 676 | for(lp2 = 0 ; lp2 < DMA_RING_MAX ; lp2++){ 677 | dmaptr = pci_alloc_consistent(pdev, DMA_SIZE, &dmactl->ring_dma[lp2]); 678 | if(dmaptr == NULL){ 679 | printk(KERN_INFO "PT1:DMA ALLOC ERROR\n"); 680 | return -1 ; 681 | } 682 | dmactl->data[lp2] = dmaptr ; 683 | // DMAデータエリア初期化 684 | dmaptr[(DMA_SIZE / sizeof(__u32)) - 2] = 0 ; 685 | addr = (__u32)dmactl->ring_dma[lp2]; 686 | addr >>= 12 ; 687 | memcpy(ptr, &addr, sizeof(__u32)); 688 | ptr += 1 ; 689 | } 690 | } 691 | return 0 ; 692 | } 693 | int pt1_dma_init(struct pci_dev *pdev, PT1_DEVICE *dev_conf) 694 | { 695 | int lp ; 696 | void *ptr ; 697 | 698 | for(lp = 0 ; lp < DMA_RING_SIZE ; lp++){ 699 | ptr = pci_alloc_consistent(pdev, DMA_SIZE, &dev_conf->ring_dma[lp]); 700 | if(ptr == NULL){ 701 | printk(KERN_INFO "PT1:DMA ALLOC ERROR\n"); 702 | return -1 ; 703 | } 704 | dev_conf->dmaptr[lp] = ptr ; 705 | } 706 | 707 | return pt1_makering(pdev, dev_conf); 708 | } 709 | int pt1_dma_free(struct pci_dev *pdev, PT1_DEVICE *dev_conf) 710 | { 711 | 712 | int lp ; 713 | int lp2 ; 714 | 715 | for(lp = 0 ; lp < DMA_RING_SIZE ; lp++){ 716 | if(dev_conf->dmaptr[lp] != NULL){ 717 | pci_free_consistent(pdev, DMA_SIZE, 718 | dev_conf->dmaptr[lp], dev_conf->ring_dma[lp]); 719 | for(lp2 = 0 ; lp2 < DMA_RING_MAX ; lp2++){ 720 | if((dev_conf->dmactl[lp])->data[lp2] != NULL){ 721 | pci_free_consistent(pdev, DMA_SIZE, 722 | (dev_conf->dmactl[lp])->data[lp2], 723 | (dev_conf->dmactl[lp])->ring_dma[lp2]); 724 | } 725 | } 726 | } 727 | } 728 | return 0 ; 729 | } 730 | static int __devinit pt1_pci_init_one (struct pci_dev *pdev, 731 | const struct pci_device_id *ent) 732 | { 733 | int rc ; 734 | int lp ; 735 | int minor ; 736 | u16 cmd ; 737 | PT1_DEVICE *dev_conf ; 738 | PT1_CHANNEL *channel ; 739 | int i; 740 | struct resource *dummy; 741 | 742 | rc = pci_enable_device(pdev); 743 | if (rc) 744 | return rc; 745 | rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 746 | if (rc) { 747 | printk(KERN_ERR "PT1:DMA MASK ERROR"); 748 | return rc; 749 | } 750 | 751 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); 752 | if (!(cmd & PCI_COMMAND_MASTER)) { 753 | printk(KERN_INFO "Attempting to enable Bus Mastering\n"); 754 | pci_set_master(pdev); 755 | pci_read_config_word(pdev, PCI_COMMAND, &cmd); 756 | if (!(cmd & PCI_COMMAND_MASTER)) { 757 | printk(KERN_ERR "Bus Mastering is not enabled\n"); 758 | return -EIO; 759 | } 760 | } 761 | printk(KERN_INFO "Bus Mastering Enabled.\n"); 762 | 763 | dev_conf = kzalloc(sizeof(PT1_DEVICE), GFP_KERNEL); 764 | if(!dev_conf){ 765 | printk(KERN_ERR "PT1:out of memory !"); 766 | return -ENOMEM ; 767 | } 768 | for (i = 0; i < DMA_RING_SIZE; i++) { 769 | dev_conf->dmactl[i] = kzalloc(sizeof(DMA_CONTROL), GFP_KERNEL); 770 | if(!dev_conf->dmactl[i]){ 771 | int j; 772 | for (j = 0; j < i; j++) { 773 | kfree(dev_conf->dmactl[j]); 774 | } 775 | kfree(dev_conf); 776 | printk(KERN_ERR "PT1:out of memory !"); 777 | return -ENOMEM ; 778 | } 779 | } 780 | 781 | switch(ent->device) { 782 | case PCI_PT1_ID: 783 | dev_conf->cardtype = PT1; 784 | break; 785 | case PCI_PT2_ID: 786 | dev_conf->cardtype = PT2; 787 | break; 788 | default: 789 | break; 790 | } 791 | 792 | // PCIアドレスをマップする 793 | dev_conf->mmio_start = pci_resource_start(pdev, 0); 794 | dev_conf->mmio_len = pci_resource_len(pdev, 0); 795 | dummy = request_mem_region(dev_conf->mmio_start, dev_conf->mmio_len, DEV_NAME); 796 | if (!dummy) { 797 | printk(KERN_ERR "PT1:cannot request iomem (0x%llx).\n", (unsigned long long) dev_conf->mmio_start); 798 | goto out_err_regbase; 799 | } 800 | 801 | dev_conf->regs = ioremap(dev_conf->mmio_start, dev_conf->mmio_len); 802 | if (!dev_conf->regs){ 803 | printk(KERN_ERR "pt1:Can't remap register area.\n"); 804 | goto out_err_regbase; 805 | } 806 | // 初期化処理 807 | if(xc3s_init(dev_conf->regs, dev_conf->cardtype)){ 808 | printk(KERN_ERR "Error xc3s_init\n"); 809 | goto out_err_fpga; 810 | } 811 | // チューナリセット 812 | settuner_reset(dev_conf->regs, dev_conf->cardtype, LNB_OFF, TUNER_POWER_ON_RESET_ENABLE); 813 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 814 | 815 | settuner_reset(dev_conf->regs, dev_conf->cardtype, LNB_OFF, TUNER_POWER_ON_RESET_DISABLE); 816 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 817 | mutex_init(&dev_conf->lock); 818 | 819 | // Tuner 初期化処理 820 | for(lp = 0 ; lp < MAX_TUNER ; lp++){ 821 | rc = tuner_init(dev_conf->regs, dev_conf->cardtype, &dev_conf->lock, lp); 822 | if(rc < 0){ 823 | printk(KERN_ERR "Error tuner_init\n"); 824 | goto out_err_fpga; 825 | } 826 | } 827 | // 初期化完了 828 | for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ 829 | set_sleepmode(dev_conf->regs, &dev_conf->lock, 830 | i2c_address[lp], channeltype[lp], TYPE_SLEEP); 831 | 832 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 833 | } 834 | rc = alloc_chrdev_region(&dev_conf->dev, 0, MAX_CHANNEL, DEV_NAME); 835 | if(rc < 0){ 836 | goto out_err_fpga; 837 | } 838 | 839 | // 初期化 840 | init_waitqueue_head(&dev_conf->dma_wait_q); 841 | 842 | minor = MINOR(dev_conf->dev) ; 843 | dev_conf->base_minor = minor ; 844 | for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ 845 | printk(KERN_INFO "PT1:device[%d]=%p\n", lp, device[lp]); 846 | if(device[lp] == NULL){ 847 | device[lp] = dev_conf ; 848 | dev_conf->card_number = lp; 849 | break ; 850 | } 851 | } 852 | for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ 853 | cdev_init(&dev_conf->cdev[lp], &pt1_fops); 854 | dev_conf->cdev[lp].owner = THIS_MODULE; 855 | cdev_add(&dev_conf->cdev[lp], 856 | MKDEV(MAJOR(dev_conf->dev), (MINOR(dev_conf->dev) + lp)), 1); 857 | channel = kzalloc(sizeof(PT1_CHANNEL), GFP_KERNEL); 858 | if(!channel){ 859 | printk(KERN_ERR "PT1:out of memory !"); 860 | return -ENOMEM ; 861 | } 862 | 863 | // 共通情報 864 | mutex_init(&channel->lock); 865 | // 待ち状態を解除 866 | channel->req_dma = FALSE ; 867 | // マイナー番号設定 868 | channel->minor = MINOR(dev_conf->dev) + lp ; 869 | // 対象のI2Cデバイス 870 | channel->address = i2c_address[lp] ; 871 | channel->type = channeltype[lp] ; 872 | // 実際のチューナ番号 873 | channel->channel = real_channel[lp] ; 874 | channel->ptr = dev_conf ; 875 | channel->size = 0 ; 876 | dev_conf->channel[lp] = channel ; 877 | 878 | init_waitqueue_head(&channel->wait_q); 879 | 880 | switch(channel->type){ 881 | case CHANNEL_TYPE_ISDB_T: 882 | channel->maxsize = CHANNEL_DMA_SIZE ; 883 | channel->buf = vmalloc(CHANNEL_DMA_SIZE); 884 | channel->pointer = 0; 885 | break ; 886 | case CHANNEL_TYPE_ISDB_S: 887 | channel->maxsize = BS_CHANNEL_DMA_SIZE ; 888 | channel->buf = vmalloc(BS_CHANNEL_DMA_SIZE); 889 | channel->pointer = 0; 890 | break ; 891 | } 892 | if(channel->buf == NULL){ 893 | goto out_err_v4l; 894 | } 895 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) 896 | printk(KERN_INFO "PT1:card_number = %d\n", 897 | dev_conf->card_number); 898 | device_create(pt1video_class, 899 | NULL, 900 | MKDEV(MAJOR(dev_conf->dev), 901 | (MINOR(dev_conf->dev) + lp)), 902 | NULL, 903 | "pt1video%u", 904 | MINOR(dev_conf->dev) + lp + 905 | dev_conf->card_number * MAX_CHANNEL); 906 | #else 907 | device_create(pt1video_class, 908 | NULL, 909 | MKDEV(MAJOR(dev_conf->dev), 910 | (MINOR(dev_conf->dev) + lp)), 911 | "pt1video%u", 912 | MINOR(dev_conf->dev) + lp + 913 | dev_conf->card_number * MAX_CHANNEL); 914 | #endif 915 | 916 | #if 0 917 | dev_conf->vdev[lp] = video_device_alloc(); 918 | memcpy(dev_conf->vdev[lp], &pt1_template, sizeof(pt1_template)); 919 | video_set_drvdata(dev_conf->vdev[lp], channel); 920 | video_register_device(dev_conf->vdev[lp], VFL_TYPE_GRABBER, -1); 921 | #endif 922 | } 923 | 924 | if(pt1_dma_init(pdev, dev_conf) < 0){ 925 | goto out_err_dma; 926 | } 927 | dev_conf->kthread = kthread_run(pt1_thread, dev_conf, "pt1"); 928 | pci_set_drvdata(pdev, dev_conf); 929 | return 0; 930 | 931 | out_err_dma: 932 | pt1_dma_free(pdev, dev_conf); 933 | out_err_v4l: 934 | for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ 935 | if(dev_conf->channel[lp] != NULL){ 936 | if(dev_conf->channel[lp]->buf != NULL){ 937 | vfree(dev_conf->channel[lp]->buf); 938 | } 939 | kfree(dev_conf->channel[lp]); 940 | } 941 | } 942 | out_err_fpga: 943 | writel(0xb0b0000, dev_conf->regs); 944 | writel(0, dev_conf->regs + CFG_REGS_ADDR); 945 | iounmap(dev_conf->regs); 946 | release_mem_region(dev_conf->mmio_start, dev_conf->mmio_len); 947 | for (i = 0; i < DMA_RING_SIZE; i++) { 948 | kfree(dev_conf->dmactl[i]); 949 | } 950 | kfree(dev_conf); 951 | out_err_regbase: 952 | return -EIO; 953 | 954 | } 955 | 956 | static void __devexit pt1_pci_remove_one(struct pci_dev *pdev) 957 | { 958 | 959 | int lp ; 960 | __u32 val ; 961 | PT1_DEVICE *dev_conf = (PT1_DEVICE *)pci_get_drvdata(pdev); 962 | int i; 963 | 964 | if(dev_conf){ 965 | if(dev_conf->kthread) { 966 | kthread_stop(dev_conf->kthread); 967 | dev_conf->kthread = NULL; 968 | } 969 | 970 | // DMA終了 971 | writel(0x08080000, dev_conf->regs); 972 | for(lp = 0 ; lp < 10 ; lp++){ 973 | val = readl(dev_conf->regs); 974 | if(!(val & (1 << 6))){ 975 | break ; 976 | } 977 | schedule_timeout_interruptible(msecs_to_jiffies(100)); 978 | } 979 | pt1_dma_free(pdev, dev_conf); 980 | for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ 981 | if(dev_conf->channel[lp] != NULL){ 982 | cdev_del(&dev_conf->cdev[lp]); 983 | vfree(dev_conf->channel[lp]->buf); 984 | kfree(dev_conf->channel[lp]); 985 | } 986 | device_destroy(pt1video_class, 987 | MKDEV(MAJOR(dev_conf->dev), 988 | (MINOR(dev_conf->dev) + lp))); 989 | } 990 | 991 | unregister_chrdev_region(dev_conf->dev, MAX_CHANNEL); 992 | writel(0xb0b0000, dev_conf->regs); 993 | writel(0, dev_conf->regs + CFG_REGS_ADDR); 994 | settuner_reset(dev_conf->regs, dev_conf->cardtype, LNB_OFF, TUNER_POWER_OFF); 995 | release_mem_region(dev_conf->mmio_start, dev_conf->mmio_len); 996 | iounmap(dev_conf->regs); 997 | for (i = 0; i < DMA_RING_SIZE; i++) { 998 | kfree(dev_conf->dmactl[i]); 999 | } 1000 | device[dev_conf->card_number] = NULL; 1001 | kfree(dev_conf); 1002 | } 1003 | pci_set_drvdata(pdev, NULL); 1004 | } 1005 | #ifdef CONFIG_PM 1006 | 1007 | static int pt1_pci_suspend (struct pci_dev *pdev, pm_message_t state) 1008 | { 1009 | return 0; 1010 | } 1011 | 1012 | static int pt1_pci_resume (struct pci_dev *pdev) 1013 | { 1014 | return 0; 1015 | } 1016 | 1017 | #endif /* CONFIG_PM */ 1018 | 1019 | 1020 | static struct pci_driver pt1_driver = { 1021 | .name = DRV_NAME, 1022 | .probe = pt1_pci_init_one, 1023 | .remove = __devexit_p(pt1_pci_remove_one), 1024 | .id_table = pt1_pci_tbl, 1025 | #ifdef CONFIG_PM 1026 | .suspend = pt1_pci_suspend, 1027 | .resume = pt1_pci_resume, 1028 | #endif /* CONFIG_PM */ 1029 | 1030 | }; 1031 | 1032 | 1033 | static int __init pt1_pci_init(void) 1034 | { 1035 | printk(KERN_INFO "%s", version); 1036 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0) 1037 | pt1video_class = class_create(DRIVERNAME); 1038 | #else 1039 | pt1video_class = class_create(THIS_MODULE, DRIVERNAME); 1040 | #endif 1041 | if (IS_ERR(pt1video_class)) 1042 | return PTR_ERR(pt1video_class); 1043 | return pci_register_driver(&pt1_driver); 1044 | } 1045 | 1046 | 1047 | static void __exit pt1_pci_cleanup(void) 1048 | { 1049 | pci_unregister_driver(&pt1_driver); 1050 | class_destroy(pt1video_class); 1051 | } 1052 | 1053 | module_init(pt1_pci_init); 1054 | module_exit(pt1_pci_cleanup); 1055 | --------------------------------------------------------------------------------