/*********************************************
NAME: linux.h
FUNCTION: linux based cddb id generation code
CREATED BY: David Shultz
CREATED ON: 08/03/2001
*********************************************/
#ifndef LINUX_H
#define LINUX_H
struct toc {
int min, sec, frame;
} cdtoc[100];
struct discdata {
unsigned long discid;
int num_of_trks;
int track_offsets[100];
int seconds;
};
unsigned int cddb_sum(int n) {
unsigned int ret;
ret = 0;
while (n > 0) {
ret += (n % 10);
n /= 10;
}
return ret;
}
unsigned long cddb_discid(int tot_trks) {
unsigned int i, t = 0, n = 0;
i = 0;
while (i < tot_trks) {
n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
i++;
}
t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) -
((cdtoc[0].min * 60) + cdtoc[0].sec);
return ((n % 0xff) << 24 | t << 8 | tot_trks);
}
struct discdata get_disc_id(char* dev) {
struct discdata data;
int i;
data.num_of_trks = read_toc(dev);
if (data.num_of_trks == -1) {
return data;
}
data.discid = cddb_discid(data.num_of_trks);
for (i = 0; i < data.num_of_trks; i++) {
data.track_offsets[i] = (cdtoc[i].frame);
}
data.seconds = (cdtoc[data.num_of_trks].frame)/75;
return data;
}
int read_toc(char* dev) {
int drive;
struct cdrom_tochdr tochdr;
struct cdrom_tocentry tocentry;
int i, status;
drive = open(dev, O_RDONLY | O_NONBLOCK);
if (drive == -1) {
//printf("Device Error: %d\n", errno);
return(-1);
}
status = ioctl(drive, CDROM_DRIVE_STATUS, CDSL_CURRENT);
if (status<0) {
//printf("Error: Error getting drive status\n");
return(-1);
} else {
switch(status) {
case CDS_DISC_OK:
//printf("Disc ok, moving on\n");
break;
case CDS_TRAY_OPEN:
//printf("Error: Drive reporting tray open...exiting\n");
close(drive);
return(-1);
case CDS_DRIVE_NOT_READY:
//printf("Error: Drive Not Ready...exiting\n");
close(drive);
return(-1);
default:
//printf("This shouldn't happen\n");
close(drive);
return(-1);
}
}
if (ioctl(drive, CDROMREADTOCHDR, &tochdr) == -1) {
switch(errno) {
case EBADF:
//printf("Error: Invalid device...exiting\n");
break;
case EFAULT:
//printf("Error: Memory Write Error...exiting\n");
break;
case ENOTTY:
//printf("Error: Invalid device or Request type...exiting\n");
break;
case EINVAL:
//printf("Error: Invalid REQUEST...exiting\n");
break;
case EAGAIN:
//printf("Error: Drive not ready...exiting\n");
break;
default:
//printf("Error: %d\n", errno);
break;
}
}
for (i = tochdr.cdth_trk0; i <= tochdr.cdth_trk1; i++) {
tocentry.cdte_track = i;
tocentry.cdte_format = CDROM_MSF;
ioctl(drive, CDROMREADTOCENTRY, &tocentry);
cdtoc[i-1].min = tocentry.cdte_addr.msf.minute;
cdtoc[i-1].sec = tocentry.cdte_addr.msf.second;
cdtoc[i-1].frame = tocentry.cdte_addr.msf.frame;
cdtoc[i-1].frame += cdtoc[i-1].min*60*75;
cdtoc[i-1].frame += cdtoc[i-1].sec*75;
}
tocentry.cdte_track = 0xAA;
tocentry.cdte_format = CDROM_MSF;
ioctl(drive, CDROMREADTOCENTRY, &tocentry);
cdtoc[tochdr.cdth_trk1].min = tocentry.cdte_addr.msf.minute;
cdtoc[tochdr.cdth_trk1].sec = tocentry.cdte_addr.msf.second;
cdtoc[tochdr.cdth_trk1].frame = tocentry.cdte_addr.msf.frame;
cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].min*60*75;
cdtoc[tochdr.cdth_trk1].frame += cdtoc[tochdr.cdth_trk1].sec*75;
close(drive);
return tochdr.cdth_trk1;
}
#endif //LINUX_H