linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Hauppauge 950Q TS capture intermittent lock up
@ 2014-05-09 15:19 Trevor Anonymous
  2014-05-11 14:58 ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 5+ messages in thread
From: Trevor Anonymous @ 2014-05-09 15:19 UTC (permalink / raw)
  To: linux-media

Hello all,

I have written a simple application to capture RF QAM transport
streams with the Hauppauge 950Q, and save to a file. This is
essentially the same as dvbstream, but with unnecessary stuff removed
(and I have verified this bug using dvbstream as well):
- tune using frontend device
- demux device: DMX_SET_PES_FILTER on pid 8192 with DMX_OUT_TS_TAP output.
- Read from dvr device, save to file.
- Interrupt app using alarm() and stop pes filter, close devices.


This works as expected. The problem is after running this a bunch of
times (sometimes 15-20+), the device seems to eventually get into a
bad state, and nothing is available to read on the dvr device. The
lockup never seems to happen while reading data (i.e., either data
comes and the app works completely, or the app reads 0 bytes). When
this happens, all the tuning/demod locks look good, and everything
appears to be working -- there just isn't data ready to read from the
dvr device.

When it gets into a bad state, I have to physically remove/reinsert
the 950Q device or otherwise reset the device (e.g., usb reset -
USBDEVFS_RESET ioctl).

Has anyone seen this issue before?

I am running Fedora 19 with 3.13.9 kernel. Hardware is:
- au0828, au8522, xc5000 (with dvb-fe-xc5000c-4.1.30.7.fw)


Thanks,
-Trevor

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Hauppauge 950Q TS capture intermittent lock up
  2014-05-09 15:19 Hauppauge 950Q TS capture intermittent lock up Trevor Anonymous
@ 2014-05-11 14:58 ` Mauro Carvalho Chehab
  2014-05-11 16:45   ` Trevor Graffa
  2014-05-13 15:53   ` Trevor G
  0 siblings, 2 replies; 5+ messages in thread
From: Mauro Carvalho Chehab @ 2014-05-11 14:58 UTC (permalink / raw)
  To: Trevor Anonymous; +Cc: linux-media, Devin Heitmueller, cb.xiong

Hi Trevor,

Em Fri, 9 May 2014 11:19:49 -0400
Trevor Anonymous <trevor.forums@gmail.com> escreveu:

> Hello all,
> 
> I have written a simple application to capture RF QAM transport
> streams with the Hauppauge 950Q, and save to a file. This is
> essentially the same as dvbstream, but with unnecessary stuff removed
> (and I have verified this bug using dvbstream as well):
> - tune using frontend device
> - demux device: DMX_SET_PES_FILTER on pid 8192 with DMX_OUT_TS_TAP output.
> - Read from dvr device, save to file.
> - Interrupt app using alarm() and stop pes filter, close devices.
> 
> 
> This works as expected. The problem is after running this a bunch of
> times (sometimes 15-20+), the device seems to eventually get into a
> bad state, and nothing is available to read on the dvr device. The
> lockup never seems to happen while reading data (i.e., either data
> comes and the app works completely, or the app reads 0 bytes). When
> this happens, all the tuning/demod locks look good, and everything
> appears to be working -- there just isn't data ready to read from the
> dvr device.
> 
> When it gets into a bad state, I have to physically remove/reinsert
> the 950Q device or otherwise reset the device (e.g., usb reset -
> USBDEVFS_RESET ioctl).

Yes, I noticed a similar issue with last devel Kernel. I suspect
that the culprit could be due to a sheduled work that fixes a
hardware bug. Such scheduled work task should be cancelled when
the device is closed or the channel is changed. This is likely
a partial fix for it (untested):
	https://patchwork.linuxtv.org/patch/23860/

It makes sure that the thread is canceled when a new set frontend
ioctl is sent. Yet, this patch won't solve your specific problem.

I suspect that the right approach would be to also call
cancel_work_sync(&dev->restart_streaming) on all other places
where stop_urb_transfer() is called.

Btw, could you share your small test application? That would
help us to test the bug locally and work on a patch.

> 
> Has anyone seen this issue before?
> 
> I am running Fedora 19 with 3.13.9 kernel. Hardware is:
> - au0828, au8522, xc5000 (with dvb-fe-xc5000c-4.1.30.7.fw)
> 
> 
> Thanks,
> -Trevor
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Hauppauge 950Q TS capture intermittent lock up
  2014-05-11 14:58 ` Mauro Carvalho Chehab
@ 2014-05-11 16:45   ` Trevor Graffa
  2014-05-13 15:53   ` Trevor G
  1 sibling, 0 replies; 5+ messages in thread
From: Trevor Graffa @ 2014-05-11 16:45 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Trevor Anonymous, linux-media, Devin Heitmueller, cb.xiong

Mauro,

Thanks. (Resending in plain text as last email was rejected by email
list). I'll look at the patch, and let you know if that helps. I'll
send out the application tomorrow as I'm not on my dev machine right
now.

-Trevor

On Sun, May 11, 2014 at 10:58 AM, Mauro Carvalho Chehab
<mchehab@infradead.org> wrote:
> Hi Trevor,
>
> Em Fri, 9 May 2014 11:19:49 -0400
> Trevor Anonymous <trevor.forums@gmail.com> escreveu:
>
>> Hello all,
>>
>> I have written a simple application to capture RF QAM transport
>> streams with the Hauppauge 950Q, and save to a file. This is
>> essentially the same as dvbstream, but with unnecessary stuff removed
>> (and I have verified this bug using dvbstream as well):
>> - tune using frontend device
>> - demux device: DMX_SET_PES_FILTER on pid 8192 with DMX_OUT_TS_TAP output.
>> - Read from dvr device, save to file.
>> - Interrupt app using alarm() and stop pes filter, close devices.
>>
>>
>> This works as expected. The problem is after running this a bunch of
>> times (sometimes 15-20+), the device seems to eventually get into a
>> bad state, and nothing is available to read on the dvr device. The
>> lockup never seems to happen while reading data (i.e., either data
>> comes and the app works completely, or the app reads 0 bytes). When
>> this happens, all the tuning/demod locks look good, and everything
>> appears to be working -- there just isn't data ready to read from the
>> dvr device.
>>
>> When it gets into a bad state, I have to physically remove/reinsert
>> the 950Q device or otherwise reset the device (e.g., usb reset -
>> USBDEVFS_RESET ioctl).
>
> Yes, I noticed a similar issue with last devel Kernel. I suspect
> that the culprit could be due to a sheduled work that fixes a
> hardware bug. Such scheduled work task should be cancelled when
> the device is closed or the channel is changed. This is likely
> a partial fix for it (untested):
>         https://patchwork.linuxtv.org/patch/23860/
>
> It makes sure that the thread is canceled when a new set frontend
> ioctl is sent. Yet, this patch won't solve your specific problem.
>
> I suspect that the right approach would be to also call
> cancel_work_sync(&dev->restart_streaming) on all other places
> where stop_urb_transfer() is called.
>
> Btw, could you share your small test application? That would
> help us to test the bug locally and work on a patch.
>
>>
>> Has anyone seen this issue before?
>>
>> I am running Fedora 19 with 3.13.9 kernel. Hardware is:
>> - au0828, au8522, xc5000 (with dvb-fe-xc5000c-4.1.30.7.fw)
>>
>>
>> Thanks,
>> -Trevor
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Hauppauge 950Q TS capture intermittent lock up
  2014-05-11 14:58 ` Mauro Carvalho Chehab
  2014-05-11 16:45   ` Trevor Graffa
@ 2014-05-13 15:53   ` Trevor G
  2014-05-21 13:22     ` Mauro Carvalho Chehab
  1 sibling, 1 reply; 5+ messages in thread
From: Trevor G @ 2014-05-13 15:53 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: linux-media, Devin Heitmueller, cb.xiong

[-- Attachment #1: Type: text/plain, Size: 3975 bytes --]

Example app is attached. My build is just "gcc -O2 dvbcapture.c -o dvbcapture".

Here's example output and usage of this app - both working and with
data lockup. Params mean: DVB adapter 0, frequency 357Mhz, 4 seconds,
output to "stuff.ts", QAM256. The app returns exit code 3 if no data
is available on the DVR device (as in 2nd run below), which is my
trigger to reset the USB (via usbreset:
https://gist.github.com/x2q/5124616). Resetting the USB device then
enables the capture to work.

[trevor@xxx bin]$ ./dvbcapture -c 0 -f 357000000 -t 4 -o stuff.ts -q 256
Frontend type: ATSC
DVB card: Auvitek AU8522 QAM/8VSB Frontend
Frequency: 357000000
Getting frontend status
Locked frequency: 357000000
Locked modulation: 5
Bit error rate: 96
Signal strength: 65535
SNR: 398
FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
Setting TS filter to capture all PIDs
Capturing for 4 seconds
Caught timeout
DONE - wrote 19415136 bytes!

[trevor@xxx bin]$ ./dvbcapture -c 0 -f 357000000 -t 4 -o stuff.ts -q 256
Frontend type: ATSC
DVB card: Auvitek AU8522 QAM/8VSB Frontend
Frequency: 357000000
Getting frontend status
Locked frequency: 357000000
Locked modulation: 5
Bit error rate: 94
Signal strength: 65535
SNR: 398
FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
Setting TS filter to capture all PIDs
Capturing for 4 seconds
No data available on DVR device!





On Sun, May 11, 2014 at 10:58 AM, Mauro Carvalho Chehab
<mchehab@infradead.org> wrote:
> Hi Trevor,
>
> Em Fri, 9 May 2014 11:19:49 -0400
> Trevor Anonymous <trevor.forums@gmail.com> escreveu:
>
>> Hello all,
>>
>> I have written a simple application to capture RF QAM transport
>> streams with the Hauppauge 950Q, and save to a file. This is
>> essentially the same as dvbstream, but with unnecessary stuff removed
>> (and I have verified this bug using dvbstream as well):
>> - tune using frontend device
>> - demux device: DMX_SET_PES_FILTER on pid 8192 with DMX_OUT_TS_TAP output.
>> - Read from dvr device, save to file.
>> - Interrupt app using alarm() and stop pes filter, close devices.
>>
>>
>> This works as expected. The problem is after running this a bunch of
>> times (sometimes 15-20+), the device seems to eventually get into a
>> bad state, and nothing is available to read on the dvr device. The
>> lockup never seems to happen while reading data (i.e., either data
>> comes and the app works completely, or the app reads 0 bytes). When
>> this happens, all the tuning/demod locks look good, and everything
>> appears to be working -- there just isn't data ready to read from the
>> dvr device.
>>
>> When it gets into a bad state, I have to physically remove/reinsert
>> the 950Q device or otherwise reset the device (e.g., usb reset -
>> USBDEVFS_RESET ioctl).
>
> Yes, I noticed a similar issue with last devel Kernel. I suspect
> that the culprit could be due to a sheduled work that fixes a
> hardware bug. Such scheduled work task should be cancelled when
> the device is closed or the channel is changed. This is likely
> a partial fix for it (untested):
>         https://patchwork.linuxtv.org/patch/23860/
>
> It makes sure that the thread is canceled when a new set frontend
> ioctl is sent. Yet, this patch won't solve your specific problem.
>
> I suspect that the right approach would be to also call
> cancel_work_sync(&dev->restart_streaming) on all other places
> where stop_urb_transfer() is called.
>
> Btw, could you share your small test application? That would
> help us to test the bug locally and work on a patch.
>
>>
>> Has anyone seen this issue before?
>>
>> I am running Fedora 19 with 3.13.9 kernel. Hardware is:
>> - au0828, au8522, xc5000 (with dvb-fe-xc5000c-4.1.30.7.fw)
>>
>>
>> Thanks,
>> -Trevor
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: dvbcapture.c --]
[-- Type: text/x-csrc, Size: 10343 bytes --]

/** dvbcapture.c -- Application to capture TS stream from DVB device (currently ATSC (QAM) only)
 * NOTE: Some of the code (especially tuning) is from dvbstream (available at http://sourceforge.net/projects/dvbtools/), which is GPL licensed software.
 */

// Linux includes:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <resolv.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <values.h>
#include <string.h>

// DVB includes:
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>

enum ExitStatus {
	EXIT_OK = 0, EXIT_ERR_ARGS = 1, /* Bad command line */
	EXIT_ERR_DEVICE = 2, /* Error opening/reading/ioctl, etc */
	EXIT_ERR_DATA = 3, /* No data */
	EXIT_ERR_INT = 4 /* User interrupt signal caught */
};

#define TS_SIZE 188

struct config_t {
	char* frontenddev;
	char* demuxdev;
	char* dvrdev;
	char* outputname;
	int time;
	int frequency;
	int modulation;
};

/**
 * Tuning Functions
 */

void print_status(FILE* fd, fe_status_t festatus) {
	fprintf(fd, "FE_STATUS:");
	if (festatus & FE_HAS_SIGNAL)
		fprintf(fd, " FE_HAS_SIGNAL");
	if (festatus & FE_TIMEDOUT)
		fprintf(fd, " FE_TIMEDOUT");
	if (festatus & FE_HAS_LOCK)
		fprintf(fd, " FE_HAS_LOCK");
	if (festatus & FE_HAS_CARRIER)
		fprintf(fd, " FE_HAS_CARRIER");
	if (festatus & FE_HAS_VITERBI)
		fprintf(fd, " FE_HAS_VITERBI");
	if (festatus & FE_HAS_SYNC)
		fprintf(fd, " FE_HAS_SYNC");
	fprintf(fd, "\n");
}


/* Note: TODO - start_uncorrected, get_uncorrected not working as expected. */
static int uncorrected_start_blocks = 0;
void start_uncorrected(int fd_frontend) {
	int ioret = 0;
	if (ioctl(fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &ioret) >= 0)
		fprintf(stderr, "Start UNC: %d\n", ioret);
	uncorrected_start_blocks = ioret;
}

int get_uncorrected(int fd_frontend) {
	int ioret = 0;
	if (ioctl(fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &ioret) >= 0)
		fprintf(stderr, "Stop UNC: %d\n", ioret);
	int unc = ioret - uncorrected_start_blocks;
	fprintf(stderr, "UNC: %d\n", unc);
}



int tune(int fd_frontend, int frequency, int modulation) {
	struct dvb_frontend_parameters feparams = { 0 };
	struct dvb_frontend_info feinfo = { 0 };

	const char* card_types[] = {"QPSK", "QAM", "OFDM", "ATSC"};


	if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) < 0) {
		perror("FE_GET_INFO: ");
		return -1;
	}

	fprintf(stderr, "Frontend type: %s\n", card_types[feinfo.type]);

	if (feinfo.type != FE_ATSC) {
		fprintf(stderr, "Error: Only ATSC cards are currently supported\n");
	}

	fprintf(stderr, "DVB card: %s\n", feinfo.name, frequency);
	fprintf(stderr, "Frequency: %d\n", frequency);


	feparams.frequency = frequency;
	feparams.u.vsb.modulation = modulation;

	fe_status_t festatus;
	struct pollfd pfd[1];
	int locks = 0, ok = 0;
	time_t tm1, tm2;

	if (ioctl(fd_frontend, FE_SET_FRONTEND, &feparams) < 0) {
		perror("Error tuning channel");
		return -1;
	}

	pfd[0].fd = fd_frontend;
	pfd[0].events = POLLPRI;

	tm1 = tm2 = time((time_t*) NULL);
	fprintf(stderr, "Getting frontend status\n");
	while (!ok) {
		festatus = 0;
		if (poll(pfd, 1, 3000) > 0) {
			if (pfd[0].revents & POLLPRI) {
				if (ioctl(fd_frontend, FE_READ_STATUS, &festatus) >= 0)
					if (festatus & FE_HAS_LOCK)
						locks++;
			}
		}
		usleep(10000);
		tm2 = time((time_t*) NULL);
		if ((festatus & FE_TIMEDOUT) || (locks >= 2) || (tm2 - tm1 >= 3))
			ok = 1;
	}

	if (festatus & FE_HAS_LOCK) {
		int32_t ioret;

		if (ioctl(fd_frontend, FE_GET_FRONTEND, &feparams) >= 0) {
			fprintf(stderr, "Locked frequency: %d\n", feparams.frequency);
			fprintf(stderr, "Locked modulation: %d\n", feparams.u.vsb.modulation);
		}

		ioret = 0;
		if (ioctl(fd_frontend, FE_READ_BER, &ioret) >= 0)
			fprintf(stderr, "Bit error rate: %d\n", ioret);

		ioret = 0;
		if (ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &ioret) >= 0)
			fprintf(stderr, "Signal strength: %d\n", ioret);

		ioret = 0;
		if (ioctl(fd_frontend, FE_READ_SNR, &ioret) >= 0)
			fprintf(stderr, "SNR: %d\n", ioret);

		print_status(stderr, festatus);
	} else {
		fprintf(stderr,
				"Not able to lock to the signal on the given frequency\n");
		return -1;
	}
	return 0;
}

/**
 *  Demux Functions
 */

int set_ts_filt(int fd_demux) {
	struct dmx_pes_filter_params pesFilterParams;

	fprintf(stderr, "Setting TS filter to capture all PIDs\n");
	pesFilterParams.pid = 8192;
	pesFilterParams.input = DMX_IN_FRONTEND;
	pesFilterParams.output = DMX_OUT_TS_TAP;
	pesFilterParams.pes_type = DMX_PES_OTHER;
	pesFilterParams.flags = DMX_IMMEDIATE_START;

	if (ioctl(fd_demux, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
		fprintf(stderr, "Failed setting filter");
		perror("DMX SET PES FILTER");
		return -1;
	}
	if (ioctl(fd_demux, DMX_START) < 0) {
		perror("DMX_STOP");
		return -1;
	}

	return 0;
}

int stop_ts_filt(int fd_demux) {
	if (ioctl(fd_demux, DMX_STOP) < 0) {
		perror("DMX_STOP");
		return -1;
	}
	return 0;
}

/**
 * DVR/Capture Functions
 */

int capture(int fd_dvr, FILE* outfile) {
	int bytes_read;
	int bytes_written = 0;
	uint8_t buf[TS_SIZE];

	bytes_read = read(fd_dvr, buf, TS_SIZE);
	if (bytes_read > 0) {
		if (buf[0] == 0x47) {
			bytes_written = fwrite(buf, 1, bytes_read, outfile);
		} else {
			fprintf(stderr, "NON 0X47\n");
		}
	} else {
		if (errno != EAGAIN && errno != EINTR) {
			perror("Error dvrdev read");
		}
	}
	return bytes_written;
}

/**
 * Utility/Initialization
 */

/* Signal handler to cause completion of app */
volatile int finished = 0;
volatile int user_interrupted = 0;
void stop_signal_handler(int sig) {
	if (sig == SIGALRM) {
		fprintf(stderr, "Caught timeout\n");
	} else if (sig == SIGINT) {
		user_interrupted = 1;
		fprintf(stderr, "Caught interrupt signal\n");
	}
	finished = 1;
}

/* Wait for data on file descriptor for duration in milliseconds. Return 1 if data is available, 0 otherwise */
int wait_for_data(int fd, int millis) {
	struct pollfd pfd[1];

	pfd[0].fd = fd;
	pfd[0].events = POLLIN;

	if (poll(pfd, 1, millis) > 0) {
		if (pfd[0].revents & POLLIN) {
			return 1;
		}
	}

	return 0;
}

/* Print usage */
void printhelp() {
	fprintf(stderr,
			"Usage: dvbcapture -c <card_number> -f <frequency> -t <time> -o <output_file> -q <qam>\n");
	fprintf(stderr, "card_number      DVB device adapter number\n");
	fprintf(stderr, "frequency        Frequency to tune to\n");
	fprintf(stderr, "time             Time to capture in seconds\n");
	fprintf(stderr, "output_file      File name to store capture\n");
	fprintf(stderr, "qam              Either 16 or 256 for QAM16 and QAM256\n");
}

/* Set config parameters based on command line args */
int initialize(int argc, char* argv[], struct config_t *config) {
	int card_number = 0;
	int time = -1;
	int card_selected_flag = 0;
	int time_selected_flag = 0;
	int frequency = 0;
	int modulation = 0;
	char* outputname;

	opterr = 0;
	int c;

	while ((c = getopt(argc, argv, "hc:t:o:f:q:")) != -1)
		switch (c) {
		case 'h':
			printhelp();
			return EXIT_ERR_ARGS;
		case 'c':
			card_number = atoi(optarg);
			card_selected_flag = 1;
			break;
		case 't':
			time = atoi(optarg);
			time_selected_flag = 1;
			break;
		case 'o':
			outputname = optarg;
			break;
		case 'f':
			frequency = atoi(optarg);
			break;
		case 'q':
			modulation = atoi(optarg);
			break;
		}

	if (!card_selected_flag || !time_selected_flag || card_number < 0
			|| time <= 0 || !outputname || !frequency
			|| (modulation != 16 && modulation != 256)) {
		printhelp();
		return EXIT_ERR_ARGS;
	}

	asprintf(&config->frontenddev, "/dev/dvb/adapter%d/frontend0", card_number);
	asprintf(&config->demuxdev, "/dev/dvb/adapter%d/demux0", card_number);
	asprintf(&config->dvrdev, "/dev/dvb/adapter%d/dvr0", card_number);

	config->time = time;
	config->outputname = outputname;
	config->frequency = frequency;
	if (modulation == 16) {
		config->modulation = QAM_16;
	} else if (modulation == 256) {
		config->modulation = QAM_256;
	}

	return EXIT_OK;
}


/* MAIN */
int main(int argc, char* argv[]) {
	FILE* outfile;
	struct config_t config = { 0 };
	int ret;

	int fd_frontend, fd_demux, fd_dvr;

	fd_frontend = fd_demux = fd_dvr = -1;

	ret = initialize(argc, argv, &config);
	if (ret != 0) {
		return ret;
	}

	if ((fd_frontend = open(config.frontenddev, O_RDWR)) < 0) {
		fprintf(stderr, "Error opening frontend device %s: %s\n",
				config.frontenddev, strerror(errno));
		ret = EXIT_ERR_DEVICE;
		goto complete;
	}
	if ((fd_demux = open(config.demuxdev, O_RDONLY)) < 0) {
		fprintf(stderr, "Error opening demux device %s: %s\n", config.demuxdev,
				strerror(errno));
		ret = EXIT_ERR_DEVICE;
		goto complete;
	}
	if ((fd_dvr = open(config.dvrdev, O_RDONLY)) < 0) {
		fprintf(stderr, "Error opening dvr device %s: %s\n", config.dvrdev,
				strerror(errno));
		ret = EXIT_ERR_DEVICE;
		goto complete;
	}
	if ((outfile = fopen(config.outputname, "wb")) == 0) {
		perror("Error opening output file");
		ret = EXIT_ERR_DEVICE;
		goto complete;
	}
	if (tune(fd_frontend, config.frequency, config.modulation) != 0) {
		fprintf(stderr, "Error tuning\n");
		ret = EXIT_ERR_DEVICE;
		goto complete;
	}

	if (set_ts_filt(fd_demux) != 0) {
		ret = EXIT_ERR_DEVICE;
		goto complete;
	}

	// start_uncorrected(fd_frontend);

	/* Install SIGINT handler */
	struct sigaction int_action = { 0 };

	int_action.sa_handler = stop_signal_handler;
	sigaction(SIGINT, &int_action, NULL);

	/* Capture */
	int size = 0;

	fprintf(stderr, "Capturing for %d seconds\n", config.time);

	/* Ensure data is available to read */
	if (wait_for_data(fd_dvr, 2000) != 1) {
		if (!user_interrupted) {
			fprintf(stderr, "No data available on DVR device!\n");
			ret = EXIT_ERR_DATA;
			goto complete;
		}
	}

	/* Set up alarm */
	struct sigaction alarm_action = { 0 };

	alarm_action.sa_handler = stop_signal_handler;
	sigaction(SIGALRM, &alarm_action, NULL);

	alarm(config.time);

	/* Capture data */
	while (!finished) {
		size += capture(fd_dvr, outfile);
	}

	// get_uncorrected(fd_frontend);

	fprintf(stderr, "%sDONE - wrote %d bytes!\n",
			user_interrupted ? "(User Interrupt) " : "", size);
	ret = EXIT_OK;

	complete: if (fd_demux >= 0)
		stop_ts_filt(fd_demux);
	if (fd_dvr >= 0)
		close(fd_dvr);
	if (fd_demux >= 0)
		close(fd_demux);
	if (fd_frontend >= 0)
		close(fd_frontend);
	if (outfile)
		fclose(outfile);

	return ret;
}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Hauppauge 950Q TS capture intermittent lock up
  2014-05-13 15:53   ` Trevor G
@ 2014-05-21 13:22     ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 5+ messages in thread
From: Mauro Carvalho Chehab @ 2014-05-21 13:22 UTC (permalink / raw)
  To: Trevor G; +Cc: linux-media, Devin Heitmueller, cb.xiong

Hi Trevor,

Em Tue, 13 May 2014 11:53:24 -0400
Trevor G <trevor.forums@gmail.com> escreveu:

> Example app is attached. My build is just "gcc -O2 dvbcapture.c -o dvbcapture".

Thanks, it was very useful, as I could reproduce your issues.

What is happening is that, after ~10-15 times it opens the demux,
the DMA engine starts to fail: some URBs were never filled.

That looks to be a hardware bug to me. It is hard to properly fix
it, without some datasheet. On my tests, I even tried to remove/reinsert
the module, and this didn't solve. As you mentioned, only either a
device removal or a module reset fixes it.

Eventually, there are some registers that could do something similar,
but, if such register exists, it is not touched by the driver, as a
module remove/insert doesn't solve.

I found, however, two ways to minimize the issue:
	1) stop streaming before set_frontend;
	2) not letting xc5000 sleep.

I have already a patch done for (1), but I'm thinking on doing a patch
for xc5000 to do an alternative approach: only let the hardware to sleep
after some time. That would likely reduce the risk of hitting the bug,
while keeping the device in sleep state, while not in usage.

I would love to have some documentation about this device, in order to
see if are there something else that could be done, but, unfortunately,
I don't have it.

I'll do more tests today, and I should be posting some patches at the
ML soon.

> 
> Here's example output and usage of this app - both working and with
> data lockup. Params mean: DVB adapter 0, frequency 357Mhz, 4 seconds,
> output to "stuff.ts", QAM256. The app returns exit code 3 if no data
> is available on the DVR device (as in 2nd run below), which is my
> trigger to reset the USB (via usbreset:
> https://gist.github.com/x2q/5124616). Resetting the USB device then
> enables the capture to work.
> 
> [trevor@xxx bin]$ ./dvbcapture -c 0 -f 357000000 -t 4 -o stuff.ts -q 256
> Frontend type: ATSC
> DVB card: Auvitek AU8522 QAM/8VSB Frontend
> Frequency: 357000000
> Getting frontend status
> Locked frequency: 357000000
> Locked modulation: 5
> Bit error rate: 96
> Signal strength: 65535
> SNR: 398
> FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
> Setting TS filter to capture all PIDs
> Capturing for 4 seconds
> Caught timeout
> DONE - wrote 19415136 bytes!
> 
> [trevor@xxx bin]$ ./dvbcapture -c 0 -f 357000000 -t 4 -o stuff.ts -q 256
> Frontend type: ATSC
> DVB card: Auvitek AU8522 QAM/8VSB Frontend
> Frequency: 357000000
> Getting frontend status
> Locked frequency: 357000000
> Locked modulation: 5
> Bit error rate: 94
> Signal strength: 65535
> SNR: 398
> FE_STATUS: FE_HAS_SIGNAL FE_HAS_LOCK FE_HAS_CARRIER FE_HAS_VITERBI FE_HAS_SYNC
> Setting TS filter to capture all PIDs
> Capturing for 4 seconds
> No data available on DVR device!
> 
> 
> 
> 
> 
> On Sun, May 11, 2014 at 10:58 AM, Mauro Carvalho Chehab
> <mchehab@infradead.org> wrote:
> > Hi Trevor,
> >
> > Em Fri, 9 May 2014 11:19:49 -0400
> > Trevor Anonymous <trevor.forums@gmail.com> escreveu:
> >
> >> Hello all,
> >>
> >> I have written a simple application to capture RF QAM transport
> >> streams with the Hauppauge 950Q, and save to a file. This is
> >> essentially the same as dvbstream, but with unnecessary stuff removed
> >> (and I have verified this bug using dvbstream as well):
> >> - tune using frontend device
> >> - demux device: DMX_SET_PES_FILTER on pid 8192 with DMX_OUT_TS_TAP output.
> >> - Read from dvr device, save to file.
> >> - Interrupt app using alarm() and stop pes filter, close devices.
> >>
> >>
> >> This works as expected. The problem is after running this a bunch of
> >> times (sometimes 15-20+), the device seems to eventually get into a
> >> bad state, and nothing is available to read on the dvr device. The
> >> lockup never seems to happen while reading data (i.e., either data
> >> comes and the app works completely, or the app reads 0 bytes). When
> >> this happens, all the tuning/demod locks look good, and everything
> >> appears to be working -- there just isn't data ready to read from the
> >> dvr device.
> >>
> >> When it gets into a bad state, I have to physically remove/reinsert
> >> the 950Q device or otherwise reset the device (e.g., usb reset -
> >> USBDEVFS_RESET ioctl).
> >
> > Yes, I noticed a similar issue with last devel Kernel. I suspect
> > that the culprit could be due to a sheduled work that fixes a
> > hardware bug. Such scheduled work task should be cancelled when
> > the device is closed or the channel is changed. This is likely
> > a partial fix for it (untested):
> >         https://patchwork.linuxtv.org/patch/23860/
> >
> > It makes sure that the thread is canceled when a new set frontend
> > ioctl is sent. Yet, this patch won't solve your specific problem.
> >
> > I suspect that the right approach would be to also call
> > cancel_work_sync(&dev->restart_streaming) on all other places
> > where stop_urb_transfer() is called.
> >
> > Btw, could you share your small test application? That would
> > help us to test the bug locally and work on a patch.
> >
> >>
> >> Has anyone seen this issue before?
> >>
> >> I am running Fedora 19 with 3.13.9 kernel. Hardware is:
> >> - au0828, au8522, xc5000 (with dvb-fe-xc5000c-4.1.30.7.fw)
> >>
> >>
> >> Thanks,
> >> -Trevor
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-05-21 13:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-09 15:19 Hauppauge 950Q TS capture intermittent lock up Trevor Anonymous
2014-05-11 14:58 ` Mauro Carvalho Chehab
2014-05-11 16:45   ` Trevor Graffa
2014-05-13 15:53   ` Trevor G
2014-05-21 13:22     ` Mauro Carvalho Chehab

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).