1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
/*\
|*| PLatform dependent code for accessing CDROM units.
|*| For now, Linux and FreeBSD
\*/
#ifndef CDROMLINUX_H
#define CDROMLINUX_H
/*\
|*| Linux specific code
\*/
#define GET_LBA(entry) ((entry.cdte_format == CDROM_LBA) ? \
entry.cdte_addr.lba : \
((entry.cdte_addr.msf.minute * 60 + \
entry.cdte_addr.msf.second) * 75 + \
entry.cdte_addr.msf.frame))
/*\
|*| Open cdrom device
|*| Return -1 on error.
\*/
static int
cdrom_open(const char *device, int *flags)
{
int fd;
fd = open(device, O_RDONLY|O_NONBLOCK);
if (fd < 0) return -1;
if (!(*flags & FLAG_FAIL_SPD) &&
(ioctl(fd, CDROM_SELECT_SPEED, cd_cfg.cdrom_speed) < 0)) {
if (errno == ENOTTY) {
close(fd);
return -1;
}
*flags |= FLAG_FAIL_SPD;
}
return fd;
}
/*\
|*| Close cdrom device
|*| Return -1 on error.
\*/
static int
cdrom_close(int cdfd)
{
return close(cdfd);
}
/*\ Read the toc into:
|*| cd->first_trk .. cd->last_trk
|*| cd->lba[..], cd->data[..]
|*|
|*| Return -1 on error.
\*/
static int
cdrom_read_toc(struct cd_struct *cd, int cdfd)
{
int i;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry entry;
if (ioctl(cdfd, CDROMREADTOCHDR, &toc_hdr) < 0) {
cd->first_trk = 1;
cd->last_trk = 0;
return -1;
}
cd->first_trk = toc_hdr.cdth_trk0;
cd->last_trk = toc_hdr.cdth_trk1;
i = cd->last_trk + 1;
entry.cdte_track = CDROM_LEADOUT;
entry.cdte_format = CDROM_MSF;
ioctl(cdfd, CDROMREADTOCENTRY, &entry);
cd->lba[i] = GET_LBA(entry);
cd->data[i] = entry.cdte_ctrl & 4;
while (--i >= cd->first_trk) {
entry.cdte_track = i;
entry.cdte_format = CDROM_MSF;
ioctl(cdfd, CDROMREADTOCENTRY, &entry);
cd->lba[i] = GET_LBA(entry);
cd->data[i] = entry.cdte_ctrl & 4;
}
return 0;
}
/*\ Read btw frames of audio data into buf,
|*| from device cdfd, at position lba
|*| Return number of successfully read frames, -1 on error.
\*/
static int
cdrom_read_audio(int cdfd, int lba, char *buf, int btw)
{
int rtr = 3;
do {
struct cdrom_read_audio cdra;
cdra.buf = buf;
cdra.nframes = btw;
cdra.addr.msf.minute = lba / (75 * 60);
cdra.addr.msf.second = (lba / 75) % 60;
cdra.addr.msf.frame = lba % 75;
cdra.addr_format = CDROM_MSF;
if (ioctl(cdfd, CDROMREADAUDIO, &cdra) >= 0)
return cdra.nframes;
} while (--rtr >= 0);
return -1;
}
/*\ Play audio from lba address from, to lba address to
|*| return -1 on failure
\*/
static int
cdrom_play_lba(int cdfd, int from, int to)
{
struct cdrom_msf cmsf;
cmsf.cdmsf_min0 = from / (75 * 60);
cmsf.cdmsf_sec0 = (from / 75) % 60;
cmsf.cdmsf_frame0 = from % 75;
cmsf.cdmsf_min1 = to / (75 * 60);
cmsf.cdmsf_sec1 = (to / 75) % 60;
cmsf.cdmsf_frame1 = to % 75;
return ioctl(cdfd, CDROMPLAYMSF, &cmsf);
}
/*\ Stop audio playback
|*| return -1 on failure
\*/
static int
cdrom_stop(int cdfd)
{
/*\ CDROMPAUSE: Rude hack, because stop takes so long.
|*| It looks like it actually stops the disc spinning..
\*/
if (cdfd >= 0) return ioctl(cdfd, CDROMPAUSE, 0);
return 0;
}
/*\ Pause/resume audio playback
|*| return -1 on failure
\*/
static int
cdrom_pause(int cdfd, short p)
{
return ioctl(cdfd, p ? CDROMPAUSE : CDROMRESUME);
}
/*\ Get currently playing relative time
|*| return -1 on failure
|*| (Closes cdfd if not playing)
\*/
static gint32
cdrom_get_time(struct cd_struct *cd)
{
gint32 f;
struct cdrom_subchnl cdsc;
if (cd->cdfd < 0)
return -1;
cdsc.cdsc_format = CDROM_MSF;
if (ioctl(cd->cdfd, CDROMSUBCHNL, &cdsc) < 0)
return -2;
if (cdsc.cdsc_audiostatus == CDROM_AUDIO_ERROR)
return -2;
if (cdsc.cdsc_audiostatus == CDROM_AUDIO_COMPLETED)
return -1;
f = ((cdsc.cdsc_absaddr.msf.minute * 60 +
cdsc.cdsc_absaddr.msf.second) * 75 +
cdsc.cdsc_absaddr.msf.frame);
if (f > (end_lba - 20))
return -1;
f -= cd->lba[cur_trk];
if (f < 0) f = 0;
return (f * 40) / 3;
}
#endif /*\ CDROMLINUX_H \*/
|