Search
lxdream.org :: lxdream/src/drivers/cdrom/cd_osx.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/cdrom/cd_osx.c
changeset 1168:66e5113d4155
prev1109:700c5ab26a63
next1298:d0eb2307b847
author nkeynes
date Thu Feb 23 14:59:58 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change mem_stream_class should be static (to avoid potential conflicts with the
real one)
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/IOBSD.h>
    21 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
    22 #include <IOKit/storage/IOCDMediaBSDClient.h>
    23 #include <IOKit/storage/IOCDTypes.h>
    24 #include <sys/param.h>
    25 #include <errno.h>
    26 #include <stdio.h>
    27 #include <string.h>
    28 #include <paths.h>
    29 #include "drivers/osx_iokit.h"
    30 #include "drivers/cdrom/cdimpl.h"
    31 #include "drivers/cdrom/drive.h"
    33 #define MAXTOCENTRIES 600  /* This is a fairly generous overestimate really */
    34 #define MAXTOCSIZE 4 + (MAXTOCENTRIES*11)
    36 static gboolean cdrom_osx_image_is_valid( FILE *f );
    37 static cdrom_disc_t cdrom_osx_open_file( FILE *f, const gchar *filename, ERROR *err );
    38 static gboolean cdrom_osx_read_toc( cdrom_disc_t disc, ERROR *err );
    39 static cdrom_error_t cdrom_osx_read_sectors( sector_source_t disc, cdrom_lba_t sector, cdrom_count_t count,
    40                                              cdrom_read_mode_t mode, unsigned char *buf, size_t *length );
    42 /* Note: We don't support opening OS X devices by filename, so no disc factory */
    44 #define OSX_DRIVE(disc) ( (osx_cdrom_drive_t)(((cdrom_disc_t)disc)->impl_data) )
    46 static void cdrom_osx_destroy( sector_source_t disc )
    47 {
    48     osx_cdrom_close_drive( OSX_DRIVE(disc) );
    49     default_cdrom_disc_destroy( disc );
    50 }
    52 static void cdrom_osx_media_changed( osx_cdrom_drive_t drive, gboolean present,
    53                                      void *user_data )
    54 {
    55     cdrom_disc_t disc = (cdrom_disc_t)user_data;
    56     if( present ) {
    57         cdrom_osx_read_toc( disc, NULL );
    58     } else {
    59         disc->disc_type = CDROM_DISC_NONE;
    60         disc->track_count = 0;        
    61     }
    62 }
    65 static cdrom_disc_t cdrom_osx_new( const char *name, osx_cdrom_drive_t drive, ERROR *err )
    66 {
    67     cdrom_disc_t disc = cdrom_disc_new(name, err);
    68     disc->impl_data = drive;
    70     disc->source.read_sectors = cdrom_osx_read_sectors;
    71     disc->source.destroy = cdrom_osx_destroy;
    72     disc->read_toc = cdrom_osx_read_toc;
    73     cdrom_disc_read_toc(disc, err);
    74     osx_cdrom_set_media_changed_callback( drive, cdrom_osx_media_changed, disc );
    75     return (cdrom_disc_t)disc;
    76 }
    78 static cdrom_disc_t cdrom_osx_open( cdrom_drive_t drive, ERROR *err )
    79 {
    80     cdrom_disc_t result = NULL;
    82     osx_cdrom_drive_t osx_drive = osx_cdrom_open_drive(drive->name);
    83     if( osx_drive == NULL ) {
    84         SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open CDROM drive" );
    85         return NULL;
    86     } else {
    87         return cdrom_osx_new( drive->name, osx_drive, err );
    88     }
    89 }
    93 static gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, char *iopath, void *ptr )
    94 {
    95     char tmp1[sizeof(io_string_t) + 6];
    96     char tmp2[512];
    97     snprintf( tmp1, sizeof(tmp1), "dvd://%s", iopath );
    98     snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product );
    99     cdrom_drive_add( iopath, tmp2, cdrom_osx_open );
   100     return FALSE;
   101 }
   103 void cdrom_drive_scan(void)
   104 {
   105     find_cdrom_drive(cdrom_enum_callback, NULL);
   106     osx_register_iokit_notifications();
   107 }
   109 static gboolean cdrom_osx_image_is_valid( FILE *f )
   110 {
   111     return FALSE;
   112 }
   114 static cdrom_disc_t cdrom_osx_open_file( FILE *f, const gchar *filename, ERROR *err )
   115 {
   116     return NULL; /* Not supported */
   117 }
   119 static gboolean cdrom_osx_read_toc( cdrom_disc_t disc, ERROR *err )
   120 {
   121     osx_cdrom_drive_t drive = OSX_DRIVE(disc);
   123     int fh = osx_cdrom_get_media_handle(drive);
   124     if( fh == -1 ) {
   125         disc->disc_type = CDROM_DISC_NONE;
   126         disc->track_count = 0;
   127         return FALSE;
   128     } else {
   129         unsigned char buf[MAXTOCSIZE];
   130         dk_cd_read_toc_t readtoc;
   131         memset( &readtoc, 0, sizeof(readtoc) );
   132         readtoc.format = 2;
   133         readtoc.formatAsTime = 0;
   134         readtoc.address.session = 0;
   135         readtoc.bufferLength = sizeof(buf);
   136         readtoc.buffer = buf;
   138         if( ioctl(fh, DKIOCCDREADTOC, &readtoc ) == -1 ) {
   139             WARN( "Failed to read TOC (%s)", strerror(errno) );
   140             disc->disc_type = CDROM_DISC_NONE;
   141             disc->track_count = 0;
   142             return FALSE;
   143         } else {
   144             mmc_parse_toc2( disc, buf );
   145         }
   146     }
   147     return TRUE;
   148 }
   150 static cdrom_error_t cdrom_osx_read_sectors( sector_source_t source, cdrom_lba_t lba, cdrom_count_t count,
   151                                             cdrom_read_mode_t mode, unsigned char *buf, size_t *length )
   152 {
   153     cdrom_disc_t disc = (cdrom_disc_t)source;
   154     int sector_size = 2352;
   155     char data[CDROM_MAX_SECTOR_SIZE];
   156     osx_cdrom_drive_t drive = OSX_DRIVE(disc);
   158     int fh = osx_cdrom_get_media_handle(drive);
   159     if( fh == -1 ) {
   160         return CDROM_ERROR_NODISC;
   161     } else {
   162         dk_cd_read_t readcd;
   163         memset( &readcd, 0, sizeof(readcd) );
   164         readcd.buffer = buf;
   165         readcd.sectorType = CDROM_READ_TYPE(mode) >> 2;
   167         cdrom_track_t track = cdrom_disc_get_track_by_lba(disc,lba);
   168         if( track == NULL ) {
   169             return CDROM_ERROR_BADREAD;
   170         }
   172         /* This is complicated by needing to know the exact read size. Gah.
   173          * For now, anything other than a data-only read of known size is
   174          * executed by a raw read + extraction.
   175          */
   176         if( (CDROM_READ_FIELDS(mode) == CDROM_READ_DATA && CDROM_READ_TYPE(mode) != CDROM_READ_ANY) ||
   177             ((track->flags & TRACK_FLAG_DATA) == 0 && CDROM_READ_FIELDS(mode) != CDROM_READ_NONE) ) {
   178             switch( CDROM_READ_TYPE(mode) ) {
   179             case CDROM_READ_ANY:
   180             case CDROM_READ_CDDA:
   181                 sector_size = 2352;
   182                 break;
   183             case CDROM_READ_MODE1:
   184             case CDROM_READ_MODE2_FORM1:
   185                 sector_size = 2048;
   186                 break;
   187             case CDROM_READ_MODE2:
   188                 sector_size = 2336;
   189                 break;
   190             case CDROM_READ_MODE2_FORM2:
   191                 sector_size = 2324;
   192                 break;
   193             }
   194             readcd.sectorArea = kCDSectorAreaUser;
   195             readcd.offset = sector_size * lba;
   196             readcd.bufferLength = sector_size * count;
   197             if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {
   198                 return CDROM_ERROR_BADREAD;
   199             }
   200             *length = sector_size * count;
   201         } else {
   202             /* Sector could be anything - need to do a raw read and then parse
   203              * the requested data out ourselves
   204              */
   205             sector_size = 2352;
   206             size_t tmplen, len = 0;
   208             readcd.offset = sector_size * lba;
   209             readcd.sectorArea = 0xf8;
   210             readcd.buffer = data;
   211             readcd.bufferLength = sector_size;
   212             while( count > 0 ) {
   213                 if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {
   214                     return CDROM_ERROR_BADREAD;
   215                 }
   216                 cdrom_error_t err = sector_extract_from_raw( data, mode, &buf[len], &tmplen );
   217                 if( err != CDROM_ERROR_OK )
   218                     return err;
   219                 len += tmplen;
   220                 readcd.offset += sector_size;
   221             }
   222             *length = len;
   223         }
   225         return CDROM_ERROR_OK;
   226     }
   227 }
.