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 1298:d0eb2307b847
prev1168:66e5113d4155
author nkeynes
date Wed Feb 04 08:38:23 2015 +1000 (5 years ago)
permissions -rw-r--r--
last change Fix assorted compile warnings reported by Clang
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_read_toc( cdrom_disc_t disc, ERROR *err );
    37 static cdrom_error_t cdrom_osx_read_sectors( sector_source_t disc, cdrom_lba_t sector, cdrom_count_t count,
    38                                              cdrom_read_mode_t mode, unsigned char *buf, size_t *length );
    40 /* Note: We don't support opening OS X devices by filename, so no disc factory */
    42 #define OSX_DRIVE(disc) ( (osx_cdrom_drive_t)(((cdrom_disc_t)disc)->impl_data) )
    44 static void cdrom_osx_destroy( sector_source_t disc )
    45 {
    46     osx_cdrom_close_drive( OSX_DRIVE(disc) );
    47     default_cdrom_disc_destroy( disc );
    48 }
    50 static void cdrom_osx_media_changed( osx_cdrom_drive_t drive, gboolean present,
    51                                      void *user_data )
    52 {
    53     cdrom_disc_t disc = (cdrom_disc_t)user_data;
    54     if( present ) {
    55         cdrom_osx_read_toc( disc, NULL );
    56     } else {
    57         disc->disc_type = CDROM_DISC_NONE;
    58         disc->track_count = 0;        
    59     }
    60 }
    63 static cdrom_disc_t cdrom_osx_new( const char *name, osx_cdrom_drive_t drive, ERROR *err )
    64 {
    65     cdrom_disc_t disc = cdrom_disc_new(name, err);
    66     disc->impl_data = drive;
    68     disc->source.read_sectors = cdrom_osx_read_sectors;
    69     disc->source.destroy = cdrom_osx_destroy;
    70     disc->read_toc = cdrom_osx_read_toc;
    71     cdrom_disc_read_toc(disc, err);
    72     osx_cdrom_set_media_changed_callback( drive, cdrom_osx_media_changed, disc );
    73     return (cdrom_disc_t)disc;
    74 }
    76 static cdrom_disc_t cdrom_osx_open( cdrom_drive_t drive, ERROR *err )
    77 {
    78     osx_cdrom_drive_t osx_drive = osx_cdrom_open_drive(drive->name);
    79     if( osx_drive == NULL ) {
    80         SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open CDROM drive" );
    81         return NULL;
    82     } else {
    83         return cdrom_osx_new( drive->name, osx_drive, err );
    84     }
    85 }
    89 static gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, char *iopath, void *ptr )
    90 {
    91     char tmp1[sizeof(io_string_t) + 6];
    92     char tmp2[512];
    93     snprintf( tmp1, sizeof(tmp1), "dvd://%s", iopath );
    94     snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product );
    95     cdrom_drive_add( iopath, tmp2, cdrom_osx_open );
    96     return FALSE;
    97 }
    99 void cdrom_drive_scan(void)
   100 {
   101     find_cdrom_drive(cdrom_enum_callback, NULL);
   102     osx_register_iokit_notifications();
   103 }
   105 static gboolean cdrom_osx_read_toc( cdrom_disc_t disc, ERROR *err )
   106 {
   107     osx_cdrom_drive_t drive = OSX_DRIVE(disc);
   109     int fh = osx_cdrom_get_media_handle(drive);
   110     if( fh == -1 ) {
   111         disc->disc_type = CDROM_DISC_NONE;
   112         disc->track_count = 0;
   113         return FALSE;
   114     } else {
   115         unsigned char buf[MAXTOCSIZE];
   116         dk_cd_read_toc_t readtoc;
   117         memset( &readtoc, 0, sizeof(readtoc) );
   118         readtoc.format = 2;
   119         readtoc.formatAsTime = 0;
   120         readtoc.address.session = 0;
   121         readtoc.bufferLength = sizeof(buf);
   122         readtoc.buffer = buf;
   124         if( ioctl(fh, DKIOCCDREADTOC, &readtoc ) == -1 ) {
   125             WARN( "Failed to read TOC (%s)", strerror(errno) );
   126             disc->disc_type = CDROM_DISC_NONE;
   127             disc->track_count = 0;
   128             return FALSE;
   129         } else {
   130             mmc_parse_toc2( disc, buf );
   131         }
   132     }
   133     return TRUE;
   134 }
   136 static cdrom_error_t cdrom_osx_read_sectors( sector_source_t source, cdrom_lba_t lba, cdrom_count_t count,
   137                                             cdrom_read_mode_t mode, unsigned char *buf, size_t *length )
   138 {
   139     cdrom_disc_t disc = (cdrom_disc_t)source;
   140     int sector_size = 2352;
   141     unsigned char data[CDROM_MAX_SECTOR_SIZE];
   142     osx_cdrom_drive_t drive = OSX_DRIVE(disc);
   144     int fh = osx_cdrom_get_media_handle(drive);
   145     if( fh == -1 ) {
   146         return CDROM_ERROR_NODISC;
   147     } else {
   148         dk_cd_read_t readcd;
   149         memset( &readcd, 0, sizeof(readcd) );
   150         readcd.buffer = buf;
   151         readcd.sectorType = CDROM_READ_TYPE(mode) >> 2;
   153         cdrom_track_t track = cdrom_disc_get_track_by_lba(disc,lba);
   154         if( track == NULL ) {
   155             return CDROM_ERROR_BADREAD;
   156         }
   158         /* This is complicated by needing to know the exact read size. Gah.
   159          * For now, anything other than a data-only read of known size is
   160          * executed by a raw read + extraction.
   161          */
   162         if( (CDROM_READ_FIELDS(mode) == CDROM_READ_DATA && CDROM_READ_TYPE(mode) != CDROM_READ_ANY) ||
   163             ((track->flags & TRACK_FLAG_DATA) == 0 && CDROM_READ_FIELDS(mode) != CDROM_READ_NONE) ) {
   164             switch( CDROM_READ_TYPE(mode) ) {
   165             case CDROM_READ_ANY:
   166             case CDROM_READ_CDDA:
   167                 sector_size = 2352;
   168                 break;
   169             case CDROM_READ_MODE1:
   170             case CDROM_READ_MODE2_FORM1:
   171                 sector_size = 2048;
   172                 break;
   173             case CDROM_READ_MODE2:
   174                 sector_size = 2336;
   175                 break;
   176             case CDROM_READ_MODE2_FORM2:
   177                 sector_size = 2324;
   178                 break;
   179             }
   180             readcd.sectorArea = kCDSectorAreaUser;
   181             readcd.offset = sector_size * lba;
   182             readcd.bufferLength = sector_size * count;
   183             if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {
   184                 return CDROM_ERROR_BADREAD;
   185             }
   186             *length = sector_size * count;
   187         } else {
   188             /* Sector could be anything - need to do a raw read and then parse
   189              * the requested data out ourselves
   190              */
   191             sector_size = 2352;
   192             size_t tmplen, len = 0;
   194             readcd.offset = sector_size * lba;
   195             readcd.sectorArea = 0xf8;
   196             readcd.buffer = data;
   197             readcd.bufferLength = sector_size;
   198             while( count > 0 ) {
   199                 if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {
   200                     return CDROM_ERROR_BADREAD;
   201                 }
   202                 cdrom_error_t err = sector_extract_from_raw( data, mode, &buf[len], &tmplen );
   203                 if( err != CDROM_ERROR_OK )
   204                     return err;
   205                 len += tmplen;
   206                 readcd.offset += sector_size;
   207             }
   208             *length = len;
   209         }
   211         return CDROM_ERROR_OK;
   212     }
   213 }
.