summaryrefslogtreecommitdiffstats
path: root/usr.sbin/fwcontrol/fwcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/fwcontrol/fwcontrol.c')
-rw-r--r--usr.sbin/fwcontrol/fwcontrol.c102
1 files changed, 86 insertions, 16 deletions
diff --git a/usr.sbin/fwcontrol/fwcontrol.c b/usr.sbin/fwcontrol/fwcontrol.c
index e99473a..de4206e 100644
--- a/usr.sbin/fwcontrol/fwcontrol.c
+++ b/usr.sbin/fwcontrol/fwcontrol.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <dev/firewire/firewire.h>
#include <dev/firewire/iec13213.h>
#include <dev/firewire/fwphyreg.h>
+#include <dev/firewire/iec68113.h>
#include <netinet/in.h>
#include <fcntl.h>
@@ -53,12 +54,11 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
#include <unistd.h>
+#include "fwmethods.h"
-extern int dvrecv(int, char *, char, int);
-extern int dvsend(int, char *, char, int);
-
-int sysctl_set_int(const char *, int);
+static void sysctl_set_int(const char *, int);
static void
usage(void)
@@ -77,10 +77,10 @@ usage(void)
"\t-t: read topology map\n"
"\t-d: hex dump of configuration ROM\n"
"\t-l: load and parse hex dump file of configuration ROM\n"
- "\t-R: Receive DV stream\n"
+ "\t-R: Receive DV or MPEG TS stream\n"
"\t-S: Send DV stream\n"
"\t-m: set fwmem target\n");
- exit(0);
+ exit(EX_USAGE);
}
static void
@@ -276,7 +276,7 @@ reset_start(int fd, int node)
}
static void
-set_pri_req(int fd, int pri_req)
+set_pri_req(int fd, u_int32_t pri_req)
{
struct fw_devlstreq *data;
struct fw_devinfo *devinfo;
@@ -296,7 +296,7 @@ set_pri_req(int fd, int pri_req)
eui64_ntoa(&eui, addr, sizeof(addr));
printf("%d %s, %08x",
devinfo->dst, addr, reg);
- if (reg > 0 && pri_req >= 0) {
+ if (reg > 0) {
old = (reg & 0x3f);
max = (reg & 0x3f00) >> 8;
if (pri_req > max)
@@ -311,7 +311,7 @@ set_pri_req(int fd, int pri_req)
}
static void
-parse_bus_info_block(u_int32_t *p, int info_len)
+parse_bus_info_block(u_int32_t *p)
{
char addr[EUI64_SIZ];
struct bus_info *bi;
@@ -392,7 +392,7 @@ show_crom(u_int32_t *crom_buf)
printf("(OK)\n");
else
printf("(NG)\n");
- parse_bus_info_block(crom_buf+1, hdr->info_len);
+ parse_bus_info_block(crom_buf+1);
crom_init_context(&cc, crom_buf);
dir = cc.stack[0].dir;
@@ -603,21 +603,71 @@ open_dev(int *fd, char *devbase)
}
}
-int
+static void
sysctl_set_int(const char *name, int val)
{
if (sysctlbyname(name, NULL, NULL, &val, sizeof(int)) < 0)
err(1, "sysctl %s failed.", name);
}
+static fwmethod *
+detect_recv_fn(int fd, char ich)
+{
+ char *buf;
+ struct fw_isochreq isoreq;
+ struct fw_isobufreq bufreq;
+ int len;
+ u_int32_t *ptr;
+ struct ciphdr *ciph;
+ fwmethod *retfn;
+
+ bufreq.rx.nchunk = 8;
+ bufreq.rx.npacket = 16;
+ bufreq.rx.psize = 1024;
+ bufreq.tx.nchunk = 0;
+ bufreq.tx.npacket = 0;
+ bufreq.tx.psize = 0;
+
+ if (ioctl(fd, FW_SSTBUF, &bufreq) < 0)
+ err(1, "ioctl FW_SSTBUF");
+
+ isoreq.ch = ich & 0x3f;
+ isoreq.tag = (ich >> 6) & 3;
+
+ if (ioctl(fd, FW_SRSTREAM, &isoreq) < 0)
+ err(1, "ioctl FW_SRSTREAM");
+
+ buf = (char *)malloc(1024*16);
+ len = read(fd, buf, 1024*16);
+ ptr = (u_int32_t *) buf;
+ ciph = (struct ciphdr *)(ptr + 1);
+
+ switch(ciph->fmt) {
+ case CIP_FMT_DVCR:
+ fprintf(stderr, "Detected DV format on input.\n");
+ retfn = dvrecv;
+ break;
+ case CIP_FMT_MPEG:
+ fprintf(stderr, "Detected MPEG TS format on input.\n");
+ retfn = mpegtsrecv;
+ break;
+ default:
+ errx(1, "Unsupported format for receiving: fmt=0x%x", ciph->fmt);
+ }
+ free(buf);
+ return retfn;
+}
+
int
main(int argc, char **argv)
{
u_int32_t crom_buf[1024/4];
char devbase[1024] = "/dev/fw0";
- int fd, tmp, ch, len=1024;
+ int fd, ch, len=1024;
+ long tmp;
struct fw_eui64 eui;
struct eui64 target;
+ fwmethod *recvfn = NULL;
fd = -1;
@@ -626,10 +676,12 @@ main(int argc, char **argv)
list_dev(fd);
}
- while ((ch = getopt(argc, argv, "g:m:o:s:b:prtc:d:l:u:R:S:")) != -1)
+ while ((ch = getopt(argc, argv, "M:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1)
switch(ch) {
case 'b':
tmp = strtol(optarg, NULL, 0);
+ if (tmp < 0 || tmp > (long)0xffffffff)
+ errx(EX_USAGE, "invalid number: %s", optarg);
open_dev(&fd, devbase);
set_pri_req(fd, tmp);
break;
@@ -657,7 +709,7 @@ main(int argc, char **argv)
case 'm':
if (eui64_hostton(optarg, &target) != 0 &&
eui64_aton(optarg, &target) != 0)
- errx(1, "invalid target: %s", optarg);
+ errx(EX_USAGE, "invalid target: %s", optarg);
eui.hi = ntohl(*(u_int32_t*)&(target.octet[0]));
eui.lo = ntohl(*(u_int32_t*)&(target.octet[4]));
sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi);
@@ -688,7 +740,7 @@ main(int argc, char **argv)
break;
case 'u':
tmp = strtol(optarg, NULL, 0);
- snprintf(devbase, sizeof(devbase), "/dev/fw%d", tmp);
+ snprintf(devbase, sizeof(devbase), "/dev/fw%ld", tmp);
if (fd > 0) {
close(fd);
fd = -1;
@@ -700,9 +752,27 @@ main(int argc, char **argv)
break;
#define TAG (1<<6)
#define CHANNEL 63
+ case 'M':
+ switch (optarg[0]) {
+ case 'm':
+ recvfn = mpegtsrecv;
+ break;
+ case 'd':
+ recvfn = dvrecv;
+ break;
+ default:
+ errx(EX_USAGE, "unrecognized method: %s",
+ optarg);
+ }
+ break;
case 'R':
open_dev(&fd, devbase);
- dvrecv(fd, optarg, TAG | CHANNEL, -1);
+ if (recvfn == NULL) /* guess... */
+ recvfn = detect_recv_fn(fd, TAG | CHANNEL);
+ close(fd);
+ fd = -1;
+ open_dev(&fd, devbase);
+ (*recvfn)(fd, optarg, TAG | CHANNEL, -1);
break;
case 'S':
open_dev(&fd, devbase);
OpenPOWER on IntegriCloud