/********************************************* NAME: freebsd.h FUNCTION: FreeBSD based cddb id generation code ORIGINALLY CREATED BY: David Shultz ORIGINALLY CREATED ON: 08/03/2001 ADAPTED BY: Peter Pentchev ADAPTED ON: 09/28/2005 *********************************************/ #ifndef FREEBSD_H #define FREEBSD_H struct discdata { unsigned long discid; int num_of_trks; int track_offsets[100]; int seconds; }; /* * The following has been blatantly stolen from FreeBSD 5.4's * cdcontrol(8) utility. */ int msf; struct cd_toc_entry toc_buffer[100]; int read_toc_entrys (int fd, int len) { struct ioc_read_toc_entry t; t.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT; t.starting_track = 0; t.data_len = len; t.data = toc_buffer; return (ioctl (fd, CDIOREADTOCENTRYS, (char *) &t)); } void lba2msf (unsigned long lba, u_char *m, u_char *s, u_char *f) { lba += 150; /* block start offset */ lba &= 0xffffff; /* negative lbas use only 24 bits */ *m = lba / (60 * 75); lba %= (60 * 75); *s = lba / 75; *f = lba % 75; } /* * dbprog_sum * Convert an integer to its text string representation, and * compute its checksum. Used by dbprog_discid to derive the * disc ID. * * Args: * n - The integer value. * * Return: * The integer checksum. */ static int dbprog_sum(int n) { char buf[12], *p; int ret = 0; /* For backward compatibility this algorithm must not change */ sprintf(buf, "%u", n); for (p = buf; *p != '\0'; p++) ret += (*p - '0'); return(ret); } /* * dbprog_discid * Compute a magic disc ID based on the number of tracks, * the length of each track, and a checksum of the string * that represents the offset of each track. * * Args: * s - Pointer to the curstat_t structure. * * Return: * The integer disc ID. */ int dbprog_discid(int fd, struct discdata *d) { struct ioc_toc_header h; int rc; int i, ntr, t = 0, n = 0; long block; u_char m, s, f; rc = ioctl (fd, CDIOREADTOCHEADER, &h); if (rc < 0) return (0); ntr = h.ending_track - h.starting_track + 1; i = msf; msf = 1; rc = read_toc_entrys (fd, (ntr + 1) * sizeof (struct cd_toc_entry)); msf = i; if (rc < 0) return (0); d->num_of_trks = ntr; /* For backward compatibility this algorithm must not change */ d->track_offsets[0] = 150; for (i = 0; i < ntr; i++) { #define TC_FR(a) toc_buffer[a].addr.msf.frame #define TC_MM(a) toc_buffer[a].addr.msf.minute #define TC_SS(a) toc_buffer[a].addr.msf.second n += dbprog_sum((TC_MM(i) * 60) + TC_SS(i)); t += ((TC_MM(i+1) * 60) + TC_SS(i+1)) - ((TC_MM(i) * 60) + TC_SS(i)); d->track_offsets[i + 1] = TC_FR(i + 1) + TC_MM(i + 1) * 60 * 75 + TC_SS(i+1)*75; fprintf(stderr, "i %d mm %d ss %d fr %d ofs %ld\n", i + 1, TC_MM(i + 1), TC_SS(i + 1), TC_FR(i + 1), d->track_offsets[i]); } d->discid = (n % 0xff) << 24 | t << 8 | ntr; /* block = ntohl(toc_buffer[ntr - 1].addr.lba); d->seconds = ((block + 150) & 0xfffff) / 75; */ d->seconds = TC_SS(ntr) + TC_MM(ntr) * 60; fprintf(stderr, "block is %ld, seconds are %ld\n", block, d->seconds); return (d->discid); } struct discdata get_disc_id(const char *dev) { int fd; struct discdata d; fd = open(dev, O_RDONLY | O_NONBLOCK); if (fd < 0) { memset(&d, 0, sizeof(d)); return (d); } dbprog_discid(fd, &d); close(fd); return (d); } #endif //FREEBSD_H