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