/********************************************* 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