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