mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-21 09:40:18 +00:00
* format is now entered as a parameter string (-g <mode>) * expect currently buffers as big as needed (exactly one frame) TODO: revide if isn't possible to read whole buffer at once (ideally the memmapped one, and extract frames by hand) * now it is needed to set /sys/class/sdivideo/sdivideorxX/bufsize * bump to new driver (2.7.2)
703 lines
16 KiB
C
703 lines
16 KiB
C
/* rxtest.c
|
|
*
|
|
* Example program for DVB ASI receivers.
|
|
*
|
|
* Copyright (C) 2000-2005 Linear Systems Ltd. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of Linear Systems Ltd. nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY LINEAR SYSTEMS LTD. "AS IS" AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL LINEAR SYSTEMS LTD. OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Linear Systems can be contacted at <http://www.linsys.ca/>.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/poll.h>
|
|
#include <sys/time.h>
|
|
|
|
#include "asi.h"
|
|
#include "master.h"
|
|
#include "../util.h"
|
|
|
|
#ifndef _LFS_LARGEFILE
|
|
#error Large file support not found
|
|
#endif
|
|
|
|
#define BUFLEN 256
|
|
|
|
static const char *argv0;
|
|
static const char progname[] = "rxtest";
|
|
|
|
static int
|
|
set_invsync (int fd,
|
|
int inv_sync,
|
|
unsigned int cap,
|
|
int verbose,
|
|
int quiet)
|
|
{
|
|
switch (inv_sync) {
|
|
case 0:
|
|
if (verbose && !quiet) {
|
|
printf ("Synchronizing on 0x47 packets.\n");
|
|
}
|
|
break;
|
|
case 1:
|
|
if (!(cap & ASI_CAP_RX_INVSYNC)) {
|
|
if (!quiet) {
|
|
fprintf (stderr,
|
|
"%s: synchronization on 0xB8 packets "
|
|
"not supported\n", argv0);
|
|
}
|
|
return -1;
|
|
}
|
|
if (verbose && !quiet) {
|
|
printf ("Synchronizing on 0x47 or 0xB8 packets.\n");
|
|
}
|
|
break;
|
|
default:
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: invalid 0xB8 "
|
|
"packet synchronization mode\n", argv0);
|
|
}
|
|
return -1;
|
|
}
|
|
if (ioctl (fd, ASI_IOC_RXSETINVSYNC, &inv_sync) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to set the 0xB8 "
|
|
"packet synchronization mode");
|
|
}
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
set_dsync (int fd,
|
|
int double_sync,
|
|
unsigned int cap,
|
|
int verbose,
|
|
int quiet)
|
|
{
|
|
switch (double_sync) {
|
|
case 0:
|
|
if (verbose && !quiet) {
|
|
printf ("Disabling double packet synchronization.\n");
|
|
}
|
|
break;
|
|
case 1:
|
|
if (!(cap & ASI_CAP_RX_DSYNC)) {
|
|
if (!quiet) {
|
|
fprintf (stderr,
|
|
"%s: double packet synchronization "
|
|
"not supported\n", argv0);
|
|
}
|
|
return -1;
|
|
}
|
|
if (verbose && !quiet) {
|
|
printf ("Enabling double packet synchronization.\n");
|
|
}
|
|
break;
|
|
default:
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: invalid double "
|
|
"packet synchronization mode\n", argv0);
|
|
}
|
|
return -1;
|
|
}
|
|
if (ioctl (fd, ASI_IOC_RXSETDSYNC, &double_sync) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to set the "
|
|
"double packet synchronization mode");
|
|
}
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
const char fmt[] = "/sys/class/asi/asirx%i/%s";
|
|
int opt;
|
|
int fd, val;
|
|
int double_sync, inv_sync;
|
|
int period, seconds, pid, quiet, verbose, num;
|
|
unsigned long int bufsize, mode, timestamps;
|
|
int ofd, read_ret, write_ret;
|
|
struct stat buf;
|
|
unsigned char *data;
|
|
unsigned int cap, bytes_written, uval;
|
|
struct timeval tv;
|
|
struct pollfd pfd;
|
|
double bytes, time_sec, lasttime, dt, status_time;
|
|
char name[BUFLEN], str[BUFLEN], *endptr;
|
|
|
|
argv0 = argv[0];
|
|
|
|
/* Parse the command line */
|
|
double_sync = -1;
|
|
inv_sync = -1;
|
|
period = 0;
|
|
seconds = -1;
|
|
pid = -1;
|
|
quiet = 0;
|
|
verbose = 0;
|
|
while ((opt = getopt (argc, argv, "dDhiIn:p:qs:vV")) != -1) {
|
|
switch (opt) {
|
|
case 'd':
|
|
double_sync = 1;
|
|
break;
|
|
case 'D':
|
|
double_sync = 0;
|
|
break;
|
|
case 'h':
|
|
printf ("Usage: %s [OPTION]... DEVICE_FILE [FILE]\n",
|
|
argv0);
|
|
printf ("Copy DEVICE_FILE to FILE and monitor for "
|
|
"DVB ASI receiver events.\n\n");
|
|
printf (" -d\t\tgain packet synchronization "
|
|
"after two sychronization bytes\n");
|
|
printf (" -D\t\tgain packet synchronization "
|
|
"after one synchronization byte\n");
|
|
printf (" -h\t\tdisplay this help and exit\n");
|
|
printf (" -i\t\tsynchronize on packets starting with "
|
|
"0x47 or 0xB8\n");
|
|
printf (" -I\t\tsynchronize on packets starting with "
|
|
"0x47 only\n");
|
|
printf (" -n TIME\tstop receiving after "
|
|
"TIME seconds\n");
|
|
printf (" -p PID\tcount packets "
|
|
"with the given PID\n");
|
|
printf (" -q\t\tquiet operation\n");
|
|
printf (" -s PERIOD\tdisplay status "
|
|
"every PERIOD seconds\n");
|
|
printf (" -v\t\tverbose output\n");
|
|
printf (" -V\t\toutput version information "
|
|
"and exit\n");
|
|
printf ("\nReport bugs to <support@linsys.ca>.\n");
|
|
return 0;
|
|
case 'i':
|
|
inv_sync = 1;
|
|
break;
|
|
case 'I':
|
|
inv_sync = 0;
|
|
break;
|
|
case 'n':
|
|
seconds = strtol (optarg, &endptr, 0);
|
|
if (*endptr != '\0') {
|
|
fprintf (stderr,
|
|
"%s: invalid timeout: %s\n",
|
|
argv0, optarg);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'p':
|
|
pid = strtol (optarg, &endptr, 0);
|
|
if ((*endptr != '\0') || (pid < 0) || (pid > 0x1fff)) {
|
|
fprintf (stderr, "%s: invalid PID: %s\n",
|
|
argv0, optarg);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'q':
|
|
quiet = 1;
|
|
break;
|
|
case 's':
|
|
period = strtol (optarg, &endptr, 0);
|
|
if (*endptr != '\0') {
|
|
fprintf (stderr,
|
|
"%s: invalid period: %s\n",
|
|
argv0, optarg);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'v':
|
|
verbose = 1;
|
|
break;
|
|
case 'V':
|
|
printf ("%s from master-%s (%s)\n", progname,
|
|
MASTER_DRIVER_VERSION,
|
|
MASTER_DRIVER_DATE);
|
|
printf ("\nCopyright (C) 2000-2005 "
|
|
"Linear Systems Ltd.\n"
|
|
"This is free software; "
|
|
"see the source for copying conditions. "
|
|
"There is NO\n"
|
|
"warranty; not even for MERCHANTABILITY "
|
|
"or FITNESS FOR A PARTICULAR PURPOSE.\n");
|
|
return 0;
|
|
case '?':
|
|
goto USAGE;
|
|
}
|
|
}
|
|
|
|
/* Check the number of arguments */
|
|
if ((argc - optind) < 1) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: missing arguments\n", argv0);
|
|
goto USAGE;
|
|
}
|
|
return -1;
|
|
} else if ((argc - optind) > 2) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: extra operand\n", argv0);
|
|
goto USAGE;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/* Get the sysfs info */
|
|
memset (&buf, 0, sizeof (buf));
|
|
if (stat (argv[optind], &buf) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get the file status");
|
|
}
|
|
return -1;
|
|
}
|
|
if (!S_ISCHR (buf.st_mode)) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: not a character device\n",
|
|
argv0);
|
|
}
|
|
return -1;
|
|
}
|
|
if (!(buf.st_rdev & 0x0080)) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: not a receiver\n", argv0);
|
|
}
|
|
return -1;
|
|
}
|
|
num = buf.st_rdev & 0x007f;
|
|
snprintf (name, sizeof (name), fmt, num, "dev");
|
|
memset (str, 0, sizeof (str));
|
|
if (util_read (name, str, sizeof (str)) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get the device number");
|
|
}
|
|
return -1;
|
|
}
|
|
if (strtoul (str, &endptr, 0) != (buf.st_rdev >> 8)) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: not an ASI device\n", argv0);
|
|
}
|
|
return -1;
|
|
}
|
|
if (*endptr != ':') {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: error reading %s\n",
|
|
argv0, name);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/* Open the file. */
|
|
if (verbose && !quiet) {
|
|
printf ("Opening %s.\n", argv[optind]);
|
|
}
|
|
if ((fd = open (argv[optind], O_RDONLY, 0)) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to open file for reading");
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/* Get the receiver capabilities */
|
|
if (ioctl (fd, ASI_IOC_RXGETCAP, &cap) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get the receiver capabilities");
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
|
|
/* Get the buffer size */
|
|
snprintf (name, sizeof (name), fmt, num, "bufsize");
|
|
if (util_strtoul (name, &bufsize) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get "
|
|
"the receiver buffer size");
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
|
|
/* Get the receiver operating mode */
|
|
if (cap & ASI_CAP_RX_SYNC) {
|
|
snprintf (name, sizeof (name), fmt, num, "mode");
|
|
if (util_strtoul (name, &mode) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get "
|
|
"the receiver operating mode");
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
} else {
|
|
mode = ASI_CTL_RX_MODE_RAW;
|
|
}
|
|
if (verbose && !quiet) {
|
|
switch (mode) {
|
|
case ASI_CTL_RX_MODE_RAW:
|
|
printf ("Receiving in raw mode.\n");
|
|
break;
|
|
case ASI_CTL_RX_MODE_188:
|
|
printf ("Synchronizing on 188-byte packets.\n");
|
|
break;
|
|
case ASI_CTL_RX_MODE_204:
|
|
printf ("Synchronizing on 204-byte packets.\n");
|
|
break;
|
|
case ASI_CTL_RX_MODE_AUTO:
|
|
printf ("Synchronizing on detected packet size.\n");
|
|
break;
|
|
case ASI_CTL_RX_MODE_AUTOMAKE188:
|
|
printf ("Synchronizing on "
|
|
"detected packet size\n"
|
|
" and stripping the last "
|
|
"sixteen bytes from "
|
|
"each 204-byte packet.\n");
|
|
break;
|
|
case ASI_CTL_RX_MODE_204MAKE188:
|
|
printf ("Synchronizing on "
|
|
"204-byte packets\n"
|
|
" and stripping the last "
|
|
"sixteen bytes from "
|
|
"each packet.\n");
|
|
break;
|
|
default:
|
|
printf ("Receiving in unknown mode.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Get the packet timestamping mode */
|
|
if (cap & ASI_CAP_RX_TIMESTAMPS) {
|
|
snprintf (name, sizeof (name), fmt, num, "timestamps");
|
|
if (util_strtoul (name, ×tamps) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get "
|
|
"the packet timestamping mode");
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
} else {
|
|
timestamps = ASI_CTL_TSTAMP_NONE;
|
|
}
|
|
if (verbose && !quiet) {
|
|
switch (timestamps) {
|
|
case ASI_CTL_TSTAMP_NONE:
|
|
break;
|
|
case ASI_CTL_TSTAMP_APPEND:
|
|
printf ("Appending an eight-byte timestamp "
|
|
"to each packet.\n");
|
|
break;
|
|
case ASI_CTL_TSTAMP_PREPEND:
|
|
printf ("Prepending an eight-byte timestamp "
|
|
"to each packet.\n");
|
|
break;
|
|
default:
|
|
printf ("Unknown timestamping mode.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Enable/disable synchronization on 0xB8 */
|
|
if (inv_sync >= 0) {
|
|
if (set_invsync (fd, inv_sync, cap, verbose, quiet)) {
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
} else if (verbose && !quiet) {
|
|
printf ("Packet synchronization byte(s) not specified, "
|
|
"using default.\n");
|
|
}
|
|
|
|
/* Enable/disable double packet synchronization */
|
|
if (double_sync >= 0) {
|
|
if (set_dsync (fd, double_sync, cap, verbose, quiet)) {
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
} else if (verbose && !quiet) {
|
|
printf ("Double packet synchronization mode not specified, "
|
|
"using default.\n");
|
|
}
|
|
|
|
/* Set the PID counter */
|
|
if (!quiet) {
|
|
if (pid >= 0) {
|
|
if (mode == ASI_CTL_RX_MODE_RAW) {
|
|
fprintf (stderr, "%s: "
|
|
"PID counter not supported "
|
|
"in raw mode\n", argv0);
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
if (cap & ASI_CAP_RX_PIDCOUNTER) {
|
|
if (ioctl (fd, ASI_IOC_RXSETPID0, &pid) < 0) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to set "
|
|
"the PID counter");
|
|
close (fd);
|
|
return -1;
|
|
} else if (verbose) {
|
|
printf ("Counting PID %4Xh.\n", pid);
|
|
}
|
|
} else {
|
|
fprintf (stderr,
|
|
"%s: PID counter not supported\n",
|
|
argv0);
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
} else if (verbose) {
|
|
printf ("Ignoring the PID counter.\n");
|
|
}
|
|
}
|
|
|
|
/* Allocate some memory */
|
|
if (verbose && !quiet) {
|
|
printf ("Allocating %lu bytes of memory.\n", bufsize);
|
|
}
|
|
if ((data = (unsigned char *)malloc (bufsize)) == NULL) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: unable to allocate memory\n",
|
|
argv0);
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
|
|
/* Open output file */
|
|
ofd = -1;
|
|
if ((argc - optind) == 2) {
|
|
if (verbose && !quiet) {
|
|
printf ("Opening %s.\n", argv[optind + 1]);
|
|
}
|
|
if ((ofd = open (argv[optind + 1],
|
|
O_CREAT | O_WRONLY | O_TRUNC,
|
|
0664)) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to open output file");
|
|
}
|
|
free (data);
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Receive the data and estimate the throughput */
|
|
bytes = 0.0;
|
|
status_time = 0.0;
|
|
pfd.fd = fd;
|
|
pfd.events = POLLIN | POLLPRI;
|
|
if (verbose && !quiet) {
|
|
printf ("Listening for data...\n");
|
|
}
|
|
if (gettimeofday (&tv, NULL) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get time");
|
|
}
|
|
free (data);
|
|
if (ofd >= 0) {
|
|
close (ofd);
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
lasttime = tv.tv_sec + (double)tv.tv_usec / 1000000;
|
|
while (seconds) {
|
|
if (poll (&pfd, 1, 1000) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to poll device file");
|
|
}
|
|
free (data);
|
|
if (ofd >= 0) {
|
|
close (ofd);
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
if (pfd.revents & POLLIN) {
|
|
if ((read_ret = read (fd, data, bufsize)) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to read "
|
|
"from device file");
|
|
}
|
|
free (data);
|
|
if (ofd >= 0) {
|
|
close (ofd);
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
bytes += read_ret;
|
|
if (ofd >= 0) {
|
|
bytes_written = 0;
|
|
while ((read_ret - bytes_written) > 0) {
|
|
if ((write_ret = write (ofd,
|
|
data + bytes_written,
|
|
read_ret - bytes_written)) < 0) {
|
|
if (!quiet) {
|
|
fprintf (stderr,
|
|
"%s: ",
|
|
argv0);
|
|
perror ("unable to "
|
|
"write to "
|
|
"output "
|
|
"file");
|
|
}
|
|
free (data);
|
|
close (ofd);
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
bytes_written += write_ret;
|
|
}
|
|
}
|
|
}
|
|
if ((pfd.revents & POLLPRI) && !quiet) {
|
|
if (ioctl (fd, ASI_IOC_RXGETEVENTS, &val) < 0) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get "
|
|
"the receiver event flags");
|
|
free (data);
|
|
if (ofd >= 0) {
|
|
close (ofd);
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
if (val & ASI_EVENT_RX_BUFFER) {
|
|
fprinttime (stdout, progname);
|
|
printf ("driver receive buffer queue "
|
|
"overrun detected\n");
|
|
}
|
|
if (val & ASI_EVENT_RX_FIFO) {
|
|
fprinttime (stdout, progname);
|
|
printf ("onboard receive FIFO overrun "
|
|
"detected\n");
|
|
}
|
|
if (val & ASI_EVENT_RX_CARRIER) {
|
|
fprinttime (stdout, progname);
|
|
printf ("carrier status "
|
|
"change detected\n");
|
|
}
|
|
if (val & ASI_EVENT_RX_LOS) {
|
|
fprinttime (stdout, progname);
|
|
printf ("loss of packet "
|
|
"synchronization detected\n");
|
|
}
|
|
if (val & ASI_EVENT_RX_AOS) {
|
|
fprinttime (stdout, progname);
|
|
printf ("acquisition of packet "
|
|
"synchronization detected\n");
|
|
}
|
|
if (val & ASI_EVENT_RX_DATA) {
|
|
fprinttime (stdout, progname);
|
|
printf ("receive data status "
|
|
"change detected\n");
|
|
}
|
|
}
|
|
gettimeofday (&tv, NULL);
|
|
time_sec = tv.tv_sec + (double)tv.tv_usec / 1000000;
|
|
dt = time_sec - lasttime;
|
|
if (dt >= 1) {
|
|
status_time += dt;
|
|
lasttime = time_sec;
|
|
if (seconds > 0) {
|
|
seconds--;
|
|
}
|
|
}
|
|
if ((period > 0) && (!quiet) && (status_time >= period)) {
|
|
if (ioctl (fd, ASI_IOC_RXGETSTATUS, &val) < 0) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get "
|
|
"the receiver status");
|
|
free (data);
|
|
if (ofd >= 0) {
|
|
close (ofd);
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
}
|
|
printf ("%8.0f bytes in %f seconds = "
|
|
"%9.0f bps, status = %i.\n",
|
|
bytes, status_time,
|
|
8 * bytes / status_time, val);
|
|
if (pid >= 0) {
|
|
if (ioctl (fd, ASI_IOC_RXGETPID0COUNT, &uval)
|
|
< 0) {
|
|
fprintf (stderr, "%s: ", argv0);
|
|
perror ("unable to get "
|
|
"the PID count");
|
|
free (data);
|
|
if (ofd >= 0) {
|
|
close (ofd);
|
|
}
|
|
close (fd);
|
|
return -1;
|
|
} else if (uval) {
|
|
printf ("PID %4Xh count = %u.\n",
|
|
pid, uval);
|
|
}
|
|
}
|
|
bytes = 0.0;
|
|
status_time = 0.0;
|
|
}
|
|
}
|
|
free (data);
|
|
if (ofd >= 0) {
|
|
close (ofd);
|
|
}
|
|
close (fd);
|
|
return 0;
|
|
|
|
USAGE:
|
|
fprintf (stderr, "Try '%s -h' for more information.\n", argv0);
|
|
return -1;
|
|
}
|
|
|