FreeBSD port - data needed

Marc van Woerkom (van.woerkom nospam at netcologne.de)
Wed, 10 Mar 1999 07:07:35 +0100 (CET)

Hi!

I ported the linux sources to my FreeBSD 3.0-RELEASE system.

Too bad I can't identify the CDs I tried so far, so I suspect
that there is a bug in the ID calculation. (see code below)

Could anyone with one of these CDs send me his/hers LBA values?

1.

Björk - Debut yields:

track 01: lba = 0
track 02: lba = -1656160256
track 03: lba = 1738473472
track 04: lba = 988938240
track 05: lba = -1221918464
track 06: lba = 1199374592
track 07: lba = -1430126336
track 08: lba = -300023296
track 09: lba = 1231421952
track 10: lba = -474217984
track 11: lba = -1961622784
track 12: lba = 962855680
http://www.freeamp.org/cgi-bin/cdi/hget.pl?id=28E7E4967299A723D21F8F1F6722D813

2. Björk - Post yields

track 01: lba = 536870912
track 02: lba = -1119617024
track 03: lba = -509476864
track 04: lba = 753664000
track 05: lba = 1093402880
track 06: lba = -1385103104
track 07: lba = -2070085376
track 08: lba = 956498432
track 09: lba = 509411840
track 10: lba = -2036071936
track 11: lba = 2009661952
http://www.freeamp.org/cgi-bin/cdi/hget.pl?id=AE14A9BE68987CD87FF0238C0D774495

3. The Verve - Urban Hymns yields

track 01: lba = 0
track 02: lba = 40435712
track 03: lba = -1699414016
track 04: lba = 959512832
track 05: lba = -1719009024
track 06: lba = -419757824
track 07: lba = 472515072
track 08: lba = -1131675136
track 09: lba = -1377762816
track 10: lba = -1456012544
track 11: lba = 1854931712
track 12: lba = 349438720
track 13: lba = 808125440
http://www.freeamp.org/cgi-bin/cdi/hget.pl?id=588FF815688CBB777B5E107CC25EE4D3

Regards,
Marc

-------------------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////////////
//
// cdindex.cpp
//

// system headers

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <string.h>

// CD control

#if defined(__FreeBSD__)
#include <sys/cdio.h>
#else // don't know Linux id
#include <linux/cdrom.h>
#endif

// project headers

#include "cdindex.h"
#include "md5.h"

// stupid macros

#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif

#if defined(__FreeBSD__)
#define DEFAULT_DEVICE "/dev/cd0c"
#else // don't know Linux id
#define DEFAULT_DEVICE "/dev/cdrom"
#endif

// some types

typedef unsigned char byte;

int lbas[128];

//
// calculate index
//

void CDIndex_Calculate(CDINDEX_CDINFO* pCDInfo, // Charles Simonyi's (Hungarian) notation is ugly
char DiscId[33])
{
MD5_CTX md5;
char HexTbl[] = "0123456789ABCDEF";
unsigned char digest[16];

// go!

MD5Init(&md5);

MD5Update(&md5,
(unsigned char*) pCDInfo,
sizeof(CDINDEX_CDINFO));

MD5Final(digest, &md5);

for (int i=0; i<16; i++) {
DiscId[i << 1] = HexTbl[digest[i] / 0x10];
DiscId[(i << 1) + 1] = HexTbl[digest[i] % 0x10];
}

DiscId[32] = '\0';
}

//
// OS specific CD inquiries
//

#if defined(__FreeBSD__)

int readtochdr(int fd,
int& first,
int& last)
{
struct ioc_toc_header th;

int ret = ioctl(fd,
CDIOREADTOCHEADER,
&th);

if (!ret) {
first = th.starting_track;
last = th.ending_track;
}

return ret;
}

int readtocentry(int fd,
int track,
int& lba)
{
struct ioc_read_toc_entry te;

te.starting_track = (u_char) track;
te.address_format = CD_LBA_FORMAT;

struct cd_toc_entry cte;

te.data = &cte;
te.data_len = sizeof(cd_toc_entry);

int ret = ioctl(fd,
CDIOREADTOCENTRYS,
&te);

if (!ret) {
assert(te.address_format == CD_LBA_FORMAT);

lba = te.data->addr.lba;

printf("track %02d: lba = %d\n",
(u_char) track,
lba);
}

return ret;
}

#else // don't know Linux id

/// SHAMELESSLY RIPPED FROM LINUX KERNEL

static inline void lba_to_msf(int lba,
byte* m,
byte* s,
byte* f)
{
lba += CD_BLOCK_OFFSET;
lba &= 0xffffff; /* negative lbas use only 24 bits */
*m = lba / (CD_SECS * CD_FRAMES);
lba %= (CD_SECS * CD_FRAMES);
*s = lba / CD_FRAMES;
*f = lba % CD_FRAMES;
}

/// END OF SHAMELESS RIP

int readtochdr(int fd,
int& first, // some sign of C++ :-)
int& last)
{
struct cdrom_tochdr tochdr;

int ret = ioctl(fd, CDROMREADTOCHDR, &tochdr);

if (!ret) {
first = tochdr.cdth_trk0;
last = tochdr.cdth_trk1;
}

return ret;
}

int readtocentry(int fd,
int track,
int& lba,
int& control,
int& adr)
{
struct cdrom_tocentry tocentry;
tocentry.cdte_track = track;
tocentry.cdte_format = CDROM_LBA;

int ret = ioctl(fd, CDROMREADTOCENTRY, &tocentry);
if (!ret) {
assert (tocentry.cdte_format == CDROM_LBA);
lba = tocentry.cdte_addr.lba;
control = tocentry.cdte_ctrl;
adr = tocentry.cdte_adr;
}

return ret;
}

#endif

void usage()
{
printf("usage: cdindex <options> [cdrom device]\n");
printf("\n");
printf("Options:\n");
printf(" -s Submit the given CD\n");
printf(" -g Get the information for this CD\n");
printf(" -l Print the URL used, but don't launch browser\n");
printf("\n");
printf("If no device is given, " DEFAULT_DEVICE " will be used.\n");

exit(0);
}

//
// start here
//

int main(int argc,
char* argv[])
{
#if defined(__FreeBSD__)
#else
unsigned char buf[CD_FRAMESIZE_RAW]; // who ordered this?
#endif

int ret;
int first;
int last;
int i;
int lba;
int control;
int adr;
int opt_s = 0;
int opt_g = 0;
int opt_l = 0;

byte m;
byte s;
byte f;

char* device = DEFAULT_DEVICE;

CDINDEX_CDINFO cdinfo;

char id[33];
char url[255];

// go!

if (argc == 1 || (argc > 1 && strcasecmp(argv[1], "--help") == 0))
usage();

// command-line argument processing loop

for (i=1; i<argc; i++) {

if (strcmp(argv[i], "-s") == 0) {
opt_s = 1;
continue;
}

if (strcmp(argv[i], "-g") == 0) {
opt_g = 1;
continue;
}

if (strcmp(argv[i], "-l") == 0) {
opt_l = 1;
continue;
}

// special case the standalone optional final argument (device)
if (i != argc - 1)
usage();

device = argv[i];
}

int fd = open(device, O_RDONLY);

if (fd < 0) {
printf("Cannot open '%s'\n", device);
exit(0);
}

memset(&cdinfo, 0, sizeof(CDINDEX_CDINFO));

if (readtochdr(fd, first, last)) {
printf("Cannot read table of contents.\n");
close(fd);
exit(0);
}

cdinfo.FrameOffset[0] = 0;

for (i=first; i<=last; i++) {
#if defined(__FreeBSD__)
readtocentry(fd, i, lba);
// what use is msf here?
#else
readtocentry(fd, i, lba, control, adr);
lba_to_msf(lba, &m, &s, &f);
#endif

cdinfo.FrameOffset[i] = lba + 150;
}

cdinfo.FirstTrack = first;
cdinfo.LastTrack = last;

CDIndex_Calculate(&cdinfo, id);
close(fd);

if (opt_s)
sprintf(url,
"http://www.freeamp.org/cgi-bin/cdi/submit.pl?"
"id=%s&tracks=%d",
id,
(last - first) + 1);
else
sprintf(url,
"http://www.freeamp.org/cgi-bin/cdi/hget.pl?"
"id=%s",
id);

if (opt_l) { // just print the url
printf("%s\n", url);
exit(0);
}

printf("Opening netscape to: '%s'\n"
"(Please open it by hand if the browser doesn't "
"start automatically)\n",
url);

#if defined(__FreeBSD__)
execlp("netscape",
"netscape", // arg[0] is name
url,
NULL);
#else
execlp("netscape",
url,
NULL);
#endif

perror("Could not launch netscape browser");

return 1;
}

-------------------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////////////
//
// cdindex.h
//

#if !defined(___CDINDEX___H___)
#define ___CDINDEX___H___

#pragma pack(1) // FreeBSD: investigate

typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
typedef signed char sbyte;
typedef signed short sword;
typedef signed long sdword;

struct CDINDEX_CDINFO {
byte FirstTrack; // The first track on CD : normally 1
byte LastTrack; // The last track on CD: max number 99
dword FrameOffset[100]; // Track 2 is TrackFrameOffset[2] etc.
}; // Leadout Track will be TrackFrameOffset[0]

void CDIndex_Calculate(CDINDEX_CDINFO* pCDInfo,
char DiscId[17]);

// true = ok
// false = error

#if !defined(CD_BLOCK_OFFSET)
#define CD_BLOCK_OFFSET CD_MSF_OFFSET
#endif

#endif

// end of cdindex.h

-------------------------------------------------------------------------------

Bye!