I have attached a couple of patches that fix the FreeBSD IOCTL interface
in libcdio.
1. The patch "patch-lib_driver_FreeBSD_freebsd_ioctl.c" fixes the
read_audio_sectors_freebsd_ioctl() function.
2. The patch "patch-lib_driver_FreeBSD_freebsd.c" resets the 'exists'
variable to true before scanning for ATAPI devices and adds a function
to set the default access mode. This is required when enumerating
devices with "cdio_get_devices_with_cap", since one is unable to set
the access mode in this case and it defaults to CAM.
Since the ATAPI driver is in the GENERIC FreeBSD kernel and the ATPICAM
driver must be loaded manually, these changes make libcdio work
immediately upon installation.
Also, my older model drive fails with "xmms2" (when using the CAM
interface) with "transport failed" but the IOCTL interface works.
--- lib/driver/FreeBSD/freebsd_ioctl.c Thu Apr 2 09:18:23 PDT 2009
+++ lib/driver/FreeBSD/freebsd_ioctl.c Thu Apr 2 09:18:23 PDT 2009
@@ -77,21 +77,17 @@
read_audio_sectors_freebsd_ioctl (_img_private_t *_obj, void *data, lsn_t lsn,
unsigned int nblocks)
{
- unsigned char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
- struct ioc_read_audio cdda;
-
- cdda.address.lba = lsn;
- cdda.buffer = buf;
- cdda.nframes = nblocks;
- cdda.address_format = CDIO_CDROM_LBA;
-
+ int bsize = CDIO_CD_FRAMESIZE_RAW;
+
+ /* set block size */
+ if (ioctl(_obj->gen.fd, CDRIOCSETBLOCKSIZE, &bsize) == -1) return 1;
+
/* read a frame */
- if(ioctl(_obj->gen.fd, CDIOCREADAUDIO, &cdda) < 0) {
- perror("CDIOCREADAUDIO");
+ if (pread(_obj->gen.fd, data, nblocks*bsize, lsn*bsize) != nblocks*bsize) {
+ perror("read_audio_sectors_freebsd_ioctl");
return 1;
}
- memcpy (data, buf, CDIO_CD_FRAMESIZE_RAW);
-
+
return 0;
}
--- lib/driver/FreeBSD/freebsd.c Fri Oct 16 18:23:24 PDT 2009
+++ lib/driver/FreeBSD/freebsd.c Fri Oct 16 18:23:24 PDT 2009
@@ -22,7 +22,7 @@
control of the CD drive. Culled initially I think from xine's or
mplayer's FreeBSD code with lots of modifications.
*/
-
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -652,6 +652,8 @@
}
/* Scan are ATAPI devices */
+ exists = true;
+
for ( c='0'; exists && c <='9'; c++ ) {
sprintf(drive, "/dev/acd%c%s", c, DEVICE_POSTFIX);
exists = cdio_is_cdrom(drive, NULL);
@@ -708,6 +710,8 @@
}
/* Scan are ATAPI devices */
+ exists = true;
+
for ( c='0'; exists && c <='9'; c++ ) {
sprintf(drive, "/dev/acd%c%s", c, DEVICE_POSTFIX);
exists = cdio_is_cdrom(drive, NULL);
@@ -743,6 +747,57 @@
#endif /*HAVE_FREEBSD_CDROM*/
}
+/*! Find out if media has changed since the last call. @param
+ p_user_data the environment of the CD object to be acted upon.
+ @return 1 if media has changed since last call, 0 if not. Error
+ return codes are the same as driver_return_code_t
+ */
+
+int
+get_media_changed_freebsd (const void *p_user_data)
+{
+#ifdef HAVE_FREEBSD_CDROM
+ const _img_private_t *p_env = p_user_data;
+ int changed = 0 ;
+
+ if ( p_env->access_mode == _AM_CAM ) {
+ changed = mmc_get_media_changed( p_env->gen.cdio );
+ }
+ else if ( p_env->access_mode == _AM_IOCTL ) {
+ changed = mmc_get_media_changed( p_env->gen.cdio );
+ }
+ else
+ return DRIVER_OP_UNSUPPORTED;
+
+ return ((changed > 0) ? changed : 0);
+
+#else
+ return DRIVER_OP_NO_DRIVER;
+
+#endif /*HAVE_FREEBSD_CDROM*/
+}
+
+static const char*
+get_access_mode(const char *source)
+{
+ if(source) {
+ if (!(strncmp(source, "/dev/acd", 8)))
+ return "ioctl";
+ else {
+ char devname[256];
+ int bytes = readlink(source, devname, 255);
+
+ if(bytes >0) {
+ devname[bytes]=0;
+ if (!(strncmp(devname, "acd", 3)))
+ return "ioctl";
+ }
+ }
+ }
+
+ return "CAM";
+}
+
/*!
Initialization routine. This is the only thing that doesn't
get called via a function pointer. In fact *we* are the
@@ -769,6 +824,9 @@
CdIo *ret;
_img_private_t *_data;
char *psz_source_name;
+
+ if(!psz_access_mode)
+ psz_access_mode = get_access_mode(psz_orig_source_name);
cdio_funcs_t _funcs = {
.audio_get_volume = audio_get_volume_freebsd,
@@ -790,6 +848,7 @@
.get_discmode = get_discmode_generic,
.get_drive_cap = get_drive_cap_freebsd,
.get_first_track_num = get_first_track_num_generic,
+ .get_media_changed = get_media_changed_freebsd,
.get_mcn = get_mcn_freebsd,
.get_num_tracks = get_num_tracks_generic,
.get_track_channels = get_track_channels_generic,
$FreeBSD: ports/sysutils/libcdio/files/patch-lib_driver_FreeBSD_freebsd.h,v 1.1
2008/01/02 13:51:57 mich Exp $
--- lib/driver/FreeBSD/freebsd.h.orig
+++ lib/driver/FreeBSD/freebsd.h
@@ -158,6 +158,8 @@
cdio_drive_write_cap_t *p_write_cap,
cdio_drive_misc_cap_t *p_misc_cap);
+int get_media_changed_freebsd (const void *p_user_data);
+
char *get_mcn_freebsd_ioctl (const _img_private_t *p_env);
void free_freebsd_cam (void *obj);