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 786:8f6ece92500e
prev782:1af8b5ce627c
next1023:264e2fd90be8
author nkeynes
date Tue Oct 14 08:44:37 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Fix a few more subtle flag problems
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 "gdrom/gddriver.h"
    30 #include "gdrom/packet.h"
    31 #include "drivers/osx_iokit.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 gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f );
    38 static gdrom_error_t cdrom_osx_read_toc( gdrom_image_t disc );
    39 static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t sector,
    40                                             int mode, unsigned char *buf, uint32_t *length );
    42 struct gdrom_image_class cdrom_device_class = { "osx", NULL,
    43         cdrom_osx_image_is_valid, cdrom_osx_open_device };
    45 #define OSX_DRIVE(disc) ( (osx_cdrom_drive_t)(((gdrom_image_t)disc)->private) )
    47 static void cdrom_osx_destroy( gdrom_disc_t disc )
    48 {
    49     osx_cdrom_close_drive( OSX_DRIVE(disc) );
    50     gdrom_image_destroy_no_close( disc );
    51 }
    53 static void cdrom_osx_media_changed( osx_cdrom_drive_t drive, gboolean present,
    54                                      void *user_data )
    55 {
    56     gdrom_image_t image = (gdrom_image_t)user_data;
    57     if( present ) {
    58         cdrom_osx_read_toc( image );
    59     } else {
    60         image->disc_type = IDE_DISC_NONE;
    61         image->track_count = 0;        
    62     }
    63 }
    66 static gdrom_disc_t cdrom_osx_new( const char *name, osx_cdrom_drive_t drive )
    67 {
    68     char tmp[strlen(name)+7];
    69     sprintf( tmp, "dvd://%s", name );
    70     gdrom_image_t image = (gdrom_image_t)gdrom_image_new(tmp, NULL);
    71     image->private = drive;
    73     image->disc.read_sector = cdrom_osx_read_sector;
    74     image->disc.close = cdrom_osx_destroy;
    75     cdrom_osx_read_toc(image);
    76     osx_cdrom_set_media_changed_callback( drive, cdrom_osx_media_changed, image );
    77     return (gdrom_disc_t)image;
    78 }
    80 gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path )
    81 {
    82     gdrom_disc_t result = NULL;
    84     osx_cdrom_drive_t drive = osx_cdrom_open_drive(path);
    85     if( drive == NULL ) {
    86         return NULL;
    87     } else {
    88         return cdrom_osx_new( path, drive );
    89     }
    90 }
    94 static gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, char *iopath, void *ptr )
    95 {
    96     GList **list = (GList **)ptr;
    97     char tmp1[sizeof(io_string_t) + 6];
    98     char tmp2[512];
    99     snprintf( tmp1, sizeof(tmp1), "dvd://%s", iopath );
   100     snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product );
   101     *list = g_list_append( *list, gdrom_device_new( tmp1, tmp2 ) );
   102     return FALSE;
   103 }
   105 GList *cdrom_get_native_devices(void)
   106 {
   107     GList *list = NULL;
   108     find_cdrom_drive(cdrom_enum_callback, &list);
   110     osx_register_iokit_notifications();
   111     return list;
   112 }
   116 static gboolean cdrom_osx_image_is_valid( FILE *f )
   117 {
   118     return FALSE;
   119 }
   121 static gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f )
   122 {
   123     return NULL;
   124 }
   126 static gdrom_error_t cdrom_osx_read_toc( gdrom_image_t image )
   127 {
   128     osx_cdrom_drive_t drive = OSX_DRIVE(image);
   130     int fh = osx_cdrom_get_media_handle(drive);
   131     if( fh == -1 ) {
   132         image->disc_type = IDE_DISC_NONE;
   133         image->track_count = 0;
   134         return -1;
   135     } else {
   136         unsigned char buf[MAXTOCSIZE];
   137         dk_cd_read_toc_t readtoc;
   138         memset( &readtoc, 0, sizeof(readtoc) );
   139         readtoc.format = 2;
   140         readtoc.formatAsTime = 0;
   141         readtoc.address.session = 0;
   142         readtoc.bufferLength = sizeof(buf);
   143         readtoc.buffer = buf;
   145         if( ioctl(fh, DKIOCCDREADTOC, &readtoc ) == -1 ) {
   146             image->disc_type = IDE_DISC_NONE;
   147             image->track_count = 0;
   148             return -1;
   149         } else {
   150             mmc_parse_toc2( image, buf );
   151         }
   152     }
   153     return 0;
   154 }
   156 static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t lba,
   157                                             int mode, unsigned char *buf, uint32_t *length ) 
   158 {
   159     gdrom_image_t image = (gdrom_image_t)disc;
   160     int real_lba = lba - 150;
   161     int sector_size = 2352;
   162     int direct_read = 1;
   163     char data[MAX_SECTOR_SIZE];
   164     osx_cdrom_drive_t drive = OSX_DRIVE(disc);
   166     int fh = osx_cdrom_get_media_handle(drive);
   167     if( fh == -1 ) {
   168         return PKT_ERR_NODISC;
   169     } else {
   170         dk_cd_read_t readcd;
   171         memset( &readcd, 0, sizeof(readcd) );
   172         readcd.buffer = buf;
   174         // This is complicated by needing to know the exact read size. Gah.
   175         if( READ_CD_RAW(mode) ) {
   176             sector_size = 2352;
   177             readcd.sectorArea = 0xF8; 
   178         } else if ( READ_CD_MODE(mode) == READ_CD_MODE_ANY ) {
   179             /* Sector could be anything - need to do a raw read and then parse
   180              * the requested data out ourselves
   181              */
   182             int track_no = gdrom_image_get_track_by_lba( image, lba );
   183             struct gdrom_track *track = &image->track[track_no-1];
   185             sector_size = 2352;
   186             if( track->mode == GDROM_CDDA ) {
   187                 readcd.sectorArea = kCDSectorAreaUser;
   188             } else {
   189                 readcd.sectorArea = 0xF8;
   190                 readcd.buffer = data;
   191                 direct_read = 0;
   192             }
   193         } else {
   194             // This is incomplete...
   195             if( READ_CD_DATA(mode) ) {
   196                 readcd.sectorArea = kCDSectorAreaUser;
   197                 switch( READ_CD_MODE(mode) ) {
   198                 case READ_CD_MODE_CDDA:
   199                     sector_size = 2352;
   200                     break;
   201                 case READ_CD_MODE_1:
   202                 case READ_CD_MODE_2_FORM_1:
   203                     sector_size = 2048;
   204                     break;
   205                 case READ_CD_MODE_2:
   206                     sector_size = 2336;
   207                     break;
   208                 case READ_CD_MODE_2_FORM_2:
   209                     sector_size = 2324;
   210                     break;
   211                 }
   212             }
   213         }
   215         readcd.offset = sector_size * real_lba;
   216         readcd.sectorType = READ_CD_MODE(mode)>>1;
   217         readcd.bufferLength = sector_size;
   218         if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {
   219             return -1;
   220         }
   222         if( direct_read ) {
   223             *length = sector_size;
   224         } else {
   225             gdrom_extract_raw_data_sector( data, mode, buf, length );
   226         }
   227         return 0;
   228     }
   229 }
.