Search
lxdream.org :: lxdream :: r720:b5594d1ac80a
lxdream 0.9.1
released Jun 29
Download Now
changeset720:b5594d1ac80a
parent719:8ce31b3d0dab
child721:98e1ae02bf36
authornkeynes
dateSat 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.
configure
configure.in
src/drivers/cd_linux.c
src/drivers/cd_osx.c
src/drivers/osx_iokit.c
src/drivers/osx_iokit.h
src/gdrom/gddriver.h
src/gdrom/gdimage.c
src/gdrom/gdrom.h
src/gdrom/mmc.c
1.1 --- a/configure Sat Jul 05 11:49:45 2008 +0000
1.2 +++ b/configure Sat Jul 05 11:57:36 2008 +0000
1.3 @@ -9259,6 +9259,142 @@
1.4 fi
1.5
1.6
1.7 +if test "${ac_cv_header_IOKit_IOKitLib_h+set}" = set; then
1.8 + { $as_echo "$as_me:$LINENO: checking for IOKit/IOKitLib.h" >&5
1.9 +$as_echo_n "checking for IOKit/IOKitLib.h... " >&6; }
1.10 +if test "${ac_cv_header_IOKit_IOKitLib_h+set}" = set; then
1.11 + $as_echo_n "(cached) " >&6
1.12 +fi
1.13 +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_IOKit_IOKitLib_h" >&5
1.14 +$as_echo "$ac_cv_header_IOKit_IOKitLib_h" >&6; }
1.15 +else
1.16 + # Is the header compilable?
1.17 +{ $as_echo "$as_me:$LINENO: checking IOKit/IOKitLib.h usability" >&5
1.18 +$as_echo_n "checking IOKit/IOKitLib.h usability... " >&6; }
1.19 +cat >conftest.$ac_ext <<_ACEOF
1.20 +/* confdefs.h. */
1.21 +_ACEOF
1.22 +cat confdefs.h >>conftest.$ac_ext
1.23 +cat >>conftest.$ac_ext <<_ACEOF
1.24 +/* end confdefs.h. */
1.25 +$ac_includes_default
1.26 +#include <IOKit/IOKitLib.h>
1.27 +_ACEOF
1.28 +rm -f conftest.$ac_objext
1.29 +if { (ac_try="$ac_compile"
1.30 +case "(($ac_try" in
1.31 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1.32 + *) ac_try_echo=$ac_try;;
1.33 +esac
1.34 +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
1.35 +$as_echo "$ac_try_echo") >&5
1.36 + (eval "$ac_compile") 2>conftest.er1
1.37 + ac_status=$?
1.38 + grep -v '^ *+' conftest.er1 >conftest.err
1.39 + rm -f conftest.er1
1.40 + cat conftest.err >&5
1.41 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
1.42 + (exit $ac_status); } && {
1.43 + test -z "$ac_c_werror_flag" ||
1.44 + test ! -s conftest.err
1.45 + } && test -s conftest.$ac_objext; then
1.46 + ac_header_compiler=yes
1.47 +else
1.48 + $as_echo "$as_me: failed program was:" >&5
1.49 +sed 's/^/| /' conftest.$ac_ext >&5
1.50 +
1.51 + ac_header_compiler=no
1.52 +fi
1.53 +
1.54 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
1.55 +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
1.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" >&5
1.60 +$as_echo_n "checking IOKit/IOKitLib.h presence... " >&6; }
1.61 +cat >conftest.$ac_ext <<_ACEOF
1.62 +/* confdefs.h. */
1.63 +_ACEOF
1.64 +cat confdefs.h >>conftest.$ac_ext
1.65 +cat >>conftest.$ac_ext <<_ACEOF
1.66 +/* end confdefs.h. */
1.67 +#include <IOKit/IOKitLib.h>
1.68 +_ACEOF
1.69 +if { (ac_try="$ac_cpp conftest.$ac_ext"
1.70 +case "(($ac_try" in
1.71 + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
1.72 + *) ac_try_echo=$ac_try;;
1.73 +esac
1.74 +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
1.75 +$as_echo "$ac_try_echo") >&5
1.76 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
1.77 + ac_status=$?
1.78 + grep -v '^ *+' conftest.er1 >conftest.err
1.79 + rm -f conftest.er1
1.80 + cat conftest.err >&5
1.81 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
1.82 + (exit $ac_status); } >/dev/null && {
1.83 + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
1.84 + test ! -s conftest.err
1.85 + }; then
1.86 + ac_header_preproc=yes
1.87 +else
1.88 + $as_echo "$as_me: failed program was:" >&5
1.89 +sed 's/^/| /' conftest.$ac_ext >&5
1.90 +
1.91 + ac_header_preproc=no
1.92 +fi
1.93 +
1.94 +rm -f conftest.err conftest.$ac_ext
1.95 +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
1.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 in
1.100 + yes:no: )
1.101 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: accepted by the compiler, rejected by the preprocessor!" >&5
1.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" >&5
1.104 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: proceeding with the compiler's result" >&2;}
1.105 + ac_header_preproc=yes
1.106 + ;;
1.107 + no:yes:* )
1.108 + { $as_echo "$as_me:$LINENO: WARNING: IOKit/IOKitLib.h: present but cannot be compiled" >&5
1.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?" >&5
1.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" >&5
1.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\"" >&5
1.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" >&5
1.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" >&5
1.119 +$as_echo "$as_me: WARNING: IOKit/IOKitLib.h: in the future, the compiler will take precedence" >&2;}
1.120 +
1.121 + ;;
1.122 +esac
1.123 +{ $as_echo "$as_me:$LINENO: checking for IOKit/IOKitLib.h" >&5
1.124 +$as_echo_n "checking for IOKit/IOKitLib.h... " >&6; }
1.125 +if test "${ac_cv_header_IOKit_IOKitLib_h+set}" = set; then
1.126 + $as_echo_n "(cached) " >&6
1.127 +else
1.128 + ac_cv_header_IOKit_IOKitLib_h=$ac_header_preproc
1.129 +fi
1.130 +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_IOKit_IOKitLib_h" >&5
1.131 +$as_echo "$ac_cv_header_IOKit_IOKitLib_h" >&6; }
1.132 +
1.133 +fi
1.134 +if test $ac_cv_header_IOKit_IOKitLib_h = yes; then
1.135 +
1.136 + CDROM_DRIVER=osx
1.137 + LIBS="$LIBS -framework IOKit"
1.138 +else
1.139 + true
1.140 +fi
1.141 +
1.142 +
1.143
1.144
1.145 if test "x$CDROM_DRIVER" = "xlinux"; then
2.1 --- a/configure.in Sat Jul 05 11:49:45 2008 +0000
2.2 +++ b/configure.in Sat Jul 05 11:57:36 2008 +0000
2.3 @@ -205,9 +205,9 @@
2.4
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=osx
2.9 -dnl LIBS="$LIBS -framework IOKit"],[true])
2.10 +AC_CHECK_HEADER([IOKit/IOKitLib.h], [
2.11 + CDROM_DRIVER=osx
2.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 +0000
3.2 +++ b/src/drivers/cd_linux.c Sat Jul 05 11:57:36 2008 +0000
3.3 @@ -34,8 +34,6 @@
3.4 #define MAXTOCSIZE 4 + (MAXTOCENTRIES*11)
3.5 #define MAX_SECTORS_PER_CALL 1
3.6
3.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.71
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.103
3.104 gdrom_error_t status = linux_send_command( fd, cmd, buf, &sector_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 +0000
4.2 +++ b/src/drivers/cd_osx.c Sat Jul 05 11:57:36 2008 +0000
4.3 @@ -17,166 +17,86 @@
4.4 */
4.5
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.21
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.32
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.36
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.45
4.46 -/**
4.47 - * CD-ROM drive visitor. Returns FALSE to continue iterating, TRUE if the desired CD-ROM
4.48 - * has been found. In the latter case, the io_object is returned from find_cdrom_device
4.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.104
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.124
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.134
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.159
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.169
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.207
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.232
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.248
4.249
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.256
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 +0000
5.2 +++ b/src/drivers/osx_iokit.c Sat Jul 05 11:57:36 2008 +0000
5.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 modify
5.15 + * it under the terms of the GNU General Public License as published by
5.16 + * the Free Software Foundation; either version 2 of the License, or
5.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 of
5.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.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 -1
5.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 message
5.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? currently
5.77 + * we watch for all IOMedia events and compare the device path to see if it's one we
5.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 interest
5.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 registering
5.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 drives
5.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 Mac
5.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 notifications
5.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 +0000
6.2 +++ b/src/drivers/osx_iokit.h Sat Jul 05 11:57:36 2008 +0000
6.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 modify
6.12 + * it under the terms of the GNU General Public License as published by
6.13 + * the Free Software Foundation; either version 2 of the License, or
6.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 of
6.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.19 + * GNU General Public License for more details.
6.20 + */
6.21 +
6.22 +#ifndef lxdream_osx_iokit_H
6.23 +#define lxdream_osx_iokit_H 1
6.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-ROM
6.34 + * has been found. In the latter case, the io_object is returned from find_cdrom_device
6.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 drives
6.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 Mac
6.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 or
6.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 +0000
7.2 +++ b/src/gdrom/gddriver.h Sat Jul 05 11:57:36 2008 +0000
7.3 @@ -28,6 +28,9 @@
7.4
7.5 #define MAX_SECTOR_SIZE 2352
7.6
7.7 +#define CD_FRAMES_PER_SECOND 75
7.8 +#define CD_SECONDS_PER_MINUTE 60
7.9 +#define CD_FRAMES_PER_MINUTE (CD_FRAMES_PER_SECOND*CD_SECONDS_PER_MINUTE)
7.10
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.19
7.20 /**
7.21 @@ -207,4 +211,15 @@
7.22
7.23 void gdrom_device_destroy( gdrom_device_t dev );
7.24
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 + mode
7.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 +0000
8.2 +++ b/src/gdrom/gdimage.c Sat Jul 05 11:57:36 2008 +0000
8.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.14
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 +0000
9.2 +++ b/src/gdrom/gdrom.h Sat Jul 05 11:57:36 2008 +0000
9.3 @@ -37,8 +37,10 @@
9.4 typedef struct gdrom_disc *gdrom_disc_t;
9.5
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.8
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.12
9.13 /**
9.14 * Open an image file
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/src/gdrom/mmc.c Sat Jul 05 11:57:36 2008 +0000
10.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 modify
10.12 + * it under the terms of the GNU General Public License as published by
10.13 + * the Free Software Foundation; either version 2 of the License, or
10.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 of
10.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.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
.