3 * Hidetoshi Shimokawa. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
16 * This product includes software developed by Hidetoshi Shimokawa.
18 * 4. Neither the name of the author nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $FreeBSD: src/usr.sbin/fwcontrol/fwdv.c,v 1.2.2.4 2003/04/28 03:29:18 simokawa Exp $
37 #include <sys/param.h>
38 #include <sys/ioctl.h>
40 #include <sys/types.h>
51 #include <bus/firewire/firewire.h>
52 #include <bus/firewire/iec68113.h>
61 struct frac frame_cycle
[2] = {
62 {8000*100, 2997}, /* NTSC 8000 cycle / 29.97 Hz */
63 {320, 1}, /* PAL 8000 cycle / 25 Hz */
69 struct frac pad_rate
[2] = {
70 {203, 2997}, /* = (8000 - 29.97 * 250)/(29.97 * 250) */
71 {1, 15}, /* = (8000 - 25 * 300)/(25 * 300) */
73 const char *system_name
[] = {"NTSC", "PAL"};
74 int frame_rate
[] = {30, 25};
82 #define TNBUF 100 /* XXX too large value causes block noise */
83 #define NEMPTY 10 /* depends on TNBUF */
84 #define RBUFSIZE (PSIZE * NPACKET_R)
85 #define MAXBLOCKS (300)
86 #define CYCLE_FRAC 0xc00
88 int dvrecv(int, char *, char, int);
89 int dvsend(int, char *, char, int);
92 dvrecv(int d
, char *filename
, char ich
, int count
)
94 struct fw_isochreq isoreq
;
95 struct fw_isobufreq bufreq
;
101 int len
, tlen
, npad
, fd
, k
, m
, vec
, systype
= -1, nb
;
102 int nblocks
[] = {250 /* NTSC */, 300 /* PAL */};
103 struct iovec wbuf
[NPACKET_R
];
105 fd
= open(filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0660);
106 buf
= (char *)malloc(RBUFSIZE
);
107 pad
= (char *)malloc(DSIZE
*MAXBLOCKS
);
108 memset(pad
, 0xff, DSIZE
*MAXBLOCKS
);
109 bzero(wbuf
, sizeof(wbuf
));
111 bufreq
.rx
.nchunk
= NCHUNK
;
112 bufreq
.rx
.npacket
= NPACKET_R
;
113 bufreq
.rx
.psize
= PSIZE
;
114 bufreq
.tx
.nchunk
= 0;
115 bufreq
.tx
.npacket
= 0;
117 if (ioctl(d
, FW_SSTBUF
, &bufreq
) < 0) {
121 isoreq
.ch
= ich
& 0x3f;
122 isoreq
.tag
= (ich
>> 6) & 3;
124 if( ioctl(d
, FW_SRSTREAM
, &isoreq
) < 0)
128 while (count
<= 0 || k
<= count
) {
131 while ((len
= read(d
, buf
+ tlen
, PSIZE
132 /* RBUFSIZE - tlen */)) > 0) {
134 if (errno
== EAGAIN
) {
135 fprintf(stderr
, "(EAGAIN)\n");
140 err(1, "read failed");
143 if ((RBUFSIZE
- tlen
) < PSIZE
)
147 tlen
= len
= read(d
, buf
, RBUFSIZE
);
149 if (errno
== EAGAIN
) {
150 fprintf(stderr
, "(EAGAIN)\n");
155 err(1, "read failed");
159 ptr
= (u_int32_t
*) buf
;
161 pkt
= (struct fw_pkt
*) ptr
;
163 fprintf(stderr
, "%08x %08x %08x %08x\n",
164 htonl(ptr
[0]), htonl(ptr
[1]),
165 htonl(ptr
[2]), htonl(ptr
[3]));
167 ciph
= (struct ciphdr
*)(ptr
+ 1); /* skip iso header */
168 if (ciph
->fmt
!= CIP_FMT_DVCR
)
169 errx(1, "unknown format 0x%x", ciph
->fmt
);
170 ptr
= (u_int32_t
*) (ciph
+ 1); /* skip cip header */
172 if (ciph
->fdf
.dv
.cyc
!= 0xffff && k
== 0) {
173 fprintf(stderr
, "0x%04x\n", ntohs(ciph
->fdf
.dv
.cyc
));
176 if (pkt
->mode
.stream
.len
<= sizeof(struct ciphdr
))
179 for (dv
= (struct dvdbc
*)ptr
;
180 (char *)dv
< (char *)(ptr
+ ciph
->len
);
184 fprintf(stderr
, "(%d,%d) ", dv
->sct
, dv
->dseq
);
186 if (dv
->sct
== DV_SCT_HEADER
&& dv
->dseq
== 0) {
188 systype
= ciph
->fdf
.dv
.fs
;
189 printf("%s\n", system_name
[systype
]);
194 (dv
->payload
[0] & DV_DSF_12
) == 0)
195 dv
->payload
[0] |= DV_DSF_12
;
196 nb
= nblocks
[systype
];
197 fprintf(stderr
, "%d", k
%10);
199 if (m
> 0 && m
!= nb
) {
200 /* padding bad frame */
201 npad
= ((nb
- m
) % nb
);
204 fprintf(stderr
, "(%d blocks padded)",
207 wbuf
[vec
].iov_base
= pad
;
208 wbuf
[vec
++].iov_len
= npad
;
209 if (vec
>= NPACKET_R
) {
210 writev(fd
, wbuf
, vec
);
216 if (k
% frame_rate
[systype
] == 0) {
218 fprintf(stderr
, "\n");
223 if (k
== 0 || (count
> 0 && k
> count
))
226 wbuf
[vec
].iov_base
= (char *) dv
;
227 wbuf
[vec
++].iov_len
= DSIZE
;
228 if (vec
>= NPACKET_R
) {
229 writev(fd
, wbuf
, vec
);
233 ptr
= (u_int32_t
*)dv
;
235 if ((char *)ptr
< buf
+ tlen
)
238 writev(fd
, wbuf
, vec
);
241 fprintf(stderr
, "\n");
247 dvsend(int d
, char *filename
, char ich
, int count
)
249 struct fw_isochreq isoreq
;
250 struct fw_isobufreq bufreq
;
253 int len
, tlen
, header
, fd
, frames
, packets
, vec
, offset
, nhdr
, i
;
254 int systype
=-1, pad_acc
, cycle_acc
=0, cycle
=0, f_frac
;
255 struct iovec wbuf
[TNBUF
*2 + NEMPTY
];
257 u_int32_t iso_data
, iso_empty
, hdr
[TNBUF
+ NEMPTY
][3];
259 struct timeval start
, end
;
265 fd
= open(filename
, O_RDONLY
);
266 pbuf
= (char *)malloc(DSIZE
* TNBUF
);
267 bzero(wbuf
, sizeof(wbuf
));
269 bufreq
.rx
.nchunk
= 0;
270 bufreq
.rx
.npacket
= 0;
272 bufreq
.tx
.nchunk
= NCHUNK
;
273 bufreq
.tx
.npacket
= NPACKET_T
;
274 bufreq
.tx
.psize
= PSIZE
;
275 if (ioctl(d
, FW_SSTBUF
, &bufreq
) < 0) {
279 isoreq
.ch
= ich
& 0x3f;
280 isoreq
.tag
= (ich
>> 6) & 3;
282 if( ioctl(d
, FW_STSTREAM
, &isoreq
) < 0)
286 pkt
= (struct fw_pkt
*) &iso_data
;
287 pkt
->mode
.stream
.len
= DSIZE
+ sizeof(struct ciphdr
);
288 pkt
->mode
.stream
.sy
= 0;
289 pkt
->mode
.stream
.tcode
= FWTCODE_STREAM
;
290 pkt
->mode
.stream
.chtag
= ich
;
291 iso_empty
= iso_data
;
292 pkt
= (struct fw_pkt
*) &iso_empty
;
293 pkt
->mode
.stream
.len
= sizeof(struct ciphdr
);
295 bzero(hdr
[0], sizeof(hdr
[0]));
296 hdr
[0][0] = iso_data
;
297 ciph
= (struct ciphdr
*)&hdr
[0][1];
298 ciph
->src
= 0; /* XXX */
302 ciph
->fdf
.dv
.cyc
= 0xffff;
304 for (i
= 1; i
< TNBUF
; i
++) {
305 bcopy(hdr
[0], hdr
[i
], sizeof(hdr
[0]));
308 gettimeofday(&start
, NULL
);
310 fprintf(stderr
, "%08x %08x %08x\n",
311 htonl(hdr
[0]), htonl(hdr
[1]), htonl(hdr
[2]));
318 while (tlen
< DSIZE
* TNBUF
) {
319 len
= read(fd
, pbuf
+ tlen
, DSIZE
* TNBUF
- tlen
);
326 printf("\nend of file\n");
335 dv
= (struct dvdbc
*)(pbuf
+ offset
* DSIZE
);
337 header
= (dv
->sct
== 0 && dv
->dseq
== 0);
339 header
= (packets
== 0 || packets
% npackets
[systype
] == 0);
342 ciph
= (struct ciphdr
*)&hdr
[nhdr
][1];
345 systype
= ((dv
->payload
[0] & DV_DSF_12
) != 0);
346 printf("%s\n", system_name
[systype
]);
348 cycle_acc
= frame_cycle
[systype
].d
* cycle
;
350 fprintf(stderr
, "%d", frames
% 10);
352 if (count
> 0 && frames
> count
)
354 if (frames
% frame_rate
[systype
] == 0)
355 fprintf(stderr
, "\n");
358 f_cycle
= (cycle_acc
/ frame_cycle
[systype
].d
) & 0xf;
360 f_frac
= (cycle_acc
% frame_cycle
[systype
].d
361 * CYCLE_FRAC
) / frame_cycle
[systype
].d
;
363 ciph
->fdf
.dv
.cyc
= htons(f_cycle
<< 12 | f_frac
);
365 ciph
->fdf
.dv
.cyc
= htons(cycle
<< 12 | f_frac
);
367 cycle_acc
+= frame_cycle
[systype
].n
;
368 cycle_acc
%= frame_cycle
[systype
].d
* 0x10;
371 ciph
->fdf
.dv
.cyc
= 0xffff;
373 ciph
->dbc
= packets
++ % 256;
374 pad_acc
+= pad_rate
[systype
].n
;
375 if (pad_acc
>= pad_rate
[systype
].d
) {
376 pad_acc
-= pad_rate
[systype
].d
;
377 bcopy(hdr
[nhdr
], hdr
[nhdr
+1], sizeof(hdr
[0]));
378 hdr
[nhdr
][0] = iso_empty
;
379 wbuf
[vec
].iov_base
= (char *)hdr
[nhdr
];
380 wbuf
[vec
++].iov_len
= sizeof(hdr
[0]);
384 hdr
[nhdr
][0] = iso_data
;
385 wbuf
[vec
].iov_base
= (char *)hdr
[nhdr
];
386 wbuf
[vec
++].iov_len
= sizeof(hdr
[0]);
387 wbuf
[vec
].iov_base
= (char *)dv
;
388 wbuf
[vec
++].iov_len
= DSIZE
;
392 if (offset
* DSIZE
< tlen
)
396 len
= writev(d
, wbuf
, vec
);
398 if (errno
== EAGAIN
) {
399 fprintf(stderr
, "(EAGAIN)\n");
403 err(1, "write failed");
407 fprintf(stderr
, "\n");
409 gettimeofday(&end
, NULL
);
410 rtime
= end
.tv_sec
- start
.tv_sec
411 + (end
.tv_usec
- start
.tv_usec
) * 1e-6;
412 fprintf(stderr
, "%d frames, %.2f secs, %.2f frames/sec\n",
413 frames
, rtime
, frames
/rtime
);