4 #include <sys/inttypes.h>
7 #include <sys/scsiio.h>
9 #define CDROM_LEADOUT 0xAA
11 typedef struct mp_vcd_priv_st
{
13 struct ioc_read_toc_entry entry
;
14 struct cd_toc_entry entry_data
;
18 vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
)
20 vcd
->entry_data
.addr
.msf
.frame
= sect
% 75;
22 vcd
->entry_data
.addr
.msf
.second
= sect
% 60;
24 vcd
->entry_data
.addr
.msf
.minute
= sect
;
28 vcd_inc_msf(mp_vcd_priv_t
* vcd
)
30 vcd
->entry_data
.addr
.msf
.frame
++;
31 if (vcd
->entry_data
.addr
.msf
.frame
==75){
32 vcd
->entry_data
.addr
.msf
.frame
=0;
33 vcd
->entry_data
.addr
.msf
.second
++;
34 if (vcd
->entry_data
.addr
.msf
.second
==60){
35 vcd
->entry_data
.addr
.msf
.second
=0;
36 vcd
->entry_data
.addr
.msf
.minute
++;
41 static inline unsigned int
42 vcd_get_msf(mp_vcd_priv_t
* vcd
)
44 return vcd
->entry_data
.addr
.msf
.frame
+
45 (vcd
->entry_data
.addr
.msf
.second
+
46 vcd
->entry_data
.addr
.msf
.minute
* 60) * 75;
50 vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
52 vcd
->entry
.address_format
= CD_MSF_FORMAT
;
53 vcd
->entry
.starting_track
= track
;
54 vcd
->entry
.data_len
= sizeof(struct cd_toc_entry
);
55 vcd
->entry
.data
= &vcd
->entry_data
;
56 if (ioctl(vcd
->fd
, CDIOREADTOCENTRIES
, &vcd
->entry
)) {
57 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
60 return VCD_SECTOR_DATA
* vcd_get_msf(vcd
);
64 vcd_get_track_end(mp_vcd_priv_t
* vcd
, int track
)
66 struct ioc_toc_header tochdr
;
67 if (ioctl(vcd
->fd
, CDIOREADTOCHEADER
, &tochdr
) == -1) {
68 mp_msg(MSGT_STREAM
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
71 vcd
->entry
.address_format
= CD_MSF_FORMAT
;
72 vcd
->entry
.starting_track
= track
< tochdr
.ending_track
? (track
+ 1) : CDROM_LEADOUT
;
73 vcd
->entry
.data_len
= sizeof(struct cd_toc_entry
);
74 vcd
->entry
.data
= &vcd
->entry_data
;
75 if (ioctl(vcd
->fd
, CDIOREADTOCENTRYS
, &vcd
->entry
)) {
76 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
79 return VCD_SECTOR_DATA
* vcd_get_msf(vcd
);
85 struct ioc_toc_header tochdr
;
87 int i
, min
= 0, sec
= 0, frame
= 0;
88 if (ioctl(fd
, CDIOREADTOCHEADER
, &tochdr
) == -1) {
89 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
92 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.starting_track
);
93 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.ending_track
);
94 for (i
= tochdr
.starting_track
; i
<= tochdr
.ending_track
+ 1; i
++) {
95 struct ioc_read_toc_entry tocentry
;
96 struct cd_toc_entry tocentry_data
;
98 tocentry
.starting_track
= i
<=tochdr
.ending_track
? i
: CDROM_LEADOUT
;
99 tocentry
.address_format
= CD_MSF_FORMAT
;
100 tocentry
.data_len
= sizeof(struct cd_toc_entry
);
101 tocentry
.data
= &tocentry_data
;
103 if (ioctl(fd
, CDIOREADTOCENTRYS
, &tocentry
) == -1) {
104 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
107 if (i
<= tochdr
.ending_track
)
108 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d\n",
109 (int) tocentry
.starting_track
,
110 (int) tocentry
.data
->addr_type
,
111 (int) tocentry
.data
->control
,
112 (int) tocentry
.address_format
,
113 (int) tocentry
.data
->addr
.msf
.minute
,
114 (int) tocentry
.data
->addr
.msf
.second
,
115 (int) tocentry
.data
->addr
.msf
.frame
118 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
120 if (i
> tochdr
.starting_track
)
122 min
= tocentry
.data
->addr
.msf
.minute
- min
;
123 sec
= tocentry
.data
->addr
.msf
.second
- sec
;
124 frame
= tocentry
.data
->addr
.msf
.frame
- frame
;
135 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
137 min
= tocentry
.data
->addr
.msf
.minute
;
138 sec
= tocentry
.data
->addr
.msf
.second
;
139 frame
= tocentry
.data
->addr
.msf
.frame
;
142 vcd
= malloc(sizeof(mp_vcd_priv_t
));
148 vcd_read(mp_vcd_priv_t
* vcd
, char *mem
)
151 int lba
= vcd_get_msf(vcd
);
154 int sync
, header_code
, user_data
, edc_ecc
, error_field
;
159 sector_type
= 5; /* mode2/form2 */
167 memset(&sc
, 0, sizeof(sc
));
169 sc
.cmd
[1] = (sector_type
) << 2;
170 sc
.cmd
[2] = (lba
>> 24) & 0xff;
171 sc
.cmd
[3] = (lba
>> 16) & 0xff;
172 sc
.cmd
[4] = (lba
>> 8) & 0xff;
173 sc
.cmd
[5] = lba
& 0xff;
174 sc
.cmd
[6] = (blocks
>> 16) & 0xff;
175 sc
.cmd
[7] = (blocks
>> 8) & 0xff;
176 sc
.cmd
[8] = blocks
& 0xff;
177 sc
.cmd
[9] = (sync
<< 7) | (header_code
<< 5) | (user_data
<< 4) |
178 (edc_ecc
<< 3) | (error_field
<< 1);
179 sc
.cmd
[10] = sub_channel
;
181 sc
.databuf
= (caddr_t
) mem
;
183 sc
.senselen
= sizeof(sc
.sense
);
184 sc
.flags
= SCCMD_READ
;
186 rc
= ioctl(vcd
->fd
, SCIOCCOMMAND
, &sc
);
188 mp_msg(MSGT_STREAM
,MSGL_ERR
,"SCIOCCOMMAND: %s\n",strerror(errno
));
191 if (sc
.retsts
|| sc
.error
) {
192 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed: status %d error %d\n",
197 return VCD_SECTOR_DATA
;