--- /dev/null
+DVB PT1 ドライバ用tuneプログラム(rec10用改変版)
+
+2012-01-08版
+
+このプログラムはDVB PT1付属のtuneプログラムを、
+rec10にて使いやすいように改変を行った物です。
+
+変更点
+チャンネルリストを無効化、周波数およびtsIDの指定で動作するようにしました。
+
+使い方
+$ ./tune <DVBアダプタ番号> <周波数> [tsid(省略可)]
+
+ライセンス
+>7. 使用上の注意
+>
+>このソフトウェアは、 sourceforge.jp で開発されている独自仕様のドライバ
+>を改竄し v4l-dvb の仕様に合わせようとしているものです。これは単に AS
+>IS で提供しているもので、開発途上であり、完全に無保証です。テストプログ
+>ラムは MIT ライセンスで提供します。
+
+gn64_jp(gn64@rec10.org)
+
+DVB PT1 ドライバ
+
+2009-03-07 版
+
+1. このドキュメントについて
+
+このドキュメントは DVB ベース の PT1 ドライバのチェックアウト、コンパイ
+ル、インストールおよびテスト方法を説明するものです。
+
+
+2. ドライバのチェックアウト
+
+DVB ベースの PT1 ドライバのソースコードは現在 mercurial で管理されてい
+ます。開発マシンに mercurial をインストールした上で、次のコマンドでチェッ
+クアウトしてください。
+
+ $ hg clone http://bitbucket.org/hiranotaka/dvb-pt1/
+
+一度チェックアウトを行うと二度めからは dvb-pt1 ディレクトリにて次のコマ
+ンドを実行することで更新することができます。ただし次の更新は 3 月下旬以
+降の予定です。
+
+ $ hg pull && hg update
+
+詳しくは mercurial のマニュアルや bitbucket.org のマニュアルを参照して
+ください。
+
+
+3. ドライバのコンパイル
+
+ターゲットとなるカーネルと同じバージョンのカーネルヘッダまたはソースが
+必要です。 linux-headers-$(uname -r) パッケージなどで入手してください。
+準備ができたら、v4l ディレクトリ下に .config という名前のファイルを作成
+し、
+
+ CONFIG_DVB_CORE=m
+ CONFIG_DVB_PT1=m
+
+のように記述します。後は、 /lib/modules/$(uname -r)/source または
+/lib/modules/$(uname -r)/build にカーネルヘッダまたはソースが展開されて
+いる場合、同じ v4l ディレクトリにて、
+
+$ make
+
+するだけで OK です。うまくいけば dvb-core.ko と pt1_drv.ko という二つの
+モジュールができるはずです。
+
+なお、カーネルヘッダやソースが違うディレクトリに展開されている場合は、
+SRCDIR オプションが必要です。
+
+
+4. ドライバのロード
+
+コンパイルでできた 2 つのモジュールを順にロードします。
+
+ $ sudo insmod dvb-core.ko
+ $ sudo insmod pt1_drv.ko
+
+無事ロードされると次のようになるはずです。
+
+ $ dmesg
+ ...
+ DVB: registering new adapter (pt1-pci)
+ DVB: registering adapter 0 frontend 0 (VA1J5JF8007 ISDB-S)...
+ DVB: registering new adapter (pt1-pci)
+ DVB: registering adapter 1 frontend 0 (VA1J5JF8007 ISDB-T)...
+ DVB: registering new adapter (pt1-pci)
+ DVB: registering adapter 2 frontend 0 (VA1J5JF8007 ISDB-S)...
+ DVB: registering new adapter (pt1-pci)
+ DVB: registering adapter 3 frontend 0 (VA1J5JF8007 ISDB-T)...
+ pt1_thread run
+
+現在、一部のマシンで DMA 領域の確保に失敗する事象が確認されています。こ
+の場合、デバッグ用のスタックトレースなどとともに、次のように表示されま
+す。
+
+ $ dmesg
+ ...
+ PT1:DMA ALLOC ERROR
+ pt1-pci: probe of 0000:01:0a.0 failed with error -5
+
+これは特に 32 ビットマシンにおいて貴重な LOWMEM 領域(DMA 可能な領域で、
+最大でも 756 MB)にその 1/6 にあたる 128 MB もの巨大な領域を確保している
+ためと考えられます。うまい対処方法があれば教えて下さい。
+
+
+5. テストプログラムのビルド
+
+簡単なテストプログラムを用意しました。先ほどチェックアウトした dvb-pt1
+と同じ階層にこの README.ja を含むディレクトリを移動します。別の言い方を
+すると、このディレクトリから見てドライバが ../dvb-pt1 の位置に来るよう
+にします。その状態で
+
+ $ make
+
+してください。
+
+
+6. テストプログラムの実行
+
+チャンネルを設定するには、
+
+ $ ./tune <DVBアダプタ番号> <リモコンキーID>
+
+とします。設定がうまくいけば
+
+ Successfully tuned to NHK東京 総合 .
+
+などと表示されます。
+
+ Failed to tune to NHK BS-1 (status 03).
+
+などと表示された場合は、ステータスによって次の原因が考えられます。
+
+ 00: PLL に問題がある
+ 01: 指定された周波数に信号がない
+ 03: 他の TS-ID の信号はあるが、指定された TS-ID のものはない
+
+DVB アダプタ番号は、他にアダプタが無い場合、チューナ 0 の ISDB-S が 0
+、チューナ 0 の ISDB-T が 1 、チューナ 1 の ISDB-S が 2 、チューナ 1 の
+ISDB-T が 3 になります。 アダプタが ISDB-T か ISDB-S かは自動判定され、
+ISDB-T であればリモコンキー ID は地上波のものと、 ISDB-S であれば衛星の
+ものと解釈されます。
+
+リモコンキー ID と周波数の対応表は、東京都のものになっています。東京都
+以外では、 tune.c の上部にある対応表の書き換えが必要になります。
+
+テストプログラムを実行したままの状態で、
+
+ $ cat /dev/dvb/adapter1/dvr > dump.ts
+
+などとすれば録画できます(例はアダプタ番号 1 の場合)。また同様に
+
+ $ b25 -v 0 /dev/dvb/adapter1/dvr /dev/stdout | \
+ mplayer -cache 8192 -
+
+とすればリアルタイムで視聴できると思います。ただしリアルタイム視聴には
+それなりの CPU 性能が求められます。
+
+
+7. 使用上の注意
+
+このソフトウェアは、 sourceforge.jp で開発されている独自仕様のドライバ
+を改竄し v4l-dvb の仕様に合わせようとしているものです。これは単に AS
+IS で提供しているもので、開発途上であり、完全に無保証です。テストプログ
+ラムは MIT ライセンスで提供します。
--- /dev/null
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/audio.h>
+#include <linux/dvb/version.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct channel {
+ int id;
+ const char *name;
+ unsigned int frequency;
+ unsigned int ts_id;
+};
+static int search(int adapter_nr,struct channel *ch)
+{
+ char file[256];
+ int fd;
+ struct dvb_frontend_info info;
+ struct channel *channel;
+ struct dtv_property prop[3];
+ struct dtv_properties props;
+ int i;
+ fe_status_t status;
+
+ sprintf(file, "/dev/dvb/adapter%d/frontend0", adapter_nr);
+ if ((fd = open(file, (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
+ perror("open");
+ return -1;
+ }
+
+ if (ioctl(fd, FE_GET_INFO, &info) < 0) {
+ perror("ioctl FE_GET_INFO");
+ goto out;
+ }
+
+ if (info.type == FE_QPSK) {
+ channel = ch;
+ //channel = lookup_channel(channel_id, isdbs_channels,
+ // ARRAY_SIZE(isdbs_channels));
+ } else if (info.type == FE_OFDM) {
+ channel = ch;
+ //channel = lookup_channel(channel_id, isdbt_channels,
+ // ARRAY_SIZE(isdbt_channels));
+ } else {
+ fprintf(stderr, "Unknown type of adapter\n");
+ goto out;
+ }
+ if (channel == NULL) {
+ fprintf(stderr, "Unknown id of channel\n");
+ goto out;
+ }
+
+ prop[0].cmd = DTV_FREQUENCY;
+ prop[0].u.data = channel->frequency;
+ prop[1].cmd = DTV_ISDBS_TS_ID;
+ prop[1].u.data = channel->ts_id;
+ prop[2].cmd = DTV_TUNE;
+
+ props.props = prop;
+ props.num = 3;
+
+ if ((ioctl(fd, FE_SET_PROPERTY, &props)) < 0) {
+ perror("ioctl FE_SET_PROPERTY");
+ goto out;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (ioctl(fd, FE_READ_STATUS, &status) < 0) {
+ perror("ioctl FE_READ_STATUS");
+ goto out;
+ }
+ if (status & FE_HAS_LOCK) {
+ fprintf(stderr, "Successfully tuned to %d(%d) .\n",
+ channel->frequency,channel->ts_id);
+ return 0;
+ }
+ usleep(250 * 1000);
+ }
+
+ fprintf(stderr, "Failed to tune to %s (status %02x).\n",
+ channel->name, status);
+
+out:
+ close(fd);
+ return -1;
+}
+
+static int track(int adapter_nr)
+{
+ char file[256];
+ int fd;
+ struct dmx_pes_filter_params filter;
+
+ filter.pid = 0x2000;
+ filter.input = DMX_IN_FRONTEND;
+ filter.output = DMX_OUT_TS_TAP;
+ filter.pes_type = DMX_PES_VIDEO;
+ filter.flags = DMX_IMMEDIATE_START;
+
+ sprintf(file, "/dev/dvb/adapter%d/demux0", adapter_nr);
+ if ((fd = open(file, O_RDWR)) < 0) {
+ perror("open");
+ return -1;
+ }
+
+
+ if (ioctl(fd, DMX_SET_PES_FILTER, &filter) < 0) {
+ perror("ioctl DMX_SET_PES_FILTER");
+ close(fd);
+ return -1;
+ }
+}
+
+void record(int adapter_nr, char* output, int rectime) {
+ int fin, fout;
+ char input[256];
+ time_t start_time, current_time;
+ char buf[1316];
+ ssize_t rt, wt;
+ int size_remain;
+
+ fout = open(output, (O_WRONLY | O_CREAT | O_TRUNC));
+ if ( fout < 0 ) {
+ printf("output file open failed\n");
+ return;
+ }
+ sprintf(input, "/dev/dvb/adapter%d/dvr0", adapter_nr);
+ start_time = time(NULL);
+ fin = open(input, (O_RDONLY));
+ while ( rt = read(fin, buf, 1316) ) {
+ while ( wt = write(fout, buf, rt) ) {
+ rt -= wt;
+ if ( rt == 0 ) break;
+ if ( wt == 0 ) {
+ printf("output file write failed\n");
+ goto error;
+ }
+ }
+ current_time = time(NULL);
+ if ( current_time - start_time > rectime ) {
+ break;
+ }
+ }
+
+ error:
+ close(fin);
+ close(fout);
+}
+
+int main(int argc, char *argv[]) {
+ int adapter_nr;
+ int channel_id;
+ int channel_freq;
+ int fd;
+ int ret;
+ int rectime;
+
+ if (argc <= 2) {
+ fprintf(stderr, "Usage: %s adapter_nr freq [tsid]\n", argv[0]);
+ return 1;
+ }
+ struct channel *ch;
+ adapter_nr = strtol(argv[1], NULL, 0);
+ channel_freq = strtol(argv[2], NULL, 10);
+ channel_id=0;
+ if (argc >= 4){
+ channel_id = strtol(argv[3], NULL, 10);
+ }
+ if ( argc == 5 ) {
+ rectime = atoi(argv[4]);
+ }
+ struct channel ch1 ={0,"",channel_freq,channel_id};
+ ch = &ch1;
+ //struct channel ch;//{ 1, "NHK BS-1", 1318000, 0x40f1 }
+ //ch={0,"",argv}
+ fd = search(adapter_nr, ch);
+ if (fd < 0)
+ return 1;
+
+ ret = track(adapter_nr);
+ record(adapter_nr, argv[3], rectime);
+ close(fd);
+
+ return ret < 0;
+}