Search
lxdream.org :: lxdream/src/drivers/cd_osx.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/cd_osx.c
changeset 709:18c39a8e504c
next720:b5594d1ac80a
author nkeynes
date Wed Jun 25 10:40:45 2008 +0000 (14 years ago)
permissions -rw-r--r--
last change Commit OSX CD-ROM driver work-in-progress
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * OSX native cd-rom driver.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <IOKit/IOKitLib.h>
    20 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
    21 #include <IOKit/scsi-commands/SCSITaskLib.h>
    22 #include <IOKit/scsi-commands/SCSICommandOperationCodes.h>
    23 #include <stdio.h>
    24 #include "gdrom/gddriver.h"
    26 static gboolean osx_image_is_valid( FILE *f );
    27 static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f );
    29 struct gdrom_image_class cdrom_device_class = { "osx", NULL,
    30                         osx_image_is_valid, osx_open_device };
    32 typedef struct osx_cdrom_disc {
    33     struct gdrom_disc disc;
    35     io_object_t entry;
    36     MMCDeviceInterface **mmc;
    37     SCSITaskDeviceInterface **scsi;
    38 } *osx_cdrom_disc_t;
    40 /**
    41  * CD-ROM drive visitor. Returns FALSE to continue iterating, TRUE if the desired CD-ROM
    42  * has been found. In the latter case, the io_object is returned from find_cdrom_device
    43  * (and not freed)
    44  */ 
    45 typedef gboolean (*find_cdrom_callback_t)( io_object_t object, char *vendor, char *product,
    46                                       void *user_data );
    48 io_object_t find_cdrom_device( find_cdrom_callback_t callback, void *user_data )
    49 {
    50     mach_port_t master_port;
    51     CFMutableDictionaryRef match;
    52     io_iterator_t services;
    53     io_object_t object;
    55     if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) {
    56         return; // Failed to get the master port?
    57     }
    59     match = IOServiceMatching("IODVDServices");
    60     if( IOServiceGetMatchingServices(master_port, match, &services) != kIOReturnSuccess ) {
    61         return;
    62     }
    64     while( (object = IOIteratorNext(services)) != 0 ) {
    65         CFMutableDictionaryRef props = 0;
    66         if( IORegistryEntryCreateCFProperties(object, &props, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS ) {
    67             CFDictionaryRef dict = 
    68                 (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOPropertyDeviceCharacteristicsKey));
    69             if( dict ) {
    70                 /* The vendor name. */
    71                 char vendor[256] = "", product[256] = "";
    72                 CFTypeRef value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyVendorNameKey));
    73                 if( value && CFGetTypeID(value) == CFStringGetTypeID() ) {
    74                     CFStringGetCString( (CFStringRef)value, vendor, sizeof(vendor), 
    75                                         kCFStringEncodingUTF8 );
    76                 }
    77                 value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyProductNameKey));
    78                 if ( value && CFGetTypeID(value) == CFStringGetTypeID() ) {
    79                     CFStringGetCString( (CFStringRef)value, product, sizeof(product), 
    80                                         kCFStringEncodingUTF8 );
    81                 }
    82                 if( callback(object, vendor, product, user_data) ) {
    83                     CFRelease(props);
    84                     IOObjectRelease(services);
    85                     return object;
    86                 }
    87             }
    88             CFRelease(props);
    89         }
    91         IOObjectRelease(object);
    92     }
    93     IOObjectRelease(services);
    94 }
    96 io_object_t get_cdrom_by_service_path( const gchar *path )
    97 {
    98     mach_port_t master_port;
    99     io_object_t result;
   101     if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) {
   102         return MACH_PORT_NULL; // Failed to get the master port?
   103     }
   105     return IORegistryEntryFromPath( master_port, path );
   106 }
   108 void cdrom_osx_destroy( gdrom_disc_t disc )
   109 {
   110     osx_cdrom_disc_t cdrom = (osx_cdrom_disc_t)disc;
   112     if( cdrom->scsi != NULL ) {
   113         (*cdrom->scsi)->Release(cdrom->scsi);
   114         cdrom->scsi = NULL;
   115     }
   116     if( cdrom->mmc != NULL ) {
   117         (*cdrom->mmc)->Release(cdrom->mmc);
   118         cdrom->mmc = NULL;
   119     }
   120     if( cdrom->entry != MACH_PORT_NULL ) {
   121         IOObjectRelease( cdrom->entry );
   122         cdrom->entry = MACH_PORT_NULL;
   123     }
   125     if( disc->name != NULL ) {
   126         g_free( (gpointer)disc->name );
   127         disc->name = NULL;
   128     }
   129     g_free(disc);
   130 }
   132 gdrom_disc_t cdrom_osx_new( io_object_t obj )
   133 {
   134     osx_cdrom_disc_t cdrom = g_malloc0( sizeof(struct osx_cdrom_disc) );
   135     gdrom_disc_t disc = &cdrom->disc;
   136     IOCFPlugInInterface **pluginInterface = NULL;
   137     HRESULT herr;
   138     SInt32 score = 0;
   140     cdrom->entry = obj;
   142     if( IOCreatePlugInInterfaceForService( obj, kIOMMCDeviceUserClientTypeID,
   143             kIOCFPlugInInterfaceID, &pluginInterface, &score ) != KERN_SUCCESS ) {
   144         ERROR( "Failed to create plugin interface" );
   145         cdrom_osx_destroy(disc);
   146         return NULL;
   147     }
   149     herr = (*pluginInterface)->QueryInterface( pluginInterface,
   150             CFUUIDGetUUIDBytes( kIOMMCDeviceInterfaceID ), (LPVOID *)&cdrom->mmc );
   151     (*pluginInterface)->Release(pluginInterface);
   152     pluginInterface = NULL;
   153     if( herr != S_OK ) {
   154         ERROR( "Failed to create MMC interface" );
   155         cdrom_osx_destroy(disc);
   156         return NULL;
   157     }
   159     cdrom->scsi = (*cdrom->mmc)->GetSCSITaskDeviceInterface( cdrom->mmc );
   160     if( cdrom->scsi == NULL ) {
   161         ERROR( "Failed to create SCSI interface" );
   162         cdrom_osx_destroy(disc);
   163         return NULL;
   164     }
   166     char name[sizeof(io_string_t) + 6] = "dvd://";
   167     IORegistryEntryGetPath( cdrom->entry, kIOServicePlane, name+6 );
   168     disc->name = g_strdup(name);
   170     disc->close = cdrom_osx_destroy;
   171     return disc;
   172 }
   174 gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, void *ptr )
   175 {
   176     GList **list = (GList **)ptr;
   177     char tmp1[sizeof(io_string_t) + 6] = "dvd://";
   178     char tmp2[512];
   179     IORegistryEntryGetPath( object, kIOServicePlane, tmp1+6 );
   180     snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product );
   181     *list = g_list_append( *list, gdrom_device_new( tmp1, tmp2 ) );
   182     return FALSE;
   183 }
   185 GList *cdrom_get_native_devices(void)
   186 {
   187     GList *list = NULL;
   188     find_cdrom_device(cdrom_enum_callback, &list);
   189     return list;
   190 }
   192 gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )
   193 {
   194     io_object_t obj;
   195     gdrom_disc_t result = NULL;
   197     if( strncasecmp( path, "IOService:", 10 ) == 0 ) {
   198         obj = get_cdrom_by_service_path( path );
   199     }
   201     if( obj == MACH_PORT_NULL ) {
   202         return NULL;
   203     } else {
   204         return cdrom_osx_new( obj );
   205     }
   206 }
   210 static gboolean osx_image_is_valid( FILE *f )
   211 {
   212     return FALSE;
   213 }
   215 static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f )
   216 {
   217     return NULL;
   218 }
.