revision 720:b5594d1ac80a
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 720:b5594d1ac80a |
parent | 719:8ce31b3d0dab |
child | 721:98e1ae02bf36 |
author | nkeynes |
date | Sat Jul 05 11:57:36 2008 +0000 (15 years ago) |
Get OS X cdrom driver to the 'sort of working' stage. Hide most of the IOKit
fun in a separate osx_iokit module.
fun in a separate osx_iokit module.
1.1 --- a/configure Sat Jul 05 11:49:45 2008 +00001.2 +++ b/configure Sat Jul 05 11:57:36 2008 +00001.3 @@ -9259,6 +9259,142 @@1.4 fi1.7 +if test "${ac_cv_header_IOKit_IOKitLib_h+set}" = set; then1.8 + { $as_echo "$as_me:$LINENO: checking for IOKit/IOKitLib.h" >&51.9 +$as_echo_n "checking for IOKit/IOKitLib.h... " >&6; }1.10 +if test "${ac_cv_header_IOKit_IOKitLib_h+set}" = set; then1.11 + $as_echo_n "(cached) " >&61.12 +fi1.13 +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_IOKit_IOKitLib_h" >&51.14 +$as_echo "$ac_cv_header_IOKit_IOKitLib_h" >&6; }1.15 +else1.16 + # Is the header compilable?1.17 +{ $as_echo "$as_me:$LINENO: checking IOKit/IOKitLib.h usability" >&51.18 +$as_echo_n "checking IOKit/IOKitLib.h usability... " >&6; }1.19 +cat >conftest.$ac_ext <<_ACEOF1.20 +/* confdefs.h. */1.21 +_ACEOF1.22 +cat confdefs.h >>conftest.$ac_ext1.23 +cat >>conftest.$ac_ext <<_ACEOF1.24 +/* end confdefs.h. */1.25 +$ac_includes_default1.26 +#include <IOKit/IOKitLib.h>1.27 +_ACEOF1.28 +rm -f conftest.$ac_objext1.29 +if { (ac_try="$ac_compile"1.30 +case "(($ac_try" in1.31 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;1.32 + *) ac_try_echo=$ac_try;;1.33 +esac1.34 +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""1.35 +$as_echo "$ac_try_echo") >&51.36 + (eval "$ac_compile") 2>conftest.er11.37 + ac_status=$?1.38 + grep -v '^ *+' conftest.er1 >conftest.err1.39 + rm -f conftest.er11.40 + cat conftest.err >&51.41 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&51.42 + (exit $ac_status); } && {1.43 + test -z "$ac_c_werror_flag" ||1.44 + test ! -s conftest.err1.45 + } && test -s conftest.$ac_objext; then1.46 + ac_header_compiler=yes1.47 +else1.48 + $as_echo "$as_me: failed program was:" >&51.49 +sed 's/^/| /' conftest.$ac_ext >&51.50 +1.51 + ac_header_compiler=no1.52 +fi1.53 +1.54 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext1.55 +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&51.56 +$as_echo "$ac_header_compiler" >&6; }1.57 +1.58 +# Is the header present?1.59 +{ $as_echo "$as_me:$LINENO: checking IOKit/IOKitLib.h presence" >&51.60 +$as_echo_n "checking IOKit/IOKitLib.h presence... " >&6; }1.61 +cat >conftest.$ac_ext <<_ACEOF1.62 +/* confdefs.h. */1.63 +_ACEOF1.64 +cat confdefs.h >>conftest.$ac_ext1.65 +cat >>conftest.$ac_ext <<_ACEOF1.66 +/* end confdefs.h. */1.67 +#include <IOKit/IOKitLib.h>1.68 +_ACEOF1.69 +if { (ac_try="$ac_cpp conftest.$ac_ext"1.70 +case "(($ac_try" in1.71 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;1.72 + *) ac_try_echo=$ac_try;;1.73 +esac1.74 +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""1.75 +$as_echo "$ac_try_echo") >&51.76 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er11.77 + ac_status=$?1.78 + grep -v '^ *+' conftest.er1 >conftest.err1.79 + rm -f conftest.er11.80 + cat conftest.err >&51.81 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&51.82 + (exit $ac_status); } >/dev/null && {1.83 + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||1.84 + test ! -s conftest.err1.85 + }; then1.86 + ac_header_preproc=yes1.87 +else1.88 + $as_echo "$as_me: failed program was:" >&51.89 +sed 's/^/| /' conftest.$ac_ext >&51.90 +1.91 + ac_header_preproc=no1.92 +fi1.93 +1.94 +rm -f conftest.err conftest.$ac_ext1.95 +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&51.96 +$as_echo "$ac_header_preproc" >&6; }1.97 +1.98 +# So? What about this header?1.99 +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in1.100 + yes:no: )1.101 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: accepted by the compiler, rejected by the preprocessor!" >&51.102 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}1.103 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: proceeding with the compiler's result" >&51.104 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: proceeding with the compiler's result" >&2;}1.105 + ac_header_preproc=yes1.106 + ;;1.107 + no:yes:* )1.108 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: present but cannot be compiled" >&51.109 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: present but cannot be compiled" >&2;}1.110 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: check for missing prerequisite headers?" >&51.111 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: check for missing prerequisite headers?" >&2;}1.112 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: see the Autoconf documentation" >&51.113 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: see the Autoconf documentation" >&2;}1.114 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: section \"Present But Cannot Be Compiled\"" >&51.115 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: section \"Present But Cannot Be Compiled\"" >&2;}1.116 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: proceeding with the preprocessor's result" >&51.117 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: proceeding with the preprocessor's result" >&2;}1.118 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: in the future, the compiler will take precedence" >&51.119 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: in the future, the compiler will take precedence" >&2;}1.120 +1.121 + ;;1.122 +esac1.123 +{ $as_echo "$as_me:$LINENO: checking for IOKit/IOKitLib.h" >&51.124 +$as_echo_n "checking for IOKit/IOKitLib.h... " >&6; }1.125 +if test "${ac_cv_header_IOKit_IOKitLib_h+set}" = set; then1.126 + $as_echo_n "(cached) " >&61.127 +else1.128 + ac_cv_header_IOKit_IOKitLib_h=$ac_header_preproc1.129 +fi1.130 +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_IOKit_IOKitLib_h" >&51.131 +$as_echo "$ac_cv_header_IOKit_IOKitLib_h" >&6; }1.132 +1.133 +fi1.134 +if test $ac_cv_header_IOKit_IOKitLib_h = yes; then1.135 +1.136 + CDROM_DRIVER=osx1.137 + LIBS="$LIBS -framework IOKit"1.138 +else1.139 + true1.140 +fi1.141 +1.142 +1.145 if test "x$CDROM_DRIVER" = "xlinux"; then
2.1 --- a/configure.in Sat Jul 05 11:49:45 2008 +00002.2 +++ b/configure.in Sat Jul 05 11:57:36 2008 +00002.3 @@ -205,9 +205,9 @@2.5 dnl Check for native cdrom support. There can be only one.2.6 AC_CHECK_HEADER([linux/cdrom.h], [CDROM_DRIVER=linux], [true])2.7 -dnl AC_CHECK_HEADER([IOKit/IOKitLib.h], [2.8 -dnl CDROM_DRIVER=osx2.9 -dnl LIBS="$LIBS -framework IOKit"],[true])2.10 +AC_CHECK_HEADER([IOKit/IOKitLib.h], [2.11 + CDROM_DRIVER=osx2.12 + LIBS="$LIBS -framework IOKit"],[true])2.13 AM_CONDITIONAL(CDROM_LINUX, [test "x$CDROM_DRIVER" = "xlinux"])2.14 AM_CONDITIONAL(CDROM_OSX, [test "x$CDROM_DRIVER" = "xosx"])2.15 AM_CONDITIONAL(CDROM_NONE, [test "x$CDROM_DRIVER" = "x"])
3.1 --- a/src/drivers/cd_linux.c Sat Jul 05 11:49:45 2008 +00003.2 +++ b/src/drivers/cd_linux.c Sat Jul 05 11:57:36 2008 +00003.3 @@ -34,8 +34,6 @@3.4 #define MAXTOCSIZE 4 + (MAXTOCENTRIES*11)3.5 #define MAX_SECTORS_PER_CALL 13.7 -#define MSFTOLBA( m,s,f ) (f + (s*CD_FRAMES) + (m*CD_FRAMES*CD_SECS))3.8 -3.9 static uint32_t inline lbatomsf( uint32_t lba ) {3.10 union cdrom_addr addr;3.11 lba = lba + CD_MSF_OFFSET;3.12 @@ -164,57 +162,9 @@3.13 memset( buf, 0, sizeof(buf) );3.14 gdrom_error_t status = linux_send_command( fd, cmd, buf, &buflen, CGC_DATA_READ );3.15 if( status != 0 ) {3.16 - return status;3.17 + return status;3.18 }3.19 -3.20 - int max_track = 0;3.21 - int last_track = -1;3.22 - int leadout = -1;3.23 - int len = (buf[0] << 8) | buf[1];3.24 - int session_type = -1;3.25 - int i;3.26 - for( i = 4; i<len; i+=11 ) {3.27 - int session = buf[i];3.28 - int adr = buf[i+1] >> 4;3.29 - int point = buf[i+3];3.30 - if( adr == 0x01 && point > 0 && point < 100 ) {3.31 - /* Track info */3.32 - int trackno = point-1;3.33 - if( point > max_track ) {3.34 - max_track = point;3.35 - }3.36 - disc->track[trackno].flags = (buf[i+1] & 0x0F) << 4;3.37 - disc->track[trackno].session = session - 1;3.38 - disc->track[trackno].lba = MSFTOLBA(buf[i+8],buf[i+9],buf[i+10]);3.39 - if( disc->track[trackno].flags & TRACK_DATA ) {3.40 - disc->track[trackno].mode = GDROM_MODE1;3.41 - } else {3.42 - disc->track[trackno].mode = GDROM_CDDA;3.43 - }3.44 - if( last_track != -1 ) {3.45 - disc->track[last_track].sector_count = disc->track[trackno].lba -3.46 - disc->track[last_track].lba;3.47 - }3.48 - last_track = trackno;3.49 - } else switch( (adr << 8) | point ) {3.50 - case 0x1A0: /* session info */3.51 - if( buf[i+9] == 0x20 ) {3.52 - session_type = IDE_DISC_CDROMXA;3.53 - } else {3.54 - session_type = IDE_DISC_CDROM;3.55 - }3.56 - disc->disc_type = session_type;3.57 - break;3.58 - case 0x1A2: /* leadout */3.59 - leadout = MSFTOLBA(buf[i+8], buf[i+9], buf[i+10]);3.60 - break;3.61 - }3.62 - }3.63 - disc->track_count = max_track;3.64 -3.65 - if( leadout != -1 && last_track != -1 ) {3.66 - disc->track[last_track].sector_count = leadout - disc->track[last_track].lba;3.67 - }3.68 + mmc_parse_toc2( disc, buf );3.69 return 0;3.70 }3.72 @@ -252,34 +202,13 @@3.73 int fd = fileno(image->file);3.74 uint32_t real_sector = sector - CD_MSF_OFFSET;3.75 uint32_t sector_size = MAX_SECTOR_SIZE;3.76 - char cmd[12] = { 0xBE, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };3.77 -3.78 - cmd[1] = (mode & 0x0E) << 1;3.79 - cmd[2] = (real_sector >> 24) & 0xFF;3.80 - cmd[3] = (real_sector >> 16) & 0xFF;3.81 - cmd[4] = (real_sector >> 8) & 0xFF;3.82 - cmd[5] = real_sector & 0xFF;3.83 - cmd[6] = 0;3.84 - cmd[7] = 0;3.85 - cmd[8] = 1;3.86 -3.87 - if( READ_CD_RAW(mode) ) {3.88 - cmd[9] = 0xF0;3.89 - } else {3.90 - if( READ_CD_HEADER(mode) ) {3.91 - cmd[9] = 0xA0;3.92 - }3.93 - if( READ_CD_SUBHEAD(mode) ) {3.94 - cmd[9] |= 0x40;3.95 - }3.96 - if( READ_CD_DATA(mode) ) {3.97 - cmd[9] |= 0x10;3.98 - }3.99 - }3.100 + char cmd[12];3.101 +3.102 + mmc_make_read_cd_cmd( cmd, real_sector, mode );3.104 gdrom_error_t status = linux_send_command( fd, cmd, buf, §or_size, CGC_DATA_READ );3.105 if( status != 0 ) {3.106 - return status;3.107 + return status;3.108 }3.109 *length = 2048;3.110 return 0;
4.1 --- a/src/drivers/cd_osx.c Sat Jul 05 11:49:45 2008 +00004.2 +++ b/src/drivers/cd_osx.c Sat Jul 05 11:57:36 2008 +00004.3 @@ -17,166 +17,86 @@4.4 */4.6 #include <IOKit/IOKitLib.h>4.7 +#include <IOKit/IOBSD.h>4.8 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>4.9 -#include <IOKit/scsi-commands/SCSITaskLib.h>4.10 -#include <IOKit/scsi-commands/SCSICommandOperationCodes.h>4.11 +#include <IOKit/storage/IOCDMediaBSDClient.h>4.12 +#include <IOKit/storage/IOCDTypes.h>4.13 +#include <sys/param.h>4.14 +#include <errno.h>4.15 #include <stdio.h>4.16 +#include <string.h>4.17 +#include <paths.h>4.18 #include "gdrom/gddriver.h"4.19 +#include "gdrom/packet.h"4.20 +#include "drivers/osx_iokit.h"4.22 -static gboolean osx_image_is_valid( FILE *f );4.23 -static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f );4.24 +#define MAXTOCENTRIES 600 /* This is a fairly generous overestimate really */4.25 +#define MAXTOCSIZE 4 + (MAXTOCENTRIES*11)4.26 +4.27 +static gboolean cdrom_osx_image_is_valid( FILE *f );4.28 +static gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f );4.29 +static gdrom_error_t cdrom_osx_read_toc( gdrom_image_t disc );4.30 +static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t sector,4.31 + int mode, unsigned char *buf, uint32_t *length );4.33 struct gdrom_image_class cdrom_device_class = { "osx", NULL,4.34 - osx_image_is_valid, osx_open_device };4.35 + cdrom_osx_image_is_valid, cdrom_osx_open_device };4.37 -typedef struct osx_cdrom_disc {4.38 - struct gdrom_disc disc;4.39 -4.40 - io_object_t entry;4.41 - MMCDeviceInterface **mmc;4.42 - SCSITaskDeviceInterface **scsi;4.43 -} *osx_cdrom_disc_t;4.44 +#define OSX_DRIVE(disc) ( (osx_cdrom_drive_t)(((gdrom_image_t)disc)->private) )4.46 -/**4.47 - * CD-ROM drive visitor. Returns FALSE to continue iterating, TRUE if the desired CD-ROM4.48 - * has been found. In the latter case, the io_object is returned from find_cdrom_device4.49 - * (and not freed)4.50 - */4.51 -typedef gboolean (*find_cdrom_callback_t)( io_object_t object, char *vendor, char *product,4.52 - void *user_data );4.53 -4.54 -io_object_t find_cdrom_device( find_cdrom_callback_t callback, void *user_data )4.55 +static void cdrom_osx_destroy( gdrom_disc_t disc )4.56 {4.57 - mach_port_t master_port;4.58 - CFMutableDictionaryRef match;4.59 - io_iterator_t services;4.60 - io_object_t object;4.61 -4.62 - if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) {4.63 - return; // Failed to get the master port?4.64 - }4.65 -4.66 - match = IOServiceMatching("IODVDServices");4.67 - if( IOServiceGetMatchingServices(master_port, match, &services) != kIOReturnSuccess ) {4.68 - return;4.69 - }4.70 -4.71 - while( (object = IOIteratorNext(services)) != 0 ) {4.72 - CFMutableDictionaryRef props = 0;4.73 - if( IORegistryEntryCreateCFProperties(object, &props, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS ) {4.74 - CFDictionaryRef dict =4.75 - (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOPropertyDeviceCharacteristicsKey));4.76 - if( dict ) {4.77 - /* The vendor name. */4.78 - char vendor[256] = "", product[256] = "";4.79 - CFTypeRef value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyVendorNameKey));4.80 - if( value && CFGetTypeID(value) == CFStringGetTypeID() ) {4.81 - CFStringGetCString( (CFStringRef)value, vendor, sizeof(vendor),4.82 - kCFStringEncodingUTF8 );4.83 - }4.84 - value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyProductNameKey));4.85 - if ( value && CFGetTypeID(value) == CFStringGetTypeID() ) {4.86 - CFStringGetCString( (CFStringRef)value, product, sizeof(product),4.87 - kCFStringEncodingUTF8 );4.88 - }4.89 - if( callback(object, vendor, product, user_data) ) {4.90 - CFRelease(props);4.91 - IOObjectRelease(services);4.92 - return object;4.93 - }4.94 - }4.95 - CFRelease(props);4.96 - }4.97 -4.98 - IOObjectRelease(object);4.99 - }4.100 - IOObjectRelease(services);4.101 + osx_cdrom_close_drive( OSX_DRIVE(disc) );4.102 + gdrom_image_destroy_no_close( disc );4.103 }4.105 -io_object_t get_cdrom_by_service_path( const gchar *path )4.106 +static void cdrom_osx_media_changed( osx_cdrom_drive_t drive, gboolean present,4.107 + void *user_data )4.108 {4.109 - mach_port_t master_port;4.110 - io_object_t result;4.111 -4.112 - if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) {4.113 - return MACH_PORT_NULL; // Failed to get the master port?4.114 + gdrom_image_t image = (gdrom_image_t)user_data;4.115 + if( present ) {4.116 + cdrom_osx_read_toc( image );4.117 + } else {4.118 + image->disc_type = IDE_DISC_NONE;4.119 + image->track_count = 0;4.120 }4.121 -4.122 - return IORegistryEntryFromPath( master_port, path );4.123 }4.125 -void cdrom_osx_destroy( gdrom_disc_t disc )4.126 +4.127 +static gdrom_disc_t cdrom_osx_new( const char *name, osx_cdrom_drive_t drive )4.128 {4.129 - osx_cdrom_disc_t cdrom = (osx_cdrom_disc_t)disc;4.130 + char tmp[strlen(name)+7];4.131 + sprintf( tmp, "dvd://%s", name );4.132 + gdrom_image_t image = (gdrom_image_t)gdrom_image_new(tmp, NULL);4.133 + image->private = drive;4.135 - if( cdrom->scsi != NULL ) {4.136 - (*cdrom->scsi)->Release(cdrom->scsi);4.137 - cdrom->scsi = NULL;4.138 - }4.139 - if( cdrom->mmc != NULL ) {4.140 - (*cdrom->mmc)->Release(cdrom->mmc);4.141 - cdrom->mmc = NULL;4.142 - }4.143 - if( cdrom->entry != MACH_PORT_NULL ) {4.144 - IOObjectRelease( cdrom->entry );4.145 - cdrom->entry = MACH_PORT_NULL;4.146 - }4.147 -4.148 - if( disc->name != NULL ) {4.149 - g_free( (gpointer)disc->name );4.150 - disc->name = NULL;4.151 - }4.152 - g_free(disc);4.153 + image->disc.read_sector = cdrom_osx_read_sector;4.154 + image->disc.close = cdrom_osx_destroy;4.155 + cdrom_osx_read_toc(image);4.156 + osx_cdrom_set_media_changed_callback( drive, cdrom_osx_media_changed, image );4.157 + return (gdrom_disc_t)image;4.158 }4.160 -gdrom_disc_t cdrom_osx_new( io_object_t obj )4.161 +gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )4.162 {4.163 - osx_cdrom_disc_t cdrom = g_malloc0( sizeof(struct osx_cdrom_disc) );4.164 - gdrom_disc_t disc = &cdrom->disc;4.165 - IOCFPlugInInterface **pluginInterface = NULL;4.166 - HRESULT herr;4.167 - SInt32 score = 0;4.168 + gdrom_disc_t result = NULL;4.170 - cdrom->entry = obj;4.171 -4.172 - if( IOCreatePlugInInterfaceForService( obj, kIOMMCDeviceUserClientTypeID,4.173 - kIOCFPlugInInterfaceID, &pluginInterface, &score ) != KERN_SUCCESS ) {4.174 - ERROR( "Failed to create plugin interface" );4.175 - cdrom_osx_destroy(disc);4.176 + osx_cdrom_drive_t drive = osx_cdrom_open_drive(path);4.177 + if( drive == NULL ) {4.178 return NULL;4.179 + } else {4.180 + return cdrom_osx_new( path, drive );4.181 }4.182 -4.183 - herr = (*pluginInterface)->QueryInterface( pluginInterface,4.184 - CFUUIDGetUUIDBytes( kIOMMCDeviceInterfaceID ), (LPVOID *)&cdrom->mmc );4.185 - (*pluginInterface)->Release(pluginInterface);4.186 - pluginInterface = NULL;4.187 - if( herr != S_OK ) {4.188 - ERROR( "Failed to create MMC interface" );4.189 - cdrom_osx_destroy(disc);4.190 - return NULL;4.191 - }4.192 -4.193 - cdrom->scsi = (*cdrom->mmc)->GetSCSITaskDeviceInterface( cdrom->mmc );4.194 - if( cdrom->scsi == NULL ) {4.195 - ERROR( "Failed to create SCSI interface" );4.196 - cdrom_osx_destroy(disc);4.197 - return NULL;4.198 - }4.199 -4.200 - char name[sizeof(io_string_t) + 6] = "dvd://";4.201 - IORegistryEntryGetPath( cdrom->entry, kIOServicePlane, name+6 );4.202 - disc->name = g_strdup(name);4.203 -4.204 - disc->close = cdrom_osx_destroy;4.205 - return disc;4.206 }4.208 -gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, void *ptr )4.209 +4.210 +4.211 +static gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, char *iopath, void *ptr )4.212 {4.213 GList **list = (GList **)ptr;4.214 - char tmp1[sizeof(io_string_t) + 6] = "dvd://";4.215 + char tmp1[sizeof(io_string_t) + 6];4.216 char tmp2[512];4.217 - IORegistryEntryGetPath( object, kIOServicePlane, tmp1+6 );4.218 + snprintf( tmp1, sizeof(tmp1), "dvd://%s", iopath );4.219 snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product );4.220 *list = g_list_append( *list, gdrom_device_new( tmp1, tmp2 ) );4.221 return FALSE;4.222 @@ -185,34 +105,102 @@4.223 GList *cdrom_get_native_devices(void)4.224 {4.225 GList *list = NULL;4.226 - find_cdrom_device(cdrom_enum_callback, &list);4.227 + find_cdrom_drive(cdrom_enum_callback, &list);4.228 +4.229 + osx_register_iokit_notifications();4.230 return list;4.231 }4.233 -gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )4.234 -{4.235 - io_object_t obj;4.236 - gdrom_disc_t result = NULL;4.237 -4.238 - if( strncasecmp( path, "IOService:", 10 ) == 0 ) {4.239 - obj = get_cdrom_by_service_path( path );4.240 - }4.241 -4.242 - if( obj == MACH_PORT_NULL ) {4.243 - return NULL;4.244 - } else {4.245 - return cdrom_osx_new( obj );4.246 - }4.247 -}4.250 -4.251 -static gboolean osx_image_is_valid( FILE *f )4.252 +static gboolean cdrom_osx_image_is_valid( FILE *f )4.253 {4.254 return FALSE;4.255 }4.257 -static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f )4.258 +static gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f )4.259 {4.260 return NULL;4.261 }4.262 +4.263 +static gdrom_error_t cdrom_osx_read_toc( gdrom_image_t image )4.264 +{4.265 + osx_cdrom_drive_t drive = OSX_DRIVE(image);4.266 +4.267 + int fh = osx_cdrom_get_media_handle(drive);4.268 + if( fh == -1 ) {4.269 + image->disc_type = IDE_DISC_NONE;4.270 + image->track_count = 0;4.271 + return -1;4.272 + } else {4.273 + unsigned char buf[MAXTOCSIZE];4.274 + dk_cd_read_toc_t readtoc;4.275 + memset( &readtoc, 0, sizeof(readtoc) );4.276 + readtoc.format = 2;4.277 + readtoc.formatAsTime = 0;4.278 + readtoc.address.session = 0;4.279 + readtoc.bufferLength = sizeof(buf);4.280 + readtoc.buffer = buf;4.281 +4.282 + if( ioctl(fh, DKIOCCDREADTOC, &readtoc ) == -1 ) {4.283 + ERROR( "Failed to read TOC: %s", strerror(errno) );4.284 + image->disc_type = IDE_DISC_NONE;4.285 + image->track_count = 0;4.286 + return -1;4.287 + } else {4.288 + mmc_parse_toc2( image, buf );4.289 + }4.290 + }4.291 + return 0;4.292 +}4.293 +4.294 +static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t sector,4.295 + int mode, unsigned char *buf, uint32_t *length )4.296 +{4.297 + osx_cdrom_drive_t drive = OSX_DRIVE(disc);4.298 + int fh = osx_cdrom_get_media_handle(drive);4.299 + if( fh == -1 ) {4.300 + return PKT_ERR_NODISC;4.301 + } else {4.302 + dk_cd_read_t readcd;4.303 +4.304 + memset( &readcd, 0, sizeof(readcd) );4.305 + // This is complicated by needing to know the exact read size. Gah.4.306 + if( READ_CD_RAW(mode) ) {4.307 + *length = 2352;4.308 + readcd.sectorArea = 0xF8;4.309 + } else {4.310 + // This is incomplete...4.311 + if( READ_CD_DATA(mode) ) {4.312 + readcd.sectorArea = kCDSectorAreaUser;4.313 + switch( READ_CD_MODE(mode) ) {4.314 + case READ_CD_MODE_CDDA:4.315 + *length = 2352;4.316 + break;4.317 + case READ_CD_MODE_1:4.318 + case READ_CD_MODE_2_FORM_1:4.319 + *length = 2048;4.320 + break;4.321 + case READ_CD_MODE_2:4.322 + *length = 2336;4.323 + break;4.324 + case READ_CD_MODE_2_FORM_2:4.325 + *length = 2324;4.326 + break;4.327 + }4.328 + }4.329 + }4.330 +4.331 + readcd.offset = *length * (sector - 150);4.332 + readcd.sectorType = READ_CD_MODE(mode)>>1;4.333 + readcd.bufferLength = *length;4.334 + readcd.buffer = buf;4.335 + if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {4.336 + ERROR( "Failed to read CD: %s", strerror(errno) );4.337 + return -1;4.338 + } else {4.339 + return 0;4.340 + }4.341 + }4.342 +}4.343 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00005.2 +++ b/src/drivers/osx_iokit.c Sat Jul 05 11:57:36 2008 +00005.3 @@ -0,0 +1,348 @@5.4 +/**5.5 + * $Id: cd_osx.c 727 2008-06-25 10:40:45Z nkeynes $5.6 + *5.7 + * OSX support functions for handling the IOKit registry.5.8 + * Currently this manages access to CD/DVD drives + media, plus HID devices.5.9 + *5.10 + * The HID part is much simpler...5.11 + *5.12 + * Copyright (c) 2008 Nathan Keynes.5.13 + *5.14 + * This program is free software; you can redistribute it and/or modify5.15 + * it under the terms of the GNU General Public License as published by5.16 + * the Free Software Foundation; either version 2 of the License, or5.17 + * (at your option) any later version.5.18 + *5.19 + * This program is distributed in the hope that it will be useful,5.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of5.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the5.22 + * GNU General Public License for more details.5.23 + */5.24 +5.25 +#include <sys/param.h>5.26 +#include <paths.h>5.27 +#include <string.h>5.28 +#include <stdio.h>5.29 +#include <fcntl.h>5.30 +#include <IOKit/IOMessage.h>5.31 +#include <IOKit/hid/IOHIDLib.h>5.32 +#include "osx_iokit.h"5.33 +5.34 +static IONotificationPortRef notify_port = 0;5.35 +static io_iterator_t iokit_iterators[4] = {0,0,0,0};5.36 +5.37 +struct osx_cdrom_drive {5.38 + io_string_t ioservice_path;5.39 + io_string_t vendor_name;5.40 + io_string_t product_name;5.41 + char media_path[MAXPATHLEN]; // BSD device path if media present, otherwise the empty string.5.42 + io_iterator_t media_load_iterator;5.43 + io_iterator_t media_unload_iterator;5.44 + int media_fh; // BSD device handle if open, otherwise -15.45 + media_changed_callback_t media_changed;5.46 + void *media_changed_user_data;5.47 +};5.48 +5.49 +static gboolean get_bsdname_for_iomedia( io_object_t iomedia, char *buf, int buflen );5.50 +5.51 +/***************** IOKit Callbacks ******************/5.52 +5.53 +/**5.54 + * Called from IOKit for any IOMessages on an IOMedia. Currently the only message5.55 + * we're interested in is service termination.5.56 + */5.57 +static void osx_cdrom_media_notify( void *ref, io_service_t service, uint32_t msgType,5.58 + void *msgArgument )5.59 +{5.60 + if( msgType == kIOMessageServiceIsTerminated ) {5.61 + osx_cdrom_drive_t drive = (osx_cdrom_drive_t)ref;5.62 + if( drive->media_changed != NULL ) {5.63 + drive->media_changed( drive, FALSE, drive->media_changed_user_data );5.64 + }5.65 + if( drive->media_fh != -1 ) {5.66 + close(drive->media_fh);5.67 + drive->media_fh = -1;5.68 + }5.69 + drive->media_path[0] = '\0';5.70 + IOObjectRelease( drive->media_unload_iterator );5.71 + }5.72 +}5.73 +5.74 +/**5.75 + * Called from IOKit when an IOMedia is inserted that we have be interested in.5.76 + * FIXME: Can the matcher be restricted to descendents of the drive node? currently5.77 + * we watch for all IOMedia events and compare the device path to see if it's one we5.78 + * care about.5.79 + * FIXME: We assume for now that a drive has at most one piece of media at a time.5.80 + * If this isn't the case, the system may get a little confused.5.81 + */5.82 +static void osx_cdrom_media_inserted( void *ref, io_iterator_t iterator )5.83 +{5.84 + osx_cdrom_drive_t drive = (osx_cdrom_drive_t)ref;5.85 +5.86 + io_object_t object;5.87 + while( (object = IOIteratorNext(iterator)) != 0 ) {5.88 + io_string_t iopath = "";5.89 + IORegistryEntryGetPath( object, kIOServicePlane, iopath );5.90 + if( drive != NULL && g_str_has_prefix(iopath, drive->ioservice_path ) &&5.91 + get_bsdname_for_iomedia(object, drive->media_path, sizeof(drive->media_path)) ) {5.92 + // A disc was inserted within the drive of interest5.93 + if( drive->media_fh != -1 ) {5.94 + close(drive->media_fh);5.95 + drive->media_fh = -1;5.96 + }5.97 +5.98 + if( drive->media_changed != NULL ) {5.99 + drive->media_changed(drive, TRUE, drive->media_changed_user_data);5.100 + }5.101 + // Add a notification listener to get removal events.5.102 + IOServiceAddInterestNotification( notify_port, object, kIOGeneralInterest,5.103 + osx_cdrom_media_notify, drive, &drive->media_unload_iterator );5.104 +5.105 + }5.106 + IOObjectRelease( object );5.107 + }5.108 +}5.109 +5.110 +static void osx_drives_changed( void *ref, io_iterator_t iterator )5.111 +{5.112 + io_object_t object;5.113 + while( (object = IOIteratorNext(iterator)) != 0 ) {5.114 + IOObjectRelease(object);5.115 + }5.116 +5.117 +}5.118 +5.119 +/******************** Support functions *********************/5.120 +5.121 +/**5.122 + * Determine the BSD device name (ie "/dev/rdisk1") for a given IO object.5.123 + * @return TRUE if the device name was retrieved, FALSE if the request failed.5.124 + */5.125 +static gboolean get_bsdname_for_iomedia( io_object_t iomedia, char *buf, int buflen )5.126 +{5.127 + gboolean result = FALSE;5.128 + CFTypeRef pathRef = IORegistryEntryCreateCFProperty(iomedia, CFSTR(kIOBSDNameKey),5.129 + kCFAllocatorDefault, 0 );5.130 + if( pathRef ) {5.131 + char pathlen;5.132 + strcpy( buf, _PATH_DEV "r" );5.133 + pathlen = strlen(buf);5.134 + if( CFStringGetCString( pathRef, buf + pathlen, buflen-pathlen,5.135 + kCFStringEncodingASCII ) != noErr ) {5.136 + result = TRUE;5.137 + }5.138 + CFRelease(pathRef);5.139 + }5.140 + return result;5.141 +}5.142 +5.143 +static gboolean osx_cdrom_drive_get_name( io_object_t object, char *vendor, int vendor_len,5.144 + char *product, int product_len )5.145 +{5.146 + gboolean result = FALSE;5.147 + CFMutableDictionaryRef props = 0;5.148 + if( IORegistryEntryCreateCFProperties(object, &props, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS ) {5.149 + CFDictionaryRef dict =5.150 + (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOPropertyDeviceCharacteristicsKey));5.151 + if( dict != NULL ) {5.152 + CFTypeRef value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyVendorNameKey));5.153 + if( value && CFGetTypeID(value) == CFStringGetTypeID() ) {5.154 + CFStringGetCString( (CFStringRef)value, vendor, vendor_len, kCFStringEncodingUTF8 );5.155 + } else {5.156 + vendor[0] = 0;5.157 + }5.158 +5.159 + value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyProductNameKey));5.160 + if ( value && CFGetTypeID(value) == CFStringGetTypeID() ) {5.161 + CFStringGetCString( (CFStringRef)value, product, product_len, kCFStringEncodingUTF8 );5.162 + } else {5.163 + product[0] = 0;5.164 + }5.165 + result = TRUE;5.166 + }5.167 +5.168 + CFRelease(props);5.169 + }5.170 + return result;5.171 +}5.172 +5.173 +/**5.174 + * Construct and initialize a new osx_cdrom_drive object, including registering5.175 + * it's media inserted notification.5.176 + */5.177 +static osx_cdrom_drive_t osx_cdrom_drive_new( io_object_t device )5.178 +{5.179 + osx_cdrom_drive_t drive = g_malloc0(sizeof(struct osx_cdrom_drive));5.180 +5.181 + IORegistryEntryGetPath( device, kIOServicePlane, drive->ioservice_path );5.182 + osx_cdrom_drive_get_name( device, drive->vendor_name, sizeof(drive->vendor_name),5.183 + drive->product_name, sizeof(drive->product_name) );5.184 + drive->media_path[0] = '\0';5.185 + drive->media_changed = NULL;5.186 + drive->media_changed_user_data = NULL;5.187 + drive->media_fh = -1;5.188 +5.189 + IOServiceAddMatchingNotification( notify_port, kIOFirstPublishNotification,5.190 + IOServiceMatching("IOMedia"),5.191 + osx_cdrom_media_inserted, drive,5.192 + &drive->media_load_iterator );5.193 + osx_cdrom_media_inserted( drive, drive->media_load_iterator );5.194 + return drive;5.195 +}5.196 +5.197 +/************************ Exported functions *************************/5.198 +5.199 +osx_cdrom_drive_t osx_cdrom_open_drive( const char *devname )5.200 +{5.201 + io_object_t object = IORegistryEntryFromPath( kIOMasterPortDefault, devname );5.202 + if( object == MACH_PORT_NULL ) {5.203 + return NULL;5.204 + }5.205 +5.206 + osx_cdrom_drive_t drive = osx_cdrom_drive_new( object );5.207 + IOObjectRelease( object );5.208 + return drive;5.209 +}5.210 +5.211 +void osx_cdrom_set_media_changed_callback( osx_cdrom_drive_t drive,5.212 + media_changed_callback_t callback,5.213 + void *user_data )5.214 +{5.215 + drive->media_changed = callback;5.216 + drive->media_changed_user_data = user_data;5.217 +}5.218 +5.219 +void osx_cdrom_close_drive( osx_cdrom_drive_t drive )5.220 +{5.221 + IOObjectRelease( drive->media_load_iterator );5.222 + IOObjectRelease( drive->media_unload_iterator );5.223 + if( drive->media_fh != -1 ) {5.224 + close(drive->media_fh);5.225 + drive->media_fh = -1;5.226 + }5.227 + g_free( drive );5.228 +}5.229 +5.230 +int osx_cdrom_get_media_handle( osx_cdrom_drive_t drive )5.231 +{5.232 + if( drive->media_fh == -1 ) {5.233 + if( drive->media_path[0] != '\0' ) {5.234 + drive->media_fh = open( drive->media_path, O_RDONLY|O_NONBLOCK );5.235 + }5.236 + }5.237 + return drive->media_fh;5.238 +}5.239 +5.240 +void osx_cdrom_release_media_handle( osx_cdrom_drive_t drive )5.241 +{5.242 + if( drive->media_fh != -1 ) {5.243 + close( drive->media_fh );5.244 + drive->media_fh = -1;5.245 + }5.246 +}5.247 +5.248 +static io_object_t iterator_find_cdrom( io_object_t iterator, find_drive_callback_t callback, void *user_data )5.249 +{5.250 + io_object_t object;5.251 + while( (object = IOIteratorNext(iterator)) != 0 ) {5.252 + io_string_t iopath = "";5.253 + char product[256], vendor[256];5.254 + IORegistryEntryGetPath( object, kIOServicePlane, iopath );5.255 + osx_cdrom_drive_get_name( object, vendor, sizeof(vendor), product, sizeof(product) );5.256 + if( callback( object, vendor, product, iopath, user_data ) ) {5.257 + IOObjectRelease(iterator);5.258 + return object;5.259 + }5.260 + IOObjectRelease(object);5.261 + }5.262 + IOObjectRelease(iterator);5.263 +}5.264 +5.265 +5.266 +/**5.267 + * Search for a CD or DVD drive (instance of IODVDServices or IOCompactDiscServices).5.268 + * The callback will be called repeatedly until either it returns TRUE, or all drives5.269 + * have been iterated over.5.270 + *5.271 + * @return an IO registry entry for the matched drive, or 0 if no drives matched.5.272 + *5.273 + * Note: Use of IOCompactDiscServices is somewhat tentative since I don't have a Mac5.274 + * with a CD-Rom drive.5.275 + */5.276 +io_object_t find_cdrom_drive( find_drive_callback_t callback, void *user_data )5.277 +{5.278 + mach_port_t master_port;5.279 + CFMutableDictionaryRef match;5.280 + io_iterator_t services;5.281 + io_object_t result;5.282 +5.283 + if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) {5.284 + return 0; // Failed to get the master port?5.285 + }5.286 +5.287 + match = IOServiceMatching("IODVDServices");5.288 + if( IOServiceGetMatchingServices(master_port, match, &services) != kIOReturnSuccess ) {5.289 + return 0;5.290 + }5.291 +5.292 + result = iterator_find_cdrom( services, callback, user_data );5.293 + if( result != 0 ) {5.294 + return result;5.295 + }5.296 +5.297 + match = IOServiceMatching("IOCompactDiscServices");5.298 + if( IOServiceGetMatchingServices(master_port, match, &services) != kIOReturnSuccess ) {5.299 + return 0;5.300 + }5.301 + return iterator_find_cdrom( services, callback, user_data );5.302 +}5.303 +5.304 +5.305 +// *********************** Notification management ************************/5.306 +5.307 +static void osx_hid_inserted( void *ref, io_iterator_t iterator )5.308 +{5.309 + io_object_t object;5.310 + while( (object = IOIteratorNext(iterator)) != 0 ) {5.311 + io_string_t iopath = "";5.312 + IORegistryEntryGetPath( object, kIOServicePlane, iopath );5.313 + IOObjectRelease( object );5.314 + }5.315 +}5.316 +5.317 +gboolean osx_register_iokit_notifications()5.318 +{5.319 + notify_port = IONotificationPortCreate( kIOMasterPortDefault );5.320 + CFRunLoopSourceRef runloop_source = IONotificationPortGetRunLoopSource( notify_port );5.321 + CFRunLoopAddSource( CFRunLoopGetMain(), runloop_source, kCFRunLoopCommonModes );5.322 +5.323 + // Drive notifications5.324 + if( IOServiceAddMatchingNotification( notify_port, kIOFirstPublishNotification,5.325 + IOServiceMatching("IOCompactDiscServies"),5.326 + osx_drives_changed, NULL, &iokit_iterators[0] ) != kIOReturnSuccess ) {5.327 + ERROR( "IOServiceAddMatchingNotification failed" );5.328 + }5.329 + osx_drives_changed(NULL, iokit_iterators[0]);5.330 + if( IOServiceAddMatchingNotification( notify_port, kIOFirstPublishNotification,5.331 + IOServiceMatching("IODVDServies"),5.332 + osx_drives_changed, NULL, &iokit_iterators[1] ) != kIOReturnSuccess ) {5.333 + ERROR( "IOServiceAddMatchingNotification failed" );5.334 + }5.335 + osx_drives_changed(NULL, iokit_iterators[1]);5.336 +5.337 + if( IOServiceAddMatchingNotification( notify_port, kIOFirstPublishNotification,5.338 + IOServiceMatching(kIOHIDDeviceKey),5.339 + osx_hid_inserted, NULL, &iokit_iterators[4] ) != kIOReturnSuccess ) {5.340 + ERROR( "IOServiceAddMatchingNotification failed" );5.341 + }5.342 + osx_hid_inserted(NULL, iokit_iterators[2]);5.343 +}5.344 +5.345 +void osx_unregister_iokit_notifications()5.346 +{5.347 + CFRunLoopSourceRef runloop_source = IONotificationPortGetRunLoopSource( notify_port );5.348 + CFRunLoopRemoveSource( CFRunLoopGetMain(), runloop_source, kCFRunLoopCommonModes );5.349 + IONotificationPortDestroy( notify_port );5.350 + notify_port = 0;5.351 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00006.2 +++ b/src/drivers/osx_iokit.h Sat Jul 05 11:57:36 2008 +00006.3 @@ -0,0 +1,80 @@6.4 +/**6.5 + * $Id: osx_iokit.h 687 2008-05-12 10:00:13Z nkeynes $6.6 + *6.7 + * General OS X IOKit support (primarily for cdrom support)6.8 + *6.9 + * Copyright (c) 2008 Nathan Keynes.6.10 + *6.11 + * This program is free software; you can redistribute it and/or modify6.12 + * it under the terms of the GNU General Public License as published by6.13 + * the Free Software Foundation; either version 2 of the License, or6.14 + * (at your option) any later version.6.15 + *6.16 + * This program is distributed in the hope that it will be useful,6.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of6.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the6.19 + * GNU General Public License for more details.6.20 + */6.21 +6.22 +#ifndef lxdream_osx_iokit_H6.23 +#define lxdream_osx_iokit_H 16.24 +6.25 +#include <IOKit/IOKitLib.h>6.26 +#include <IOKit/IOBSD.h>6.27 +#include <IOKit/storage/IOStorageDeviceCharacteristics.h>6.28 +#include <IOKit/storage/IOCDMediaBSDClient.h>6.29 +#include "lxdream.h"6.30 +#include "hook.h"6.31 +6.32 +/**6.33 + * CD-ROM drive visitor. Returns FALSE to continue iterating, TRUE if the desired CD-ROM6.34 + * has been found. In the latter case, the io_object is returned from find_cdrom_device6.35 + * (and not freed)6.36 + */6.37 +typedef gboolean (*find_drive_callback_t)( io_object_t object, char *vendor, char *product,6.38 + char *iopath, void *user_data );6.39 +6.40 +/**6.41 + * Search for a CD or DVD drive (instance of IODVDServices or IOCompactDiscServices).6.42 + * The callback will be called repeatedly until either it returns TRUE, or all drives6.43 + * have been iterated over.6.44 + *6.45 + * @return an IO registry entry for the matched drive, or 0 if no drives matched.6.46 + *6.47 + * Note: Use of IOCompactDiscServices is somewhat tentative since I don't have a Mac6.48 + * with a CD-Rom drive.6.49 + */6.50 +io_object_t find_cdrom_drive( find_drive_callback_t callback, void *user_data );6.51 +6.52 +typedef struct osx_cdrom_drive *osx_cdrom_drive_t;6.53 +6.54 +/**6.55 + * Construct an osx_cdrom_drive_t on the given device specification.6.56 + * @return a new osx_cdrom_drive_t, or NULL if the device name was invalid.6.57 + */6.58 +6.59 +osx_cdrom_drive_t osx_cdrom_open_drive( const char *devname );6.60 +6.61 +typedef void (*media_changed_callback_t)( osx_cdrom_drive_t drive, gboolean disc_present, void *user_data );6.62 +6.63 +/**6.64 + * Set the media changed callback for the drive. (NULL == no callback)6.65 + */6.66 +void osx_cdrom_set_media_changed_callback( osx_cdrom_drive_t drive,6.67 + media_changed_callback_t callback,6.68 + void *user_data );6.69 +6.70 +/**6.71 + * Return a file handle for the cdrom drive (actually for the media).6.72 + * @return an open file handle, or -1 if there was no media present or6.73 + * the media could not be opened.6.74 + */6.75 +int osx_cdrom_get_media_handle( osx_cdrom_drive_t drive );6.76 +6.77 +void osx_cdrom_release_media_handle( osx_cdrom_drive_t drive );6.78 +6.79 +/** Close on osx_cdrom_drive_t and release all associated resources.6.80 + */6.81 +void osx_cdrom_close_drive( osx_cdrom_drive_t drive );6.82 +6.83 +#endif /* !lxdream_osx_iokit_H */
7.1 --- a/src/gdrom/gddriver.h Sat Jul 05 11:49:45 2008 +00007.2 +++ b/src/gdrom/gddriver.h Sat Jul 05 11:57:36 2008 +00007.3 @@ -28,6 +28,9 @@7.5 #define MAX_SECTOR_SIZE 23527.7 +#define CD_FRAMES_PER_SECOND 757.8 +#define CD_SECONDS_PER_MINUTE 607.9 +#define CD_FRAMES_PER_MINUTE (CD_FRAMES_PER_SECOND*CD_SECONDS_PER_MINUTE)7.11 struct gdrom_toc {7.12 uint32_t track[99];7.13 @@ -167,6 +170,7 @@7.14 struct gdrom_track track[99];7.15 gchar mcn[14]; /* Media catalogue number */7.16 FILE *file; /* Open file stream */7.17 + void *private; /* image private data */7.18 } *gdrom_image_t;7.20 /**7.21 @@ -207,4 +211,15 @@7.23 void gdrom_device_destroy( gdrom_device_t dev );7.25 +/************* Host-native support functions ***************/7.26 +7.27 +/**7.28 + * Parse a format 2 TOC, and write the results into the supplied disc structure.7.29 + */7.30 +void mmc_parse_toc2( gdrom_image_t disc, unsigned char *buf );7.31 +7.32 +/**7.33 + * Construct a Read CD command for the given sector + mode7.34 + */7.35 +void mmc_make_read_cd_cmd( char *cmd, uint32_t sector, int mode );7.36 #endif
8.1 --- a/src/gdrom/gdimage.c Sat Jul 05 11:49:45 2008 +00008.2 +++ b/src/gdrom/gdimage.c Sat Jul 05 11:57:36 2008 +00008.3 @@ -441,7 +441,11 @@8.4 static int gdrom_image_drive_status( gdrom_disc_t disc )8.5 {8.6 gdrom_image_t image = (gdrom_image_t)disc;8.7 - return image->disc_type | IDE_DISC_READY;8.8 + if( image->disc_type == IDE_DISC_NONE ) {8.9 + return IDE_DISC_NONE;8.10 + } else {8.11 + return image->disc_type | IDE_DISC_READY;8.12 + }8.13 }8.15 void gdrom_image_dump_info( gdrom_disc_t d ) {
9.1 --- a/src/gdrom/gdrom.h Sat Jul 05 11:49:45 2008 +00009.2 +++ b/src/gdrom/gdrom.h Sat Jul 05 11:57:36 2008 +00009.3 @@ -37,8 +37,10 @@9.4 typedef struct gdrom_disc *gdrom_disc_t;9.6 typedef gboolean (*gdrom_disc_change_hook_t)( gdrom_disc_t new_disc, const gchar *new_disc_name, void *user_data );9.7 +DECLARE_HOOK(gdrom_disc_change_hook, gdrom_disc_change_hook_t);9.9 -DECLARE_HOOK(gdrom_disc_change_hook, gdrom_disc_change_hook_t);9.10 +typedef gboolean (*gdrom_drive_list_change_hook_t)( GList *drive_list, void *user_data );9.11 +DECLARE_HOOK(gdrom_drive_list_change_hook, gdrom_drive_list_change_hook_t);9.13 /**9.14 * Open an image file
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +000010.2 +++ b/src/gdrom/mmc.c Sat Jul 05 11:57:36 2008 +000010.3 @@ -0,0 +1,101 @@10.4 +/**10.5 + * $Id: mmc.c 662 2008-03-02 11:38:08Z nkeynes $10.6 + *10.7 + * MMC host-side support functions.10.8 + *10.9 + * Copyright (c) 2008 Nathan Keynes.10.10 + *10.11 + * This program is free software; you can redistribute it and/or modify10.12 + * it under the terms of the GNU General Public License as published by10.13 + * the Free Software Foundation; either version 2 of the License, or10.14 + * (at your option) any later version.10.15 + *10.16 + * This program is distributed in the hope that it will be useful,10.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of10.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the10.19 + * GNU General Public License for more details.10.20 + */10.21 +10.22 +#include "gdrom/gddriver.h"10.23 +#include "gdrom/packet.h"10.24 +10.25 +#define MSFTOLBA( m,s,f ) (f + (s*CD_FRAMES_PER_SECOND) + (m*CD_FRAMES_PER_MINUTE))10.26 +10.27 +void mmc_make_read_cd_cmd( char *cmd, uint32_t real_sector, int mode )10.28 +{10.29 + cmd[0] = 0xBE;10.30 + cmd[1] = (mode & 0x0E) << 1;10.31 + cmd[2] = (real_sector >> 24) & 0xFF;10.32 + cmd[3] = (real_sector >> 16) & 0xFF;10.33 + cmd[4] = (real_sector >> 8) & 0xFF;10.34 + cmd[5] = real_sector & 0xFF;10.35 + cmd[6] = 0;10.36 + cmd[7] = 0;10.37 + cmd[8] = 1;10.38 +10.39 + if( READ_CD_RAW(mode) ) {10.40 + cmd[9] = 0xF0;10.41 + } else {10.42 + if( READ_CD_HEADER(mode) ) {10.43 + cmd[9] = 0xA0;10.44 + }10.45 + if( READ_CD_SUBHEAD(mode) ) {10.46 + cmd[9] |= 0x40;10.47 + }10.48 + if( READ_CD_DATA(mode) ) {10.49 + cmd[9] |= 0x10;10.50 + }10.51 + }10.52 +}10.53 +10.54 +void mmc_parse_toc2( gdrom_image_t disc, unsigned char *buf )10.55 +{10.56 + int max_track = 0;10.57 + int last_track = -1;10.58 + int leadout = -1;10.59 + int len = (buf[0] << 8) | buf[1];10.60 + int session_type = -1;10.61 + int i;10.62 + for( i = 4; i<len; i+=11 ) {10.63 + int session = buf[i];10.64 + int adr = buf[i+1] >> 4;10.65 + int point = buf[i+3];10.66 + if( adr == 0x01 && point > 0 && point < 100 ) {10.67 + /* Track info */10.68 + int trackno = point-1;10.69 + if( point > max_track ) {10.70 + max_track = point;10.71 + }10.72 + disc->track[trackno].flags = (buf[i+1] & 0x0F) << 4;10.73 + disc->track[trackno].session = session - 1;10.74 + disc->track[trackno].lba = MSFTOLBA(buf[i+8],buf[i+9],buf[i+10]);10.75 + if( disc->track[trackno].flags & TRACK_DATA ) {10.76 + disc->track[trackno].mode = GDROM_MODE1;10.77 + } else {10.78 + disc->track[trackno].mode = GDROM_CDDA;10.79 + }10.80 + if( last_track != -1 ) {10.81 + disc->track[last_track].sector_count = disc->track[trackno].lba -10.82 + disc->track[last_track].lba;10.83 + }10.84 + last_track = trackno;10.85 + } else switch( (adr << 8) | point ) {10.86 + case 0x1A0: /* session info */10.87 + if( buf[i+9] == 0x20 ) {10.88 + session_type = IDE_DISC_CDROMXA;10.89 + } else {10.90 + session_type = IDE_DISC_CDROM;10.91 + }10.92 + disc->disc_type = session_type;10.93 + break;10.94 + case 0x1A2: /* leadout */10.95 + leadout = MSFTOLBA(buf[i+8], buf[i+9], buf[i+10]);10.96 + break;10.97 + }10.98 + }10.99 + disc->track_count = max_track;10.100 +10.101 + if( leadout != -1 && last_track != -1 ) {10.102 + disc->track[last_track].sector_count = leadout - disc->track[last_track].lba;10.103 + }10.104 +}10.105 \ No newline at end of file
.