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 $
35 * $DragonFly: src/usr.sbin/fwcontrol/fwdv.c,v 1.3 2003/08/08 04:18:44 dillon Exp $
37 #include <sys/param.h>
38 #include <sys/ioctl.h>
40 #include <sys/types.h>
43 #if __FreeBSD_version >= 500000
44 #include <arpa/inet.h>
55 #include <bus/firewire/firewire.h>
56 #include <bus/firewire/iec68113.h>
65 struct frac frame_cycle
[2] = {
66 {8000*100, 2997}, /* NTSC 8000 cycle / 29.97 Hz */
67 {320, 1}, /* PAL 8000 cycle / 25 Hz */
73 struct frac pad_rate
[2] = {
74 {203, 2997}, /* = (8000 - 29.97 * 250)/(29.97 * 250) */
75 {1, 15}, /* = (8000 - 25 * 300)/(25 * 300) */
77 char *system_name
[] = {"NTSC", "PAL"};
78 int frame_rate
[] = {30, 25};
86 #define TNBUF 100 /* XXX too large value causes block noise */
87 #define NEMPTY 10 /* depends on TNBUF */
88 #define RBUFSIZE (PSIZE * NPACKET_R)
89 #define MAXBLOCKS (300)
90 #define CYCLE_FRAC 0xc00
93 dvrecv(int d
, char *filename
, char ich
, int count
)
95 struct fw_isochreq isoreq
;
96 struct fw_isobufreq bufreq
;
102 int len
, tlen
, npad
, fd
, k
, m
, vec
, system
= -1, nb
;
103 int nblocks
[] = {250 /* NTSC */, 300 /* PAL */};
104 struct iovec wbuf
[NPACKET_R
];
106 fd
= open(filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0660);
107 buf
= (char *)malloc(RBUFSIZE
);
108 pad
= (char *)malloc(DSIZE
*MAXBLOCKS
);
109 memset(pad
, 0xff, DSIZE
*MAXBLOCKS
);
110 bzero(wbuf
, sizeof(wbuf
));
112 bufreq
.rx
.nchunk
= NCHUNK
;
113 bufreq
.rx
.npacket
= NPACKET_R
;
114 bufreq
.rx
.psize
= PSIZE
;
115 bufreq
.tx
.nchunk
= 0;
116 bufreq
.tx
.npacket
= 0;
118 if (ioctl(d
, FW_SSTBUF
, &bufreq
) < 0) {
122 isoreq
.ch
= ich
& 0x3f;
123 isoreq
.tag
= (ich
>> 6) & 3;
125 if( ioctl(d
, FW_SRSTREAM
, &isoreq
) < 0)
129 while (count
<= 0 || k
<= count
) {
132 while ((len
= read(d
, buf
+ tlen
, PSIZE
133 /* RBUFSIZE - tlen */)) > 0) {
135 if (errno
== EAGAIN
) {
136 fprintf(stderr
, "(EAGAIN)\n");
141 err(1, "read failed");
144 if ((RBUFSIZE
- tlen
) < PSIZE
)
148 tlen
= len
= read(d
, buf
, RBUFSIZE
);
150 if (errno
== EAGAIN
) {
151 fprintf(stderr
, "(EAGAIN)\n");
156 err(1, "read failed");
160 ptr
= (u_int32_t
*) buf
;
162 pkt
= (struct fw_pkt
*) ptr
;
164 fprintf(stderr
, "%08x %08x %08x %08x\n",
165 htonl(ptr
[0]), htonl(ptr
[1]),
166 htonl(ptr
[2]), htonl(ptr
[3]));
168 ciph
= (struct ciphdr
*)(ptr
+ 1); /* skip iso header */
169 if (ciph
->fmt
!= CIP_FMT_DVCR
)
170 errx(1, "unknown format 0x%x", ciph
->fmt
);
171 ptr
= (u_int32_t
*) (ciph
+ 1); /* skip cip header */
173 if (ciph
->fdf
.dv
.cyc
!= 0xffff && k
== 0) {
174 fprintf(stderr
, "0x%04x\n", ntohs(ciph
->fdf
.dv
.cyc
));
177 if (pkt
->mode
.stream
.len
<= sizeof(struct ciphdr
))
180 for (dv
= (struct dvdbc
*)ptr
;
181 (char *)dv
< (char *)(ptr
+ ciph
->len
);
185 fprintf(stderr
, "(%d,%d) ", dv
->sct
, dv
->dseq
);
187 if (dv
->sct
== DV_SCT_HEADER
&& dv
->dseq
== 0) {
189 system
= ciph
->fdf
.dv
.fs
;
190 printf("%s\n", system_name
[system
]);
195 (dv
->payload
[0] & DV_DSF_12
) == 0)
196 dv
->payload
[0] |= DV_DSF_12
;
197 nb
= nblocks
[system
];
198 fprintf(stderr
, "%d", k
%10);
200 if (m
> 0 && m
!= nb
) {
201 /* padding bad frame */
202 npad
= ((nb
- m
) % nb
);
205 fprintf(stderr
, "(%d blocks padded)",
208 wbuf
[vec
].iov_base
= pad
;
209 wbuf
[vec
++].iov_len
= npad
;
210 if (vec
>= NPACKET_R
) {
211 writev(fd
, wbuf
, vec
);
217 if (k
% frame_rate
[system
] == 0) {
219 fprintf(stderr
, "\n");
224 if (k
== 0 || (count
> 0 && k
> count
))
227 wbuf
[vec
].iov_base
= (char *) dv
;
228 wbuf
[vec
++].iov_len
= DSIZE
;
229 if (vec
>= NPACKET_R
) {
230 writev(fd
, wbuf
, vec
);
234 ptr
= (u_int32_t
*)dv
;
236 if ((char *)ptr
< buf
+ tlen
)
239 writev(fd
, wbuf
, vec
);
242 fprintf(stderr
, "\n");
248 dvsend(int d
, char *filename
, char ich
, int count
)
250 struct fw_isochreq isoreq
;
251 struct fw_isobufreq bufreq
;
254 int len
, tlen
, header
, fd
, frames
, packets
, vec
, offset
, nhdr
, i
;
255 int system
=-1, pad_acc
, cycle_acc
, cycle
, f_cycle
, f_frac
;
256 struct iovec wbuf
[TNBUF
*2 + NEMPTY
];
258 u_int32_t iso_data
, iso_empty
, hdr
[TNBUF
+ NEMPTY
][3];
260 struct timeval start
, end
;
263 fd
= open(filename
, O_RDONLY
);
264 pbuf
= (char *)malloc(DSIZE
* TNBUF
);
265 bzero(wbuf
, sizeof(wbuf
));
267 bufreq
.rx
.nchunk
= 0;
268 bufreq
.rx
.npacket
= 0;
270 bufreq
.tx
.nchunk
= NCHUNK
;
271 bufreq
.tx
.npacket
= NPACKET_T
;
272 bufreq
.tx
.psize
= PSIZE
;
273 if (ioctl(d
, FW_SSTBUF
, &bufreq
) < 0) {
277 isoreq
.ch
= ich
& 0x3f;
278 isoreq
.tag
= (ich
>> 6) & 3;
280 if( ioctl(d
, FW_STSTREAM
, &isoreq
) < 0)
284 pkt
= (struct fw_pkt
*) &iso_data
;
285 pkt
->mode
.stream
.len
= DSIZE
+ sizeof(struct ciphdr
);
286 pkt
->mode
.stream
.sy
= 0;
287 pkt
->mode
.stream
.tcode
= FWTCODE_STREAM
;
288 pkt
->mode
.stream
.chtag
= ich
;
289 iso_empty
= iso_data
;
290 pkt
= (struct fw_pkt
*) &iso_empty
;
291 pkt
->mode
.stream
.len
= sizeof(struct ciphdr
);
293 bzero(hdr
[0], sizeof(hdr
[0]));
294 hdr
[0][0] = iso_data
;
295 ciph
= (struct ciphdr
*)&hdr
[0][1];
296 ciph
->src
= 0; /* XXX */
300 ciph
->fdf
.dv
.cyc
= 0xffff;
302 for (i
= 1; i
< TNBUF
; i
++) {
303 bcopy(hdr
[0], hdr
[i
], sizeof(hdr
[0]));
306 gettimeofday(&start
, NULL
);
308 fprintf(stderr
, "%08x %08x %08x\n",
309 htonl(hdr
[0]), htonl(hdr
[1]), htonl(hdr
[2]));
316 while (tlen
< DSIZE
* TNBUF
) {
317 len
= read(fd
, pbuf
+ tlen
, DSIZE
* TNBUF
- tlen
);
324 printf("\nend of file\n");
333 dv
= (struct dvdbc
*)(pbuf
+ offset
* DSIZE
);
335 header
= (dv
->sct
== 0 && dv
->dseq
== 0);
337 header
= (packets
== 0 || packets
% npackets
[system
] == 0);
340 ciph
= (struct ciphdr
*)&hdr
[nhdr
][1];
343 system
= ((dv
->payload
[0] & DV_DSF_12
) != 0);
344 printf("%s\n", system_name
[system
]);
346 cycle_acc
= frame_cycle
[system
].d
* cycle
;
348 fprintf(stderr
, "%d", frames
% 10);
350 if (count
> 0 && frames
> count
)
352 if (frames
% frame_rate
[system
] == 0)
353 fprintf(stderr
, "\n");
355 f_cycle
= (cycle_acc
/ frame_cycle
[system
].d
) & 0xf;
356 f_frac
= (cycle_acc
% frame_cycle
[system
].d
357 * CYCLE_FRAC
) / frame_cycle
[system
].d
;
359 ciph
->fdf
.dv
.cyc
= htons(f_cycle
<< 12 | f_frac
);
361 ciph
->fdf
.dv
.cyc
= htons(cycle
<< 12 | f_frac
);
363 cycle_acc
+= frame_cycle
[system
].n
;
364 cycle_acc
%= frame_cycle
[system
].d
* 0x10;
367 ciph
->fdf
.dv
.cyc
= 0xffff;
369 ciph
->dbc
= packets
++ % 256;
370 pad_acc
+= pad_rate
[system
].n
;
371 if (pad_acc
>= pad_rate
[system
].d
) {
372 pad_acc
-= pad_rate
[system
].d
;
373 bcopy(hdr
[nhdr
], hdr
[nhdr
+1], sizeof(hdr
[0]));
374 hdr
[nhdr
][0] = iso_empty
;
375 wbuf
[vec
].iov_base
= (char *)hdr
[nhdr
];
376 wbuf
[vec
++].iov_len
= sizeof(hdr
[0]);
380 hdr
[nhdr
][0] = iso_data
;
381 wbuf
[vec
].iov_base
= (char *)hdr
[nhdr
];
382 wbuf
[vec
++].iov_len
= sizeof(hdr
[0]);
383 wbuf
[vec
].iov_base
= (char *)dv
;
384 wbuf
[vec
++].iov_len
= DSIZE
;
388 if (offset
* DSIZE
< tlen
)
392 len
= writev(d
, wbuf
, vec
);
394 if (errno
== EAGAIN
) {
395 fprintf(stderr
, "(EAGAIN)\n");
399 err(1, "write failed");
403 fprintf(stderr
, "\n");
405 gettimeofday(&end
, NULL
);
406 rtime
= end
.tv_sec
- start
.tv_sec
407 + (end
.tv_usec
- start
.tv_usec
) * 1e-6;
408 fprintf(stderr
, "%d frames, %.2f secs, %.2f frames/sec\n",
409 frames
, rtime
, frames
/rtime
);