nkeynes@709: /** nkeynes@709: * $Id$ nkeynes@709: * nkeynes@709: * OSX native cd-rom driver. nkeynes@709: * nkeynes@709: * Copyright (c) 2005 Nathan Keynes. nkeynes@709: * nkeynes@709: * This program is free software; you can redistribute it and/or modify nkeynes@709: * it under the terms of the GNU General Public License as published by nkeynes@709: * the Free Software Foundation; either version 2 of the License, or nkeynes@709: * (at your option) any later version. nkeynes@709: * nkeynes@709: * This program is distributed in the hope that it will be useful, nkeynes@709: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@709: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@709: * GNU General Public License for more details. nkeynes@709: */ nkeynes@709: nkeynes@709: #include nkeynes@720: #include nkeynes@709: #include nkeynes@720: #include nkeynes@720: #include nkeynes@720: #include nkeynes@720: #include nkeynes@709: #include nkeynes@720: #include nkeynes@720: #include nkeynes@709: #include "gdrom/gddriver.h" nkeynes@720: #include "gdrom/packet.h" nkeynes@720: #include "drivers/osx_iokit.h" nkeynes@709: nkeynes@720: #define MAXTOCENTRIES 600 /* This is a fairly generous overestimate really */ nkeynes@720: #define MAXTOCSIZE 4 + (MAXTOCENTRIES*11) nkeynes@720: nkeynes@720: static gboolean cdrom_osx_image_is_valid( FILE *f ); nkeynes@720: static gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f ); nkeynes@720: static gdrom_error_t cdrom_osx_read_toc( gdrom_image_t disc ); nkeynes@720: static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t sector, nkeynes@736: int mode, unsigned char *buf, uint32_t *length ); nkeynes@709: nkeynes@709: struct gdrom_image_class cdrom_device_class = { "osx", NULL, nkeynes@736: cdrom_osx_image_is_valid, cdrom_osx_open_device }; nkeynes@709: nkeynes@720: #define OSX_DRIVE(disc) ( (osx_cdrom_drive_t)(((gdrom_image_t)disc)->private) ) nkeynes@709: nkeynes@720: static void cdrom_osx_destroy( gdrom_disc_t disc ) nkeynes@709: { nkeynes@720: osx_cdrom_close_drive( OSX_DRIVE(disc) ); nkeynes@720: gdrom_image_destroy_no_close( disc ); nkeynes@709: } nkeynes@709: nkeynes@720: static void cdrom_osx_media_changed( osx_cdrom_drive_t drive, gboolean present, nkeynes@720: void *user_data ) nkeynes@709: { nkeynes@720: gdrom_image_t image = (gdrom_image_t)user_data; nkeynes@720: if( present ) { nkeynes@720: cdrom_osx_read_toc( image ); nkeynes@720: } else { nkeynes@720: image->disc_type = IDE_DISC_NONE; nkeynes@720: image->track_count = 0; nkeynes@709: } nkeynes@709: } nkeynes@709: nkeynes@720: nkeynes@720: static gdrom_disc_t cdrom_osx_new( const char *name, osx_cdrom_drive_t drive ) nkeynes@709: { nkeynes@720: char tmp[strlen(name)+7]; nkeynes@720: sprintf( tmp, "dvd://%s", name ); nkeynes@720: gdrom_image_t image = (gdrom_image_t)gdrom_image_new(tmp, NULL); nkeynes@720: image->private = drive; nkeynes@736: nkeynes@720: image->disc.read_sector = cdrom_osx_read_sector; nkeynes@720: image->disc.close = cdrom_osx_destroy; nkeynes@720: cdrom_osx_read_toc(image); nkeynes@720: osx_cdrom_set_media_changed_callback( drive, cdrom_osx_media_changed, image ); nkeynes@720: return (gdrom_disc_t)image; nkeynes@709: } nkeynes@709: nkeynes@720: gdrom_disc_t cdrom_open_device( const gchar *method, const gchar *path ) nkeynes@709: { nkeynes@720: gdrom_disc_t result = NULL; nkeynes@736: nkeynes@720: osx_cdrom_drive_t drive = osx_cdrom_open_drive(path); nkeynes@720: if( drive == NULL ) { nkeynes@709: return NULL; nkeynes@720: } else { nkeynes@720: return cdrom_osx_new( path, drive ); nkeynes@709: } nkeynes@709: } nkeynes@709: nkeynes@720: nkeynes@720: nkeynes@720: static gboolean cdrom_enum_callback( io_object_t object, char *vendor, char *product, char *iopath, void *ptr ) nkeynes@709: { nkeynes@709: GList **list = (GList **)ptr; nkeynes@720: char tmp1[sizeof(io_string_t) + 6]; nkeynes@709: char tmp2[512]; nkeynes@720: snprintf( tmp1, sizeof(tmp1), "dvd://%s", iopath ); nkeynes@709: snprintf( tmp2, sizeof(tmp2), "%s %s", vendor, product ); nkeynes@709: *list = g_list_append( *list, gdrom_device_new( tmp1, tmp2 ) ); nkeynes@709: return FALSE; nkeynes@709: } nkeynes@709: nkeynes@709: GList *cdrom_get_native_devices(void) nkeynes@709: { nkeynes@709: GList *list = NULL; nkeynes@720: find_cdrom_drive(cdrom_enum_callback, &list); nkeynes@736: nkeynes@720: osx_register_iokit_notifications(); nkeynes@709: return list; nkeynes@709: } nkeynes@709: nkeynes@709: nkeynes@709: nkeynes@720: static gboolean cdrom_osx_image_is_valid( FILE *f ) nkeynes@709: { nkeynes@709: return FALSE; nkeynes@709: } nkeynes@709: nkeynes@720: static gdrom_disc_t cdrom_osx_open_device( const gchar *filename, FILE *f ) nkeynes@709: { nkeynes@709: return NULL; nkeynes@709: } nkeynes@720: nkeynes@720: static gdrom_error_t cdrom_osx_read_toc( gdrom_image_t image ) nkeynes@720: { nkeynes@720: osx_cdrom_drive_t drive = OSX_DRIVE(image); nkeynes@736: nkeynes@720: int fh = osx_cdrom_get_media_handle(drive); nkeynes@720: if( fh == -1 ) { nkeynes@720: image->disc_type = IDE_DISC_NONE; nkeynes@720: image->track_count = 0; nkeynes@720: return -1; nkeynes@720: } else { nkeynes@720: unsigned char buf[MAXTOCSIZE]; nkeynes@720: dk_cd_read_toc_t readtoc; nkeynes@720: memset( &readtoc, 0, sizeof(readtoc) ); nkeynes@720: readtoc.format = 2; nkeynes@720: readtoc.formatAsTime = 0; nkeynes@720: readtoc.address.session = 0; nkeynes@720: readtoc.bufferLength = sizeof(buf); nkeynes@720: readtoc.buffer = buf; nkeynes@736: nkeynes@720: if( ioctl(fh, DKIOCCDREADTOC, &readtoc ) == -1 ) { nkeynes@720: image->disc_type = IDE_DISC_NONE; nkeynes@720: image->track_count = 0; nkeynes@720: return -1; nkeynes@720: } else { nkeynes@720: mmc_parse_toc2( image, buf ); nkeynes@720: } nkeynes@720: } nkeynes@720: return 0; nkeynes@720: } nkeynes@720: nkeynes@720: static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t sector, nkeynes@736: int mode, unsigned char *buf, uint32_t *length ) nkeynes@720: { nkeynes@720: osx_cdrom_drive_t drive = OSX_DRIVE(disc); nkeynes@720: int fh = osx_cdrom_get_media_handle(drive); nkeynes@720: if( fh == -1 ) { nkeynes@720: return PKT_ERR_NODISC; nkeynes@720: } else { nkeynes@720: dk_cd_read_t readcd; nkeynes@720: nkeynes@720: memset( &readcd, 0, sizeof(readcd) ); nkeynes@720: // This is complicated by needing to know the exact read size. Gah. nkeynes@720: if( READ_CD_RAW(mode) ) { nkeynes@720: *length = 2352; nkeynes@720: readcd.sectorArea = 0xF8; nkeynes@720: } else { nkeynes@720: // This is incomplete... nkeynes@720: if( READ_CD_DATA(mode) ) { nkeynes@720: readcd.sectorArea = kCDSectorAreaUser; nkeynes@720: switch( READ_CD_MODE(mode) ) { nkeynes@720: case READ_CD_MODE_CDDA: nkeynes@720: *length = 2352; nkeynes@720: break; nkeynes@720: case READ_CD_MODE_1: nkeynes@720: case READ_CD_MODE_2_FORM_1: nkeynes@720: *length = 2048; nkeynes@720: break; nkeynes@720: case READ_CD_MODE_2: nkeynes@720: *length = 2336; nkeynes@720: break; nkeynes@720: case READ_CD_MODE_2_FORM_2: nkeynes@720: *length = 2324; nkeynes@720: break; nkeynes@720: } nkeynes@720: } nkeynes@720: } nkeynes@736: nkeynes@720: readcd.offset = *length * (sector - 150); nkeynes@720: readcd.sectorType = READ_CD_MODE(mode)>>1; nkeynes@720: readcd.bufferLength = *length; nkeynes@720: readcd.buffer = buf; nkeynes@720: if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) { nkeynes@720: return -1; nkeynes@720: } else { nkeynes@720: return 0; nkeynes@720: } nkeynes@720: } nkeynes@720: } nkeynes@720: