1/*cc -o /tmp/modelist modelist.c -framework IOKit -framework ApplicationServices -Wall -g
2*/
3
4#include <mach/mach.h>
5#include <mach/thread_switch.h>
6#include <sys/file.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <string.h>
10#include <stdlib.h>
11
12#include <CoreFoundation/CoreFoundation.h>
13#include <ApplicationServices/ApplicationServices.h>
14
15#include <IOKit/IOKitLib.h>
16#include <libkern/OSByteOrder.h>
17#include <IOKit/IOMessage.h>
18#include <IOKit/IOCFURLAccess.h>
19#include <IOKit/graphics/IOGraphicsLib.h>
20#include <IOKit/graphics/IOGraphicsLibPrivate.h>
21
22#include <assert.h>
23
24/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
25
26struct IOFBModeList
27{
28    CFBundleRef                 bundle;
29    io_service_t                framebuffer;
30
31    CFMutableDictionaryRef      kernelInfo;
32    CFMutableDictionaryRef      modes;
33    CFMutableArrayRef           modesArray;
34    CFMutableDictionaryRef      overrides;
35
36    Boolean                     suppressRefresh;
37    Boolean                     detailedRefresh;
38
39    IOItemCount                 safemodeCount;
40    IOItemCount                 builtinCount;
41    IOItemCount                 televisionCount;
42    IOItemCount                 simulscanCount;
43    IOItemCount                 maxRefreshDigits;
44
45    CFMutableArrayRef           refreshNames;
46
47    Boolean                     refreshList;
48    uint32_t                    significantFlags;
49};
50typedef struct IOFBModeList * IOFBModeListRef;
51
52/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53
54struct ModeInfo
55{
56    IODisplayModeInformation *  info;
57    UInt32                      index;
58    UInt32                      cgIndex;
59    SInt32                      numRefresh;
60    SInt32                      numSafe;
61    SInt32                      numPreset;
62    UInt32                      digits;
63    Boolean                     notReco;
64};
65typedef struct ModeInfo ModeInfo;
66
67enum
68{
69    kCompareRefresh = 0x00000001,
70    kCompareAll     = 0xffffffff,
71};
72
73static int
74CompareModes(IOFBModeListRef modeListRef,
75            IODisplayModeInformation * left, IODisplayModeInformation * right,
76            IOOptionBits compare)
77{
78    UInt32 leftFlags, rightFlags, differFlags;
79
80    if (!left)
81        return (1);
82    else if (!right)
83        return (-1);
84
85    leftFlags = left->flags;
86    rightFlags = right->flags;
87    differFlags = leftFlags ^ rightFlags;
88
89    if (modeListRef->simulscanCount && (kDisplayModeSimulscanFlag & differFlags))
90    {
91        if (kDisplayModeSimulscanFlag & leftFlags)
92            return (1);
93        else
94            return (-1);
95    }
96    if (modeListRef->builtinCount && (kDisplayModeBuiltInFlag & differFlags))
97    {
98        if (kDisplayModeBuiltInFlag & leftFlags)
99            return (1);
100        else
101            return (-1);
102    }
103
104    if (kDisplayModeTelevisionFlag & leftFlags & rightFlags)
105    {
106        // both TV, order ntsc first
107        if ((left->refreshRate < 55*65536) && (right->refreshRate > 55*65536))
108            return (1);
109        else if ((left->refreshRate > 55*65536) && (right->refreshRate < 55*65536))
110            return (-1);
111    }
112
113    if (left->nominalWidth > right->nominalWidth)
114        return (1);
115    else if (left->nominalWidth != right->nominalWidth)
116        return (-1);
117    if (left->nominalHeight > right->nominalHeight)
118        return (1);
119    else if (left->nominalHeight != right->nominalHeight)
120        return (-1);
121
122    if (kDisplayModeStretchedFlag & differFlags)
123    {
124        if (kDisplayModeStretchedFlag & leftFlags)
125            return (1);
126        else
127            return (-1);
128    }
129
130    if (kDisplayModeInterlacedFlag & differFlags)
131    {
132        if (kDisplayModeInterlacedFlag & leftFlags)
133            return (1);
134        else
135            return (-1);
136    }
137
138    if (compare & kCompareRefresh)
139    {
140        if (left->refreshRate > right->refreshRate)
141            return (1);
142        else if (left->refreshRate != right->refreshRate)
143            return (-1);
144    }
145
146    return (0);
147}
148
149static int
150qsort_cmp(void * ref, const void * _left, const void * _right)
151{
152    IOFBModeListRef modeListRef = (IOFBModeListRef) ref;
153
154    IODisplayModeInformation * left  = ((ModeInfo *) _left)->info;
155    IODisplayModeInformation * right = ((ModeInfo *) _right)->info;
156
157    return (CompareModes(modeListRef, left, right, kCompareAll));
158}
159
160
161
162#define k256ColorString                 "256 Colors"
163#define kThousandsString                "Thousands"
164#define kMillionsString                 "Millions"
165#define kTrillionsString                "Trillions"
166
167#define kPALString                      "PAL"
168#define kNTSCString                     "NTSC"
169
170#define kNoRefreshRateString            "n/a"
171
172#define kStretchedString                "stretched"
173#define kSimulscanString                "simulscan"
174#define kInterlacedString               "interlaced"
175#define kExternalString                 "external"
176
177#define kRefreshString                  "%%.%ldf Hertz"
178#define kTVRefreshString                "%%.%ldf Hertz (%%@)"
179
180#define kHxVString                      "%d x %d"
181#define kHxVpString                     "%d x %dp"
182#define kHxViString                     "%d x %di"
183
184#define kNoHertz0FlagString             "%@"
185#define kNoHertz1FlagString             "%@ (%@)"
186#define kNoHertz2FlagString             "%@ (%@, %@)"
187#define kNoHertz3FlagString             "%@ (%@, %@, %@)"
188#define kNoHertz4FlagString             "%@ (%@, %@, %@, %@)"
189#define kNoHertz5FlagString             "%@ (%@, %@, %@, %@, %@)"
190
191#define kHertz0FlagString               "%%@, %%.%ldf Hz"
192#define kHertz1FlagString               "%%@, %%.%ldf Hz (%%@)"
193#define kHertz2FlagString               "%%@, %%.%ldf Hz (%%@, %%@)"
194#define kHertz3FlagString               "%%@, %%.%ldf Hz (%%@, %%@, %%@)"
195#define kHertz4FlagString               "%%@, %%.%ldf Hz (%%@, %%@, %%@, %%@)"
196#define kHertz5FlagString               "%%@, %%.%ldf Hz (%%@, %%@, %%@, %%@, %%@)"
197
198CFStringRef
199TimingName(IOFBModeListRef modeListRef, IODisplayModeInformation * info, CFIndex * refRateIndex)
200{
201
202    CFStringRef formatStr, formatStr2, refStr, resStr, finalStr;
203    CFStringRef palNTSCStr, stretchedStr, simulscanStr, interlacedStr, externalStr;
204    uint32_t flags, flagCount;
205    CFStringRef flagStrs[5] = { 0 };
206    CFIndex k, count;
207
208    float refRate = info->refreshRate / 65536.0;
209
210    flagCount = 0;
211
212    if (kDisplayModeTelevisionFlag & info->flags)
213    {
214        palNTSCStr = refRate < 55.0 ? CFSTR(kPALString) : CFSTR(kNTSCString);
215        palNTSCStr = CFBundleCopyLocalizedString(modeListRef->bundle, palNTSCStr, palNTSCStr, 0);
216    }
217    else
218        palNTSCStr = 0;
219
220    stretchedStr  = CFBundleCopyLocalizedString(modeListRef->bundle, CFSTR(kStretchedString), CFSTR(kStretchedString), 0);
221    simulscanStr  = CFBundleCopyLocalizedString(modeListRef->bundle, CFSTR(kSimulscanString), CFSTR(kSimulscanString), 0);
222    interlacedStr = CFBundleCopyLocalizedString(modeListRef->bundle, CFSTR(kInterlacedString), CFSTR(kInterlacedString), 0);
223    externalStr   = CFBundleCopyLocalizedString(modeListRef->bundle, CFSTR(kExternalString), CFSTR(kExternalString), 0);
224
225    if (modeListRef->refreshList)
226    {
227
228        if (modeListRef->suppressRefresh)
229        {
230            refStr = CFSTR(kNoRefreshRateString);
231            refStr = CFBundleCopyLocalizedString(modeListRef->bundle, refStr, refStr, 0);
232        }
233        else
234        {
235            if (kDisplayModeTelevisionFlag & info->flags)
236                formatStr = CFSTR(kTVRefreshString);
237            else
238                formatStr = CFSTR(kRefreshString);
239
240            formatStr = CFBundleCopyLocalizedString(modeListRef->bundle, formatStr, formatStr, 0);
241
242            formatStr2 = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
243                                    formatStr,
244                                    modeListRef->maxRefreshDigits);
245            refStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
246                    formatStr2, refRate,
247                    palNTSCStr );
248            CFRelease(formatStr);
249        }
250
251        count = CFArrayGetCount(modeListRef->refreshNames);
252        for (k = 0;
253            (k < count) && !CFEqual(refStr, CFArrayGetValueAtIndex(modeListRef->refreshNames, k));
254                k++)    {}
255
256        if (k == count)
257            CFArrayAppendValue(modeListRef->refreshNames, refStr);
258        CFRelease(refStr);
259
260        if (refRateIndex)
261            *refRateIndex = k;
262    }
263
264    flags = modeListRef->significantFlags & info->flags;
265
266    if (!modeListRef->refreshList && (kDisplayModeTelevisionFlag & info->flags))
267        flagStrs[flagCount++] = palNTSCStr;
268
269    if (flags & kDisplayModeStretchedFlag)
270        flagStrs[flagCount++] = stretchedStr;
271
272    if (flags & kDisplayModeSimulscanFlag)
273        flagStrs[flagCount++] = simulscanStr;
274
275    if ((kDisplayModeBuiltInFlag & modeListRef->significantFlags)
276     &&  !(flags & kDisplayModeBuiltInFlag))
277        flagStrs[flagCount++] = externalStr;
278
279    if (kDisplayModeInterlacedFlag ==
280            (flags & (kDisplayModeInterlacedFlag | kDisplayModeTelevisionFlag)))
281        flagStrs[flagCount++] = interlacedStr;
282
283
284    resStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
285                CFSTR(kHxVString),
286                info->nominalWidth, info->nominalHeight);
287
288    if (modeListRef->refreshList || modeListRef->suppressRefresh)
289    {
290        switch (flagCount)
291        {
292        case 0: formatStr = CFSTR(kNoHertz0FlagString); break;
293        case 1: formatStr = CFSTR(kNoHertz1FlagString); break;
294        case 2: formatStr = CFSTR(kNoHertz2FlagString); break;
295        case 3: formatStr = CFSTR(kNoHertz3FlagString); break;
296        case 4: formatStr = CFSTR(kNoHertz4FlagString); break;
297        default:
298        case 5: formatStr = CFSTR(kNoHertz5FlagString); break;
299        }
300
301        formatStr = CFBundleCopyLocalizedString(modeListRef->bundle, formatStr, formatStr, 0);
302
303        finalStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
304                        formatStr,
305                        resStr,
306                        flagStrs[0],
307                        flagStrs[1],
308                        flagStrs[2],
309                        flagStrs[3],
310                        flagStrs[4]);
311    }
312    else
313    {
314        switch (flagCount)
315        {
316        case 0: formatStr2 = CFSTR(kHertz0FlagString); break;
317        case 1: formatStr2 = CFSTR(kHertz1FlagString); break;
318        case 2: formatStr2 = CFSTR(kHertz2FlagString); break;
319        case 3: formatStr2 = CFSTR(kHertz3FlagString); break;
320        case 4: formatStr2 = CFSTR(kHertz4FlagString); break;
321        default:
322        case 5: formatStr2 = CFSTR(kHertz5FlagString); break;
323        }
324
325        formatStr2 = CFBundleCopyLocalizedString(modeListRef->bundle, formatStr2, formatStr2, 0);
326
327        formatStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
328                                formatStr2,
329                                modeListRef->maxRefreshDigits);
330
331        CFRelease(formatStr2);
332
333        finalStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
334                        formatStr,
335                        resStr,
336                        refRate,
337                        flagStrs[0],
338                        flagStrs[1],
339                        flagStrs[2],
340                        flagStrs[3],
341                        flagStrs[4]);
342    }
343
344    CFRelease(formatStr);
345
346    if (palNTSCStr)
347        CFRelease(palNTSCStr);
348    if (stretchedStr)
349        CFRelease(stretchedStr);
350    if (simulscanStr)
351        CFRelease(simulscanStr);
352    if (interlacedStr)
353        CFRelease(interlacedStr);
354    if (externalStr)
355        CFRelease(externalStr);
356
357    return (finalStr);
358}
359
360kern_return_t
361ModeList(IOFBModeListRef modeListRef, Boolean reco)
362{
363    CFMutableDictionaryRef      dict;
364    CFMutableArrayRef           array;
365    CFDataRef                   data;
366    SInt32                      i, j, k;
367    CFIndex                     modeCount, newCount, cgIndex = 0;
368    IODisplayModeInformation *  info;
369    ModeInfo *                  modeArray;
370
371    do
372    {
373        dict = CFDictionaryCreateMutable( kCFAllocatorDefault, (CFIndex) 0,
374                                                (CFDictionaryKeyCallBacks *) 0,
375                                                &kCFTypeDictionaryValueCallBacks );
376        modeListRef->modes = dict;
377
378        dict = (CFMutableDictionaryRef) IORegistryEntryCreateCFProperty(
379                                            modeListRef->framebuffer,
380                                            CFSTR(kIOFBConfigKey),
381                                            kCFAllocatorDefault, kNilOptions);
382        if (!dict)
383            break;
384        array = (CFMutableArrayRef) CFDictionaryGetValue(dict, CFSTR(kIOFBModesKey));
385        if (!array)
386            break;
387
388        // pick up existing config
389        modeListRef->kernelInfo = dict;
390        CFRetain(array);
391        modeListRef->modesArray = array;
392
393        modeListRef->suppressRefresh = (0 != CFDictionaryGetValue(dict, CFSTR("IOFB0Hz")));
394
395        modeListRef->detailedRefresh = (0 != CFDictionaryGetValue(dict, CFSTR("IOFBmHz")));
396
397        modeCount  = CFArrayGetCount( modeListRef->modesArray );
398        newCount = modeCount;
399
400        modeArray = calloc(modeCount, sizeof(ModeInfo));
401
402        for( i = 0; i < modeCount; i++ )
403        {
404            const void * key;
405            CFNumberRef  num;
406
407            dict = (CFMutableDictionaryRef) CFArrayGetValueAtIndex( modeListRef->modesArray, i );
408            num = CFDictionaryGetValue( dict, CFSTR(kIOFBModeIDKey) );
409            CFNumberGetValue( num, kCFNumberSInt32Type, (SInt32 *) &key );
410            CFDictionarySetValue( modeListRef->modes, key, dict );
411
412            if (!dict)
413                break;
414            data = CFDictionaryGetValue(dict, CFSTR(kIOFBModeDMKey));
415            if (!data)
416                break;
417
418            info = (IODisplayModeInformation *) CFDataGetBytePtr(data);
419
420//          if (info->flags & kDisplayModeNeverShowFlag)
421//              continue;
422
423            modeArray[i].index = i;
424            modeArray[i].info  = info;
425            modeArray[i].cgIndex = cgIndex;
426            cgIndex += info->maxDepthIndex + 1;
427
428#if 0
429            printf("%ld: %ld x %ld  @ %f Hz\n", modeArray[i].cgIndex,
430                    info->nominalWidth, info->nominalHeight,
431                    info->refreshRate / 65536.0);
432#endif
433
434            if (info->flags & kDisplayModeSafeFlag)
435                modeListRef->safemodeCount++;
436
437//              if (info->flags & kDisplayModeAlwaysShowFlag)
438//              if (info->flags & kDisplayModeDefaultFlag)
439
440            if (info->flags & kDisplayModeSimulscanFlag)
441                modeListRef->simulscanCount++;
442            if (info->flags & kDisplayModeBuiltInFlag)
443                modeListRef->builtinCount++;
444            if (info->flags & kDisplayModeTelevisionFlag)
445                modeListRef->televisionCount++;
446        }
447
448
449        qsort_r(modeArray, modeCount, sizeof(modeArray[0]), modeListRef, &qsort_cmp);
450
451
452#define discard()       { modeArray[i].notReco = true; continue; }
453
454
455        // group refresh rates
456
457        {
458            UInt32 lastSame;
459
460            lastSame = 0;
461            for (i = 0; i < modeCount; i++)
462            {
463                if (i != lastSame)
464                {
465                    if (0 == CompareModes(modeListRef, modeArray[lastSame].info, modeArray[i].info, 0))
466                    {
467                        // number that follow (total - 1)
468                        modeArray[lastSame].numRefresh++;
469
470                        modeArray[i].numRefresh = lastSame - i;
471                    }
472                    else
473                        lastSame = i;
474                }
475                if (modeArray[i].info->flags & kDisplayModeSafeFlag)
476                    modeArray[lastSame].numSafe++;
477
478                if (!(modeArray[i].info->flags & kDisplayModeNotPresetFlag))
479                    modeArray[lastSame].numPreset++;
480            }
481        }
482
483
484        if (reco)
485        {
486            // prune with safety / not preset
487
488            for( i = 0; i < modeCount; i++ )
489            {
490                info = modeArray[i].info;
491                do
492                {
493//                  if (modeListRef->safemodeCount
494//                   && !(info->flags & (kDisplayModeSafeFlag | kDisplayModeTelevisionFlag)))
495//                      discard();
496
497//                  if (info->flags & kDisplayModeNotPresetFlag)
498//                      discard();
499                }
500                while (false);
501            }
502        }
503
504        // prune refresh rates
505        if (reco)
506        {
507            for( i = 0; i < modeCount; i += modeArray[i].numRefresh + 1 )
508            {
509                info = modeArray[i].info;
510                do
511                {
512                    if (info->flags & kDisplayModeTelevisionFlag)
513                        continue;
514
515//                  if (modeListRef->safemodeCount)
516                    {
517                        // keep only highest
518                        Boolean haveHighestReco = false;
519                        for (j = i + modeArray[i].numRefresh; j >= i; j--)
520                        {
521                            if (haveHighestReco)
522                                modeArray[j].notReco = true;
523                            else {
524
525                                if ((!modeArray[i].numPreset)
526                                || (!(modeArray[j].info->flags & kDisplayModeNotPresetFlag)))
527                                {
528                                    uint32_t target;
529                                    target = (modeArray[j].info->flags & kDisplayModeSafeFlag)
530                                                ? (86 << 16) : (86 << 16);
531
532                                    haveHighestReco = !modeArray[j].notReco
533                                                    && (modeArray[j].info->refreshRate < target);
534                                }
535                                if (!haveHighestReco)
536                                    modeArray[j].notReco = true;
537                            }
538                        }
539                        continue;
540                    }
541                }
542                while (false);
543            }
544        }
545        // <reco/>
546
547        // unique refresh rates
548
549        for( i = 0; i < modeCount; i += modeArray[i].numRefresh + 1 )
550        {
551            float ref1, ref2, mult;
552
553            modeArray[i].digits = 0; //modeListRef->maxRefreshDigits;
554            mult = 1.0;
555
556            for (j = i; j < (i + modeArray[i].numRefresh + 1); j++)
557            {
558                if (modeArray[j].notReco)
559                    continue;
560                ref1 = modeArray[j].info->refreshRate / 65536.0;
561                for (k = i; k < (i + modeArray[i].numRefresh + 1); k++)
562                {
563                    if (k == j)
564                        continue;
565                    if (modeArray[k].notReco)
566                        continue;
567                    ref2 = modeArray[k].info->refreshRate / 65536.0;
568                    while (modeArray[i].digits < 5)
569                    {
570//if (modeArray[i].digits)
571//    printf("-----> %f, %f, %f, %f\n", ref1, ref2, roundf(ref1 * mult), roundf(ref2 * mult));
572                        if (roundf(ref1 * mult) != roundf(ref2 * mult))
573                            break;
574                        modeArray[i].digits++;
575                        mult *= 10.0;
576                    }
577                }
578            }
579
580            if (modeArray[i].digits > modeListRef->maxRefreshDigits)
581                modeListRef->maxRefreshDigits = modeArray[i].digits;
582        }
583        // <unique/>
584
585        printf("\nOut:\n");
586
587        modeListRef->refreshNames = CFArrayCreateMutable( kCFAllocatorDefault, 0,
588                                             &kCFTypeArrayCallBacks );
589
590        modeListRef->refreshList = false;
591
592        do
593        {
594            modeListRef->significantFlags =
595                        1 * kDisplayModeStretchedFlag
596                        | 1 * kDisplayModeSimulscanFlag
597                        | 0 * kDisplayModeBuiltInFlag;
598
599            printf("-------------\n");
600            for (i = 0; i < modeCount; i += modeArray[i].numRefresh + 1)
601            {
602                CFStringRef name;
603                CFIndex     idx;
604                CFIndex mask = 0;
605
606                info = modeArray[i].info;
607
608    #if 0
609                printf("%ld x %ld \n",
610                        info->nominalWidth, info->nominalHeight);
611
612                printf("numRefresh %d, numSafe %d, numPreset %d\n",
613                        modeArray[i].numRefresh,
614                        modeArray[i].numSafe,
615                        modeArray[i].numPreset);
616    #endif
617
618                for (j = i; j < (i + modeArray[i].numRefresh + 1); j++)
619                {
620                    info = modeArray[j].info;
621
622                    name = TimingName(modeListRef, info, &idx);
623                    if (!modeListRef->refreshList || (j == i))
624                    {
625                        if (!modeListRef->refreshList && modeArray[j].notReco)
626                            printf("*");
627                        printf(CFStringGetCStringPtr(name, kCFStringEncodingMacRoman));
628                        if (!modeListRef->refreshList)
629                            printf("\n");
630                    }
631                    if (modeListRef->refreshList)
632                    {
633                        printf(" %c[%d]", modeArray[j].notReco ? '*' : ' ', idx);
634                        mask |= (1 << idx);
635                    }
636
637                    CFRelease(name);
638    #if 0
639                    printf("   %s%s%s",
640                        (info->flags & kDisplayModeSafeFlag) ? "safe " : "",
641                        (info->flags & kDisplayModeDefaultFlag) ? "default " : "",
642                        (info->flags & kDisplayModeNotPresetFlag) ? "notpreset " : ""
643                    );
644    #endif
645                }
646                if (modeListRef->refreshList)
647                    printf("\n");
648            }
649            if (modeListRef->refreshList)
650            {
651                CFShow(modeListRef->refreshNames);
652                break;
653            }
654            modeListRef->refreshList = true;
655        }
656        while (true);
657    }
658    while (false);
659
660//      CFShow(modeListRef->modesArray);
661    return( kIOReturnSuccess );
662}
663
664/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
665
666int main( int argc, char * argv[] )
667{
668    kern_return_t kr;
669    io_string_t   path;
670        CFURLRef url;
671    CFIndex       i;
672    CGError             err;
673    CGDisplayCount      max;
674    CGDirectDisplayID   displayIDs[8];
675
676    err = CGGetOnlineDisplayList(8, displayIDs, &max);
677    if(err != kCGErrorSuccess)
678        exit(1);
679    if(max > 8)
680        max = 8;
681
682
683
684    for(i = 0; i < max; i++ )
685    {
686        struct IOFBModeList _xxx = { 0 };
687        IOFBModeListRef modeListRef = &_xxx;
688        modeListRef->framebuffer = CGDisplayIOServicePort(displayIDs[i]);
689
690
691        url = CFURLCreateWithFileSystemPath(
692            kCFAllocatorDefault,
693            CFSTR("/System/Library/Frameworks/IOKit.framework"),
694            kCFURLPOSIXPathStyle, true);
695        if (url)
696            modeListRef->bundle = CFBundleCreate(kCFAllocatorDefault, url);
697
698if (!modeListRef->bundle) exit(1);
699
700        kr = IORegistryEntryGetPath(modeListRef->framebuffer, kIOServicePlane, path);
701        assert( KERN_SUCCESS == kr );
702        printf("\nDisplay %p: %s\n", displayIDs[i], path);
703
704        ModeList(modeListRef, true || true);
705    }
706
707    exit(0);
708    return(0);
709}
710
711