779 lines
23 KiB
C
779 lines
23 KiB
C
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <stdlib.h>
|
|
#include "ibm.h"
|
|
#include "ide.h"
|
|
#include "cdrom-ioctl.h"
|
|
#include <util.h>
|
|
#include <IOKit/IOKitLib.h>
|
|
#include <IOKit/IOBSD.h>
|
|
#include <IOKit/storage/IOCDMedia.h>
|
|
#include <IOKit/storage/IOMedia.h>
|
|
#include <IOKit/storage/IOCDTypes.h>
|
|
#include <IOKit/storage/IOCDMediaBSDClient.h>
|
|
#include <IOKit/storage/IOMedia.h>
|
|
#include <errno.h>
|
|
static ATAPI ioctl_atapi;
|
|
|
|
int old_cdrom_drive;
|
|
|
|
static uint32_t cdrom_capacity = 0;
|
|
static int tocvalid = 0;
|
|
static int toc_tracks;
|
|
static int first_track, last_track;
|
|
static CDTOC *toc = NULL;
|
|
static CDDiscInfo disc_info;
|
|
static int track_addr[256];
|
|
|
|
static int msf_to_lba(CDMSF *msf)
|
|
{
|
|
return msf->frame + (msf->second * 75) + (msf->minute * 60 * 75);
|
|
}
|
|
|
|
enum
|
|
{
|
|
CD_STOPPED = 0,
|
|
CD_PLAYING,
|
|
CD_PAUSED
|
|
};
|
|
|
|
static int ioctl_cd_state = CD_STOPPED;
|
|
static uint32_t ioctl_cd_pos = 0, ioctl_cd_end = 0;
|
|
#define BUF_SIZE 32768
|
|
static int16_t cd_buffer[BUF_SIZE];
|
|
static int cd_buflen = 0;
|
|
static int cd_drive = -1;
|
|
|
|
static int cd_open()
|
|
{
|
|
char s[80];
|
|
|
|
if (cd_drive < 0)
|
|
return 0;
|
|
|
|
sprintf(s, "disk%i", cd_drive);
|
|
return opendev(s, O_RDONLY, 0, NULL);
|
|
}
|
|
static void cd_close(int fd)
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
void ioctl_audio_callback(int16_t *output, int len)
|
|
{
|
|
int ioctl_fd;
|
|
|
|
// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount());
|
|
if (ioctl_cd_state != CD_PLAYING)
|
|
{
|
|
memset(output, 0, len * 2);
|
|
return;
|
|
}
|
|
|
|
ioctl_fd = cd_open();
|
|
if (ioctl_fd <= 0)
|
|
{
|
|
memset(output, 0, len * 2);
|
|
return;
|
|
}
|
|
|
|
while (cd_buflen < len)
|
|
{
|
|
if (ioctl_cd_pos < ioctl_cd_end)
|
|
{
|
|
dk_cd_read_t cd_read;
|
|
|
|
bzero(&cd_read, sizeof(cd_read));
|
|
|
|
cd_read.offset = (ioctl_cd_pos-150)*kCDSectorSizeCDDA;
|
|
cd_read.buffer = &cd_buffer[cd_buflen];
|
|
cd_read.bufferLength = kCDSectorSizeCDDA;
|
|
cd_read.sectorType = kCDSectorTypeCDDA;
|
|
cd_read.sectorArea = kCDSectorAreaUser;
|
|
//pclog("CDDA read %llx %d %d\n", cd_read.offset, cd_read.bufferLength, ioctl_cd_pos);
|
|
|
|
if (ioctl(ioctl_fd, DKIOCCDREAD, &cd_read) < 0)
|
|
{
|
|
//pclog("DeviceIoControl returned false %d\n", errno);
|
|
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
|
|
ioctl_cd_state = CD_STOPPED;
|
|
cd_buflen = len;
|
|
}
|
|
else
|
|
{
|
|
//pclog("DeviceIoControl returned true\n");
|
|
ioctl_cd_pos++;
|
|
cd_buflen += (2352 / 2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
|
|
ioctl_cd_state = CD_STOPPED;
|
|
cd_buflen = len;
|
|
}
|
|
}
|
|
|
|
cd_close(ioctl_fd);
|
|
|
|
memcpy(output, cd_buffer, len * 2);
|
|
// for (c = 0; c < BUF_SIZE - len; c++)
|
|
// cd_buffer[c] = cd_buffer[c + cd_buflen];
|
|
memcpy(&cd_buffer[0], &cd_buffer[len], (BUF_SIZE - len) * 2);
|
|
cd_buflen -= len;
|
|
// pclog("Done %i\n", GetTickCount());
|
|
}
|
|
|
|
void ioctl_audio_stop()
|
|
{
|
|
ioctl_cd_state = CD_STOPPED;
|
|
}
|
|
|
|
static int get_track_nr(uint32_t pos)
|
|
{
|
|
int c;
|
|
int track = 0;
|
|
|
|
if (!tocvalid)
|
|
return 0;
|
|
|
|
for (c = first_track; c < last_track; c++)
|
|
{
|
|
uint32_t track_address = toc->descriptors[c].p.frame +
|
|
(toc->descriptors[c].p.second * 75) +
|
|
(toc->descriptors[c].p.minute * 75 * 60);
|
|
//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address);
|
|
if (track_address <= pos)
|
|
track = c;
|
|
}
|
|
return track;
|
|
}
|
|
|
|
static int is_track_audio(uint32_t pos)
|
|
{
|
|
int c;
|
|
int control = 0;
|
|
//pclog("is_track_audio: %08x %i\n", pos, tocvalid);
|
|
if (!tocvalid)
|
|
return 0;
|
|
//pclog(" scan tracks %i-%i\n", first_track, last_track);
|
|
for (c = first_track; c < last_track; c++)
|
|
{
|
|
uint32_t track_address = toc->descriptors[c].p.frame +
|
|
(toc->descriptors[c].p.second * 75) +
|
|
(toc->descriptors[c].p.minute * 75 * 60);
|
|
//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address);
|
|
if (track_address <= pos)
|
|
control = toc->descriptors[c].control;
|
|
}
|
|
return (control & 4) ? 0 : 1;
|
|
}
|
|
|
|
static int ioctl_is_track_audio(uint32_t pos, int ismsf)
|
|
{
|
|
if (ismsf)
|
|
{
|
|
CDMSF msf;
|
|
msf.minute = (pos >> 16) & 0xff;
|
|
msf.second = (pos >> 8) & 0xff;
|
|
msf.frame = pos & 0xff;
|
|
pos = msf_to_lba(&msf);
|
|
}
|
|
return is_track_audio(pos);
|
|
}
|
|
|
|
static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf)
|
|
{
|
|
//pclog("Play audio - %08X %08X %i\n", pos, len, ismsf);
|
|
if (ismsf)
|
|
{
|
|
pos = (pos & 0xff) + (((pos >> 8) & 0xff) * 75) + (((pos >> 16) & 0xff) * 75 * 60);
|
|
len = (len & 0xff) + (((len >> 8) & 0xff) * 75) + (((len >> 16) & 0xff) * 75 * 60);
|
|
//pclog("MSF - pos = %08X len = %08X\n", pos, len);
|
|
}
|
|
else
|
|
len += pos;
|
|
ioctl_cd_pos = pos;// + 150;
|
|
ioctl_cd_end = pos+len;// + 150;
|
|
ioctl_cd_state = CD_PLAYING;
|
|
if (ioctl_cd_pos < 150)
|
|
ioctl_cd_pos = 150;
|
|
// pclog("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, 0, len);
|
|
}
|
|
|
|
static void ioctl_pause(void)
|
|
{
|
|
if (ioctl_cd_state == CD_PLAYING)
|
|
ioctl_cd_state = CD_PAUSED;
|
|
}
|
|
|
|
static void ioctl_resume(void)
|
|
{
|
|
if (ioctl_cd_state == CD_PAUSED)
|
|
ioctl_cd_state = CD_PLAYING;
|
|
}
|
|
|
|
static void ioctl_stop(void)
|
|
{
|
|
ioctl_cd_state = CD_STOPPED;
|
|
}
|
|
|
|
static void ioctl_seek(uint32_t pos)
|
|
{
|
|
// pclog("Seek %08X\n", pos);
|
|
ioctl_cd_pos = pos;
|
|
ioctl_cd_state = CD_STOPPED;
|
|
}
|
|
|
|
static int read_toc(int fd)
|
|
{
|
|
dk_cd_read_toc_t cd_read_toc;
|
|
dk_cd_read_disc_info_t cd_read_disc_info;
|
|
int result;
|
|
int c;
|
|
|
|
bzero(&cd_read_toc, sizeof(cd_read_toc));
|
|
bzero(&cd_read_disc_info, sizeof(cd_read_disc_info));
|
|
bzero(toc, sizeof(CDTOC) + sizeof(CDTOCDescriptor)*100);
|
|
|
|
cd_read_toc.format = kCDTOCFormatTOC;
|
|
cd_read_toc.buffer = toc;
|
|
cd_read_toc.bufferLength = 2048;//sizeof(CDTOC) + sizeof(CDTOCDescriptor)*100;
|
|
//pclog("buffer=%p bufferLength=%u\n", cd_read_toc.buffer, cd_read_toc.bufferLength);
|
|
result = ioctl(fd, DKIOCCDREADTOC, &cd_read_toc);
|
|
|
|
//pclog("Read_toc - fd=%d result=%d errno=%d toc=%p\n", fd, result, errno, toc);
|
|
if (result < 0)
|
|
{
|
|
//pclog("read_toc: DKIOCCDREADTOC failed\n");
|
|
return 0;
|
|
}
|
|
|
|
//pclog("toc length=%u first=%u last=%u\n", toc->length, toc->sessionFirst, toc->sessionFirst);
|
|
first_track = 1;
|
|
last_track = 0;
|
|
toc_tracks = CDTOCGetDescriptorCount(toc);
|
|
|
|
for (c = 0; c < toc_tracks; c++)
|
|
{
|
|
if (toc->descriptors[c].session > 1)
|
|
continue;
|
|
track_addr[c] = msf_to_lba(&toc->descriptors[c].p);
|
|
//pclog("Track %i %02x addr %08x\n", c, toc->descriptors[c].point, track_addr[c]);
|
|
if (toc->descriptors[c].point <= 99 && toc->descriptors[c].adr == 1)
|
|
last_track++;
|
|
}
|
|
|
|
//pclog("Tracks %i %i %i\n", first_track, last_track, toc_tracks);
|
|
|
|
cd_read_disc_info.buffer = &disc_info;
|
|
cd_read_disc_info.bufferLength = sizeof(disc_info);
|
|
result = ioctl(fd, DKIOCCDREADDISCINFO, &cd_read_disc_info);
|
|
if (result < 0)
|
|
{
|
|
//pclog("read_toc: DKIOCCDREADDISCINFO failed\n");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int ioctl_ready(void)
|
|
{
|
|
int ioctl_fd = cd_open();
|
|
//pclog("ioctl_ready - %d %d\n", ioctl_fd, tocvalid);
|
|
if (ioctl_fd <= 0)
|
|
return 0;
|
|
cd_close(ioctl_fd);
|
|
|
|
if (tocvalid)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, int single)
|
|
{
|
|
int c;
|
|
int lb = 0;
|
|
int tv = 0;
|
|
int ioctl_fd;
|
|
|
|
ioctl_fd = cd_open();
|
|
if (ioctl_fd <= 0)
|
|
return 0;
|
|
|
|
//ioctl_cd_state = CD_STOPPED;
|
|
|
|
if (!tocvalid)
|
|
tv = read_toc(ioctl_fd);
|
|
|
|
cd_close(ioctl_fd);
|
|
|
|
if (!tv)
|
|
return 0;
|
|
|
|
for (c = 0; c <= toc_tracks; c++)
|
|
{
|
|
if (track_addr[c] > lb)
|
|
lb = track_addr[c];
|
|
}
|
|
return lb;
|
|
}
|
|
|
|
static int ioctl_medium_changed(void)
|
|
{
|
|
dk_cd_read_disc_info_t cd_read_disc_info;
|
|
CDDiscInfo new_disc_info;
|
|
int result;
|
|
int ioctl_fd;
|
|
|
|
ioctl_fd = cd_open();
|
|
if (ioctl_fd <= 0)
|
|
return 1;
|
|
|
|
bzero(&cd_read_disc_info, sizeof(cd_read_disc_info));
|
|
cd_read_disc_info.buffer = &new_disc_info;
|
|
cd_read_disc_info.bufferLength = sizeof(new_disc_info);
|
|
result = ioctl(ioctl_fd, DKIOCCDREADDISCINFO, &cd_read_disc_info);
|
|
if (result < 0)
|
|
{
|
|
//pclog("medium_changed: DKIOCCDREADDISCINFO failed\n");
|
|
ioctl_cd_state = CD_STOPPED;
|
|
tocvalid = 0;
|
|
cd_close(ioctl_fd);
|
|
return 1;
|
|
}
|
|
|
|
if (memcmp(&disc_info, &new_disc_info, sizeof(CDDiscInfo)))
|
|
{
|
|
//pclog("medium_changed: disc changed\n");
|
|
ioctl_cd_state = CD_STOPPED;
|
|
tocvalid = read_toc(ioctl_fd);
|
|
cd_close(ioctl_fd);
|
|
return 1;
|
|
}
|
|
|
|
cd_close(ioctl_fd);
|
|
return 0;
|
|
}
|
|
|
|
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
|
|
{
|
|
uint32_t cdpos = ioctl_cd_pos;
|
|
int track = get_track_nr(cdpos);
|
|
uint32_t track_address = track_addr[track];
|
|
long size;
|
|
int pos=0;
|
|
int err;
|
|
uint8_t ret;
|
|
|
|
|
|
if (ioctl_cd_state == CD_PLAYING)
|
|
ret = 0x11;
|
|
else if (ioctl_cd_state == CD_PAUSED)
|
|
ret = 0x12;
|
|
else
|
|
ret = 0x13;
|
|
|
|
b[pos++] = (toc->descriptors[track].adr << 4) | toc->descriptors[track].control;
|
|
b[pos++] = toc->descriptors[track].point;
|
|
b[pos++] = 0;
|
|
|
|
if (msf)
|
|
{
|
|
uint32_t dat = cdpos;
|
|
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
|
|
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
|
|
b[pos + 1] = (uint8_t)dat;
|
|
b[pos] = 0;
|
|
pos += 4;
|
|
dat = cdpos - track_address;
|
|
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
|
|
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
|
|
b[pos + 1] = (uint8_t)dat;
|
|
b[pos] = 0;
|
|
pos += 4;
|
|
}
|
|
else
|
|
{
|
|
b[pos++] = (cdpos >> 24) & 0xff;
|
|
b[pos++] = (cdpos >> 16) & 0xff;
|
|
b[pos++] = (cdpos >> 8) & 0xff;
|
|
b[pos++] = cdpos & 0xff;
|
|
cdpos -= track_address;
|
|
b[pos++] = (cdpos >> 24) & 0xff;
|
|
b[pos++] = (cdpos >> 16) & 0xff;
|
|
b[pos++] = (cdpos >> 8) & 0xff;
|
|
b[pos++] = cdpos & 0xff;
|
|
}
|
|
|
|
//pclog("ioctl_getsubchannel: cdpos=%x track_address=%x track=%i state=%i ret=%02x\n", cdpos, track_address, track, ioctl_cd_state, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void ioctl_eject(void)
|
|
{
|
|
}
|
|
|
|
static void ioctl_load(void)
|
|
{
|
|
}
|
|
|
|
static int ioctl_readsector(uint8_t *b, int sector, int count)
|
|
{
|
|
dk_cd_read_t cd_read;
|
|
int res;
|
|
int ioctl_fd;
|
|
|
|
ioctl_fd = cd_open();
|
|
if (ioctl_fd <= 0)
|
|
return -1;
|
|
//pclog("Read sector %x %i\n", sector, count);
|
|
|
|
bzero(&cd_read, sizeof(cd_read));
|
|
|
|
cd_read.offset = sector*2048;
|
|
cd_read.buffer = b;
|
|
cd_read.bufferLength = count*2048;
|
|
cd_read.sectorType = kCDSectorTypeMode1;
|
|
cd_read.sectorArea = kCDSectorAreaUser;
|
|
|
|
res = ioctl(ioctl_fd, DKIOCCDREAD, &cd_read);
|
|
//pclog("read res = %i %i %i\n", res, cd_read.bufferLength, errno);
|
|
|
|
cd_close(ioctl_fd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ioctl_readsector_raw(uint8_t *b, int sector)
|
|
{
|
|
dk_cd_read_t cd_read;
|
|
int res;
|
|
int ioctl_fd;
|
|
|
|
ioctl_fd = cd_open();
|
|
if (ioctl_fd <= 0)
|
|
return;
|
|
//pclog("Read sector %x %i\n", sector, count);
|
|
|
|
bzero(&cd_read, sizeof(cd_read));
|
|
|
|
cd_read.offset = sector*kCDSectorSizeWhole;
|
|
cd_read.buffer = b;
|
|
cd_read.bufferLength = kCDSectorSizeWhole;
|
|
cd_read.sectorType = kCDSectorTypeUnknown;
|
|
cd_read.sectorArea = kCDSectorAreaUser;
|
|
|
|
res = ioctl(ioctl_fd, DKIOCCDREAD, &cd_read);
|
|
//pclog("read res = %i %i %i\n", res, cd_read.bufferLength, errno);
|
|
|
|
cd_close(ioctl_fd);
|
|
}
|
|
|
|
static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
|
|
{
|
|
int len=4;
|
|
int c,d;
|
|
uint32_t temp;
|
|
uint32_t last_address = 0;
|
|
int seenAA = 0;
|
|
|
|
pclog("ioctl_readtoc\n");
|
|
//ioctl_cd_state = CD_STOPPED;
|
|
|
|
if (!tocvalid)
|
|
{
|
|
int ioctl_fd = cd_open();
|
|
|
|
if (ioctl_fd <= 0)
|
|
return 4;
|
|
|
|
tocvalid = read_toc(ioctl_fd);
|
|
cd_close(ioctl_fd);
|
|
}
|
|
if (!tocvalid)
|
|
return 4;
|
|
|
|
//pclog("Read TOC done! %i\n",single);
|
|
b[2] = first_track;
|
|
b[3] = last_track;
|
|
d = 0;
|
|
//pclog("Read TOC starttrack=%i\n", starttrack);
|
|
for (c = 0; c <= toc_tracks; c++)
|
|
{
|
|
if (toc->descriptors[c].point && toc->descriptors[c].point >= starttrack && toc->descriptors[c].point <= 99)
|
|
{
|
|
d = c;
|
|
break;
|
|
}
|
|
}
|
|
//pclog("Start from track %i\n",d);
|
|
b[2] = toc->descriptors[c].point;
|
|
//last_block = 0;
|
|
|
|
for (c = d; c <= toc_tracks; c++)
|
|
{
|
|
uint32_t address;
|
|
if ((len + 8) > maxlen)
|
|
break;
|
|
//pclog("Len %i max %i Track %02X - %02X %02X %02i:%02i:%02i %08X\n",len,maxlen,toc->descriptors[c].point,toc->descriptors[c].adr,toc->descriptors[c].control,toc->descriptors[c].p.minute, toc->descriptors[c].p.second, toc->descriptors[c].p.frame,track_addr[c]);
|
|
address = track_addr[c];
|
|
if (address < last_address)
|
|
continue;
|
|
if (toc->descriptors[c].point == 0xaa)
|
|
seenAA = 1;
|
|
last_address = address;
|
|
b[len++] = 0; /*Reserved*/
|
|
b[len++] = (toc->descriptors[c].adr << 4) | toc->descriptors[c].control;
|
|
b[len++] = toc->descriptors[c].point;
|
|
b[len++] = 0; /*Reserved*/
|
|
//if (address > last_block)
|
|
// last_block = address;
|
|
|
|
if (msf)
|
|
{
|
|
b[len++] = 0;
|
|
b[len++] = toc->descriptors[c].p.minute;
|
|
b[len++] = toc->descriptors[c].p.second;
|
|
b[len++] = toc->descriptors[c].p.frame;
|
|
}
|
|
else
|
|
{
|
|
temp = track_addr[c];
|
|
b[len++] = temp >> 24;
|
|
b[len++] = temp >> 16;
|
|
b[len++] = temp >> 8;
|
|
b[len++] = temp;
|
|
}
|
|
if (single)
|
|
break;
|
|
}
|
|
|
|
if (!seenAA && !single)
|
|
{
|
|
uint32_t lb = 0;
|
|
|
|
for (c = 0; c <= toc_tracks; c++)
|
|
{
|
|
if (track_addr[c] > lb)
|
|
lb = track_addr[c];
|
|
}
|
|
//pclog("Track AA - %08x %i\n", lb, len);
|
|
b[len++] = 0; /*Reserved*/
|
|
b[len++] = (1 << 4) | 1;
|
|
b[len++] = 0xaa;
|
|
b[len++] = 0; /*Reserved*/
|
|
|
|
if (msf)
|
|
{
|
|
b[len++] = 0;
|
|
b[len++] = (lb / 60) / 75;
|
|
b[len++] = (lb / 75) % 60;
|
|
b[len++] = lb % 75;
|
|
}
|
|
else
|
|
{
|
|
temp = track_addr[c];
|
|
b[len++] = lb >> 24;
|
|
b[len++] = lb >> 16;
|
|
b[len++] = lb >> 8;
|
|
b[len++] = lb;
|
|
}
|
|
}
|
|
|
|
b[0] = (uint8_t)(((len-2) >> 8) & 0xff);
|
|
b[1] = (uint8_t)((len-2) & 0xff);
|
|
/* pclog("Table of Contents (%i bytes) : \n", size);
|
|
pclog("First track - %02X\n", first_track);
|
|
pclog("Last track - %02X\n", last_track);
|
|
for (c = 0; c <= last_track; c++)
|
|
pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, 0, toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
|
|
for (c = 0;c <= last_track; c++)
|
|
pclog("Track %02X - number %02X control %02X adr %02X address %06X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame));*/
|
|
return len;
|
|
}
|
|
|
|
static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
|
|
{
|
|
int len = 4;
|
|
int session = 0, first_track_nr = 0;
|
|
int c, d;
|
|
|
|
if (!tocvalid)
|
|
{
|
|
int ioctl_fd = cd_open();
|
|
|
|
if (ioctl_fd <= 0)
|
|
return 4;
|
|
|
|
tocvalid = read_toc(ioctl_fd);
|
|
cd_close(ioctl_fd);
|
|
}
|
|
|
|
if (!tocvalid)
|
|
return 4;
|
|
|
|
for (c = 0; c <= toc_tracks; c++)
|
|
{
|
|
if (toc->descriptors[c].point && toc->descriptors[c].point <= 99)
|
|
{
|
|
if (toc->descriptors[c].session > session || (toc->descriptors[c].session == session && toc->descriptors[c].point < first_track_nr))
|
|
{
|
|
session = toc->descriptors[c].session;
|
|
first_track_nr = toc->descriptors[c].point;
|
|
d = c;
|
|
}
|
|
}
|
|
}
|
|
|
|
b[2] = toc->sessionFirst;
|
|
b[3] = toc->sessionLast;
|
|
b[len++] = 0; /*Reserved*/
|
|
b[len++] = (toc->descriptors[d].adr << 4) | toc->descriptors[d].control;
|
|
b[len++] = toc->descriptors[d].point;
|
|
b[len++] = 0; /*Reserved*/
|
|
if (msf)
|
|
{
|
|
b[len++] = 0;
|
|
b[len++] = toc->descriptors[d].p.minute;
|
|
b[len++] = toc->descriptors[d].p.second;
|
|
b[len++] = toc->descriptors[d].p.frame;
|
|
}
|
|
else
|
|
{
|
|
uint32_t temp = track_addr[d];
|
|
b[len++] = temp >> 24;
|
|
b[len++] = temp >> 16;
|
|
b[len++] = temp >> 8;
|
|
b[len++] = temp;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
|
|
{
|
|
int len = 4;
|
|
int ioctl_fd;
|
|
int track;
|
|
|
|
//pclog("read_toc\n");
|
|
if (!tocvalid)
|
|
return 0;
|
|
|
|
ioctl_fd = cd_open();
|
|
if (ioctl_fd <= 0)
|
|
return 0;
|
|
cd_close(ioctl_fd);
|
|
|
|
b[2] = toc->sessionFirst;
|
|
b[3] = toc->sessionLast;
|
|
|
|
for (track = 0; track <= toc_tracks; track++)
|
|
{
|
|
if ((len + 11) > maxlen)
|
|
{
|
|
pclog("ioctl_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n");
|
|
return len;
|
|
}
|
|
|
|
|
|
// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame);
|
|
|
|
b[len++] = toc->descriptors[track].session;
|
|
b[len++] = (toc->descriptors[track].adr << 4) | toc->descriptors[track].control;
|
|
b[len++] = toc->descriptors[track].tno;
|
|
b[len++] = toc->descriptors[track].point;
|
|
b[len++] = toc->descriptors[track].address.minute;
|
|
b[len++] = toc->descriptors[track].address.second;
|
|
b[len++] = toc->descriptors[track].address.frame;
|
|
b[len++] = toc->descriptors[track].zero;
|
|
b[len++] = toc->descriptors[track].p.minute;
|
|
b[len++] = toc->descriptors[track].p.second;
|
|
b[len++] = toc->descriptors[track].p.frame;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
static uint32_t ioctl_size()
|
|
{
|
|
return cdrom_capacity;
|
|
}
|
|
|
|
static int ioctl_status()
|
|
{
|
|
if (!ioctl_ready)
|
|
return CD_STATUS_EMPTY;
|
|
return CD_STATUS_STOPPED;
|
|
}
|
|
void ioctl_reset()
|
|
{
|
|
int ioctl_fd;
|
|
|
|
tocvalid = 0;
|
|
|
|
ioctl_fd = cd_open();
|
|
if (ioctl_fd <= 0)
|
|
return;
|
|
|
|
tocvalid = read_toc(ioctl_fd);
|
|
cd_close(ioctl_fd);
|
|
}
|
|
|
|
void ioctl_set_drive(char d)
|
|
{
|
|
ioctl_close();
|
|
atapi=&ioctl_atapi;
|
|
ioctl_open(d);
|
|
}
|
|
|
|
int ioctl_open(char d)
|
|
{
|
|
atapi = &ioctl_atapi;
|
|
|
|
toc = malloc(2048);
|
|
|
|
cd_drive = d;
|
|
return 0;
|
|
}
|
|
|
|
void ioctl_close(void)
|
|
{
|
|
if (toc)
|
|
{
|
|
free(toc);
|
|
toc = NULL;
|
|
}
|
|
}
|
|
|
|
static void ioctl_exit(void)
|
|
{
|
|
|
|
}
|
|
|
|
static ATAPI ioctl_atapi=
|
|
{
|
|
ioctl_ready,
|
|
ioctl_medium_changed,
|
|
ioctl_readtoc,
|
|
ioctl_readtoc_session,
|
|
ioctl_readtoc_raw,
|
|
ioctl_getcurrentsubchannel,
|
|
ioctl_readsector,
|
|
ioctl_readsector_raw,
|
|
ioctl_playaudio,
|
|
ioctl_seek,
|
|
ioctl_load,
|
|
ioctl_eject,
|
|
ioctl_pause,
|
|
ioctl_resume,
|
|
ioctl_size,
|
|
ioctl_status,
|
|
ioctl_is_track_audio,
|
|
ioctl_stop,
|
|
ioctl_exit
|
|
};
|