filename | src/drivers/cdrom/cd_osx.c |
changeset | 1109:700c5ab26a63 |
prev | 1097:d4807997e450 |
next | 1168:66e5113d4155 |
author | nkeynes |
date | Thu Jun 10 22:13:16 2010 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Integrate executable wrapping into the user interface - command-line now loads wrapped by default, -e <bin> to run binary - add support for .bin executables - Add useful (internal) error codes |
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);
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 }
.