Search
lxdream.org :: lxdream/src/drivers/cd_osx.c :: diff
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 (15 years ago)
permissions -rw-r--r--
last change Commit OSX CD-ROM driver work-in-progress
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/drivers/cd_osx.c Wed Jun 25 10:40:45 2008 +0000
1.3 @@ -0,0 +1,218 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * OSX native cd-rom driver.
1.8 + *
1.9 + * Copyright (c) 2005 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include <IOKit/IOKitLib.h>
1.23 +#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
1.24 +#include <IOKit/scsi-commands/SCSITaskLib.h>
1.25 +#include <IOKit/scsi-commands/SCSICommandOperationCodes.h>
1.26 +#include <stdio.h>
1.27 +#include "gdrom/gddriver.h"
1.28 +
1.29 +static gboolean osx_image_is_valid( FILE *f );
1.30 +static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f );
1.31 +
1.32 +struct gdrom_image_class cdrom_device_class = { "osx", NULL,
1.33 + osx_image_is_valid, osx_open_device };
1.34 +
1.35 +typedef struct osx_cdrom_disc {
1.36 + struct gdrom_disc disc;
1.37 +
1.38 + io_object_t entry;
1.39 + MMCDeviceInterface **mmc;
1.40 + SCSITaskDeviceInterface **scsi;
1.41 +} *osx_cdrom_disc_t;
1.42 +
1.43 +/**
1.44 + * CD-ROM drive visitor. Returns FALSE to continue iterating, TRUE if the desired CD-ROM
1.45 + * has been found. In the latter case, the io_object is returned from find_cdrom_device
1.46 + * (and not freed)
1.47 + */
1.48 +typedef gboolean (*find_cdrom_callback_t)( io_object_t object, char *vendor, char *product,
1.49 + void *user_data );
1.50 +
1.51 +io_object_t find_cdrom_device( find_cdrom_callback_t callback, void *user_data )
1.52 +{
1.53 + mach_port_t master_port;
1.54 + CFMutableDictionaryRef match;
1.55 + io_iterator_t services;
1.56 + io_object_t object;
1.57 +
1.58 + if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) {
1.59 + return; // Failed to get the master port?
1.60 + }
1.61 +
1.62 + match = IOServiceMatching("IODVDServices");
1.63 + if( IOServiceGetMatchingServices(master_port, match, &services) != kIOReturnSuccess ) {
1.64 + return;
1.65 + }
1.66 +
1.67 + while( (object = IOIteratorNext(services)) != 0 ) {
1.68 + CFMutableDictionaryRef props = 0;
1.69 + if( IORegistryEntryCreateCFProperties(object, &props, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS ) {
1.70 + CFDictionaryRef dict =
1.71 + (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOPropertyDeviceCharacteristicsKey));
1.72 + if( dict ) {
1.73 + /* The vendor name. */
1.74 + char vendor[256] = "", product[256] = "";
1.75 + CFTypeRef value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyVendorNameKey));
1.76 + if( value && CFGetTypeID(value) == CFStringGetTypeID() ) {
1.77 + CFStringGetCString( (CFStringRef)value, vendor, sizeof(vendor),
1.78 + kCFStringEncodingUTF8 );
1.79 + }
1.80 + value = CFDictionaryGetValue(dict, CFSTR(kIOPropertyProductNameKey));
1.81 + if ( value && CFGetTypeID(value) == CFStringGetTypeID() ) {
1.82 + CFStringGetCString( (CFStringRef)value, product, sizeof(product),
1.83 + kCFStringEncodingUTF8 );
1.84 + }
1.85 + if( callback(object, vendor, product, user_data) ) {
1.86 + CFRelease(props);
1.87 + IOObjectRelease(services);
1.88 + return object;
1.89 + }
1.90 + }
1.91 + CFRelease(props);
1.92 + }
1.93 +
1.94 + IOObjectRelease(object);
1.95 + }
1.96 + IOObjectRelease(services);
1.97 +}
1.98 +
1.99 +io_object_t get_cdrom_by_service_path( const gchar *path )
1.100 +{
1.101 + mach_port_t master_port;
1.102 + io_object_t result;
1.103 +
1.104 + if( IOMasterPort( MACH_PORT_NULL, &master_port ) != KERN_SUCCESS ) {
1.105 + return MACH_PORT_NULL; // Failed to get the master port?
1.106 + }
1.107 +
1.108 + return IORegistryEntryFromPath( master_port, path );
1.109 +}
1.110 +
1.111 +void cdrom_osx_destroy( gdrom_disc_t disc )
1.112 +{
1.113 + osx_cdrom_disc_t cdrom = (osx_cdrom_disc_t)disc;
1.114 +
1.115 + if( cdrom->scsi != NULL ) {
1.116 + (*cdrom->scsi)->Release(cdrom->scsi);
1.117 + cdrom->scsi = NULL;
1.118 + }
1.119 + if( cdrom->mmc != NULL ) {
1.120 + (*cdrom->mmc)->Release(cdrom->mmc);
1.121 + cdrom->mmc = NULL;
1.122 + }
1.123 + if( cdrom->entry != MACH_PORT_NULL ) {
1.124 + IOObjectRelease( cdrom->entry );
1.125 + cdrom->entry = MACH_PORT_NULL;
1.126 + }
1.127 +
1.128 + if( disc->name != NULL ) {
1.129 + g_free( (gpointer)disc->name );
1.130 + disc->name = NULL;
1.131 + }
1.132 + g_free(disc);
1.133 +}
1.134 +
1.135 +gdrom_disc_t cdrom_osx_new( io_object_t obj )
1.136 +{
1.137 + osx_cdrom_disc_t cdrom = g_malloc0( sizeof(struct osx_cdrom_disc) );
1.138 + gdrom_disc_t disc = &cdrom->disc;
1.139 + IOCFPlugInInterface **pluginInterface = NULL;
1.140 + HRESULT herr;
1.141 + SInt32 score = 0;
1.142 +
1.143 + cdrom->entry = obj;
1.144 +
1.145 + if( IOCreatePlugInInterfaceForService( obj, kIOMMCDeviceUserClientTypeID,
1.146 + kIOCFPlugInInterfaceID, &pluginInterface, &score ) != KERN_SUCCESS ) {
1.147 + ERROR( "Failed to create plugin interface" );
1.148 + cdrom_osx_destroy(disc);
1.149 + return NULL;
1.150 + }
1.151 +
1.152 + herr = (*pluginInterface)->QueryInterface( pluginInterface,
1.153 + CFUUIDGetUUIDBytes( kIOMMCDeviceInterfaceID ), (LPVOID *)&cdrom->mmc );
1.154 + (*pluginInterface)->Release(pluginInterface);
1.155 + pluginInterface = NULL;
1.156 + if( herr != S_OK ) {
1.157 + ERROR( "Failed to create MMC interface" );
1.158 + cdrom_osx_destroy(disc);
1.159 + return NULL;
1.160 + }
1.161 +
1.162 + cdrom->scsi = (*cdrom->mmc)->GetSCSITaskDeviceInterface( cdrom->mmc );
1.163 + if( cdrom->scsi == NULL ) {
1.164 + ERROR( "Failed to create SCSI interface" );
1.165 + cdrom_osx_destroy(disc);
1.166 + return NULL;
1.167 + }
1.168 +
1.169 + char name[sizeof(io_string_t) + 6] = "dvd://";
1.170 + IORegistryEntryGetPath( cdrom->entry, kIOServicePlane, name+6 );
1.171 + disc->name = g_strdup(name);
1.172 +
1.173 + disc->close = cdrom_osx_destroy;
1.174 + return disc;
1.175 +}
1.176 +
1.177 +gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, void *ptr )
1.178 +{
1.179 + GList **list = (GList **)ptr;
1.180 + char tmp1[sizeof(io_string_t) + 6] = "dvd://";
1.181 + char tmp2[512];
1.182 + IORegistryEntryGetPath( object, kIOServicePlane, tmp1+6 );
1.183 + snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product );
1.184 + *list = g_list_append( *list, gdrom_device_new( tmp1, tmp2 ) );
1.185 + return FALSE;
1.186 +}
1.187 +
1.188 +GList *cdrom_get_native_devices(void)
1.189 +{
1.190 + GList *list = NULL;
1.191 + find_cdrom_device(cdrom_enum_callback, &list);
1.192 + return list;
1.193 +}
1.194 +
1.195 +gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )
1.196 +{
1.197 + io_object_t obj;
1.198 + gdrom_disc_t result = NULL;
1.199 +
1.200 + if( strncasecmp( path, "IOService:", 10 ) == 0 ) {
1.201 + obj = get_cdrom_by_service_path( path );
1.202 + }
1.203 +
1.204 + if( obj == MACH_PORT_NULL ) {
1.205 + return NULL;
1.206 + } else {
1.207 + return cdrom_osx_new( obj );
1.208 + }
1.209 +}
1.210 +
1.211 +
1.212 +
1.213 +static gboolean osx_image_is_valid( FILE *f )
1.214 +{
1.215 + return FALSE;
1.216 +}
1.217 +
1.218 +static gdrom_disc_t osx_open_device( const gchar *filename, FILE *f )
1.219 +{
1.220 + return NULL;
1.221 +}
.