summaryrefslogtreecommitdiff
path: root/misc/libcdio
diff options
context:
space:
mode:
authordrochner <drochner@pkgsrc.org>2004-04-08 17:40:06 +0000
committerdrochner <drochner@pkgsrc.org>2004-04-08 17:40:06 +0000
commit90c98f9c86841dbde2d0f20f83faa9e4c5c2e869 (patch)
treea3a6754c6657002c02c7e59e5e480af6442050af /misc/libcdio
parent248a4a951d699107fca62c60a11146386b99ba5d (diff)
downloadpkgsrc-90c98f9c86841dbde2d0f20f83faa9e4c5c2e869.tar.gz
-add some NetBSD CD reading support
-depend on devel/popt and audio/libcddb, this makes that the frontend utilities are built
Diffstat (limited to 'misc/libcdio')
-rw-r--r--misc/libcdio/Makefile8
-rw-r--r--misc/libcdio/PLIST4
-rw-r--r--misc/libcdio/files/_cdio_netbsd.c497
3 files changed, 507 insertions, 2 deletions
diff --git a/misc/libcdio/Makefile b/misc/libcdio/Makefile
index 433d9c747ab..1db16dfc69f 100644
--- a/misc/libcdio/Makefile
+++ b/misc/libcdio/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.3 2004/02/14 18:26:28 jmmv Exp $
+# $NetBSD: Makefile,v 1.4 2004/04/08 17:40:06 drochner Exp $
#
DISTNAME= libcdio-0.65
@@ -16,4 +16,10 @@ PKGCONFIG_OVERRIDE+= libcdio.pc.in
PKGCONFIG_OVERRIDE+= libiso9660.pc.in
GNU_CONFIGURE= yes
+# XXX we just replace the freebsd module so save patches
+pre-patch:
+ ${CP} ${FILESDIR}/_cdio_netbsd.c ${WRKSRC}/lib/_cdio_freebsd.c
+
+.include "../../devel/popt/buildlink2.mk"
+.include "../../audio/libcddb/buildlink2.mk"
.include "../../mk/bsd.pkg.mk"
diff --git a/misc/libcdio/PLIST b/misc/libcdio/PLIST
index 78ad6055318..36357c417e4 100644
--- a/misc/libcdio/PLIST
+++ b/misc/libcdio/PLIST
@@ -1,4 +1,6 @@
-@comment $NetBSD: PLIST,v 1.1.1.1 2004/01/17 14:38:22 recht Exp $
+@comment $NetBSD: PLIST,v 1.2 2004/04/08 17:40:06 drochner Exp $
+bin/cd-info
+bin/cd-read
include/cdio/cd_types.h
include/cdio/cdio.h
include/cdio/iso9660.h
diff --git a/misc/libcdio/files/_cdio_netbsd.c b/misc/libcdio/files/_cdio_netbsd.c
new file mode 100644
index 00000000000..9320b452ef0
--- /dev/null
+++ b/misc/libcdio/files/_cdio_netbsd.c
@@ -0,0 +1,497 @@
+/* $NetBSD: _cdio_netbsd.c,v 1.1 2004/04/08 17:40:06 drochner Exp $ */
+
+/*
+ * Copyright (c) 2003
+ * Matthias Drochner. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * XXX This is for NetBSD but uses "freebsd" function names to plug
+ * nicely into the existing libcdio.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cdio/sector.h>
+#include <cdio/util.h>
+#include "cdio_assert.h"
+#include "cdio_private.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/cdio.h>
+#include <sys/scsiio.h>
+
+#ifdef __i386__
+#define DEFAULT_CDIO_DEVICE "/dev/rcd0d"
+#else
+#define DEFAULT_CDIO_DEVICE "/dev/rcd0c"
+#endif
+
+#define TOTAL_TRACKS (_obj->tochdr.ending_track \
+ - _obj->tochdr.starting_track + 1)
+#define FIRST_TRACK_NUM (_obj->tochdr.starting_track)
+
+typedef struct {
+ generic_img_private_t gen;
+
+ bool toc_valid;
+ struct ioc_toc_header tochdr;
+ struct cd_toc_entry tocent[100];
+
+ bool sessionformat_valid;
+ int sessionformat[100]; /* format of the session the track is in */
+} _img_private_t;
+
+static int
+_cdio_read_audio_sectors(void *user_data, void *data, lsn_t lsn,
+ unsigned int nblocks)
+{
+ scsireq_t req;
+ _img_private_t *_obj = user_data;
+
+ memset(&req, 0, sizeof(req));
+ req.cmd[0] = 0xbe;
+ req.cmd[1] = 0;
+ req.cmd[2] = (lsn >> 24) & 0xff;
+ req.cmd[3] = (lsn >> 16) & 0xff;
+ req.cmd[4] = (lsn >> 8) & 0xff;
+ req.cmd[5] = (lsn >> 0) & 0xff;
+ req.cmd[6] = (nblocks >> 16) & 0xff;
+ req.cmd[7] = (nblocks >> 8) & 0xff;
+ req.cmd[8] = (nblocks >> 0) & 0xff;
+ req.cmd[9] = 0x78;
+ req.cmdlen = 10;
+
+ req.datalen = nblocks * CDIO_CD_FRAMESIZE_RAW;
+ req.databuf = data;
+ req.timeout = 10000;
+ req.flags = SCCMD_READ;
+
+ if (ioctl(_obj->gen.fd, SCIOCCOMMAND, &req) < 0) {
+ perror("SCIOCCOMMAND");
+ return 1;
+ }
+ if (req.retsts != SCCMD_OK) {
+ fprintf(stderr, "SCIOCCOMMAND sts %d\n", req.retsts);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+_cdio_read_mode2_sector(void *user_data, void *data, lsn_t lsn,
+ bool mode2_form2)
+{
+ scsireq_t req;
+ _img_private_t *_obj = user_data;
+ char buf[M2RAW_SECTOR_SIZE] = { 0, };
+
+ memset(&req, 0, sizeof(req));
+ req.cmd[0] = 0xbe;
+ req.cmd[1] = 0;
+ req.cmd[2] = (lsn >> 24) & 0xff;
+ req.cmd[3] = (lsn >> 16) & 0xff;
+ req.cmd[4] = (lsn >> 8) & 0xff;
+ req.cmd[5] = (lsn >> 0) & 0xff;
+ req.cmd[6] = 0;
+ req.cmd[7] = 0;
+ req.cmd[8] = 1;
+ req.cmd[9] = 0x58; /* subheader + userdata + ECC */
+ req.cmdlen = 10;
+
+ req.datalen = M2RAW_SECTOR_SIZE;
+ req.databuf = buf;
+ req.timeout = 10000;
+ req.flags = SCCMD_READ;
+
+ if (ioctl(_obj->gen.fd, SCIOCCOMMAND, &req) < 0) {
+ perror("SCIOCCOMMAND");
+ return 1;
+ }
+ if (req.retsts != SCCMD_OK) {
+ fprintf(stderr, "SCIOCCOMMAND sts %d\n", req.retsts);
+ return 1;
+ }
+
+ if (mode2_form2)
+ memcpy(data, buf, M2RAW_SECTOR_SIZE);
+ else
+ memcpy(data, buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
+
+ return 0;
+}
+
+static int
+_cdio_read_mode2_sectors(void *user_data, void *data, lsn_t lsn,
+ bool mode2_form2, unsigned int nblocks)
+{
+ int i, res;
+ char *buf = data;
+
+ for (i = 0; i < nblocks; i++) {
+ res = _cdio_read_mode2_sector(user_data, buf, lsn, mode2_form2);
+ if (res)
+ return res;
+
+ buf += (mode2_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE);
+ lsn++;
+ }
+
+ return 0;
+}
+
+static uint32_t
+_cdio_stat_size(void *user_data)
+{
+ _img_private_t *_obj = user_data;
+ struct ioc_read_toc_entry req;
+ struct cd_toc_entry tocent;
+
+ req.address_format = CD_LBA_FORMAT;
+ req.starting_track = 0xaa;
+ req.data_len = sizeof(tocent);
+ req.data = &tocent;
+
+ if (ioctl(_obj->gen.fd, CDIOREADTOCENTRIES, &req) < 0) {
+ perror("ioctl(CDIOREADTOCENTRY) leadout");
+ exit(EXIT_FAILURE);
+ }
+
+ return (tocent.addr.lba);
+}
+
+static int
+_cdio_set_arg(void *user_data, const char key[], const char value[])
+{
+ _img_private_t *_obj = user_data;
+
+ if (!strcmp(key, "source")) {
+ if (!value)
+ return -2;
+
+ free(_obj->gen.source_name);
+ _obj->gen.source_name = strdup(value);
+ } else if (!strcmp(key, "access-mode")) {
+ if (strcmp(value, "READ_CD"))
+ cdio_error("unknown access type: %s ignored.", value);
+ } else
+ return -1;
+
+ return 0;
+}
+
+static bool
+_cdio_read_toc(_img_private_t *_obj)
+{
+ int res;
+ struct ioc_read_toc_entry req;
+
+ res = ioctl(_obj->gen.fd, CDIOREADTOCHEADER, &_obj->tochdr);
+ if (res < 0) {
+ cdio_error("error in ioctl(CDIOREADTOCHEADER): %s\n",
+ strerror(errno));
+ return false;
+ }
+
+ req.address_format = CD_MSF_FORMAT;
+ req.starting_track = FIRST_TRACK_NUM;
+ req.data_len = (TOTAL_TRACKS + 1) /* leadout! */
+ * sizeof(struct cd_toc_entry);
+ req.data = _obj->tocent;
+
+ res = ioctl(_obj->gen.fd, CDIOREADTOCENTRIES, &req);
+ if (res < 0) {
+ cdio_error("error in ioctl(CDROMREADTOCENTRIES): %s\n",
+ strerror(errno));
+ return false;
+ }
+
+ _obj->toc_valid = 1;
+ return true;
+}
+
+static int
+_cdio_read_discinfo(_img_private_t *_obj)
+{
+ scsireq_t req;
+#define FULLTOCBUF (4 + 1000*11)
+ unsigned char buf[FULLTOCBUF] = { 0, };
+ int i, j;
+
+ memset(&req, 0, sizeof(req));
+ req.cmd[0] = 0x43; /* READ TOC/PMA/ATIP */
+ req.cmd[1] = 0x02;
+ req.cmd[2] = 0x02; /* full TOC */
+ req.cmd[3] = 0;
+ req.cmd[4] = 0;
+ req.cmd[5] = 0;
+ req.cmd[6] = 0;
+ req.cmd[7] = FULLTOCBUF / 256;
+ req.cmd[8] = FULLTOCBUF % 256;
+ req.cmd[9] = 0;
+ req.cmdlen = 10;
+
+ req.datalen = FULLTOCBUF;
+ req.databuf = buf;
+ req.timeout = 10000;
+ req.flags = SCCMD_READ;
+
+ if (ioctl(_obj->gen.fd, SCIOCCOMMAND, &req) < 0) {
+ perror("SCIOCCOMMAND");
+ return 1;
+ }
+ if (req.retsts != SCCMD_OK) {
+ fprintf(stderr, "SCIOCCOMMAND sts %d\n", req.retsts);
+ return 1;
+ }
+#if 1
+ printf("discinfo:");
+ for (i = 0; i < 4; i++)
+ printf(" %02x", buf[i]);
+ printf("\n");
+ for (i = 0; i < buf[1] - 2; i++) {
+ printf(" %02x", buf[i + 4]);
+ if (!((i + 1) % 11))
+ printf("\n");
+ }
+#endif
+
+ for (i = 4; i < req.datalen_used; i += 11) {
+ if (buf[i + 3] == 0xa0) { /* POINT */
+ /* XXX: assume entry 0xa1 follows */
+ for (j = buf[i + 8] - 1; j <= buf[i + 11 + 8] - 1; j++)
+ _obj->sessionformat[j] = buf[i + 9];
+ }
+ }
+
+ _obj->sessionformat_valid = true;
+ return 0;
+}
+
+static int
+_cdio_eject_media(void *user_data) {
+
+ _img_private_t *_obj = user_data;
+ int fd, res, ret = 0;
+
+ fd = open(_obj->gen.source_name, O_RDONLY|O_NONBLOCK);
+ if (fd < 0)
+ return 2;
+
+ res = ioctl(fd, CDIOCALLOW);
+ if (res < 0) {
+ cdio_error("ioctl(fd, CDIOCALLOW) failed: %s\n",
+ strerror(errno));
+ /* go on... */
+ }
+ res = ioctl(fd, CDIOCEJECT);
+ if (res < 0) {
+ cdio_error("ioctl(CDIOCEJECT) failed: %s\n",
+ strerror(errno));
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static const char *
+_cdio_get_arg(void *user_data, const char key[])
+{
+ _img_private_t *_obj = user_data;
+
+ if (!strcmp(key, "source")) {
+ return _obj->gen.source_name;
+ } else if (!strcmp(key, "access-mode")) {
+ return "READ_CD";
+ }
+
+ return NULL;
+}
+
+static track_t
+_cdio_get_first_track_num(void *user_data)
+{
+ _img_private_t *_obj = user_data;
+ int res;
+
+ if (!_obj->toc_valid) {
+ res = _cdio_read_toc(_obj);
+ if (!res)
+ return CDIO_INVALID_TRACK;
+ }
+
+ return FIRST_TRACK_NUM;
+}
+
+static track_t
+_cdio_get_num_tracks(void *user_data)
+{
+ _img_private_t *_obj = user_data;
+ int res;
+
+ if (!_obj->toc_valid) {
+ res = _cdio_read_toc(_obj);
+ if (!res)
+ return CDIO_INVALID_TRACK;
+ }
+
+ return TOTAL_TRACKS;
+}
+
+static track_format_t
+_cdio_get_track_format(void *user_data, track_t track_num)
+{
+ _img_private_t *_obj = user_data;
+ int res;
+
+ if (!_obj->toc_valid) {
+ res = _cdio_read_toc(_obj);
+ if (!res)
+ return CDIO_INVALID_TRACK;
+ }
+
+ if (track_num > TOTAL_TRACKS || track_num == 0)
+ return TRACK_FORMAT_ERROR;
+
+ if (_obj->tocent[track_num - 1].control & 0x04) {
+ if (!_obj->sessionformat_valid) {
+ res = _cdio_read_discinfo(_obj);
+ if (res)
+ return CDIO_INVALID_TRACK;
+ }
+
+ if (_obj->sessionformat[track_num - 1] == 0x10)
+ return TRACK_FORMAT_CDI;
+ else if (_obj->sessionformat[track_num - 1] == 0x20)
+ return TRACK_FORMAT_XA;
+ else
+ return TRACK_FORMAT_DATA;
+ } else
+ return TRACK_FORMAT_AUDIO;
+}
+
+static bool
+_cdio_get_track_green(void *user_data, track_t track_num)
+{
+
+ return (_cdio_get_track_format(user_data, track_num)
+ == TRACK_FORMAT_XA);
+}
+
+static bool
+_cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf)
+{
+ _img_private_t *_obj = user_data;
+ int res;
+
+ if (!msf)
+ return false;
+
+ if (!_obj->toc_valid) {
+ res = _cdio_read_toc(_obj);
+ if (!res)
+ return CDIO_INVALID_TRACK;
+ }
+
+ if (track_num == CDIO_CDROM_LEADOUT_TRACK)
+ track_num = TOTAL_TRACKS + 1;
+
+ if (track_num > TOTAL_TRACKS + 1 || track_num == 0)
+ return false;
+
+ msf->m = to_bcd8(_obj->tocent[track_num - 1].addr.msf.minute);
+ msf->s = to_bcd8(_obj->tocent[track_num - 1].addr.msf.second);
+ msf->f = to_bcd8(_obj->tocent[track_num - 1].addr.msf.frame);
+
+ return true;
+}
+
+char *
+cdio_get_default_device_freebsd()
+{
+ return strdup(DEFAULT_CDIO_DEVICE);
+}
+
+static cdio_funcs _funcs = {
+ .eject_media = _cdio_eject_media,
+ .free = cdio_generic_free,
+ .get_arg = _cdio_get_arg,
+ .get_default_device = cdio_get_default_device_freebsd,
+ .get_first_track_num= _cdio_get_first_track_num,
+ .get_num_tracks = _cdio_get_num_tracks,
+ .get_track_format = _cdio_get_track_format,
+ .get_track_green = _cdio_get_track_green,
+ .get_track_lba = NULL,
+ .get_track_msf = _cdio_get_track_msf,
+ .lseek = cdio_generic_lseek,
+ .read = cdio_generic_read,
+ .read_audio_sectors = _cdio_read_audio_sectors,
+ .read_mode2_sector = _cdio_read_mode2_sector,
+ .read_mode2_sectors = _cdio_read_mode2_sectors,
+ .set_arg = _cdio_set_arg,
+ .stat_size = _cdio_stat_size
+};
+
+CdIo *
+cdio_open_freebsd(const char *source_name)
+{
+ CdIo *ret;
+ _img_private_t *_data;
+
+ _data = _cdio_malloc(sizeof(_img_private_t));
+ _data->gen.init = false;
+ _data->gen.fd = -1;
+ _data->toc_valid = false;
+ _data->sessionformat_valid = false;
+
+ _cdio_set_arg(_data, "source",
+ (source_name ? source_name : DEFAULT_CDIO_DEVICE));
+
+ ret = cdio_new(_data, &_funcs);
+ if (!ret)
+ return NULL;
+
+ if (cdio_generic_init(_data)) {
+ return ret;
+ } else {
+ cdio_generic_free(_data);
+ return NULL;
+ }
+}
+
+bool
+cdio_have_freebsd(void)
+{
+ return true;
+}