$NetBSD: patch-cn,v 1.3 2023/08/16 01:01:35 gutteridge Exp $ Interface for MacOS. --- /dev/null 2006-09-03 09:28:05.000000000 -0700 +++ interface/osx_interface.c 2006-09-03 09:35:39.000000000 -0700 @@ -0,0 +1,267 @@ +/****************************************************************** + * CopyPolicy: GNU Public License 2 applies + * Copyright (C) 1998 Monty xiphmont@mit.edu + ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "osx_interface.h" +#include "utils.h" + +char *osx_bsd_device_for_media(io_object_t media) +{ + char buf[PATH_MAX]; + size_t dev_path_length; + CFTypeRef str_bsd_path; + char *result; + + str_bsd_path = IORegistryEntryCreateCFProperty(media, + CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0); + + if(str_bsd_path == NULL) { + return NULL; + } + + snprintf(buf, sizeof(buf), "%s%c", _PATH_DEV, 'r' ); + dev_path_length = strlen(buf); + + if (CFStringGetCString(str_bsd_path, + buf + dev_path_length, + sizeof(buf) - dev_path_length, + kCFStringEncodingASCII)) { + result = strdup(buf); + } else { + result = NULL; + } + CFRelease(str_bsd_path); + return result; +} + +int osx_enumerate_devices(cdrom_drive *d, + int (*device_found)(cdrom_drive *, io_object_t, void *), + void *data) +{ + kern_return_t ret; + mach_port_t port; + int drives = 0; + CFMutableDictionaryRef classes_to_match; + kern_return_t kern_result; + io_iterator_t media_iterator; + io_object_t next_media; + + /* get port for IOKit communication */ + if ((ret = IOMasterPort(MACH_PORT_NULL, &port)) != KERN_SUCCESS) { + cderror(d,"099: IOMasterPort fail\n"); + return -1; + } + + classes_to_match = IOServiceMatching(kIOCDMediaClass); + if(classes_to_match == NULL) { + cderror(d,"099: IOServiceMatching: NULL\n"); + return -1; + } + + CFDictionarySetValue(classes_to_match, CFSTR(kIOMediaEjectableKey), + kCFBooleanTrue); + + kern_result = IOServiceGetMatchingServices(port, classes_to_match, + &media_iterator); + if (kern_result != KERN_SUCCESS) { + cderror(d,"099: IOServiceGetMatchingServices fail\n"); + return -1; + } + + while (1) { + drives++; + next_media = IOIteratorNext(media_iterator); + if (next_media == 0) { + break; + } + + if (!device_found(d, next_media, data)) + break; + IOObjectRelease(next_media); + } + if (next_media) IOObjectRelease(next_media); + IOObjectRelease(media_iterator); + + return drives; +} + +static int find_first_device(cdrom_drive *d, io_object_t io, void *data) +{ + io_object_t *dev = (io_object_t *)data; + *dev = io; + IOObjectRetain(io); + return 0; +} + +io_object_t osx_default_device(cdrom_drive *d) +{ + io_object_t io; + osx_enumerate_devices(d, find_first_device, (void *)&io); + return io; +} + +int osx_read_toc(cdrom_drive *d) +{ + kern_return_t ret; + char *devname; + CFRange range; + CFIndex buf_len; + int leadout; + CFMutableDictionaryRef properties; + CFDataRef data; + int i; + + devname = strrchr(d->dev, '/'); + + if (devname != NULL) { + devname++; + } else { + devname = d->dev; + } + + if (*devname == 'r') devname++; + + /* create a CF dictionary containing the TOC */ + ret = IORegistryEntryCreateCFProperties(d->io, &properties, + kCFAllocatorDefault, kNilOptions); + + if( ret != KERN_SUCCESS) { + cderror(d, "099: IORegistryEntryCreateCFProperties fail\n"); + return -1; + } + + /* get the TOC from the dictionary */ + data = (CFDataRef)CFDictionaryGetValue(properties, + CFSTR(kIOCDMediaTOCKey)); + if(data == NULL) { + cderror(d, "099: CFDictionaryGetValue fail\n"); + return -1; + } + + buf_len = CFDataGetLength(data); + range = CFRangeMake(0, buf_len); + + d->raw_toc = (CDTOC *)malloc(buf_len); + if (d->raw_toc == NULL) { + cderror(d, "099: toc malloc fail\n"); + CFRelease(properties); + return -1; + } + CFDataGetBytes(data, range, (u_char *)d->raw_toc); + + CFRelease(properties); + + d->descriptor_count = CDTOCGetDescriptorCount(d->raw_toc); + d->tracks = 0; + + for (i = 0; i < d->descriptor_count; i++) { + int track_num = d->raw_toc->descriptors[i].point; + CDMSF msf = d->raw_toc->descriptors[i].p; + int start_sector = CDConvertMSFToLBA(msf); + if (track_num == 0xa2) { + leadout = i; + } + fprintf(stderr, + "track_num = %d start sector %d msf: %d,%d,%d\n", + track_num, start_sector, + msf.minute, msf.second, msf.frame); + if (track_num > 99 || track_num < 1) { + // e.g.: + // track_num = 160 start sector 4350 msf: 1,0,0 + // track_num = 161 start sector 67350 msf: 15,0,0 + // track_num = 162 start sector 330645 msf: 73,30,45 + + continue; + // XXX don't know what happens here. tracks 0xa0, 0xa1, 0xa2 (leadout) + } + d->disc_toc[d->tracks].bTrack = track_num; + d->disc_toc[d->tracks].bFlags = (d->raw_toc->descriptors[i].adr << 4) | + d->raw_toc->descriptors[i].control; + d->disc_toc[d->tracks].dwStartSector = start_sector; + d->tracks++; + } + d->disc_toc[d->tracks].bTrack = 0xaa; + d->disc_toc[d->tracks].bFlags = (d->raw_toc->descriptors[i].adr << 4) | + d->raw_toc->descriptors[leadout].control; + d->disc_toc[d->tracks].dwStartSector = CDConvertMSFToLBA( + d->raw_toc->descriptors[leadout].p); + + return 0; +} + +int osx_open_device_orig(cdrom_drive *d, io_object_t io) +{ + if (io == NULL) { + d->io = osx_default_device(d); + } else { + IOObjectRetain(io); + d->io = io; + } + d->dev = osx_bsd_device_for_media(d->io); + if (!d->dev) { + IOObjectRelease(d->io); + return -1; + } + + d->fd = open(d->dev, O_RDONLY | O_NONBLOCK, 0); + d->enable_cdda = osx_enable_cdda; + d->read_toc = osx_read_toc; + d->read_audio = osx_read_audio; + d->set_speed = osx_set_speed; + + if (d->fd == -1) { + free(d->dev); + IOObjectRelease(d->io); + return -1; + } + + osx_read_toc(d); + + d->nsectors = 32; + d->opened = 1; + return 0; +} + +int osx_open_device(cdrom_drive *d) +{ + osx_open_device_orig(d, NULL); +} + +int osx_set_speed(cdrom_drive *d, int speed) +{ + return 0; +} + +int osx_enable_cdda(cdrom_drive *d, int enable) +{ + return 0; +} + +long osx_read_audio(cdrom_drive *d, void *buf, long begin, long sectors) +{ + dk_cd_read_t cd_read; + + // fprintf(stderr, "read_audio %p, %d, %d\n", buf, begin, sectors); + + memset(&cd_read, 0, sizeof(cd_read)); + + cd_read.offset = begin * kCDSectorSizeCDDA; + cd_read.sectorArea = kCDSectorAreaUser; + cd_read.sectorType = kCDSectorTypeCDDA; + + cd_read.buffer = buf; + cd_read.bufferLength = kCDSectorSizeCDDA * sectors; + + if( ioctl(d->fd, DKIOCCDREAD, &cd_read) == -1) { + return 0; + } + return cd_read.bufferLength / kCDSectorSizeCDDA; +}