ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/sys_darwin.cpp
(Generate patch)

Comparing BasiliskII/src/MacOSX/sys_darwin.cpp (file contents):
Revision 1.8 by gbeauche, 2005-06-12T23:36:33Z vs.
Revision 1.9 by gbeauche, 2006-05-08T12:15:58Z

# Line 38 | Line 38
38   #import <IOKit/storage/IOCDMediaBSDClient.h>
39   #import <CoreFoundation/CoreFoundation.h>
40  
41 < #import "sysdeps.h"
41 > #include "sysdeps.h"
42  
43 < #import "prefs.h"
43 > #include "sys.h"
44 > #include "prefs.h"
45  
46   #define DEBUG 0
47   #import "debug.h"
48  
49  
50 + // Global variables
51 + static CFRunLoopRef media_poll_loop = NULL;
52 + static bool media_thread_active = false;
53 + static pthread_t media_thread;
54 +
55 + // Prototypes
56 + static void *media_poll_func(void *);
57 +
58 + // From sys_unix.cpp
59 + extern void SysMediaArrived(const char *path, int type);
60 + extern void SysMediaRemoved(const char *path, int type);
61 +
62  
63   /*
64 < *  This gets called when no "cdrom" prefs items are found
52 < *  It scans for available CD-ROM drives and adds appropriate prefs items
64 > *  Initialization
65   */
66  
67 < void DarwinAddCDROMPrefs(void)
67 > void DarwinSysInit(void)
68   {
69 <        mach_port_t                             masterPort;     // The way to talk to the kernel
70 <        io_iterator_t                   allCDs;         // List of CD drives on the system
71 <        CFMutableDictionaryRef  classesToMatch;
60 <        io_object_t                             nextCD;
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));
71 > }
72  
73  
74 <        // Don't scan for drives if nocdrom option given
75 <        if ( PrefsFindBool("nocdrom") )
76 <                return;
74 > /*
75 > *  Deinitialization
76 > */
77  
78 + void DarwinSysExit(void)
79 + {
80 +        // Stop media poll thread
81 +        if (media_poll_loop)
82 +                CFRunLoopStop(media_poll_loop);
83 +        if (media_thread_active)
84 +                pthread_join(media_thread, NULL);
85 + }
86  
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");
87  
88 + /*
89 + *  Get the BSD-style path of specified object
90 + */
91  
92 <        // CD media are instances of class kIOCDMediaClass
93 <        classesToMatch = IOServiceMatching(kIOCDMediaClass);
94 <        if ( classesToMatch )
95 <        {
96 <                // Narrow the search a little further. Each IOMedia object
97 <                // has a property with key kIOMediaEjectable.  We limit
98 <                // the match only to those CDs that are actually ejectable
99 <                CFDictionarySetValue(classesToMatch,
100 <                                                         CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
92 > static kern_return_t get_device_path(io_object_t obj, char *path, size_t maxPathLength)
93 > {
94 >        kern_return_t kernResult = KERN_FAILURE;
95 >        CFTypeRef pathAsCFString = IORegistryEntryCreateCFProperty(obj, CFSTR(kIOBSDNameKey),
96 >                                                                                                                           kCFAllocatorDefault, 0);
97 >        if (pathAsCFString) {
98 >                strcpy(path, "/dev/");
99 >                size_t pathLength = strlen(path);
100 >                if (CFStringGetCString((const __CFString *)pathAsCFString,
101 >                                                           path + pathLength,
102 >                                                           maxPathLength - pathLength,
103 >                                                           kCFStringEncodingASCII))
104 >                        kernResult = KERN_SUCCESS;
105 >                CFRelease(pathAsCFString);
106          }
107 +        return kernResult;
108 + }
109 +
110 +
111 + /*
112 + *  kIOMatchedNotification handler
113 + */
114  
115 <        if ( IOServiceGetMatchingServices(masterPort,
116 <                                                                          classesToMatch, &allCDs) != KERN_SUCCESS )
117 <        {
118 <                D(bug("IOServiceGetMatchingServices failed. No CD media drives found?\n"));
119 <                return;
115 > static void media_arrived(int type, io_iterator_t iterator)
116 > {
117 >        io_object_t obj;
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);
124 >                }
125 >                kernResult = IOObjectRelease(obj);
126 >                if (kernResult != KERN_SUCCESS) {
127 >                        fprintf(stderr, "IOObjectRelease() returned %d\n", kernResult);
128 >                }
129          }
130 + }
131  
132  
133 <        // Iterate through each CD drive
134 <        while ( nextCD = IOIteratorNext(allCDs))
135 <        {
95 <                char            bsdPath[MAXPATHLEN];
96 <                CFTypeRef       bsdPathAsCFString =
97 <                                                IORegistryEntryCreateCFProperty(nextCD,
98 <                                                                                                                CFSTR(kIOBSDNameKey),
99 <                                                                                                                kCFAllocatorDefault, 0);
100 <                *bsdPath = '\0';
101 <                if ( bsdPathAsCFString )
102 <                {
103 <                        size_t devPathLength;
104 <
105 <                        strcpy(bsdPath, "/dev/");
106 <                        devPathLength = strlen(bsdPath);
107 <
108 <                        if ( CFStringGetCString((const __CFString *)bsdPathAsCFString,
109 <                                                                         bsdPath + devPathLength,
110 <                                                                         MAXPATHLEN - devPathLength,
111 <                                                                         kCFStringEncodingASCII) )
112 <                        {
113 <                                D(bug("CDROM BSD path: %s\n", bsdPath));
114 <                                PrefsAddString("cdrom", bsdPath);
115 <                        }
116 <                        else
117 <                                D(bug("Could not get BSD device path for CD\n"));
133 > /*
134 > *  kIOTerminatedNotification handler
135 > */
136  
137 <                        CFRelease(bsdPathAsCFString);
137 > static void media_removed(int type, io_iterator_t iterator)
138 > {
139 >        io_object_t obj;
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);
146 >                }
147 >                kernResult = IOObjectRelease(obj);
148 >                if (kernResult != KERN_SUCCESS) {
149 >                        fprintf(stderr, "IOObjectRelease() returned %d\n", kernResult);
150                  }
121                else
122                        D(bug("Cannot determine bsdPath for CD\n"));
151          }
152 + }
153 +
154 +
155 + /*
156 + *  Media poll function
157 + */
158 +
159 + static void *media_poll_func(void *)
160 + {
161 +        media_poll_loop = CFRunLoopGetCurrent();
162 +
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);
167 +                return NULL;
168 +        }
169 +
170 +        CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass);
171 +        if (matchingDictionary == NULL) {
172 +                fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n");
173 +                return NULL;
174 +        }
175 +        matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
176 +
177 +        IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
178 +        CFRunLoopAddSource(media_poll_loop,
179 +                                           IONotificationPortGetRunLoopSource(notificationPort),
180 +                                           kCFRunLoopDefaultMode);
181 +
182 +        io_iterator_t mediaArrivedIterator;
183 +        kernResult = IOServiceAddMatchingNotification(notificationPort,
184 +                                                                                                  kIOMatchedNotification,
185 +                                                                                                  matchingDictionary,
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);
191 +
192 +        io_iterator_t mediaRemovedIterator;
193 +        kernResult = IOServiceAddMatchingNotification(notificationPort,
194 +                                                                                                  kIOTerminatedNotification,
195 +                                                                                                  matchingDictionary,
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);
201  
202 <        IOObjectRelease(nextCD);
203 <        IOObjectRelease(allCDs);
202 >        CFRunLoopRun();
203 >        return NULL;
204   }
205  
206  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines