filename | src/drivers/cd_osx.c |
changeset | 720:b5594d1ac80a |
prev | 709:18c39a8e504c |
next | 736:a02d1475ccfd |
author | nkeynes |
date | Sat Jul 05 11:57:36 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Get OS X cdrom driver to the 'sort of working' stage. Hide most of the IOKit fun in a separate osx_iokit module. |
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 ERROR( "Failed to read TOC: %s", strerror(errno) );
147 image->disc_type = IDE_DISC_NONE;
148 image->track_count = 0;
149 return -1;
150 } else {
151 mmc_parse_toc2( image, buf );
152 }
153 }
154 return 0;
155 }
157 static gdrom_error_t cdrom_osx_read_sector( gdrom_disc_t disc, uint32_t sector,
158 int mode, unsigned char *buf, uint32_t *length )
159 {
160 osx_cdrom_drive_t drive = OSX_DRIVE(disc);
161 int fh = osx_cdrom_get_media_handle(drive);
162 if( fh == -1 ) {
163 return PKT_ERR_NODISC;
164 } else {
165 dk_cd_read_t readcd;
167 memset( &readcd, 0, sizeof(readcd) );
168 // This is complicated by needing to know the exact read size. Gah.
169 if( READ_CD_RAW(mode) ) {
170 *length = 2352;
171 readcd.sectorArea = 0xF8;
172 } else {
173 // This is incomplete...
174 if( READ_CD_DATA(mode) ) {
175 readcd.sectorArea = kCDSectorAreaUser;
176 switch( READ_CD_MODE(mode) ) {
177 case READ_CD_MODE_CDDA:
178 *length = 2352;
179 break;
180 case READ_CD_MODE_1:
181 case READ_CD_MODE_2_FORM_1:
182 *length = 2048;
183 break;
184 case READ_CD_MODE_2:
185 *length = 2336;
186 break;
187 case READ_CD_MODE_2_FORM_2:
188 *length = 2324;
189 break;
190 }
191 }
192 }
194 readcd.offset = *length * (sector - 150);
195 readcd.sectorType = READ_CD_MODE(mode)>>1;
196 readcd.bufferLength = *length;
197 readcd.buffer = buf;
198 if( ioctl( fh, DKIOCCDREAD, &readcd ) == -1 ) {
199 ERROR( "Failed to read CD: %s", strerror(errno) );
200 return -1;
201 } else {
202 return 0;
203 }
204 }
205 }
.