38
38
#import <IOKit/storage/IOCDMediaBSDClient.h>
39
39
#import <CoreFoundation/CoreFoundation.h>
51
* This gets called when no "cdrom" prefs items are found
52
* It scans for available CD-ROM drives and adds appropriate prefs items
55
void DarwinAddCDROMPrefs(void)
57
mach_port_t masterPort; // The way to talk to the kernel
58
io_iterator_t allCDs; // List of CD drives on the system
59
CFMutableDictionaryRef classesToMatch;
63
// Don't scan for drives if nocdrom option given
64
if ( PrefsFindBool("nocdrom") )
68
// Let this task talk to the guts of the kernel:
69
if ( IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS )
70
bug("IOMasterPort failed. Won't be able to do anything with CD drives\n");
73
// CD media are instances of class kIOCDMediaClass
74
classesToMatch = IOServiceMatching(kIOCDMediaClass);
77
// Narrow the search a little further. Each IOMedia object
78
// has a property with key kIOMediaEjectable. We limit
79
// the match only to those CDs that are actually ejectable
80
CFDictionarySetValue(classesToMatch,
81
CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
84
if ( IOServiceGetMatchingServices(masterPort,
85
classesToMatch, &allCDs) != KERN_SUCCESS )
87
D(bug("IOServiceGetMatchingServices failed. No CD media drives found?\n"));
92
// Iterate through each CD drive
93
while ( nextCD = IOIteratorNext(allCDs))
95
char bsdPath[MAXPATHLEN];
96
CFTypeRef bsdPathAsCFString =
97
IORegistryEntryCreateCFProperty(nextCD,
99
kCFAllocatorDefault, 0);
101
if ( bsdPathAsCFString )
103
size_t devPathLength;
105
strcpy(bsdPath, "/dev/");
106
devPathLength = strlen(bsdPath);
108
if ( CFStringGetCString((const __CFString *)bsdPathAsCFString,
109
bsdPath + devPathLength,
110
MAXPATHLEN - devPathLength,
111
kCFStringEncodingASCII) )
113
D(bug("CDROM BSD path: %s\n", bsdPath));
114
PrefsAddString("cdrom", bsdPath);
117
D(bug("Could not get BSD device path for CD\n"));
119
CFRelease(bsdPathAsCFString);
122
D(bug("Cannot determine bsdPath for CD\n"));
125
IOObjectRelease(nextCD);
126
IOObjectRelease(allCDs);
51
static CFRunLoopRef media_poll_loop = NULL;
52
static bool media_thread_active = false;
53
static pthread_t media_thread;
56
static void *media_poll_func(void *);
59
extern void SysMediaArrived(const char *path, int type);
60
extern void SysMediaRemoved(const char *path, int type);
67
void DarwinSysInit(void)
69
media_thread_active = (pthread_create(&media_thread, NULL, media_poll_func, NULL) == 0);
70
D(bug("Media poll thread installed (%ld)\n", media_thread));
78
void DarwinSysExit(void)
80
// Stop media poll thread
82
CFRunLoopStop(media_poll_loop);
83
if (media_thread_active)
84
pthread_join(media_thread, NULL);
89
* Get the BSD-style path of specified object
92
static kern_return_t get_device_path(io_object_t obj, char *path, size_t maxPathLength)
94
kern_return_t kernResult = KERN_FAILURE;
95
CFTypeRef pathAsCFString = IORegistryEntryCreateCFProperty(obj, CFSTR(kIOBSDNameKey),
96
kCFAllocatorDefault, 0);
98
strcpy(path, "/dev/");
99
size_t pathLength = strlen(path);
100
if (CFStringGetCString((const __CFString *)pathAsCFString,
102
maxPathLength - pathLength,
103
kCFStringEncodingASCII))
104
kernResult = KERN_SUCCESS;
105
CFRelease(pathAsCFString);
112
* kIOMatchedNotification handler
115
static void media_arrived(int type, io_iterator_t iterator)
118
while ((obj = IOIteratorNext(iterator)) != NULL) {
119
char path[MAXPATHLEN];
120
kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
121
if (kernResult == KERN_SUCCESS) {
122
D(bug("Media Arrived: %s\n", path));
123
SysMediaArrived(path, type);
125
kernResult = IOObjectRelease(obj);
126
if (kernResult != KERN_SUCCESS) {
127
fprintf(stderr, "IOObjectRelease() returned %d\n", kernResult);
134
* kIOTerminatedNotification handler
137
static void media_removed(int type, io_iterator_t iterator)
140
while ((obj = IOIteratorNext(iterator)) != NULL) {
141
char path[MAXPATHLEN];
142
kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
143
if (kernResult == KERN_SUCCESS) {
144
D(bug("Media Removed: %s\n", path));
145
SysMediaRemoved(path, type);
147
kernResult = IOObjectRelease(obj);
148
if (kernResult != KERN_SUCCESS) {
149
fprintf(stderr, "IOObjectRelease() returned %d\n", kernResult);
156
* Media poll function
159
static void *media_poll_func(void *)
161
media_poll_loop = CFRunLoopGetCurrent();
163
mach_port_t masterPort;
164
kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort);
165
if (kernResult != KERN_SUCCESS) {
166
fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
170
CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass);
171
if (matchingDictionary == NULL) {
172
fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n");
175
matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
177
IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
178
CFRunLoopAddSource(media_poll_loop,
179
IONotificationPortGetRunLoopSource(notificationPort),
180
kCFRunLoopDefaultMode);
182
io_iterator_t mediaArrivedIterator;
183
kernResult = IOServiceAddMatchingNotification(notificationPort,
184
kIOMatchedNotification,
186
(IOServiceMatchingCallback)media_arrived,
187
(void *)MEDIA_CD, &mediaArrivedIterator);
188
if (kernResult != KERN_SUCCESS)
189
fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
190
media_arrived(MEDIA_CD, mediaArrivedIterator);
192
io_iterator_t mediaRemovedIterator;
193
kernResult = IOServiceAddMatchingNotification(notificationPort,
194
kIOTerminatedNotification,
196
(IOServiceMatchingCallback)media_removed,
197
(void *)MEDIA_CD, &mediaRemovedIterator);
198
if (kernResult != KERN_SUCCESS)
199
fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
200
media_removed(MEDIA_CD, mediaRemovedIterator);