xref: /freebsd/usr.sbin/fwcontrol/fwdv.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
1df57947fSPedro F. Giffuni /*-
2df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
3df57947fSPedro 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 #include <sys/param.h>
37937bcaa8SHidetoshi Shimokawa #include <sys/ioctl.h>
38937bcaa8SHidetoshi Shimokawa #include <sys/time.h>
39937bcaa8SHidetoshi Shimokawa #include <sys/types.h>
40937bcaa8SHidetoshi Shimokawa #include <sys/uio.h>
41937bcaa8SHidetoshi Shimokawa #include <arpa/inet.h>
42937bcaa8SHidetoshi Shimokawa #include <err.h>
43937bcaa8SHidetoshi Shimokawa #include <errno.h>
44937bcaa8SHidetoshi Shimokawa #include <unistd.h>
45937bcaa8SHidetoshi Shimokawa #include <fcntl.h>
46937bcaa8SHidetoshi Shimokawa #include <stdio.h>
47937bcaa8SHidetoshi Shimokawa #include <stdlib.h>
48937bcaa8SHidetoshi Shimokawa #include <string.h>
496d815a7dSWarner Losh #include <sysexits.h>
50937bcaa8SHidetoshi Shimokawa 
51937bcaa8SHidetoshi Shimokawa #include <dev/firewire/firewire.h>
52937bcaa8SHidetoshi Shimokawa #include <dev/firewire/iec68113.h>
53937bcaa8SHidetoshi Shimokawa 
546d815a7dSWarner Losh #include "fwmethods.h"
556d815a7dSWarner Losh 
562932d7d5SHidetoshi Shimokawa #define DEBUG		0
572932d7d5SHidetoshi Shimokawa #define FIX_FRAME	1
58937bcaa8SHidetoshi Shimokawa 
59937bcaa8SHidetoshi Shimokawa struct frac {
60937bcaa8SHidetoshi Shimokawa 	int n,d;
61937bcaa8SHidetoshi Shimokawa };
62937bcaa8SHidetoshi Shimokawa 
63937bcaa8SHidetoshi Shimokawa struct frac frame_cycle[2]  = {
64937bcaa8SHidetoshi Shimokawa 	{8000*100, 2997},	/* NTSC 8000 cycle / 29.97 Hz */
65937bcaa8SHidetoshi Shimokawa 	{320, 1},		/* PAL  8000 cycle / 25 Hz */
66937bcaa8SHidetoshi Shimokawa };
67937bcaa8SHidetoshi Shimokawa int npackets[] = {
68937bcaa8SHidetoshi Shimokawa 	250		/* NTSC */,
69937bcaa8SHidetoshi Shimokawa 	300		/* PAL */
70937bcaa8SHidetoshi Shimokawa };
71937bcaa8SHidetoshi Shimokawa struct frac pad_rate[2]  = {
72937bcaa8SHidetoshi Shimokawa 	{203, 2997},	/* = (8000 - 29.97 * 250)/(29.97 * 250) */
73937bcaa8SHidetoshi Shimokawa 	{1, 15},	/* = (8000 - 25 * 300)/(25 * 300) */
74937bcaa8SHidetoshi Shimokawa };
752932d7d5SHidetoshi Shimokawa char *system_name[] = {"NTSC", "PAL"};
762932d7d5SHidetoshi Shimokawa int frame_rate[] = {30, 25};
77937bcaa8SHidetoshi Shimokawa 
78937bcaa8SHidetoshi Shimokawa #define PSIZE 512
79937bcaa8SHidetoshi Shimokawa #define DSIZE 480
80072d3507SHidetoshi Shimokawa #define NCHUNK 64
81013490c5SHidetoshi Shimokawa 
82013490c5SHidetoshi Shimokawa #define NPACKET_R 256
83013490c5SHidetoshi Shimokawa #define NPACKET_T 255
842932d7d5SHidetoshi Shimokawa #define TNBUF 100	/* XXX too large value causes block noise */
852932d7d5SHidetoshi Shimokawa #define NEMPTY 10	/* depends on TNBUF */
862932d7d5SHidetoshi Shimokawa #define RBUFSIZE (PSIZE * NPACKET_R)
87013490c5SHidetoshi Shimokawa #define MAXBLOCKS (300)
88937bcaa8SHidetoshi Shimokawa #define CYCLE_FRAC 0xc00
89937bcaa8SHidetoshi Shimokawa 
906d815a7dSWarner Losh void
dvrecv(int d,const char * filename,char ich,int count)916d815a7dSWarner Losh dvrecv(int d, const char *filename, char ich, int count)
92937bcaa8SHidetoshi Shimokawa {
93937bcaa8SHidetoshi Shimokawa 	struct fw_isochreq isoreq;
94937bcaa8SHidetoshi Shimokawa 	struct fw_isobufreq bufreq;
95937bcaa8SHidetoshi Shimokawa 	struct dvdbc *dv;
96937bcaa8SHidetoshi Shimokawa 	struct ciphdr *ciph;
97937bcaa8SHidetoshi Shimokawa 	struct fw_pkt *pkt;
98937bcaa8SHidetoshi Shimokawa 	char *pad, *buf;
99937bcaa8SHidetoshi Shimokawa 	u_int32_t *ptr;
1002932d7d5SHidetoshi Shimokawa 	int len, tlen, npad, fd, k, m, vec, system = -1, nb;
101013490c5SHidetoshi Shimokawa 	int nblocks[] = {250 /* NTSC */, 300 /* PAL */};
102013490c5SHidetoshi Shimokawa 	struct iovec wbuf[NPACKET_R];
103937bcaa8SHidetoshi Shimokawa 
1046d815a7dSWarner Losh 	if(strcmp(filename, "-") == 0) {
1056d815a7dSWarner Losh 		fd = STDOUT_FILENO;
1066d815a7dSWarner Losh 	} else {
107937bcaa8SHidetoshi Shimokawa 		fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0660);
1086d815a7dSWarner Losh 		if (fd == -1)
1090737626aSEd Maste 			err(EX_NOINPUT, "%s", filename);
1106d815a7dSWarner Losh 	}
1116d815a7dSWarner Losh 	buf = malloc(RBUFSIZE);
1126d815a7dSWarner Losh 	pad = malloc(DSIZE*MAXBLOCKS);
1132932d7d5SHidetoshi Shimokawa 	memset(pad, 0xff, DSIZE*MAXBLOCKS);
114937bcaa8SHidetoshi Shimokawa 	bzero(wbuf, sizeof(wbuf));
115937bcaa8SHidetoshi Shimokawa 
116013490c5SHidetoshi Shimokawa 	bufreq.rx.nchunk = NCHUNK;
117013490c5SHidetoshi Shimokawa 	bufreq.rx.npacket = NPACKET_R;
118937bcaa8SHidetoshi Shimokawa 	bufreq.rx.psize = PSIZE;
119937bcaa8SHidetoshi Shimokawa 	bufreq.tx.nchunk = 0;
120937bcaa8SHidetoshi Shimokawa 	bufreq.tx.npacket = 0;
121937bcaa8SHidetoshi Shimokawa 	bufreq.tx.psize = 0;
1226d815a7dSWarner Losh 	if (ioctl(d, FW_SSTBUF, &bufreq) < 0)
1236d815a7dSWarner Losh 		err(1, "ioctl FW_SSTBUF");
124937bcaa8SHidetoshi Shimokawa 
125937bcaa8SHidetoshi Shimokawa 	isoreq.ch = ich & 0x3f;
126937bcaa8SHidetoshi Shimokawa 	isoreq.tag = (ich >> 6) & 3;
127937bcaa8SHidetoshi Shimokawa 
128937bcaa8SHidetoshi Shimokawa 	if (ioctl(d, FW_SRSTREAM, &isoreq) < 0)
129937bcaa8SHidetoshi Shimokawa        		err(1, "ioctl");
130937bcaa8SHidetoshi Shimokawa 
131937bcaa8SHidetoshi Shimokawa 	k = m = 0;
132937bcaa8SHidetoshi Shimokawa 	while (count <= 0 || k <= count) {
133013490c5SHidetoshi Shimokawa #if 0
134013490c5SHidetoshi Shimokawa 		tlen = 0;
135013490c5SHidetoshi Shimokawa 		while ((len = read(d, buf + tlen, PSIZE
1362932d7d5SHidetoshi Shimokawa 						/* RBUFSIZE - tlen */)) > 0) {
137937bcaa8SHidetoshi Shimokawa 			if (len < 0) {
1388604e72aSHidetoshi Shimokawa 				if (errno == EAGAIN) {
1398604e72aSHidetoshi Shimokawa 					fprintf(stderr, "(EAGAIN)\n");
1408604e72aSHidetoshi Shimokawa 					fflush(stderr);
141013490c5SHidetoshi Shimokawa 					if (len <= 0)
142937bcaa8SHidetoshi Shimokawa 						continue;
143013490c5SHidetoshi Shimokawa 				} else
144937bcaa8SHidetoshi Shimokawa 					err(1, "read failed");
145937bcaa8SHidetoshi Shimokawa 			}
146013490c5SHidetoshi Shimokawa 			tlen += len;
1472932d7d5SHidetoshi Shimokawa 			if ((RBUFSIZE - tlen) < PSIZE)
148013490c5SHidetoshi Shimokawa 				break;
149013490c5SHidetoshi Shimokawa 		};
150013490c5SHidetoshi Shimokawa #else
1512932d7d5SHidetoshi Shimokawa 		tlen = len = read(d, buf, RBUFSIZE);
152013490c5SHidetoshi Shimokawa 		if (len < 0) {
153013490c5SHidetoshi Shimokawa 			if (errno == EAGAIN) {
1546d815a7dSWarner Losh 				fprintf(stderr, "(EAGAIN) - push 'Play'?\n");
155013490c5SHidetoshi Shimokawa 				fflush(stderr);
156013490c5SHidetoshi Shimokawa 				if (len <= 0)
157013490c5SHidetoshi Shimokawa 					continue;
158013490c5SHidetoshi Shimokawa 			} else
159013490c5SHidetoshi Shimokawa 				err(1, "read failed");
160013490c5SHidetoshi Shimokawa 		}
161013490c5SHidetoshi Shimokawa #endif
162013490c5SHidetoshi Shimokawa 		vec = 0;
163937bcaa8SHidetoshi Shimokawa 		ptr = (u_int32_t *) buf;
164937bcaa8SHidetoshi Shimokawa again:
165937bcaa8SHidetoshi Shimokawa 		pkt = (struct fw_pkt *) ptr;
1662932d7d5SHidetoshi Shimokawa #if DEBUG
1678604e72aSHidetoshi Shimokawa 		fprintf(stderr, "%08x %08x %08x %08x\n",
168937bcaa8SHidetoshi Shimokawa 			htonl(ptr[0]), htonl(ptr[1]),
169937bcaa8SHidetoshi Shimokawa 			htonl(ptr[2]), htonl(ptr[3]));
170937bcaa8SHidetoshi Shimokawa #endif
171937bcaa8SHidetoshi Shimokawa 		ciph = (struct ciphdr *)(ptr + 1);	/* skip iso header */
172937bcaa8SHidetoshi Shimokawa 		if (ciph->fmt != CIP_FMT_DVCR)
173013490c5SHidetoshi Shimokawa 			errx(1, "unknown format 0x%x", ciph->fmt);
174937bcaa8SHidetoshi Shimokawa 		ptr = (u_int32_t *) (ciph + 1);		/* skip cip header */
1752932d7d5SHidetoshi Shimokawa #if DEBUG
176937bcaa8SHidetoshi Shimokawa 		if (ciph->fdf.dv.cyc != 0xffff && k == 0) {
177937bcaa8SHidetoshi Shimokawa 			fprintf(stderr, "0x%04x\n", ntohs(ciph->fdf.dv.cyc));
178937bcaa8SHidetoshi Shimokawa 		}
179937bcaa8SHidetoshi Shimokawa #endif
18077ee030bSHidetoshi Shimokawa 		if (pkt->mode.stream.len <= sizeof(struct ciphdr))
181013490c5SHidetoshi Shimokawa 			/* no payload */
182013490c5SHidetoshi Shimokawa 			goto next;
183937bcaa8SHidetoshi Shimokawa 		for (dv = (struct dvdbc *)ptr;
184937bcaa8SHidetoshi Shimokawa 				(char *)dv < (char *)(ptr + ciph->len);
185013490c5SHidetoshi Shimokawa 				dv+=6) {
186937bcaa8SHidetoshi Shimokawa 
1872932d7d5SHidetoshi Shimokawa #if DEBUG
1888604e72aSHidetoshi Shimokawa 			fprintf(stderr, "(%d,%d) ", dv->sct, dv->dseq);
189937bcaa8SHidetoshi Shimokawa #endif
190937bcaa8SHidetoshi Shimokawa 			if  (dv->sct == DV_SCT_HEADER && dv->dseq == 0) {
1912932d7d5SHidetoshi Shimokawa 				if (system < 0) {
1922932d7d5SHidetoshi Shimokawa 					system = ciph->fdf.dv.fs;
1936d815a7dSWarner Losh 					fprintf(stderr, "%s\n", system_name[system]);
1942932d7d5SHidetoshi Shimokawa 				}
1952932d7d5SHidetoshi Shimokawa 
1962932d7d5SHidetoshi Shimokawa 				/* Fix DSF bit */
1972932d7d5SHidetoshi Shimokawa 				if (system == 1 &&
1982932d7d5SHidetoshi Shimokawa 					(dv->payload[0] & DV_DSF_12) == 0)
1992932d7d5SHidetoshi Shimokawa 					dv->payload[0] |= DV_DSF_12;
2002932d7d5SHidetoshi Shimokawa 				nb = nblocks[system];
201e627b033SSean Bruno  				fprintf(stderr, "%d:%02d:%02d %d\r",
202e627b033SSean Bruno 					k / (3600 * frame_rate[system]),
203e627b033SSean Bruno 					(k / (60 * frame_rate[system])) % 60,
204e627b033SSean Bruno 					(k / frame_rate[system]) % 60,
205e627b033SSean Bruno 					k % frame_rate[system]);
206e627b033SSean Bruno 
2072932d7d5SHidetoshi Shimokawa #if FIX_FRAME
208937bcaa8SHidetoshi Shimokawa 				if (m > 0 && m != nb) {
209937bcaa8SHidetoshi Shimokawa 					/* padding bad frame */
210937bcaa8SHidetoshi Shimokawa 					npad = ((nb - m) % nb);
211937bcaa8SHidetoshi Shimokawa 					if (npad < 0)
212937bcaa8SHidetoshi Shimokawa 						npad += nb;
213e627b033SSean Bruno 					fprintf(stderr, "\n%d blocks padded\n",
2148604e72aSHidetoshi Shimokawa 					    npad);
215013490c5SHidetoshi Shimokawa 					npad *= DSIZE;
216013490c5SHidetoshi Shimokawa 					wbuf[vec].iov_base = pad;
217013490c5SHidetoshi Shimokawa 					wbuf[vec++].iov_len = npad;
218013490c5SHidetoshi Shimokawa 					if (vec >= NPACKET_R) {
219013490c5SHidetoshi Shimokawa 						writev(fd, wbuf, vec);
220013490c5SHidetoshi Shimokawa 						vec = 0;
221013490c5SHidetoshi Shimokawa 					}
222937bcaa8SHidetoshi Shimokawa 				}
223937bcaa8SHidetoshi Shimokawa #endif
224937bcaa8SHidetoshi Shimokawa 				k++;
2258604e72aSHidetoshi Shimokawa 				fflush(stderr);
226937bcaa8SHidetoshi Shimokawa 				m = 0;
227937bcaa8SHidetoshi Shimokawa 			}
228937bcaa8SHidetoshi Shimokawa 			if (k == 0 || (count > 0 && k > count))
229937bcaa8SHidetoshi Shimokawa 				continue;
230937bcaa8SHidetoshi Shimokawa 			m++;
231013490c5SHidetoshi Shimokawa 			wbuf[vec].iov_base = (char *) dv;
232013490c5SHidetoshi Shimokawa 			wbuf[vec++].iov_len = DSIZE;
233013490c5SHidetoshi Shimokawa 			if (vec >= NPACKET_R) {
234937bcaa8SHidetoshi Shimokawa 				writev(fd, wbuf, vec);
235937bcaa8SHidetoshi Shimokawa 				vec = 0;
236937bcaa8SHidetoshi Shimokawa 			}
237937bcaa8SHidetoshi Shimokawa 		}
238937bcaa8SHidetoshi Shimokawa 		ptr = (u_int32_t *)dv;
239937bcaa8SHidetoshi Shimokawa next:
240013490c5SHidetoshi Shimokawa 		if ((char *)ptr < buf + tlen)
241937bcaa8SHidetoshi Shimokawa 			goto again;
242013490c5SHidetoshi Shimokawa 		if (vec > 0)
243013490c5SHidetoshi Shimokawa 			writev(fd, wbuf, vec);
244937bcaa8SHidetoshi Shimokawa 	}
245e627b033SSean Bruno 	if (fd != STDOUT_FILENO)
246937bcaa8SHidetoshi Shimokawa 		close(fd);
2478604e72aSHidetoshi Shimokawa 	fprintf(stderr, "\n");
248937bcaa8SHidetoshi Shimokawa }
249937bcaa8SHidetoshi Shimokawa 
250013490c5SHidetoshi Shimokawa 
2516d815a7dSWarner Losh void
dvsend(int d,const char * filename,char ich,int count)2526d815a7dSWarner Losh dvsend(int d, const char *filename, char ich, int count)
253937bcaa8SHidetoshi Shimokawa {
254937bcaa8SHidetoshi Shimokawa 	struct fw_isochreq isoreq;
255937bcaa8SHidetoshi Shimokawa 	struct fw_isobufreq bufreq;
256937bcaa8SHidetoshi Shimokawa 	struct dvdbc *dv;
257937bcaa8SHidetoshi Shimokawa 	struct fw_pkt *pkt;
258013490c5SHidetoshi Shimokawa 	int len, tlen, header, fd, frames, packets, vec, offset, nhdr, i;
259*2d015cffSEd Maste 	int system=-1, pad_acc, cycle_acc, cycle, f_frac;
2602932d7d5SHidetoshi Shimokawa 	struct iovec wbuf[TNBUF*2 + NEMPTY];
261937bcaa8SHidetoshi Shimokawa 	char *pbuf;
2622932d7d5SHidetoshi Shimokawa 	u_int32_t iso_data, iso_empty, hdr[TNBUF + NEMPTY][3];
263013490c5SHidetoshi Shimokawa 	struct ciphdr *ciph;
264937bcaa8SHidetoshi Shimokawa 	struct timeval start, end;
265937bcaa8SHidetoshi Shimokawa 	double rtime;
266937bcaa8SHidetoshi Shimokawa 
267937bcaa8SHidetoshi Shimokawa 	fd = open(filename, O_RDONLY);
2686d815a7dSWarner Losh 	if (fd == -1)
2690737626aSEd Maste 		err(EX_NOINPUT, "%s", filename);
2706d815a7dSWarner Losh 
2716d815a7dSWarner Losh 	pbuf = malloc(DSIZE * TNBUF);
272937bcaa8SHidetoshi Shimokawa 	bzero(wbuf, sizeof(wbuf));
273937bcaa8SHidetoshi Shimokawa 
274937bcaa8SHidetoshi Shimokawa 	bufreq.rx.nchunk = 0;
275937bcaa8SHidetoshi Shimokawa 	bufreq.rx.npacket = 0;
276937bcaa8SHidetoshi Shimokawa 	bufreq.rx.psize = 0;
277013490c5SHidetoshi Shimokawa 	bufreq.tx.nchunk = NCHUNK;
278013490c5SHidetoshi Shimokawa 	bufreq.tx.npacket = NPACKET_T;
279937bcaa8SHidetoshi Shimokawa 	bufreq.tx.psize = PSIZE;
2806d815a7dSWarner Losh 	if (ioctl(d, FW_SSTBUF, &bufreq) < 0)
2816d815a7dSWarner Losh 		err(1, "ioctl FW_SSTBUF");
282937bcaa8SHidetoshi Shimokawa 
283937bcaa8SHidetoshi Shimokawa 	isoreq.ch = ich & 0x3f;
284937bcaa8SHidetoshi Shimokawa 	isoreq.tag = (ich >> 6) & 3;
285937bcaa8SHidetoshi Shimokawa 
286937bcaa8SHidetoshi Shimokawa 	if (ioctl(d, FW_STSTREAM, &isoreq) < 0)
2876d815a7dSWarner Losh        		err(1, "ioctl FW_STSTREAM");
288937bcaa8SHidetoshi Shimokawa 
2892932d7d5SHidetoshi Shimokawa 	iso_data = 0;
290013490c5SHidetoshi Shimokawa 	pkt = (struct fw_pkt *) &iso_data;
29177ee030bSHidetoshi Shimokawa 	pkt->mode.stream.len = DSIZE + sizeof(struct ciphdr);
292937bcaa8SHidetoshi Shimokawa 	pkt->mode.stream.sy = 0;
293937bcaa8SHidetoshi Shimokawa 	pkt->mode.stream.tcode = FWTCODE_STREAM;
294937bcaa8SHidetoshi Shimokawa 	pkt->mode.stream.chtag = ich;
295013490c5SHidetoshi Shimokawa 	iso_empty = iso_data;
296013490c5SHidetoshi Shimokawa 	pkt = (struct fw_pkt *) &iso_empty;
29777ee030bSHidetoshi Shimokawa 	pkt->mode.stream.len = sizeof(struct ciphdr);
298937bcaa8SHidetoshi Shimokawa 
2992932d7d5SHidetoshi Shimokawa 	bzero(hdr[0], sizeof(hdr[0]));
300013490c5SHidetoshi Shimokawa 	hdr[0][0] = iso_data;
301013490c5SHidetoshi Shimokawa 	ciph = (struct ciphdr *)&hdr[0][1];
3022932d7d5SHidetoshi Shimokawa 	ciph->src = 0;	 /* XXX */
303937bcaa8SHidetoshi Shimokawa 	ciph->len = 120;
304937bcaa8SHidetoshi Shimokawa 	ciph->dbc = 0;
305937bcaa8SHidetoshi Shimokawa 	ciph->eoh1 = 1;
306937bcaa8SHidetoshi Shimokawa 	ciph->fdf.dv.cyc = 0xffff;
307937bcaa8SHidetoshi Shimokawa 
3086d815a7dSWarner Losh 	for (i = 1; i < TNBUF; i++)
309013490c5SHidetoshi Shimokawa 		bcopy(hdr[0], hdr[i], sizeof(hdr[0]));
310013490c5SHidetoshi Shimokawa 
311937bcaa8SHidetoshi Shimokawa 	gettimeofday(&start, NULL);
3122932d7d5SHidetoshi Shimokawa #if DEBUG
3138604e72aSHidetoshi Shimokawa 	fprintf(stderr, "%08x %08x %08x\n",
3148604e72aSHidetoshi Shimokawa 			htonl(hdr[0]), htonl(hdr[1]), htonl(hdr[2]));
315937bcaa8SHidetoshi Shimokawa #endif
316937bcaa8SHidetoshi Shimokawa 	frames = 0;
317937bcaa8SHidetoshi Shimokawa 	packets = 0;
318937bcaa8SHidetoshi Shimokawa 	pad_acc = 0;
319937bcaa8SHidetoshi Shimokawa 	while (1) {
320013490c5SHidetoshi Shimokawa 		tlen = 0;
3212932d7d5SHidetoshi Shimokawa 		while (tlen < DSIZE * TNBUF) {
3222932d7d5SHidetoshi Shimokawa 			len = read(fd, pbuf + tlen, DSIZE * TNBUF - tlen);
323937bcaa8SHidetoshi Shimokawa 			if (len <= 0) {
324013490c5SHidetoshi Shimokawa 				if (tlen > 0)
325013490c5SHidetoshi Shimokawa 					break;
326013490c5SHidetoshi Shimokawa 				if (len < 0)
327013490c5SHidetoshi Shimokawa 					warn("read");
328013490c5SHidetoshi Shimokawa 				else
3296d815a7dSWarner Losh 					fprintf(stderr, "\nend of file\n");
330937bcaa8SHidetoshi Shimokawa 				goto send_end;
331937bcaa8SHidetoshi Shimokawa 			}
332013490c5SHidetoshi Shimokawa 			tlen += len;
333937bcaa8SHidetoshi Shimokawa 		}
334013490c5SHidetoshi Shimokawa 		vec = 0;
335013490c5SHidetoshi Shimokawa 		offset = 0;
336013490c5SHidetoshi Shimokawa 		nhdr = 0;
337013490c5SHidetoshi Shimokawa next:
338013490c5SHidetoshi Shimokawa 		dv = (struct dvdbc *)(pbuf + offset * DSIZE);
339937bcaa8SHidetoshi Shimokawa #if 0
340937bcaa8SHidetoshi Shimokawa 		header = (dv->sct == 0 && dv->dseq == 0);
341937bcaa8SHidetoshi Shimokawa #else
3422932d7d5SHidetoshi Shimokawa 		header = (packets == 0 || packets % npackets[system] == 0);
343937bcaa8SHidetoshi Shimokawa #endif
344937bcaa8SHidetoshi Shimokawa 
345013490c5SHidetoshi Shimokawa 		ciph = (struct ciphdr *)&hdr[nhdr][1];
346937bcaa8SHidetoshi Shimokawa 		if (header) {
3472932d7d5SHidetoshi Shimokawa 			if (system < 0) {
3482932d7d5SHidetoshi Shimokawa 				system = ((dv->payload[0] & DV_DSF_12) != 0);
3492932d7d5SHidetoshi Shimokawa 				printf("%s\n", system_name[system]);
3502932d7d5SHidetoshi Shimokawa 				cycle = 1;
3512932d7d5SHidetoshi Shimokawa 				cycle_acc = frame_cycle[system].d * cycle;
3522932d7d5SHidetoshi Shimokawa 			}
3538604e72aSHidetoshi Shimokawa 			fprintf(stderr, "%d", frames % 10);
354937bcaa8SHidetoshi Shimokawa 			frames ++;
355937bcaa8SHidetoshi Shimokawa 			if (count > 0 && frames > count)
356937bcaa8SHidetoshi Shimokawa 				break;
3572932d7d5SHidetoshi Shimokawa 			if (frames % frame_rate[system] == 0)
3588604e72aSHidetoshi Shimokawa 				fprintf(stderr, "\n");
3598604e72aSHidetoshi Shimokawa 			fflush(stderr);
360937bcaa8SHidetoshi Shimokawa 			f_frac = (cycle_acc % frame_cycle[system].d
361937bcaa8SHidetoshi Shimokawa 					* CYCLE_FRAC) / frame_cycle[system].d;
362937bcaa8SHidetoshi Shimokawa #if 0
363*2d015cffSEd Maste 			int f_cycle;
364*2d015cffSEd Maste 			f_cycle = (cycle_acc / frame_cycle[system].d) & 0xf;
365937bcaa8SHidetoshi Shimokawa 			ciph->fdf.dv.cyc = htons(f_cycle << 12 | f_frac);
366937bcaa8SHidetoshi Shimokawa #else
367937bcaa8SHidetoshi Shimokawa 			ciph->fdf.dv.cyc = htons(cycle << 12 | f_frac);
368937bcaa8SHidetoshi Shimokawa #endif
369937bcaa8SHidetoshi Shimokawa 			cycle_acc += frame_cycle[system].n;
370937bcaa8SHidetoshi Shimokawa 			cycle_acc %= frame_cycle[system].d * 0x10;
371937bcaa8SHidetoshi Shimokawa 
372937bcaa8SHidetoshi Shimokawa 		} else {
373013490c5SHidetoshi Shimokawa 			ciph->fdf.dv.cyc = 0xffff;
374937bcaa8SHidetoshi Shimokawa 		}
375937bcaa8SHidetoshi Shimokawa 		ciph->dbc = packets++ % 256;
376937bcaa8SHidetoshi Shimokawa 		pad_acc += pad_rate[system].n;
377937bcaa8SHidetoshi Shimokawa 		if (pad_acc >= pad_rate[system].d) {
378937bcaa8SHidetoshi Shimokawa 			pad_acc -= pad_rate[system].d;
379013490c5SHidetoshi Shimokawa 			bcopy(hdr[nhdr], hdr[nhdr+1], sizeof(hdr[0]));
380013490c5SHidetoshi Shimokawa 			hdr[nhdr][0] = iso_empty;
381013490c5SHidetoshi Shimokawa 			wbuf[vec].iov_base = (char *)hdr[nhdr];
382013490c5SHidetoshi Shimokawa 			wbuf[vec++].iov_len = sizeof(hdr[0]);
383013490c5SHidetoshi Shimokawa 			nhdr ++;
384937bcaa8SHidetoshi Shimokawa 			cycle ++;
385937bcaa8SHidetoshi Shimokawa 		}
386013490c5SHidetoshi Shimokawa 		hdr[nhdr][0] = iso_data;
387013490c5SHidetoshi Shimokawa 		wbuf[vec].iov_base = (char *)hdr[nhdr];
388013490c5SHidetoshi Shimokawa 		wbuf[vec++].iov_len = sizeof(hdr[0]);
389013490c5SHidetoshi Shimokawa 		wbuf[vec].iov_base = (char *)dv;
390013490c5SHidetoshi Shimokawa 		wbuf[vec++].iov_len = DSIZE;
391013490c5SHidetoshi Shimokawa 		nhdr ++;
392013490c5SHidetoshi Shimokawa 		cycle ++;
393013490c5SHidetoshi Shimokawa 		offset ++;
394013490c5SHidetoshi Shimokawa 		if (offset * DSIZE < tlen)
395013490c5SHidetoshi Shimokawa 			goto next;
396937bcaa8SHidetoshi Shimokawa 
397013490c5SHidetoshi Shimokawa again:
398013490c5SHidetoshi Shimokawa 		len = writev(d, wbuf, vec);
399937bcaa8SHidetoshi Shimokawa 		if (len < 0) {
400937bcaa8SHidetoshi Shimokawa 			if (errno == EAGAIN) {
4016d815a7dSWarner Losh 				fprintf(stderr, "(EAGAIN) - push 'Play'?\n");
402013490c5SHidetoshi Shimokawa 				goto again;
403937bcaa8SHidetoshi Shimokawa 			}
404937bcaa8SHidetoshi Shimokawa 			err(1, "write failed");
405937bcaa8SHidetoshi Shimokawa 		}
406937bcaa8SHidetoshi Shimokawa 	}
4078604e72aSHidetoshi Shimokawa 	fprintf(stderr, "\n");
408937bcaa8SHidetoshi Shimokawa send_end:
409937bcaa8SHidetoshi Shimokawa 	gettimeofday(&end, NULL);
410937bcaa8SHidetoshi Shimokawa 	rtime = end.tv_sec - start.tv_sec
411937bcaa8SHidetoshi Shimokawa 			+ (end.tv_usec - start.tv_usec) * 1e-6;
4128604e72aSHidetoshi Shimokawa 	fprintf(stderr, "%d frames, %.2f secs, %.2f frames/sec\n",
413937bcaa8SHidetoshi Shimokawa 			frames, rtime, frames/rtime);
414d8dfc65fSWarner Losh 	close(fd);
415937bcaa8SHidetoshi Shimokawa }
416