This repository has been archived on 2025-05-24. You can view files and clone it, but cannot push or open issues or pull requests.
Files
libcdio-osx/lib/driver/FreeBSD/freebsd_ioctl.c
rocky 6029b6c3d7 Patch from Diego 'Flameeyes' Pettenò to eject_media_freebsd_ioctl():
Allegedly this works better than the CAM mode eject; CAM gets the error
"Device not ready" when trying to eject an empty CD-ROM drive.

We make use of an already open file descriptor to the CD-ROM instead
of opening a new one (else we have two file descriptor open, so when
it launch the ioctl() to eject the device it results busy because of
the other fd).

Also corrects the documentation comment about the return value.
2005-07-23 21:36:54 +00:00

263 lines
7.0 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
$Id: freebsd_ioctl.c,v 1.4 2005/07/23 21:36:54 rocky Exp $
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This file contains FreeBSD-specific code and implements low-level
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
static const char _rcsid[] = "$Id: freebsd_ioctl.c,v 1.4 2005/07/23 21:36:54 rocky Exp $";
#ifdef HAVE_FREEBSD_CDROM
#include "freebsd.h"
/* Check a drive to see if it is a CD-ROM
Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive
and -1 if no device exists .
*/
bool
cdio_is_cdrom_freebsd_ioctl(char *drive, char *mnttype)
{
bool is_cd=false;
int cdfd;
struct ioc_toc_header tochdr;
/* If it doesn't exist, return -1 */
if ( !cdio_is_device_quiet_generic(drive) ) {
return(false);
}
/* If it does exist, verify that it's an available CD-ROM */
cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
/* Should we want to test the condition in more detail:
ENOENT is the error for /dev/xxxxx does not exist;
ENODEV means there's no drive present. */
if ( cdfd >= 0 ) {
if ( ioctl(cdfd, CDIOREADTOCHEADER, &tochdr) != -1 ) {
is_cd = true;
}
close(cdfd);
}
/* Even if we can't read it, it might be mounted */
else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) {
is_cd = true;
}
return(is_cd);
}
/*!
Reads a single mode2 sector from cd device into data starting from lsn.
Returns 0 if no error.
*/
int
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;
/* read a frame */
if(ioctl(_obj->gen.fd, CDIOCREADAUDIO, &cdda) < 0) {
perror("CDIOCREADAUDIO");
return 1;
}
memcpy (data, buf, CDIO_CD_FRAMESIZE_RAW);
return 0;
}
/*!
Reads a single mode2 sector from cd device into data starting
from lsn. Returns 0 if no error.
*/
int
read_mode2_sector_freebsd_ioctl (_img_private_t *env, void *data, lsn_t lsn,
bool b_form2)
{
char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
int retval;
if ( !b_form2 )
return cdio_generic_read_form1_sector (env, buf, lsn);
if ( (retval = read_audio_sectors_freebsd_ioctl (env, buf, lsn, 1)) )
return retval;
memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, M2RAW_SECTOR_SIZE);
return 0;
}
/*!
Return the size of the CD in logical block address (LBA) units.
*/
lsn_t
get_disc_last_lsn_freebsd_ioctl (_img_private_t *_obj)
{
struct ioc_read_toc_single_entry tocent;
uint32_t size;
tocent.track = CDIO_CDROM_LEADOUT_TRACK;
tocent.address_format = CDIO_CDROM_LBA;
if (ioctl (_obj->gen.fd, CDIOREADTOCENTRY, &tocent) == -1)
{
perror ("ioctl(CDROMREADTOCENTRY)");
exit (EXIT_FAILURE);
}
size = tocent.entry.addr.lba;
return size;
}
/*!
Eject media. Return 0 if successful, 1 otherwise.
*/
int
eject_media_freebsd_ioctl (_img_private_t *env)
{
_img_private_t *_obj = env;
int ret=1;
if (ioctl(_obj->gen.fd, CDIOCALLOW) == -1) {
cdio_warn("ioctl(fd, CDIOCALLOW) failed: %s\n", strerror(errno));
} else if (ioctl(_obj->gen.fd, CDIOCEJECT) == -1) {
cdio_warn("ioctl(CDIOCEJECT) failed: %s\n", strerror(errno));
} else {
ret=0;
}
return ret;
}
/*!
Return the media catalog number MCN.
Note: string is malloc'd so caller should free() then returned
string when done with it.
FIXME: This is just a guess.
*/
char *
get_mcn_freebsd_ioctl (const _img_private_t *env) {
struct ioc_read_subchannel subchannel;
struct cd_sub_channel_info subchannel_info;
subchannel.address_format = CDIO_CDROM_MSF;
subchannel.data_format = CDIO_SUBCHANNEL_MEDIA_CATALOG;
subchannel.track = 0;
subchannel.data_len = sizeof(subchannel_info);
subchannel.data = &subchannel_info;
if(ioctl(env->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) {
perror("CDIOCREADSUBCHANNEL");
return NULL;
}
/* Probably need a loop over tracks rather than give up if we
can't find in track 0.
*/
if (subchannel_info.what.media_catalog.mc_valid)
return strdup(subchannel_info.what.media_catalog.mc_number);
else
return NULL;
}
/*!
Get format of track.
FIXME: We're just guessing this from the GNU/Linux code.
*/
track_format_t
get_track_format_freebsd_ioctl(const _img_private_t *env, track_t i_track)
{
struct ioc_read_subchannel subchannel;
struct cd_sub_channel_info subchannel_info;
subchannel.address_format = CDIO_CDROM_LBA;
subchannel.data_format = CDIO_SUBCHANNEL_CURRENT_POSITION;
subchannel.track = i_track;
subchannel.data_len = 1;
subchannel.data = &subchannel_info;
if(ioctl(env->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) {
perror("CDIOCREADSUBCHANNEL");
return 1;
}
if (subchannel_info.what.position.control == 0x04) {
if (subchannel_info.what.position.data_format == 0x10)
return TRACK_FORMAT_CDI;
else if (subchannel_info.what.position.data_format == 0x20)
return TRACK_FORMAT_XA;
else
return TRACK_FORMAT_DATA;
} else
return TRACK_FORMAT_AUDIO;
}
/*!
Return true if we have XA data (green, mode2 form1) or
XA data (green, mode2 form2). That is track begins:
sync - header - subheader
12 4 - 8
FIXME: there's gotta be a better design for this and get_track_format?
*/
bool
get_track_green_freebsd_ioctl(const _img_private_t *env, track_t i_track)
{
struct ioc_read_subchannel subchannel;
struct cd_sub_channel_info subchannel_info;
subchannel.address_format = CDIO_CDROM_LBA;
subchannel.data_format = CDIO_SUBCHANNEL_CURRENT_POSITION;
subchannel.track = i_track;
subchannel.data_len = 1;
subchannel.data = &subchannel_info;
if(ioctl(env->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) {
perror("CDIOCREADSUBCHANNEL");
return 1;
}
/* FIXME: Dunno if this is the right way, but it's what
I was using in cdinfo for a while.
*/
return (subchannel_info.what.position.control & 2) != 0;
}
#endif /* HAVE_FREEBSD_CDROM */