This repository has been archived on 2022-09-20. You can view files and clone it, but cannot push or open issues or pull requests.
libraw1394/tools/dumpiso.c
Stefan Richter ba8d2119ba tools: Fix startup of dumpiso and sendiso on juju
Quoting the errno manual:

"[errno] is set by system calls and some library functions in the
event of an error to indicate  what went wrong.  Its value is
significant only when the return value of the call indicated an
error (i.e., -1 from most system calls; -1 or NULL from most library
functions); a function that succeeds is allowed to change errno.
Valid error numbers are all nonzero; errno is never set to zero by
any system call or library function."

Dumpiso and sendiso checked for raw1394_set_port() failure by
looking at errno rather than by looking at the function's return
code.  This happened to work on top of raw1394 by lucky incident but
no longer works on top of firewire-core.

Reported-by: Vladimir Romanov <blueboar2@gmail.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2013-08-24 11:51:11 +02:00

269 lines
8 KiB
C

/*
* libraw1394 - library for raw access to the 1394 bus with the Linux subsystem.
*
* Copyright (C) 1999,2000 Andreas Bombe
*
* This library is licensed under the GNU Lesser General Public License (LGPL),
* version 2.1 or later. See the file COPYING.LIB in the distribution for
* details.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <fcntl.h>
#include "../src/raw1394.h"
#define BUFFER 1000
#define PACKET_MAX 4096
u_int64_t listen_channels;
unsigned long which_port;
char *filename;
int file;
enum raw1394_iso_dma_recv_mode mode = RAW1394_DMA_DEFAULT;
void usage_exit(int exitcode)
{
fprintf(stderr,
"Usage: dumpiso [opts] [FILE]\n"
"Dump IEEE 1394 isochronous channels to FILE or standard output.\n"
"\n"
"-c --channels CHANNELS Listen on these channels; CHANNELS is either a\n"
" number X or a range X-Y.\n"
"-p --port PORT Choose 1394 chip PORT. (default: 0)\n"
"-h --help Show this help.\n"
);
exit(exitcode);
}
void parse_args(int argc, char **argv)
{
int i;
char *tail;
unsigned long chan1, chan2;
int c;
int index;
static struct option opts[] = {
{ "channels", required_argument, NULL, 'c' },
{ "port", required_argument, NULL, 'p' },
{ "help", no_argument, NULL, 'h' },
{ 0 }
};
while (1) {
c = getopt_long(argc, argv, "hc:p:", opts, &index);
if (c == -1) break;
switch (c) {
case 'c':
chan1 = strtoul(optarg, &tail, 10);
chan2 = chan1;
if (*tail) {
if (tail[0] != '-' || !tail[1]) {
fprintf(stderr,
"invalid argument to channels: %s\n",
optarg);
usage_exit(1);
}
tail++;
chan2 = strtoul(tail, &tail, 10);
if (*tail) {
fprintf(stderr,
"invalid argument to channels: %s\n",
optarg);
usage_exit(1);
}
} else {
mode = RAW1394_DMA_PACKET_PER_BUFFER;
}
if (chan2 < chan1) {
unsigned long x = chan1;
chan1 = chan2;
chan2 = x;
}
if (chan2 > 63) {
fprintf(stderr,
"invalid channel numbers: %s\n",
optarg);
exit(1);
}
for (i = chan1; i <= chan2; i++)
listen_channels |= 1ULL << i;
break;
case 'p':
which_port = strtoul(optarg, &tail, 10);
if (*tail) {
fprintf(stderr,
"invalid argument to port: %s\n",
optarg);
usage_exit(1);
}
break;
case 'h':
usage_exit(0);
case '?':
usage_exit(1);
default:
abort();
}
}
argv += optind;
argc -= optind;
if (argc > 1) {
fprintf(stderr, "Too many arguments.\n");
usage_exit(1);
}
if (argc) filename = *argv;
if (!listen_channels) listen_channels = ~0ULL;
}
void write_header()
{
static char header[32] = "1394 isodump v2";
int i;
for (i = 0; i < 8; i++)
header[i+16] = (listen_channels >> (56 - 8*i)) & 0xff;
i = 0;
while (i < 32) {
int ret;
ret = write(file, header + i, 32 - i);
if (ret < 0) {
perror("header write");
exit(1);
}
i += ret;
}
}
void open_dumpfile()
{
if (!filename || !filename[0] || (filename[0] == '-' && !filename[1])) {
file = fileno(stdout);
write_header();
return;
}
file = creat(filename, 0666);
if (file < 0) {
perror("dumpfile open");
exit(1);
}
write_header();
}
static enum raw1394_iso_disposition
iso_handler(raw1394handle_t handle, unsigned char *data,
unsigned int length, unsigned char channel,
unsigned char tag, unsigned char sy, unsigned int cycle,
unsigned int dropped)
{
int ret;
unsigned char pad = 0;
static unsigned int counter = 0;
if (++counter % 1000 == 0)
fprintf(stderr, "\r%uK packets", counter/1000);
/* write header */
if (write(file, &length, sizeof(length)) != sizeof(length) ||
write(file, &channel, sizeof(channel)) != sizeof(channel) ||
write(file, &tag, sizeof(tag)) != sizeof(tag) ||
write(file, &sy, sizeof(sy)) != sizeof(sy) ||
write(file, &pad, sizeof(pad)) != sizeof(pad)) {
perror("data write");
return RAW1394_ISO_ERROR;
}
while (length) {
ret = write(file, data, length);
if (ret < 0) {
perror("data write");
return RAW1394_ISO_ERROR;
}
length -= ret;
data += ret;
}
return RAW1394_ISO_OK;
}
int main(int argc, char **argv)
{
raw1394handle_t handle;
int i, ret;
parse_args(argc, argv);
fprintf(stderr, "port: %ld\nchannels: %#016llx\nfile: %s\n", which_port,
(long long unsigned)listen_channels, filename);
handle = raw1394_new_handle();
if (!handle) {
if (!errno)
fprintf(stderr,
"No working kernel driver found.\n");
else
perror("raw1394_get_handle");
exit(1);
}
do {
if (raw1394_get_port_info(handle, NULL, 0) <= which_port) {
fprintf(stderr, "Port %ld does not exist.\n",
which_port);
exit(1);
}
ret = raw1394_set_port(handle, which_port);
} while (ret < 0 && errno == ESTALE);
if (ret < 0) {
perror("raw1394_set_port");
exit(1);
}
open_dumpfile();
if (mode == RAW1394_DMA_DEFAULT) {
raw1394_iso_multichannel_recv_init(handle, iso_handler,
BUFFER, 2048, -1); /* >2048 makes rawiso stall! */
raw1394_iso_recv_set_channel_mask(handle, listen_channels);
} else for (i = 0; i < 64; i++) {
if (!(listen_channels & 1ULL << i))
continue;
raw1394_iso_recv_init(handle, iso_handler, BUFFER, PACKET_MAX,
i, mode, -1);
}
raw1394_iso_recv_start(handle, -1, -1, 0);
while (raw1394_loop_iterate(handle) == 0);
fprintf(stderr, "\n");
raw1394_iso_shutdown(handle);
raw1394_destroy_handle(handle);
return 0;
}