# HG changeset patch # User nkeynes # Date 1214390445 0 # Node ID 18c39a8e504cbd5f91be61b44a60a223c08f02be # Parent 0b8b5eaa3b52dc040f6daac97760b78b4857adbc Commit OSX CD-ROM driver work-in-progress --- a/Makefile.in Wed Jun 25 10:39:05 2008 +0000 +++ b/Makefile.in Wed Jun 25 10:40:45 2008 +0000 @@ -113,6 +113,10 @@ CCDEPMODE = @CCDEPMODE@ CDROM_LINUX_FALSE = @CDROM_LINUX_FALSE@ CDROM_LINUX_TRUE = @CDROM_LINUX_TRUE@ +CDROM_NONE_FALSE = @CDROM_NONE_FALSE@ +CDROM_NONE_TRUE = @CDROM_NONE_TRUE@ +CDROM_OSX_FALSE = @CDROM_OSX_FALSE@ +CDROM_OSX_TRUE = @CDROM_OSX_TRUE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ --- a/configure Wed Jun 25 10:39:05 2008 +0000 +++ b/configure Wed Jun 25 10:40:45 2008 +0000 @@ -764,6 +764,10 @@ AUDIO_ALSA_FALSE CDROM_LINUX_TRUE CDROM_LINUX_FALSE +CDROM_OSX_TRUE +CDROM_OSX_FALSE +CDROM_NONE_TRUE +CDROM_NONE_FALSE JOY_LINUX_TRUE JOY_LINUX_FALSE SHCC @@ -9195,16 +9199,15 @@ fi if test $ac_cv_header_linux_cdrom_h = yes; then - HAVE_LINUX_CDROM_H=yes -else - - echo "Linux CDROM support not found, building without it." -fi - - - - -if test "$HAVE_LINUX_CDROM_H" = "yes"; then + CDROM_DRIVER=linux +else + true +fi + + + + +if test "x$CDROM_DRIVER" = "xlinux"; then CDROM_LINUX_TRUE= CDROM_LINUX_FALSE='#' else @@ -9213,6 +9216,26 @@ fi + +if test "x$CDROM_DRIVER" = "xosx"; then + CDROM_OSX_TRUE= + CDROM_OSX_FALSE='#' +else + CDROM_OSX_TRUE='#' + CDROM_OSX_FALSE= +fi + + + +if test "x$CDROM_DRIVER" = "x"; then + CDROM_NONE_TRUE= + CDROM_NONE_FALSE='#' +else + CDROM_NONE_TRUE='#' + CDROM_NONE_FALSE= +fi + + if test "${ac_cv_header_linux_joystick_h+set}" = set; then { $as_echo "$as_me:$LINENO: checking for linux/joystick.h" >&5 $as_echo_n "checking for linux/joystick.h... " >&6; } @@ -11448,6 +11471,20 @@ Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${CDROM_OSX_TRUE}" && test -z "${CDROM_OSX_FALSE}"; then + { { $as_echo "$as_me:$LINENO: error: conditional \"CDROM_OSX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +$as_echo "$as_me: error: conditional \"CDROM_OSX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${CDROM_NONE_TRUE}" && test -z "${CDROM_NONE_FALSE}"; then + { { $as_echo "$as_me:$LINENO: error: conditional \"CDROM_NONE\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +$as_echo "$as_me: error: conditional \"CDROM_NONE\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi if test -z "${JOY_LINUX_TRUE}" && test -z "${JOY_LINUX_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"JOY_LINUX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -12821,3 +12858,8 @@ echo " Audio drivers: $AUDIO_DRIVERS" fi +if test "x$CDROM_DRIVER" = "x"; then + echo " CD-ROM driver: none (no supported cd-rom devices found)" +else + echo " CD-ROM driver: $CDROM_DRIVER" +fi --- a/configure.in Wed Jun 25 10:39:05 2008 +0000 +++ b/configure.in Wed Jun 25 10:40:45 2008 +0000 @@ -185,10 +185,14 @@ AM_CONDITIONAL( AUDIO_ALSA, [test "$HAVE_ALSA" = 'yes'] ) -dnl Check for linux cdrom device support -AC_CHECK_HEADER([linux/cdrom.h], [HAVE_LINUX_CDROM_H=yes], [ - echo "Linux CDROM support not found, building without it."] ) -AM_CONDITIONAL(CDROM_LINUX, [test "$HAVE_LINUX_CDROM_H" = "yes"]) +dnl Check for native cdrom support. There can be only one. +AC_CHECK_HEADER([linux/cdrom.h], [CDROM_DRIVER=linux], [true]) +dnl AC_CHECK_HEADER([IOKit/IOKitLib.h], [ +dnl CDROM_DRIVER=osx +dnl LIBS="$LIBS -framework IOKit"],[true]) +AM_CONDITIONAL(CDROM_LINUX, [test "x$CDROM_DRIVER" = "xlinux"]) +AM_CONDITIONAL(CDROM_OSX, [test "x$CDROM_DRIVER" = "xosx"]) +AM_CONDITIONAL(CDROM_NONE, [test "x$CDROM_DRIVER" = "x"]) AC_CHECK_HEADER([linux/joystick.h], [ HAVE_LINUX_JOYSTICK_H=yes @@ -270,3 +274,8 @@ echo " Audio drivers: $AUDIO_DRIVERS" fi +if test "x$CDROM_DRIVER" = "x"; then + echo " CD-ROM driver: none (no supported cd-rom devices found)" +else + echo " CD-ROM driver: $CDROM_DRIVER" +fi --- a/src/Makefile.am Wed Jun 25 10:39:05 2008 +0000 +++ b/src/Makefile.am Wed Jun 25 10:40:45 2008 +0000 @@ -106,7 +106,13 @@ if CDROM_LINUX lxdream_SOURCES += drivers/cd_linux.c -else +endif + +if CDROM_OSX +lxdream_SOURCES += drivers/cd_osx.c +endif + +if CDROM_NONE lxdream_SOURCES += drivers/cd_none.c endif --- a/src/Makefile.in Wed Jun 25 10:39:05 2008 +0000 +++ b/src/Makefile.in Wed Jun 25 10:40:45 2008 +0000 @@ -63,8 +63,9 @@ @AUDIO_ESOUND_TRUE@am__append_10 = drivers/audio_esd.c @AUDIO_ALSA_TRUE@am__append_11 = drivers/audio_alsa.c @CDROM_LINUX_TRUE@am__append_12 = drivers/cd_linux.c -@CDROM_LINUX_FALSE@am__append_13 = drivers/cd_none.c -@JOY_LINUX_TRUE@am__append_14 = drivers/joy_linux.c +@CDROM_OSX_TRUE@am__append_13 = drivers/cd_osx.c +@CDROM_NONE_TRUE@am__append_14 = drivers/cd_none.c +@JOY_LINUX_TRUE@am__append_15 = drivers/joy_linux.c subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -120,7 +121,7 @@ drivers/video_glx.c drivers/video_glx.h drivers/video_nsgl.c \ drivers/video_nsgl.h drivers/audio_osx.c drivers/audio_pulse.c \ drivers/audio_esd.c drivers/audio_alsa.c drivers/cd_linux.c \ - drivers/cd_none.c drivers/joy_linux.c + drivers/cd_osx.c drivers/cd_none.c drivers/joy_linux.c @BUILD_SH4X86_TRUE@am__objects_1 = sh4x86.$(OBJEXT) sh4trans.$(OBJEXT) \ @BUILD_SH4X86_TRUE@ x86dasm.$(OBJEXT) i386-dis.$(OBJEXT) \ @BUILD_SH4X86_TRUE@ dis-init.$(OBJEXT) dis-buf.$(OBJEXT) @@ -139,8 +140,9 @@ @AUDIO_ESOUND_TRUE@am__objects_9 = audio_esd.$(OBJEXT) @AUDIO_ALSA_TRUE@am__objects_10 = audio_alsa.$(OBJEXT) @CDROM_LINUX_TRUE@am__objects_11 = cd_linux.$(OBJEXT) -@CDROM_LINUX_FALSE@am__objects_12 = cd_none.$(OBJEXT) -@JOY_LINUX_TRUE@am__objects_13 = joy_linux.$(OBJEXT) +@CDROM_OSX_TRUE@am__objects_12 = cd_osx.$(OBJEXT) +@CDROM_NONE_TRUE@am__objects_13 = cd_none.$(OBJEXT) +@JOY_LINUX_TRUE@am__objects_14 = joy_linux.$(OBJEXT) am_lxdream_OBJECTS = main.$(OBJEXT) config.$(OBJEXT) mem.$(OBJEXT) \ watch.$(OBJEXT) asic.$(OBJEXT) syscall.$(OBJEXT) \ bios.$(OBJEXT) dcload.$(OBJEXT) ide.$(OBJEXT) \ @@ -163,7 +165,8 @@ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ - $(am__objects_11) $(am__objects_12) $(am__objects_13) + $(am__objects_11) $(am__objects_12) $(am__objects_13) \ + $(am__objects_14) lxdream_OBJECTS = $(am_lxdream_OBJECTS) lxdream_DEPENDENCIES = $(am__DEPENDENCIES_1) am__test_testsh4x86_SOURCES_DIST = test/testsh4x86.c x86dasm/x86dasm.c \ @@ -234,6 +237,10 @@ CCDEPMODE = @CCDEPMODE@ CDROM_LINUX_FALSE = @CDROM_LINUX_FALSE@ CDROM_LINUX_TRUE = @CDROM_LINUX_TRUE@ +CDROM_NONE_FALSE = @CDROM_NONE_FALSE@ +CDROM_NONE_TRUE = @CDROM_NONE_TRUE@ +CDROM_OSX_FALSE = @CDROM_OSX_FALSE@ +CDROM_OSX_TRUE = @CDROM_OSX_TRUE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ @@ -393,7 +400,7 @@ $(am__append_4) $(am__append_5) $(am__append_6) \ $(am__append_7) $(am__append_8) $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ - $(am__append_13) $(am__append_14) + $(am__append_13) $(am__append_14) $(am__append_15) @BUILD_SH4X86_TRUE@test_testsh4x86_LDADD = @GLIB_LIBS@ @GTK_LIBS@ @LIBPNG_LIBS@ @BUILD_SH4X86_TRUE@test_testsh4x86_SOURCES = test/testsh4x86.c x86dasm/x86dasm.c \ @BUILD_SH4X86_TRUE@ x86dasm/x86dasm.h x86dasm/i386-dis.c x86dasm/dis-init.c \ @@ -509,6 +516,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bootstrap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cd_linux.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cd_none.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cd_osx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cocoa_gd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cocoa_win.Po@am__quote@ @@ -1667,6 +1675,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cd_linux.obj `if test -f 'drivers/cd_linux.c'; then $(CYGPATH_W) 'drivers/cd_linux.c'; else $(CYGPATH_W) '$(srcdir)/drivers/cd_linux.c'; fi` +cd_osx.o: drivers/cd_osx.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cd_osx.o -MD -MP -MF "$(DEPDIR)/cd_osx.Tpo" -c -o cd_osx.o `test -f 'drivers/cd_osx.c' || echo '$(srcdir)/'`drivers/cd_osx.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/cd_osx.Tpo" "$(DEPDIR)/cd_osx.Po"; else rm -f "$(DEPDIR)/cd_osx.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/cd_osx.c' object='cd_osx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cd_osx.o `test -f 'drivers/cd_osx.c' || echo '$(srcdir)/'`drivers/cd_osx.c + +cd_osx.obj: drivers/cd_osx.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cd_osx.obj -MD -MP -MF "$(DEPDIR)/cd_osx.Tpo" -c -o cd_osx.obj `if test -f 'drivers/cd_osx.c'; then $(CYGPATH_W) 'drivers/cd_osx.c'; else $(CYGPATH_W) '$(srcdir)/drivers/cd_osx.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/cd_osx.Tpo" "$(DEPDIR)/cd_osx.Po"; else rm -f "$(DEPDIR)/cd_osx.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='drivers/cd_osx.c' object='cd_osx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cd_osx.obj `if test -f 'drivers/cd_osx.c'; then $(CYGPATH_W) 'drivers/cd_osx.c'; else $(CYGPATH_W) '$(srcdir)/drivers/cd_osx.c'; fi` + cd_none.o: drivers/cd_none.c @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cd_none.o -MD -MP -MF "$(DEPDIR)/cd_none.Tpo" -c -o cd_none.o `test -f 'drivers/cd_none.c' || echo '$(srcdir)/'`drivers/cd_none.c; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/cd_none.Tpo" "$(DEPDIR)/cd_none.Po"; else rm -f "$(DEPDIR)/cd_none.Tpo"; exit 1; fi --- a/src/drivers/cd_linux.c Wed Jun 25 10:39:05 2008 +0000 +++ b/src/drivers/cd_linux.c Wed Jun 25 10:40:45 2008 +0000 @@ -60,7 +60,7 @@ struct gdrom_image_class cdrom_device_class = { "Linux", NULL, linux_image_is_valid, linux_open_device }; -GList *gdrom_get_native_devices(void) +GList *cdrom_get_native_devices(void) { GList *list = NULL; struct fstab *ent; @@ -76,7 +76,7 @@ int caps = ioctl(fd, CDROM_GET_CAPABILITY); if( caps != -1 ) { /* Appears to support CDROM functions */ - list = g_list_append( list, g_strdup(ent->fs_spec) ); + list = g_list_append( list, gdrom_device_new(ent->fs_spec, ent->fs_spec)); } close(fd); } @@ -84,6 +84,11 @@ return list; } +gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path ) +{ + return NULL; +} + static gboolean linux_image_is_valid( FILE *f ) { struct stat st; --- a/src/drivers/cd_none.c Wed Jun 25 10:39:05 2008 +0000 +++ b/src/drivers/cd_none.c Wed Jun 25 10:40:45 2008 +0000 @@ -24,11 +24,18 @@ struct gdrom_image_class cdrom_device_class = { "None", NULL, cdnone_image_is_valid, cdnone_open_device }; -GList *gdrom_get_native_devices(void) +GList *cdrom_get_native_devices(void) { return NULL; } +gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path ) +{ + return NULL; +} + + + static gboolean cdnone_image_is_valid( FILE *f ) { return FALSE; --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/drivers/cd_osx.c Wed Jun 25 10:40:45 2008 +0000 @@ -0,0 +1,218 @@ +/** + * $Id$ + * + * OSX native cd-rom driver. + * + * Copyright (c) 2005 Nathan Keynes. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include "gdrom/gddriver.h" + +static gboolean osx_image_is_valid( FILE *f ); +static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f ); + +struct gdrom_image_class cdrom_device_class = { "osx", NULL, + osx_image_is_valid, osx_open_device }; + +typedef struct osx_cdrom_disc { + struct gdrom_disc disc; + + io_object_t entry; + MMCDeviceInterface **mmc; + SCSITaskDeviceInterface **scsi; +} *osx_cdrom_disc_t; + +/** + * CD-ROM drive visitor. Returns FALSE to continue iterating, TRUE if the desired CD-ROM + * has been found. In the latter case, the io_object is returned from find_cdrom_device + * (and not freed) + */ +typedef gboolean (*find_cdrom_callback_t)( io_object_t object, char *vendor, char *product, + void *user_data ); + +io_object_t find_cdrom_device( find_cdrom_callback_t callback, void *user_data ) +{ + mach_port_t master_port; + CFMutableDictionaryRef match; + io_iterator_t services; + io_object_t object; + + if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) { + return; // Failed to get the master port? + } + + match = IOServiceMatching("IODVDServices"); + if( IOServiceGetMatchingServices(master_port, match, &services) != kIOReturnSuccess ) { + return; + } + + while( (object = IOIteratorNext(services)) != 0 ) { + CFMutableDictionaryRef props = 0; + if( IORegistryEntryCreateCFProperties(object, &props, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS ) { + CFDictionaryRef dict = + (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOPropertyDeviceCharacteristicsKey)); + if( dict ) { + /* The vendor name. */ + char vendor[256] = "", product[256] = ""; + CFTypeRef value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyVendorNameKey)); + if( value && CFGetTypeID(value) == CFStringGetTypeID() ) { + CFStringGetCString( (CFStringRef)value, vendor, sizeof(vendor), + kCFStringEncodingUTF8 ); + } + value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyProductNameKey)); + if ( value && CFGetTypeID(value) == CFStringGetTypeID() ) { + CFStringGetCString( (CFStringRef)value, product, sizeof(product), + kCFStringEncodingUTF8 ); + } + if( callback(object, vendor, product, user_data) ) { + CFRelease(props); + IOObjectRelease(services); + return object; + } + } + CFRelease(props); + } + + IOObjectRelease(object); + } + IOObjectRelease(services); +} + +io_object_t get_cdrom_by_service_path( const gchar *path ) +{ + mach_port_t master_port; + io_object_t result; + + if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) { + return MACH_PORT_NULL; // Failed to get the master port? + } + + return IORegistryEntryFromPath( master_port, path ); +} + +void cdrom_osx_destroy( gdrom_disc_t disc ) +{ + osx_cdrom_disc_t cdrom = (osx_cdrom_disc_t)disc; + + if( cdrom->scsi != NULL ) { + (*cdrom->scsi)->Release(cdrom->scsi); + cdrom->scsi = NULL; + } + if( cdrom->mmc != NULL ) { + (*cdrom->mmc)->Release(cdrom->mmc); + cdrom->mmc = NULL; + } + if( cdrom->entry != MACH_PORT_NULL ) { + IOObjectRelease( cdrom->entry ); + cdrom->entry = MACH_PORT_NULL; + } + + if( disc->name != NULL ) { + g_free( (gpointer)disc->name ); + disc->name = NULL; + } + g_free(disc); +} + +gdrom_disc_t cdrom_osx_new( io_object_t obj ) +{ + osx_cdrom_disc_t cdrom = g_malloc0( sizeof(struct osx_cdrom_disc) ); + gdrom_disc_t disc = &cdrom->disc; + IOCFPlugInInterface **pluginInterface = NULL; + HRESULT herr; + SInt32 score = 0; + + cdrom->entry = obj; + + if( IOCreatePlugInInterfaceForService( obj, kIOMMCDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &pluginInterface, &score ) != KERN_SUCCESS ) { + ERROR( "Failed to create plugin interface" ); + cdrom_osx_destroy(disc); + return NULL; + } + + herr = (*pluginInterface)->QueryInterface( pluginInterface, + CFUUIDGetUUIDBytes( kIOMMCDeviceInterfaceID ), (LPVOID *)&cdrom->mmc ); + (*pluginInterface)->Release(pluginInterface); + pluginInterface = NULL; + if( herr != S_OK ) { + ERROR( "Failed to create MMC interface" ); + cdrom_osx_destroy(disc); + return NULL; + } + + cdrom->scsi = (*cdrom->mmc)->GetSCSITaskDeviceInterface( cdrom->mmc ); + if( cdrom->scsi == NULL ) { + ERROR( "Failed to create SCSI interface" ); + cdrom_osx_destroy(disc); + return NULL; + } + + char name[sizeof(io_string_t) + 6] = "dvd://"; + IORegistryEntryGetPath( cdrom->entry, kIOServicePlane, name+6 ); + disc->name = g_strdup(name); + + disc->close = cdrom_osx_destroy; + return disc; +} + +gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, void *ptr ) +{ + GList **list = (GList **)ptr; + char tmp1[sizeof(io_string_t) + 6] = "dvd://"; + char tmp2[512]; + IORegistryEntryGetPath( object, kIOServicePlane, tmp1+6 ); + snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product ); + *list = g_list_append( *list, gdrom_device_new( tmp1, tmp2 ) ); + return FALSE; +} + +GList *cdrom_get_native_devices(void) +{ + GList *list = NULL; + find_cdrom_device(cdrom_enum_callback, &list); + return list; +} + +gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path ) +{ + io_object_t obj; + gdrom_disc_t result = NULL; + + if( strncasecmp( path, "IOService:", 10 ) == 0 ) { + obj = get_cdrom_by_service_path( path ); + } + + if( obj == MACH_PORT_NULL ) { + return NULL; + } else { + return cdrom_osx_new( obj ); + } +} + + + +static gboolean osx_image_is_valid( FILE *f ) +{ + return FALSE; +} + +static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f ) +{ + return NULL; +} --- a/src/gdlist.c Wed Jun 25 10:39:05 2008 +0000 +++ b/src/gdlist.c Wed Jun 25 10:40:45 2008 +0000 @@ -43,9 +43,9 @@ GList *ptr; for( ptr = gdrom_device_list; ptr != NULL; ptr = g_list_next(ptr) ) { - gchar *device = (gchar *)ptr->data; + gdrom_device_t device = (gdrom_device_t)ptr->data; posn++; - if( strcmp(device, name) == 0 ) { + if( strcmp(device->name, name) == 0 ) { return posn; } } @@ -148,7 +148,7 @@ { const gchar *recent = lxdream_get_config_value( CONFIG_RECENT ); register_gdrom_disc_change_hook( gdrom_list_disc_changed, NULL ); - gdrom_device_list = gdrom_get_native_devices(); + gdrom_device_list = cdrom_get_native_devices(); if( recent != NULL ) { gchar **list = g_strsplit(recent, ":", MAX_RECENT_ITEMS); int i; @@ -172,8 +172,8 @@ } if( posn <= gdrom_device_count ) { - gchar *entry = g_list_nth_data(gdrom_device_list, posn-1); - return gdrom_mount_image(entry); + gdrom_device_t device = g_list_nth_data(gdrom_device_list, posn-1); + return gdrom_mount_image(device->name); } posn -= FIRST_RECENT_INDEX; @@ -207,7 +207,8 @@ } if( posn <= gdrom_device_count ) { - return g_list_nth_data(gdrom_device_list, posn-1); + gdrom_device_t device = g_list_nth_data(gdrom_device_list, posn-1); + return device->device_name; } if( posn == gdrom_device_count + 1) { @@ -229,7 +230,8 @@ } if( posn <= gdrom_device_count ) { - return g_list_nth_data(gdrom_device_list, posn-1); + gdrom_device_t device = g_list_nth_data(gdrom_device_list, posn-1); + return device->name; } if( posn == gdrom_device_count + 1) { --- a/src/gdrom/gddriver.h Wed Jun 25 10:39:05 2008 +0000 +++ b/src/gdrom/gddriver.h Wed Jun 25 10:40:45 2008 +0000 @@ -28,6 +28,7 @@ #define MAX_SECTOR_SIZE 2352 + struct gdrom_toc { uint32_t track[99]; uint32_t first, last, leadout; @@ -202,4 +203,8 @@ */ gchar *gdrom_get_relative_filename( const gchar *base_name, const gchar *find_name ); +gdrom_device_t gdrom_device_new( const gchar *name, const gchar *dev_name ); + +void gdrom_device_destroy( gdrom_device_t dev ); + #endif --- a/src/gdrom/gdimage.c Wed Jun 25 10:39:05 2008 +0000 +++ b/src/gdrom/gdimage.c Wed Jun 25 10:40:45 2008 +0000 @@ -477,3 +477,24 @@ } } +gdrom_device_t gdrom_device_new( const gchar *name, const gchar *dev_name ) +{ + struct gdrom_device *dev = g_malloc0( sizeof(struct gdrom_device) ); + dev->name = g_strdup(name); + dev->device_name = g_strdup(dev_name); + return dev; +} + +void gdrom_device_destroy( gdrom_device_t dev ) +{ + if( dev->name != NULL ) { + g_free( dev->name ); + dev->name = NULL; + } + if( dev->device_name != NULL ) { + g_free( dev->device_name ); + dev->device_name = NULL; + } + g_free( dev ); +} + \ No newline at end of file --- a/src/gdrom/gdrom.c Wed Jun 25 10:39:05 2008 +0000 +++ b/src/gdrom/gdrom.c Wed Jun 25 10:40:45 2008 +0000 @@ -46,18 +46,40 @@ "Mode 2 semiraw", "XA Raw", "Non-XA Raw" }; uint32_t gdrom_sector_size[] = { 0, 2048, 2336, 2048, 2324, 2352, 2336, 2352, 2352 }; -gdrom_disc_t gdrom_image_open( const gchar *filename ) +gdrom_disc_t gdrom_image_open( const gchar *inFilename ) { + const gchar *filename = inFilename; const gchar *ext = strrchr(filename, '.'); gdrom_disc_t disc = NULL; - - int fd = open( filename, O_RDONLY | O_NONBLOCK ); + int fd; FILE *f; int i; gdrom_image_class_t extclz = NULL; + // Check for a url-style filename. + char *lizard_lips = strstr( filename, "://" ); + if( lizard_lips != NULL ) { + gchar *path = lizard_lips + 3; + int method_len = (lizard_lips-filename); + gchar method[method_len + 1]; + memcpy( method, filename, method_len ); + method[method_len] = '\0'; + + if( strcasecmp( method, "file" ) == 0 ) { + filename = path; + } else if( strcasecmp( method, "dvd" ) == 0 || + strcasecmp( method, "cd" ) == 0 || + strcasecmp( method, "cdrom" ) ) { + return cdrom_open_device( method, path ); + } else { + ERROR( "Unrecognized URL method '%s' in filename '%s'", method, filename ); + return NULL; + } + } + + fd = open( filename, O_RDONLY | O_NONBLOCK ); if( fd == -1 ) { - return NULL; + return NULL; } f = fdopen(fd, "ro"); --- a/src/gdrom/gdrom.h Wed Jun 25 10:39:05 2008 +0000 +++ b/src/gdrom/gdrom.h Wed Jun 25 10:40:45 2008 +0000 @@ -26,6 +26,14 @@ typedef uint16_t gdrom_error_t; + +struct gdrom_device { + char *name; // internal name + char *device_name; // Human-readable device name +}; + +typedef struct gdrom_device *gdrom_device_t; + typedef struct gdrom_disc *gdrom_disc_t; typedef gboolean (*gdrom_disc_change_hook_t)( gdrom_disc_t new_disc, const gchar *new_disc_name, void *user_data ); @@ -59,8 +67,6 @@ const gchar *gdrom_get_current_disc_name(); -GList *gdrom_get_native_devices(); - uint32_t gdrom_read_sectors( uint32_t sector, uint32_t sector_count, int mode, unsigned char *buf, uint32_t *length ); @@ -80,4 +86,26 @@ uint8_t gdrom_get_track_no_by_lba( uint32_t lba ); + +/** + * Native CD-ROM API - provided by drivers/cd_*.c + * + * A device name is either a system special file (most unixes) or a url of the + * form dvd:// or cd://, where is a system + * defined string that uniquely identifies a particular device. + */ + +/** + * Return a list of gdrom_device_t defining all CD/DVD drives in the host system. + */ +GList *cdrom_get_native_devices(); + +/** + * Open a native device given a device name and url method. Eg, for the url dvd://1 + * this function will be invoked with method = "dvd" and name = "1" + * + * @return NULL on failure, otherwise a valid gdrom_disc_t that can be mounted. + */ +gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *name ); + #endif