xref: /freebsd/usr.sbin/fwcontrol/fwdv.c (revision df57947f083046d50552e99b91074927d2458708)
1*df57947fSPedro F. Giffuni /*-
2*df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
3*df57947fSPedro F. Giffuni  *
4937bcaa8SHidetoshi Shimokawa  * Copyright (C) 2003
5937bcaa8SHidetoshi Shimokawa  * 	Hidetoshi Shimokawa. All rights reserved.
6937bcaa8SHidetoshi Shimokawa  *
7937bcaa8SHidetoshi Shimokawa  * Redistribution and use in source and binary forms, with or without
8937bcaa8SHidetoshi Shimokawa  * modification, are permitted provided that the following conditions
9937bcaa8SHidetoshi Shimokawa  * are met:
10937bcaa8SHidetoshi Shimokawa  * 1. Redistributions of source code must retain the above copyright
11937bcaa8SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer.
12937bcaa8SHidetoshi Shimokawa  * 2. Redistributions in binary form must reproduce the above copyright
13937bcaa8SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer in the
14937bcaa8SHidetoshi Shimokawa  *    documentation and/or other materials provided with the distribution.
15937bcaa8SHidetoshi Shimokawa  * 3. All advertising materials mentioning features or use of this software
16937bcaa8SHidetoshi Shimokawa  *    must display the following acknowledgement:
17937bcaa8SHidetoshi Shimokawa  *
18937bcaa8SHidetoshi Shimokawa  *	This product includes software developed by Hidetoshi Shimokawa.
19937bcaa8SHidetoshi Shimokawa  *
20937bcaa8SHidetoshi Shimokawa  * 4. Neither the name of the author nor the names of its contributors
21937bcaa8SHidetoshi Shimokawa  *    may be used to endorse or promote products derived from this software
22937bcaa8SHidetoshi Shimokawa  *    without specific prior written permission.
23937bcaa8SHidetoshi Shimokawa  *
24937bcaa8SHidetoshi Shimokawa  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25937bcaa8SHidetoshi Shimokawa  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26937bcaa8SHidetoshi Shimokawa  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27937bcaa8SHidetoshi Shimokawa  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28937bcaa8SHidetoshi Shimokawa  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29937bcaa8SHidetoshi Shimokawa  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30937bcaa8SHidetoshi Shimokawa  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31937bcaa8SHidetoshi Shimokawa  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32937bcaa8SHidetoshi Shimokawa  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33937bcaa8SHidetoshi Shimokawa  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34937bcaa8SHidetoshi Shimokawa  * SUCH DAMAGE.
35937bcaa8SHidetoshi Shimokawa  *
36937bcaa8SHidetoshi Shimokawa  * $FreeBSD$
37937bcaa8SHidetoshi Shimokawa  */
38937bcaa8SHidetoshi Shimokawa #include <sys/param.h>
39937bcaa8SHidetoshi Shimokawa #include <sys/ioctl.h>
40937bcaa8SHidetoshi Shimokawa #include <sys/time.h>
41937bcaa8SHidetoshi Shimokawa #include <sys/types.h>
42937bcaa8SHidetoshi Shimokawa #include <sys/uio.h>
43937bcaa8SHidetoshi Shimokawa 
44937bcaa8SHidetoshi Shimokawa #if __FreeBSD_version >= 500000
45937bcaa8SHidetoshi Shimokawa #include <arpa/inet.h>
46937bcaa8SHidetoshi Shimokawa #endif
47937bcaa8SHidetoshi Shimokawa 
48937bcaa8SHidetoshi Shimokawa #include <err.h>
49937bcaa8SHidetoshi Shimokawa #include <errno.h>
50937bcaa8SHidetoshi Shimokawa #include <unistd.h>
51937bcaa8SHidetoshi Shimokawa #include <fcntl.h>
52937bcaa8SHidetoshi Shimokawa #include <stdio.h>
53937bcaa8SHidetoshi Shimokawa #include <stdlib.h>
54937bcaa8SHidetoshi Shimokawa #include <string.h>
556d815a7dSWarner Losh #include <sysexits.h>
56937bcaa8SHidetoshi Shimokawa 
57937bcaa8SHidetoshi Shimokawa #include <dev/firewire/firewire.h>
58937bcaa8SHidetoshi Shimokawa #include <dev/firewire/iec68113.h>
59937bcaa8SHidetoshi Shimokawa 
606d815a7dSWarner Losh #include "fwmethods.h"
616d815a7dSWarner Losh 
622932d7d5SHidetoshi Shimokawa #define DEBUG		0
632932d7d5SHidetoshi Shimokawa #define FIX_FRAME	1
64937bcaa8SHidetoshi Shimokawa 
65937bcaa8SHidetoshi Shimokawa struct frac {
66937bcaa8SHidetoshi Shimokawa 	int n,d;
67937bcaa8SHidetoshi Shimokawa };
68937bcaa8SHidetoshi Shimokawa 
69937bcaa8SHidetoshi Shimokawa struct frac frame_cycle[2]  = {
70937bcaa8SHidetoshi Shimokawa 	{8000*100, 2997},	/* NTSC 8000 cycle / 29.97 Hz */
71937bcaa8SHidetoshi Shimokawa 	{320, 1},		/* PAL  8000 cycle / 25 Hz */
72937bcaa8SHidetoshi Shimokawa };
73937bcaa8SHidetoshi Shimokawa int npackets[] = {
74937bcaa8SHidetoshi Shimokawa 	250		/* NTSC */,
75937bcaa8SHidetoshi Shimokawa 	300		/* PAL */
76937bcaa8SHidetoshi Shimokawa };
77937bcaa8SHidetoshi Shimokawa struct frac pad_rate[2]  = {
78937bcaa8SHidetoshi Shimokawa 	{203, 2997},	/* = (8000 - 29.97 * 250)/(29.97 * 250) */
79937bcaa8SHidetoshi Shimokawa 	{1, 15},	/* = (8000 - 25 * 300)/(25 * 300) */
80937bcaa8SHidetoshi Shimokawa };
812932d7d5SHidetoshi Shimokawa char *system_name[] = {"NTSC", "PAL"};
822932d7d5SHidetoshi Shimokawa int frame_rate[] = {30, 25};
83937bcaa8SHidetoshi Shimokawa 
84937bcaa8SHidetoshi Shimokawa #define PSIZE 512
85937bcaa8SHidetoshi Shimokawa #define DSIZE 480
86072d3507SHidetoshi Shimokawa #define NCHUNK 64
87013490c5SHidetoshi Shimokawa 
88013490c5SHidetoshi Shimokawa #define NPACKET_R 256
89013490c5SHidetoshi Shimokawa #define NPACKET_T 255
902932d7d5SHidetoshi Shimokawa #define TNBUF 100	/* XXX too large value causes block noise */
912932d7d5SHidetoshi Shimokawa #define NEMPTY 10	/* depends on TNBUF */
922932d7d5SHidetoshi Shimokawa #define RBUFSIZE (PSIZE * NPACKET_R)
93013490c5SHidetoshi Shimokawa #define MAXBLOCKS (300)
94937bcaa8SHidetoshi Shimokawa #define CYCLE_FRAC 0xc00
95937bcaa8SHidetoshi Shimokawa 
966d815a7dSWarner Losh void
976d815a7dSWarner Losh dvrecv(int d, const char *filename, char ich, int count)
98937bcaa8SHidetoshi Shimokawa {
99937bcaa8SHidetoshi Shimokawa 	struct fw_isochreq isoreq;
100937bcaa8SHidetoshi Shimokawa 	struct fw_isobufreq bufreq;
101937bcaa8SHidetoshi Shimokawa 	struct dvdbc *dv;
102937bcaa8SHidetoshi Shimokawa 	struct ciphdr *ciph;
103937bcaa8SHidetoshi Shimokawa 	struct fw_pkt *pkt;
104937bcaa8SHidetoshi Shimokawa 	char *pad, *buf;
105937bcaa8SHidetoshi Shimokawa 	u_int32_t *ptr;
1062932d7d5SHidetoshi Shimokawa 	int len, tlen, npad, fd, k, m, vec, system = -1, nb;
107013490c5SHidetoshi Shimokawa 	int nblocks[] = {250 /* NTSC */, 300 /* PAL */};
108013490c5SHidetoshi Shimokawa 	struct iovec wbuf[NPACKET_R];
109937bcaa8SHidetoshi Shimokawa 
1106d815a7dSWarner Losh 	if(strcmp(filename, "-") == 0) {
1116d815a7dSWarner Losh 		fd = STDOUT_FILENO;
1126d815a7dSWarner Losh 	} else {
113937bcaa8SHidetoshi Shimokawa 		fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0660);
1146d815a7dSWarner Losh 		if (fd == -1)
1150737626aSEd Maste 			err(EX_NOINPUT, "%s", filename);
1166d815a7dSWarner Losh 	}
1176d815a7dSWarner Losh 	buf = malloc(RBUFSIZE);
1186d815a7dSWarner Losh 	pad = malloc(DSIZE*MAXBLOCKS);
1192932d7d5SHidetoshi Shimokawa 	memset(pad, 0xff, DSIZE*MAXBLOCKS);
120937bcaa8SHidetoshi Shimokawa 	bzero(wbuf, sizeof(wbuf));
121937bcaa8SHidetoshi Shimokawa 
122013490c5SHidetoshi Shimokawa 	bufreq.rx.nchunk = NCHUNK;
123013490c5SHidetoshi Shimokawa 	bufreq.rx.npacket = NPACKET_R;
124937bcaa8SHidetoshi Shimokawa 	bufreq.rx.psize = PSIZE;
125937bcaa8SHidetoshi Shimokawa 	bufreq.tx.nchunk = 0;
126937bcaa8SHidetoshi Shimokawa 	bufreq.tx.npacket = 0;
127937bcaa8SHidetoshi Shimokawa 	bufreq.tx.psize = 0;
1286d815a7dSWarner Losh 	if (ioctl(d, FW_SSTBUF, &bufreq) < 0)
1296d815a7dSWarner Losh 		err(1, "ioctl FW_SSTBUF");
130937bcaa8SHidetoshi Shimokawa 
131937bcaa8SHidetoshi Shimokawa 	isoreq.ch = ich & 0x3f;
132937bcaa8SHidetoshi Shimokawa 	isoreq.tag = (ich >> 6) & 3;
133937bcaa8SHidetoshi Shimokawa 
134937bcaa8SHidetoshi Shimokawa 	if (ioctl(d, FW_SRSTREAM, &isoreq) < 0)
135937bcaa8SHidetoshi Shimokawa        		err(1, "ioctl");
136937bcaa8SHidetoshi Shimokawa 
137937bcaa8SHidetoshi Shimokawa 	k = m = 0;
138937bcaa8SHidetoshi Shimokawa 	while (count <= 0 || k <= count) {
139013490c5SHidetoshi Shimokawa #if 0
140013490c5SHidetoshi Shimokawa 		tlen = 0;
141013490c5SHidetoshi Shimokawa 		while ((len = read(d, buf + tlen, PSIZE
1422932d7d5SHidetoshi Shimokawa 						/* RBUFSIZE - tlen */)) > 0) {
143937bcaa8SHidetoshi Shimokawa 			if (len < 0) {
1448604e72aSHidetoshi Shimokawa 				if (errno == EAGAIN) {
1458604e72aSHidetoshi Shimokawa 					fprintf(stderr, "(EAGAIN)\n");
1468604e72aSHidetoshi Shimokawa 					fflush(stderr);
147013490c5SHidetoshi Shimokawa 					if (len <= 0)
148937bcaa8SHidetoshi Shimokawa 						continue;
149013490c5SHidetoshi Shimokawa 				} else
150937bcaa8SHidetoshi Shimokawa 					err(1, "read failed");
151937bcaa8SHidetoshi Shimokawa 			}
152013490c5SHidetoshi Shimokawa 			tlen += len;
1532932d7d5SHidetoshi Shimokawa 			if ((RBUFSIZE - tlen) < PSIZE)
154013490c5SHidetoshi Shimokawa 				break;
155013490c5SHidetoshi Shimokawa 		};
156013490c5SHidetoshi Shimokawa #else
1572932d7d5SHidetoshi Shimokawa 		tlen = len = read(d, buf, RBUFSIZE);
158013490c5SHidetoshi Shimokawa 		if (len < 0) {
159013490c5SHidetoshi Shimokawa 			if (errno == EAGAIN) {
1606d815a7dSWarner Losh 				fprintf(stderr, "(EAGAIN) - push 'Play'?\n");
161013490c5SHidetoshi Shimokawa 				fflush(stderr);
162013490c5SHidetoshi Shimokawa 				if (len <= 0)
163013490c5SHidetoshi Shimokawa 					continue;
164013490c5SHidetoshi Shimokawa 			} else
165013490c5SHidetoshi Shimokawa 				err(1, "read failed");
166013490c5SHidetoshi Shimokawa 		}
167013490c5SHidetoshi Shimokawa #endif
168013490c5SHidetoshi Shimokawa 		vec = 0;
169937bcaa8SHidetoshi Shimokawa 		ptr = (u_int32_t *) buf;
170937bcaa8SHidetoshi Shimokawa again:
171937bcaa8SHidetoshi Shimokawa 		pkt = (struct fw_pkt *) ptr;
1722932d7d5SHidetoshi Shimokawa #if DEBUG
1738604e72aSHidetoshi Shimokawa 		fprintf(stderr, "%08x %08x %08x %08x\n",
174937bcaa8SHidetoshi Shimokawa 			htonl(ptr[0]), htonl(ptr[1]),
175937bcaa8SHidetoshi Shimokawa 			htonl(ptr[2]), htonl(ptr[3]));
176937bcaa8SHidetoshi Shimokawa #endif
177937bcaa8SHidetoshi Shimokawa 		ciph = (struct ciphdr *)(ptr + 1);	/* skip iso header */
178937bcaa8SHidetoshi Shimokawa 		if (ciph->fmt != CIP_FMT_DVCR)
179013490c5SHidetoshi Shimokawa 			errx(1, "unknown format 0x%x", ciph->fmt);
180937bcaa8SHidetoshi Shimokawa 		ptr = (u_int32_t *) (ciph + 1);		/* skip cip header */
1812932d7d5SHidetoshi Shimokawa #if DEBUG
182937bcaa8SHidetoshi Shimokawa 		if (ciph->fdf.dv.cyc != 0xffff && k == 0) {
183937bcaa8SHidetoshi Shimokawa 			fprintf(stderr, "0x%04x\n", ntohs(ciph->fdf.dv.cyc));
184937bcaa8SHidetoshi Shimokawa 		}
185937bcaa8SHidetoshi Shimokawa #endif
18677ee030bSHidetoshi Shimokawa 		if (pkt->mode.stream.len <= sizeof(struct ciphdr))
187013490c5SHidetoshi Shimokawa 			/* no payload */
188013490c5SHidetoshi Shimokawa 			goto next;
189937bcaa8SHidetoshi Shimokawa 		for (dv = (struct dvdbc *)ptr;
190937bcaa8SHidetoshi Shimokawa 				(char *)dv < (char *)(ptr + ciph->len);
191013490c5SHidetoshi Shimokawa 				dv+=6) {
192937bcaa8SHidetoshi Shimokawa 
1932932d7d5SHidetoshi Shimokawa #if DEBUG
1948604e72aSHidetoshi Shimokawa 			fprintf(stderr, "(%d,%d) ", dv->sct, dv->dseq);
195937bcaa8SHidetoshi Shimokawa #endif
196937bcaa8SHidetoshi Shimokawa 			if  (dv->sct == DV_SCT_HEADER && dv->dseq == 0) {
1972932d7d5SHidetoshi Shimokawa 				if (system < 0) {
1982932d7d5SHidetoshi Shimokawa 					system = ciph->fdf.dv.fs;
1996d815a7dSWarner Losh 					fprintf(stderr, "%s\n", system_name[system]);
2002932d7d5SHidetoshi Shimokawa 				}
2012932d7d5SHidetoshi Shimokawa 
2022932d7d5SHidetoshi Shimokawa 				/* Fix DSF bit */
2032932d7d5SHidetoshi Shimokawa 				if (system == 1 &&
2042932d7d5SHidetoshi Shimokawa 					(dv->payload[0] & DV_DSF_12) == 0)
2052932d7d5SHidetoshi Shimokawa 					dv->payload[0] |= DV_DSF_12;
2062932d7d5SHidetoshi Shimokawa 				nb = nblocks[system];
207e627b033SSean Bruno  				fprintf(stderr, "%d:%02d:%02d %d\r",
208e627b033SSean Bruno 					k / (3600 * frame_rate[system]),
209e627b033SSean Bruno 					(k / (60 * frame_rate[system])) % 60,
210e627b033SSean Bruno 					(k / frame_rate[system]) % 60,
211e627b033SSean Bruno 					k % frame_rate[system]);
212e627b033SSean Bruno 
2132932d7d5SHidetoshi Shimokawa #if FIX_FRAME
214937bcaa8SHidetoshi Shimokawa 				if (m > 0 && m != nb) {
215937bcaa8SHidetoshi Shimokawa 					/* padding bad frame */
216937bcaa8SHidetoshi Shimokawa 					npad = ((nb - m) % nb);
217937bcaa8SHidetoshi Shimokawa 					if (npad < 0)
218937bcaa8SHidetoshi Shimokawa 						npad += nb;
219e627b033SSean Bruno 					fprintf(stderr, "\n%d blocks padded\n",
2208604e72aSHidetoshi Shimokawa 					    npad);
221013490c5SHidetoshi Shimokawa 					npad *= DSIZE;
222013490c5SHidetoshi Shimokawa 					wbuf[vec].iov_base = pad;
223013490c5SHidetoshi Shimokawa 					wbuf[vec++].iov_len = npad;
224013490c5SHidetoshi Shimokawa 					if (vec >= NPACKET_R) {
225013490c5SHidetoshi Shimokawa 						writev(fd, wbuf, vec);
226013490c5SHidetoshi Shimokawa 						vec = 0;
227013490c5SHidetoshi Shimokawa 					}
228937bcaa8SHidetoshi Shimokawa 				}
229937bcaa8SHidetoshi Shimokawa #endif
230937bcaa8SHidetoshi Shimokawa 				k++;
2318604e72aSHidetoshi Shimokawa 				fflush(stderr);
232937bcaa8SHidetoshi Shimokawa 				m = 0;
233937bcaa8SHidetoshi Shimokawa 			}
234937bcaa8SHidetoshi Shimokawa 			if (k == 0 || (count > 0 && k > count))
235937bcaa8SHidetoshi Shimokawa 				continue;
236937bcaa8SHidetoshi Shimokawa 			m++;
237013490c5SHidetoshi Shimokawa 			wbuf[vec].iov_base = (char *) dv;
238013490c5SHidetoshi Shimokawa 			wbuf[vec++].iov_len = DSIZE;
239013490c5SHidetoshi Shimokawa 			if (vec >= NPACKET_R) {
240937bcaa8SHidetoshi Shimokawa 				writev(fd, wbuf, vec);
241937bcaa8SHidetoshi Shimokawa 				vec = 0;
242937bcaa8SHidetoshi Shimokawa 			}
243937bcaa8SHidetoshi Shimokawa 		}
244937bcaa8SHidetoshi Shimokawa 		ptr = (u_int32_t *)dv;
245937bcaa8SHidetoshi Shimokawa next:
246013490c5SHidetoshi Shimokawa 		if ((char *)ptr < buf + tlen)
247937bcaa8SHidetoshi Shimokawa 			goto again;
248013490c5SHidetoshi Shimokawa 		if (vec > 0)
249013490c5SHidetoshi Shimokawa 			writev(fd, wbuf, vec);
250937bcaa8SHidetoshi Shimokawa 	}
251e627b033SSean Bruno 	if (fd != STDOUT_FILENO)
252937bcaa8SHidetoshi Shimokawa 		close(fd);
2538604e72aSHidetoshi Shimokawa 	fprintf(stderr, "\n");
254937bcaa8SHidetoshi Shimokawa }
255937bcaa8SHidetoshi Shimokawa 
256013490c5SHidetoshi Shimokawa 
2576d815a7dSWarner Losh void
2586d815a7dSWarner Losh dvsend(int d, const char *filename, char ich, int count)
259937bcaa8SHidetoshi Shimokawa {
260937bcaa8SHidetoshi Shimokawa 	struct fw_isochreq isoreq;
261937bcaa8SHidetoshi Shimokawa 	struct fw_isobufreq bufreq;
262937bcaa8SHidetoshi Shimokawa 	struct dvdbc *dv;
263937bcaa8SHidetoshi Shimokawa 	struct fw_pkt *pkt;
264013490c5SHidetoshi Shimokawa 	int len, tlen, header, fd, frames, packets, vec, offset, nhdr, i;
2652932d7d5SHidetoshi Shimokawa 	int system=-1, pad_acc, cycle_acc, cycle, f_cycle, f_frac;
2662932d7d5SHidetoshi Shimokawa 	struct iovec wbuf[TNBUF*2 + NEMPTY];
267937bcaa8SHidetoshi Shimokawa 	char *pbuf;
2682932d7d5SHidetoshi Shimokawa 	u_int32_t iso_data, iso_empty, hdr[TNBUF + NEMPTY][3];
269013490c5SHidetoshi Shimokawa 	struct ciphdr *ciph;
270937bcaa8SHidetoshi Shimokawa 	struct timeval start, end;
271937bcaa8SHidetoshi Shimokawa 	double rtime;
272937bcaa8SHidetoshi Shimokawa 
273937bcaa8SHidetoshi Shimokawa 	fd = open(filename, O_RDONLY);
2746d815a7dSWarner Losh 	if (fd == -1)
2750737626aSEd Maste 		err(EX_NOINPUT, "%s", filename);
2766d815a7dSWarner Losh 
2776d815a7dSWarner Losh 	pbuf = malloc(DSIZE * TNBUF);
278937bcaa8SHidetoshi Shimokawa 	bzero(wbuf, sizeof(wbuf));
279937bcaa8SHidetoshi Shimokawa 
280937bcaa8SHidetoshi Shimokawa 	bufreq.rx.nchunk = 0;
281937bcaa8SHidetoshi Shimokawa 	bufreq.rx.npacket = 0;
282937bcaa8SHidetoshi Shimokawa 	bufreq.rx.psize = 0;
283013490c5SHidetoshi Shimokawa 	bufreq.tx.nchunk = NCHUNK;
284013490c5SHidetoshi Shimokawa 	bufreq.tx.npacket = NPACKET_T;
285937bcaa8SHidetoshi Shimokawa 	bufreq.tx.psize = PSIZE;
2866d815a7dSWarner Losh 	if (ioctl(d, FW_SSTBUF, &bufreq) < 0)
2876d815a7dSWarner Losh 		err(1, "ioctl FW_SSTBUF");
288937bcaa8SHidetoshi Shimokawa 
289937bcaa8SHidetoshi Shimokawa 	isoreq.ch = ich & 0x3f;
290937bcaa8SHidetoshi Shimokawa 	isoreq.tag = (ich >> 6) & 3;
291937bcaa8SHidetoshi Shimokawa 
292937bcaa8SHidetoshi Shimokawa 	if (ioctl(d, FW_STSTREAM, &isoreq) < 0)
2936d815a7dSWarner Losh        		err(1, "ioctl FW_STSTREAM");
294937bcaa8SHidetoshi Shimokawa 
2952932d7d5SHidetoshi Shimokawa 	iso_data = 0;
296013490c5SHidetoshi Shimokawa 	pkt = (struct fw_pkt *) &iso_data;
29777ee030bSHidetoshi Shimokawa 	pkt->mode.stream.len = DSIZE + sizeof(struct ciphdr);
298937bcaa8SHidetoshi Shimokawa 	pkt->mode.stream.sy = 0;
299937bcaa8SHidetoshi Shimokawa 	pkt->mode.stream.tcode = FWTCODE_STREAM;
300937bcaa8SHidetoshi Shimokawa 	pkt->mode.stream.chtag = ich;
301013490c5SHidetoshi Shimokawa 	iso_empty = iso_data;
302013490c5SHidetoshi Shimokawa 	pkt = (struct fw_pkt *) &iso_empty;
30377ee030bSHidetoshi Shimokawa 	pkt->mode.stream.len = sizeof(struct ciphdr);
304937bcaa8SHidetoshi Shimokawa 
3052932d7d5SHidetoshi Shimokawa 	bzero(hdr[0], sizeof(hdr[0]));
306013490c5SHidetoshi Shimokawa 	hdr[0][0] = iso_data;
307013490c5SHidetoshi Shimokawa 	ciph = (struct ciphdr *)&hdr[0][1];
3082932d7d5SHidetoshi Shimokawa 	ciph->src = 0;	 /* XXX */
309937bcaa8SHidetoshi Shimokawa 	ciph->len = 120;
310937bcaa8SHidetoshi Shimokawa 	ciph->dbc = 0;
311937bcaa8SHidetoshi Shimokawa 	ciph->eoh1 = 1;
312937bcaa8SHidetoshi Shimokawa 	ciph->fdf.dv.cyc = 0xffff;
313937bcaa8SHidetoshi Shimokawa 
3146d815a7dSWarner Losh 	for (i = 1; i < TNBUF; i++)
315013490c5SHidetoshi Shimokawa 		bcopy(hdr[0], hdr[i], sizeof(hdr[0]));
316013490c5SHidetoshi Shimokawa 
317937bcaa8SHidetoshi Shimokawa 	gettimeofday(&start, NULL);
3182932d7d5SHidetoshi Shimokawa #if DEBUG
3198604e72aSHidetoshi Shimokawa 	fprintf(stderr, "%08x %08x %08x\n",
3208604e72aSHidetoshi Shimokawa 			htonl(hdr[0]), htonl(hdr[1]), htonl(hdr[2]));
321937bcaa8SHidetoshi Shimokawa #endif
322937bcaa8SHidetoshi Shimokawa 	frames = 0;
323937bcaa8SHidetoshi Shimokawa 	packets = 0;
324937bcaa8SHidetoshi Shimokawa 	pad_acc = 0;
325937bcaa8SHidetoshi Shimokawa 	while (1) {
326013490c5SHidetoshi Shimokawa 		tlen = 0;
3272932d7d5SHidetoshi Shimokawa 		while (tlen < DSIZE * TNBUF) {
3282932d7d5SHidetoshi Shimokawa 			len = read(fd, pbuf + tlen, DSIZE * TNBUF - tlen);
329937bcaa8SHidetoshi Shimokawa 			if (len <= 0) {
330013490c5SHidetoshi Shimokawa 				if (tlen > 0)
331013490c5SHidetoshi Shimokawa 					break;
332013490c5SHidetoshi Shimokawa 				if (len < 0)
333013490c5SHidetoshi Shimokawa 					warn("read");
334013490c5SHidetoshi Shimokawa 				else
3356d815a7dSWarner Losh 					fprintf(stderr, "\nend of file\n");
336937bcaa8SHidetoshi Shimokawa 				goto send_end;
337937bcaa8SHidetoshi Shimokawa 			}
338013490c5SHidetoshi Shimokawa 			tlen += len;
339937bcaa8SHidetoshi Shimokawa 		}
340013490c5SHidetoshi Shimokawa 		vec = 0;
341013490c5SHidetoshi Shimokawa 		offset = 0;
342013490c5SHidetoshi Shimokawa 		nhdr = 0;
343013490c5SHidetoshi Shimokawa next:
344013490c5SHidetoshi Shimokawa 		dv = (struct dvdbc *)(pbuf + offset * DSIZE);
345937bcaa8SHidetoshi Shimokawa #if 0
346937bcaa8SHidetoshi Shimokawa 		header = (dv->sct == 0 && dv->dseq == 0);
347937bcaa8SHidetoshi Shimokawa #else
3482932d7d5SHidetoshi Shimokawa 		header = (packets == 0 || packets % npackets[system] == 0);
349937bcaa8SHidetoshi Shimokawa #endif
350937bcaa8SHidetoshi Shimokawa 
351013490c5SHidetoshi Shimokawa 		ciph = (struct ciphdr *)&hdr[nhdr][1];
352937bcaa8SHidetoshi Shimokawa 		if (header) {
3532932d7d5SHidetoshi Shimokawa 			if (system < 0) {
3542932d7d5SHidetoshi Shimokawa 				system = ((dv->payload[0] & DV_DSF_12) != 0);
3552932d7d5SHidetoshi Shimokawa 				printf("%s\n", system_name[system]);
3562932d7d5SHidetoshi Shimokawa 				cycle = 1;
3572932d7d5SHidetoshi Shimokawa 				cycle_acc = frame_cycle[system].d * cycle;
3582932d7d5SHidetoshi Shimokawa 			}
3598604e72aSHidetoshi Shimokawa 			fprintf(stderr, "%d", frames % 10);
360937bcaa8SHidetoshi Shimokawa 			frames ++;
361937bcaa8SHidetoshi Shimokawa 			if (count > 0 && frames > count)
362937bcaa8SHidetoshi Shimokawa 				break;
3632932d7d5SHidetoshi Shimokawa 			if (frames % frame_rate[system] == 0)
3648604e72aSHidetoshi Shimokawa 				fprintf(stderr, "\n");
3658604e72aSHidetoshi Shimokawa 			fflush(stderr);
366937bcaa8SHidetoshi Shimokawa 			f_cycle = (cycle_acc / frame_cycle[system].d) & 0xf;
367937bcaa8SHidetoshi Shimokawa 			f_frac = (cycle_acc % frame_cycle[system].d
368937bcaa8SHidetoshi Shimokawa 					* CYCLE_FRAC) / frame_cycle[system].d;
369937bcaa8SHidetoshi Shimokawa #if 0
370937bcaa8SHidetoshi Shimokawa 			ciph->fdf.dv.cyc = htons(f_cycle << 12 | f_frac);
371937bcaa8SHidetoshi Shimokawa #else
372937bcaa8SHidetoshi Shimokawa 			ciph->fdf.dv.cyc = htons(cycle << 12 | f_frac);
373937bcaa8SHidetoshi Shimokawa #endif
374937bcaa8SHidetoshi Shimokawa 			cycle_acc += frame_cycle[system].n;
375937bcaa8SHidetoshi Shimokawa 			cycle_acc %= frame_cycle[system].d * 0x10;
376937bcaa8SHidetoshi Shimokawa 
377937bcaa8SHidetoshi Shimokawa 		} else {
378013490c5SHidetoshi Shimokawa 			ciph->fdf.dv.cyc = 0xffff;
379937bcaa8SHidetoshi Shimokawa 		}
380937bcaa8SHidetoshi Shimokawa 		ciph->dbc = packets++ % 256;
381937bcaa8SHidetoshi Shimokawa 		pad_acc += pad_rate[system].n;
382937bcaa8SHidetoshi Shimokawa 		if (pad_acc >= pad_rate[system].d) {
383937bcaa8SHidetoshi Shimokawa 			pad_acc -= pad_rate[system].d;
384013490c5SHidetoshi Shimokawa 			bcopy(hdr[nhdr], hdr[nhdr+1], sizeof(hdr[0]));
385013490c5SHidetoshi Shimokawa 			hdr[nhdr][0] = iso_empty;
386013490c5SHidetoshi Shimokawa 			wbuf[vec].iov_base = (char *)hdr[nhdr];
387013490c5SHidetoshi Shimokawa 			wbuf[vec++].iov_len = sizeof(hdr[0]);
388013490c5SHidetoshi Shimokawa 			nhdr ++;
389937bcaa8SHidetoshi Shimokawa 			cycle ++;
390937bcaa8SHidetoshi Shimokawa 		}
391013490c5SHidetoshi Shimokawa 		hdr[nhdr][0] = iso_data;
392013490c5SHidetoshi Shimokawa 		wbuf[vec].iov_base = (char *)hdr[nhdr];
393013490c5SHidetoshi Shimokawa 		wbuf[vec++].iov_len = sizeof(hdr[0]);
394013490c5SHidetoshi Shimokawa 		wbuf[vec].iov_base = (char *)dv;
395013490c5SHidetoshi Shimokawa 		wbuf[vec++].iov_len = DSIZE;
396013490c5SHidetoshi Shimokawa 		nhdr ++;
397013490c5SHidetoshi Shimokawa 		cycle ++;
398013490c5SHidetoshi Shimokawa 		offset ++;
399013490c5SHidetoshi Shimokawa 		if (offset * DSIZE < tlen)
400013490c5SHidetoshi Shimokawa 			goto next;
401937bcaa8SHidetoshi Shimokawa 
402013490c5SHidetoshi Shimokawa again:
403013490c5SHidetoshi Shimokawa 		len = writev(d, wbuf, vec);
404937bcaa8SHidetoshi Shimokawa 		if (len < 0) {
405937bcaa8SHidetoshi Shimokawa 			if (errno == EAGAIN) {
4066d815a7dSWarner Losh 				fprintf(stderr, "(EAGAIN) - push 'Play'?\n");
407013490c5SHidetoshi Shimokawa 				goto again;
408937bcaa8SHidetoshi Shimokawa 			}
409937bcaa8SHidetoshi Shimokawa 			err(1, "write failed");
410937bcaa8SHidetoshi Shimokawa 		}
411937bcaa8SHidetoshi Shimokawa 	}
412937bcaa8SHidetoshi Shimokawa 	close(fd);
4138604e72aSHidetoshi Shimokawa 	fprintf(stderr, "\n");
414937bcaa8SHidetoshi Shimokawa send_end:
415937bcaa8SHidetoshi Shimokawa 	gettimeofday(&end, NULL);
416937bcaa8SHidetoshi Shimokawa 	rtime = end.tv_sec - start.tv_sec
417937bcaa8SHidetoshi Shimokawa 			+ (end.tv_usec - start.tv_usec) * 1e-6;
4188604e72aSHidetoshi Shimokawa 	fprintf(stderr, "%d frames, %.2f secs, %.2f frames/sec\n",
419937bcaa8SHidetoshi Shimokawa 			frames, rtime, frames/rtime);
420937bcaa8SHidetoshi Shimokawa }
421