2 * Copyright (c) 2010, Wei Mingzhi <whistler@openoffice.org>.
5 * Based on: Cdrom for Psemu Pro like Emulators
6 * By: linuzappz <linuzappz@hotmail.com>
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.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses>.
26 #include <IOKit/IOKitLib.h>
27 #include <IOKit/IOBSD.h>
28 #include <IOKit/storage/IOCDMedia.h>
29 #include <IOKit/storage/IODVDMedia.h>
30 #include <IOKit/storage/IOMedia.h>
31 #include <IOKit/storage/IOCDMediaBSDClient.h>
32 #include <CoreFoundation/CoreFoundation.h>
35 char cdDevice[4096] = "";
37 static int IsPsxDisc(const char *dev) {
39 char buf[CD_FRAMESIZE_RAW];
42 fd = open(dev, O_RDONLY, 0);
45 memset(&r, 0, sizeof(r));
47 r.offset = msf_to_lba(0, 2, 4) * CD_FRAMESIZE_RAW;
49 r.sectorType = kCDSectorTypeUnknown;
50 r.bufferLength = CD_FRAMESIZE_RAW;
53 if (ioctl(fd, DKIOCCDREAD, &r) != kIOReturnSuccess) {
60 if (strncmp(buf + 56, "Sony Computer Entertainment", 27) == 0) {
67 static void FindCdDevice(char *dev) {
68 io_object_t next_media;
69 kern_return_t kern_result;
70 io_iterator_t media_iterator;
71 CFMutableDictionaryRef classes_to_match;
72 const char *name, *cd = kIOCDMediaClass, *dvd = kIODVDMediaClass;
78 classes_to_match = IOServiceMatching(name);
79 if (classes_to_match == NULL) goto end;
81 CFDictionarySetValue(classes_to_match, CFSTR(kIOMediaEjectableKey),
84 kern_result = IOServiceGetMatchingServices(kIOMasterPortDefault,
85 classes_to_match, &media_iterator);
87 if (kern_result != KERN_SUCCESS) goto end;
89 next_media = IOIteratorNext(media_iterator);
90 if (next_media != 0) {
92 size_t dev_path_length;
93 CFTypeRef str_bsd_path;
96 str_bsd_path = IORegistryEntryCreateCFProperty(next_media,
97 CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0);
99 if (str_bsd_path == NULL) {
100 IOObjectRelease(next_media);
104 strcpy(psz_buf, "/dev/r");
105 dev_path_length = strlen(psz_buf);
107 if (CFStringGetCString(str_bsd_path, (char *)&psz_buf + dev_path_length,
108 sizeof(psz_buf) - dev_path_length, kCFStringEncodingASCII))
110 strcpy(dev, psz_buf);
112 if (IsPsxDisc(dev)) {
113 CFRelease(str_bsd_path);
114 IOObjectRelease(next_media);
115 IOObjectRelease(media_iterator);
120 CFRelease(str_bsd_path);
121 IOObjectRelease(next_media);
122 } while ((next_media = IOIteratorNext(media_iterator)) != 0);
125 IOObjectRelease(media_iterator);
128 if (dev[0] == '\0') {
130 name = dvd; // Is this really necessary or correct? Dunno...
136 int OpenCdHandle(const char *dev) {
137 if (dev != NULL && dev[0] != '\0') strcpy(cdDevice, dev);
138 else if (cdDevice[0] == '\0') FindCdDevice(cdDevice);
140 cdHandle = open(cdDevice, O_RDONLY, 0);
141 if (cdHandle < 0) return -1;
144 u_int16_t speed = kCDSpeedMin * CdrSpeed;
145 ioctl(cdHandle, DKIOCCDSETSPEED, &speed);
151 void CloseCdHandle() {
152 if (cdHandle != -1) close(cdHandle);
156 int IsCdHandleOpen() {
160 long GetTN(unsigned char *buffer) {
161 if (cdHandle < 0) return -1;
170 long GetTD(unsigned char track, unsigned char *buffer) {
171 if (cdHandle < 0) return -1;
174 memset(buffer + 1, 0, 3);
178 long GetTE(unsigned char track, unsigned char *m, unsigned char *s, unsigned char *f) {
182 long ReadSector(crdata *cr) {
186 if (cdHandle < 0) return -1;
188 lba = msf_to_lba(cr->msf.cdmsf_min0, cr->msf.cdmsf_sec0, cr->msf.cdmsf_frame0);
190 memset(&r, 0, sizeof(r));
192 r.offset = lba * CD_FRAMESIZE_RAW;
194 r.sectorType = kCDSectorTypeUnknown;
195 r.bufferLength = CD_FRAMESIZE_RAW;
198 if (ioctl(cdHandle, DKIOCCDREAD, &r) != kIOReturnSuccess) {
205 long PlayCDDA(unsigned char *sector) {
213 long GetStatus(int playing, struct CdrStat *stat) {
214 memset(stat, 0, sizeof(struct CdrStat));
217 // Close and reopen the CD handle. If opening failed,
218 // then there is no CD in drive.
219 // Note that this WILL be screwed if user inserted another
220 // removable device such as USB stick when tray is open.
221 // There may be a better way, but this should do the job.
227 cdHandle = open(cdDevice, O_RDONLY, 0);
231 stat->Status |= 0x10;
234 u_int16_t speed = kCDSpeedMin * CdrSpeed;
235 ioctl(cdHandle, DKIOCCDSETSPEED, &speed);
242 unsigned char *ReadSub(const unsigned char *time) {
246 char *CDRgetDriveLetter(void) {