From c8000d60e94bbfa42b5e7d0b1f7e14de8be04f3a Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 16 Aug 2004 00:52:53 +0000 Subject: [PATCH] _cdio_osx.c: first attempt at issuing general SCSI-MMC passthrough command. others: small changes. --- lib/_cdio_linux.c | 22 +++--- lib/_cdio_osx.c | 177 ++++++++++++++++++++++++++++++++++++++++++---- lib/_cdio_sunos.c | 8 +-- 3 files changed, 177 insertions(+), 30 deletions(-) diff --git a/lib/_cdio_linux.c b/lib/_cdio_linux.c index 654b06f8..01846cf1 100644 --- a/lib/_cdio_linux.c +++ b/lib/_cdio_linux.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_linux.c,v 1.91 2004/08/10 11:58:15 rocky Exp $ + $Id: _cdio_linux.c,v 1.92 2004/08/16 00:52:53 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.91 2004/08/10 11:58:15 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.92 2004/08/16 00:52:53 rocky Exp $"; #include @@ -227,14 +227,14 @@ get_arg_linux (void *env, const char key[]) */ static void get_drive_cap_linux (const void *p_user_data, - cdio_drive_read_cap_t *p_read_cap, - cdio_drive_write_cap_t *p_write_cap, - cdio_drive_misc_cap_t *p_misc_cap) + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) { - const _img_private_t *_obj = p_user_data; + const _img_private_t *p_env = p_user_data; int32_t i_drivetype; - i_drivetype = ioctl (_obj->gen.fd, CDROM_GET_CAPABILITY, CDSL_CURRENT); + i_drivetype = ioctl (p_env->gen.fd, CDROM_GET_CAPABILITY, CDSL_CURRENT); if (i_drivetype < 0) { *p_read_cap = CDIO_DRIVE_CAP_ERROR; @@ -295,9 +295,9 @@ static char * _get_mcn_linux (const void *env) { struct cdrom_mcn mcn; - const _img_private_t *_obj = env; + const _img_private_t *p_env = env; memset(&mcn, 0, sizeof(mcn)); - if (ioctl(_obj->gen.fd, CDROM_GET_MCN, &mcn) != 0) + if (ioctl(p_env->gen.fd, CDROM_GET_MCN, &mcn) != 0) return NULL; return strdup(mcn.medium_catalog_number); } @@ -632,7 +632,7 @@ _read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, msf->cdmsf_frame0 = from_bcd8(_msf.f); retry: - switch (_obj->access_mode) + switch (p_env->access_mode) { case _AM_NONE: cdio_warn ("no way to read mode1"); @@ -1123,7 +1123,7 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) .read_mode2_sector = _read_mode2_sector_linux, .read_mode2_sectors = _read_mode2_sectors_linux, .read_toc = read_toc_linux, - .run_scsi_mmc_cmd = &run_scsi_cmd_linux, + .run_scsi_mmc_cmd = run_scsi_cmd_linux, .set_arg = set_arg_linux, .stat_size = stat_size_linux }; diff --git a/lib/_cdio_osx.c b/lib/_cdio_osx.c index ee56b284..59f1328e 100644 --- a/lib/_cdio_osx.c +++ b/lib/_cdio_osx.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_osx.c,v 1.51 2004/08/15 16:15:40 rocky Exp $ + $Id: _cdio_osx.c,v 1.52 2004/08/16 00:52:53 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein from vcdimager code: @@ -34,7 +34,7 @@ #include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.51 2004/08/15 16:15:40 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.52 2004/08/16 00:52:53 rocky Exp $"; #include #include @@ -44,6 +44,14 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.51 2004/08/15 16:15:40 rocky #include #ifdef HAVE_DARWIN_CDROM +#undef VERSION + +#include +#include +#include +#include +#include +#include #include #include @@ -55,6 +63,7 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.51 2004/08/15 16:15:40 rocky #include #include + #include #include #include @@ -102,9 +111,96 @@ typedef struct { track_t i_first_session; /* first session number */ lsn_t *pp_lba; CFMutableDictionaryRef dict; + SCSITaskDeviceInterface **pp_scsiTaskDeviceInterface; } _img_private_t; +/*! + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + p_buf Buffer for data, both sending and receiving + i_buf Size of buffer + e_direction direction the transfer is to go. + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + We return true if command completed successfully and false if not. + */ +static int +run_scsi_cmd_osx( const void *p_user_data, + unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) +{ + const _img_private_t *p_env = p_user_data; + SCSITaskDeviceInterface **sc; + SCSITaskInterface **cmd = NULL; + IOVirtualRange iov; + SCSI_Sense_Data senseData; + SCSITaskStatus status; + UInt64 bytesTransferred; + IOReturn ioReturnValue; + int ret = 0; + + if (NULL == p_user_data) return 2; + + sc = p_env->pp_scsiTaskDeviceInterface; + + cmd = (*sc)->CreateSCSITask(sc); + if (cmd == NULL) { + cdio_warn("Failed to create SCSI task"); + return -1; + } + + iov.address = (IOVirtualAddress) p_buf; + iov.length = i_buf; + + ioReturnValue = (*cmd)->SetCommandDescriptorBlock(cmd, (UInt8 *) p_cdb, + i_cdb); + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("SetCommandDescriptorBlock failed with status %x", + ioReturnValue); + return -1; + } + + ioReturnValue = (*cmd)->SetScatterGatherEntries(cmd, &iov, 1, i_buf, + (SCSI_MMC_DATA_READ == e_direction ) ? + kSCSIDataTransfer_FromTargetToInitiator : + kSCSIDataTransfer_FromInitiatorToTarget); + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("SetScatterGatherEntries failed with status %x", ioReturnValue); + return -1; + } + + ioReturnValue = (*cmd)->SetTimeoutDuration(cmd, i_timeout_ms ); + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("SetTimeoutDuration failed with status %x", ioReturnValue); + return -1; + } + + memset(&senseData, 0, sizeof(senseData)); + + ioReturnValue = (*cmd)->ExecuteTaskSync(cmd, + &senseData, &status, &bytesTransferred); + + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("Command execution failed with status %x", ioReturnValue); + return -1; + } + + if (cmd != NULL) { + (*cmd)->Release(cmd); + } + + return (ret); +} + +#if 0 /*************************************************************************** * GetFeaturesFlagsForDrive -Gets the bitfield which represents the * features flags. @@ -145,8 +241,6 @@ GetFeaturesFlagsForDrive ( CFMutableDictionaryRef dict, return true; } -/*! - */ static void get_drive_cap_osx(const void *p_user_data, /*out*/ cdio_drive_read_cap_t *p_read_cap, @@ -186,15 +280,16 @@ get_drive_cap_osx(const void *p_user_data, if ( 0 != (i_dvdFlags & kDVDFeaturesReWriteableMask) ) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RW; -#if 0 + /*** if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRMask) ) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PR; if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRWMask ) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PRW; -#endif + ***/ } +#endif #if 0 /**************************************************************************** @@ -249,6 +344,10 @@ _free_osx (void *p_user_data) { if (NULL != p_env->pp_lba) free((void *) p_env->pp_lba); if (NULL != p_env->pTOC) free((void *) p_env->pTOC); if (NULL != p_env->dict) CFRelease( p_env->dict ); + if (NULL != p_env->pp_scsiTaskDeviceInterface) + ( *(p_env->pp_scsiTaskDeviceInterface) )-> + Release ( (p_env->pp_scsiTaskDeviceInterface) ); + } /*! @@ -402,18 +501,62 @@ _set_arg_osx (void *user_data, const char key[], const char value[]) return 0; } +static void TestDevice(_img_private_t *p_env, io_service_t service) +{ + SInt32 score; + HRESULT herr; + kern_return_t err; + IOCFPlugInInterface **plugInInterface = NULL; + MMCDeviceInterface **mmcInterface = NULL; + + /* Create the IOCFPlugIn interface so we can query it. */ + + err = IOCreatePlugInInterfaceForService ( service, + kIOMMCDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugInInterface, + &score ); + if ( err != noErr ) { + printf("IOCreatePlugInInterfaceForService returned %d\n", err); + return; + } + + /* Query the interface for the MMCDeviceInterface. */ + + herr = ( *plugInInterface )->QueryInterface ( plugInInterface, + CFUUIDGetUUIDBytes ( kIOMMCDeviceInterfaceID ), + ( LPVOID ) &mmcInterface ); + + if ( herr != S_OK ) { + printf("QueryInterface returned %ld\n", herr); + return; + } + + p_env->pp_scsiTaskDeviceInterface = + ( *mmcInterface )->GetSCSITaskDeviceInterface ( mmcInterface ); + + if ( NULL == p_env->pp_scsiTaskDeviceInterface ) { + printf("GetSCSITaskDeviceInterface returned NULL\n"); + return; + } + + ( *mmcInterface )->Release ( mmcInterface ); + IODestroyPlugInInterface ( plugInInterface ); +} + /*! Read and cache the CD's Track Table of Contents and track info. Return false if successful or true if an error. */ static bool -_cdio_read_toc (_img_private_t *p_env) +read_toc_osx (void *p_user_data) { + _img_private_t *p_env = p_user_data; mach_port_t port; char *psz_devname; kern_return_t ret; io_iterator_t iterator; - io_registry_entry_t service; + io_service_t service; CFDataRef data; p_env->gen.fd = open( p_env->gen.source_name, O_RDONLY | O_NONBLOCK ); @@ -511,7 +654,8 @@ _cdio_read_toc (_img_private_t *p_env) cdio_warn( "CFDictionaryGetValue failed" ); return false; } - + + TestDevice(p_env, service); IOObjectRelease( service ); p_env->i_descriptors = CDTOCGetDescriptorCount ( p_env->pTOC ); @@ -631,7 +775,7 @@ _get_track_lba_osx(void *user_data, track_t i_track) { _img_private_t *p_env = user_data; - if (!p_env->toc_init) _cdio_read_toc (p_env) ; + if (!p_env->toc_init) read_toc_osx (p_env) ; if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->i_last_track+1; @@ -732,7 +876,7 @@ _get_first_track_num_osx(void *user_data) { _img_private_t *p_env = user_data; - if (!p_env->toc_init) _cdio_read_toc (p_env) ; + if (!p_env->toc_init) read_toc_osx (p_env) ; return p_env->i_first_track; } @@ -766,7 +910,7 @@ _get_num_tracks_osx(void *user_data) { _img_private_t *p_env = user_data; - if (!p_env->toc_init) _cdio_read_toc (p_env) ; + if (!p_env->toc_init) read_toc_osx (p_env) ; return( TOTAL_TRACKS ); } @@ -828,7 +972,7 @@ _get_track_green_osx(void *user_data, track_t i_track) _img_private_t *p_env = user_data; CDTrackInfo a_track; - if (!p_env->toc_init) _cdio_read_toc (p_env) ; + if (!p_env->toc_init) read_toc_osx (p_env) ; if ( i_track > p_env->i_last_track || i_track < p_env->i_first_track ) return false; @@ -1054,10 +1198,11 @@ cdio_open_osx (const char *psz_orig_source) .eject_media = _eject_media_osx, .free = _free_osx, .get_arg = _get_arg_osx, + .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_osx, .get_devices = cdio_get_devices_osx, - .get_discmode = NULL, - .get_drive_cap = get_drive_cap_osx, + .get_discmode = get_discmode_generic, + .get_drive_cap = scsi_mmc_get_drive_cap_generic, .get_first_track_num= _get_first_track_num_osx, .get_mcn = _get_mcn_osx, .get_num_tracks = _get_num_tracks_osx, @@ -1072,6 +1217,8 @@ cdio_open_osx (const char *psz_orig_source) .read_mode1_sectors = _get_read_mode1_sectors_osx, .read_mode2_sector = _get_read_mode2_sector_osx, .read_mode2_sectors = _get_read_mode2_sectors_osx, + .read_toc = read_toc_osx, + .run_scsi_mmc_cmd = run_scsi_cmd_osx, .set_arg = _set_arg_osx, .stat_size = _stat_size_osx }; diff --git a/lib/_cdio_sunos.c b/lib/_cdio_sunos.c index 7b3fc113..9ec863a0 100644 --- a/lib/_cdio_sunos.c +++ b/lib/_cdio_sunos.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_sunos.c,v 1.72 2004/08/10 11:58:15 rocky Exp $ + $Id: _cdio_sunos.c,v 1.73 2004/08/16 00:52:53 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004 Rocky Bernstein @@ -38,7 +38,7 @@ #ifdef HAVE_SOLARIS_CDROM -static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.72 2004/08/10 11:58:15 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.73 2004/08/16 00:52:53 rocky Exp $"; #ifdef HAVE_GLOB_H #include @@ -851,8 +851,8 @@ cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode) .read_mode1_sectors = _read_mode1_sectors_solaris, .read_mode2_sector = _read_mode2_sector_solaris, .read_mode2_sectors = _read_mode2_sectors_solaris, - .read_toc = &read_toc_solaris, - .run_scsi_mmc_cmd = &run_scsi_cmd_solaris, + .read_toc = read_toc_solaris, + .run_scsi_mmc_cmd = run_scsi_cmd_solaris, .stat_size = _cdio_stat_size, .set_arg = _set_arg_solaris };