+#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;
+}