// cc -o /tmp/modesuck -g modesuck.c -framework ApplicationServices -framework IOKit -Wall #include #include #include #include #include #include #include #include #include #include #include #include #include __private_extern__ IOReturn readFile(const char *path, vm_offset_t * objAddr, vm_size_t * objSize) { int fd; int err; struct stat stat_buf; *objAddr = 0; *objSize = 0; if((fd = open(path, O_RDONLY)) == -1) return errno; do { if(fstat(fd, &stat_buf) == -1) { err = errno; continue; } if (0 == (stat_buf.st_mode & S_IFREG)) { *objAddr = 0; *objSize = 0; err = kIOReturnNotReadable; continue; } *objSize = stat_buf.st_size; if( KERN_SUCCESS != map_fd(fd, 0, objAddr, TRUE, *objSize)) { *objAddr = 0; *objSize = 0; err = errno; continue; } err = kIOReturnSuccess; } while( false ); close(fd); return( err ); } __private_extern__ CFMutableDictionaryRef readPlist( const char * path, UInt32 key ) { IOReturn err; vm_offset_t bytes; vm_size_t byteLen; CFDataRef data; CFMutableDictionaryRef obj = 0; err = readFile( path, &bytes, &byteLen ); if( kIOReturnSuccess != err) return (0); data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8 *) bytes, byteLen, kCFAllocatorNull ); if( data) { obj = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, data, kCFPropertyListMutableContainers, (CFStringRef *) NULL ); CFRelease( data ); } vm_deallocate( mach_task_self(), bytes, byteLen ); return (obj); } int main(int argc, char * argv[]) { io_service_t framebuffer; CGError err; int i; CGDisplayCount max; CGDirectDisplayID displayIDs[8]; IODisplayModeInformation * modeInfo; IODetailedTimingInformationV2 *timingInfo; CFDictionaryRef dict; CFArrayRef modes; CFIndex count; CFDictionaryRef mode; CFMutableDictionaryRef result, stdModes, timingIDs; CFDataRef data; CFNumberRef num; CFStringRef cfStr; char key[64]; const void * keys[2]; const void * values[2]; err = CGGetOnlineDisplayList(8, displayIDs, &max); if(err != kCGErrorSuccess) exit(1); if(max > 8) max = 8; for(i = 0; i < max; i++ ) { framebuffer = CGDisplayIOServicePort(displayIDs[i]); dict = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBConfigKey), kCFAllocatorDefault, kNilOptions); assert(dict); modes = CFDictionaryGetValue(dict, CFSTR(kIOFBModesKey)); assert(modes); result = readPlist("/System/Library/Frameworks/IOKit.framework/" "Resources/IOGraphicsProperties.plist", 0); if (result) { stdModes = (CFMutableDictionaryRef) CFDictionaryGetValue(result, CFSTR("std-modes")); assert(stdModes); timingIDs = (CFMutableDictionaryRef) CFDictionaryGetValue(result, CFSTR("timing-ids")); assert(timingIDs); data = CFDictionaryGetValue(result, CFSTR("apple-edid")); if (data) { UInt32 ids[24] = { 0 }; UInt32 * p = (UInt32 *) CFDataGetBytePtr(data); int i; for( i = 0; i < (CFDataGetLength(data)/4); i+=2) { UInt32 bit, id; id = p[i]; bit = p[i + 1] >> 16; if( bit < 24) { bit = (0x10 - (bit & 0xf8)) | (bit & 7); if( ids[bit]) printf("bit %ld, id %ld dup\n", bit, id); else ids[bit] = id; } } data = CFDataCreate( kCFAllocatorDefault, (const UInt8 *) ids, sizeof(ids) ); CFDictionarySetValue( result, CFSTR("established-ids"), data); CFRelease(data); } } else { result = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); assert(result); stdModes = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); assert(stdModes); timingIDs = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); assert(timingIDs); } count = CFArrayGetCount(modes); for (i = 0; i < count; i++) { SInt32 aid; mode = CFArrayGetValueAtIndex(modes, i); num = CFDictionaryGetValue(mode, CFSTR(kIOFBModeAIDKey)); if (num) CFNumberGetValue( num, kCFNumberSInt32Type, &aid ); else aid = timingInvalid; data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeDMKey)); if (!data) continue; modeInfo = (IODisplayModeInformation *) CFDataGetBytePtr(data); data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeTMKey)); if (!data) continue; timingInfo = (IODetailedTimingInformationV2 *) CFDataGetBytePtr(data); printf("%ldx%ld@%ld, %ld\n", modeInfo->nominalWidth, modeInfo->nominalHeight, ((modeInfo->refreshRate + 0x8000) >> 16), aid); if( timingInfo->horizontalActive & 7) printf("horizontalActive & 7\n"); if( timingInfo->horizontalBlanking & 7) printf("horizontalBlanking & 7\n"); if( timingInfo->horizontalSyncOffset & 7) printf("horizontalSyncOffset & 7\n"); if( timingInfo->horizontalSyncPulseWidth & 7) printf("horizontalSyncPulseWidth & 7\n"); if( (aid == timingInvalid) || (aid == timingInvalid_SM_T24) || (aid == timingApple_FixedRateLCD) || (aid == timingGTF_640x480_120hz) || (aid == timingAppleNTSC_ST) || (aid == timingAppleNTSC_FF) || (aid == timingAppleNTSC_STconv) || (aid == timingAppleNTSC_FFconv) || (aid == timingApplePAL_ST) || (aid == timingApplePAL_FF) || (aid == timingApplePAL_STconv) || (aid == timingApplePAL_FFconv) || (aid == timingSMPTE240M_60hz) || (aid == timingFilmRate_48hz) || (aid == timingApple_0x0_0hz_Offline)) continue; if(modeInfo->flags & (1<refreshRate = 72 << 16; // from 72.8 sprintf(key, "%ld", ((modeInfo->nominalWidth << 20) | (modeInfo->nominalHeight << 8) | ((modeInfo->refreshRate + 0x8000) >> 16))); cfStr = CFStringCreateWithCString( kCFAllocatorDefault, key, kCFStringEncodingMacRoman ); if (CFDictionaryGetValue( timingIDs, cfStr )) printf("%ld timing id dup\n", aid); else { printf("ADDING\n"); CFDictionarySetValue( timingIDs, cfStr, num ); } } sprintf(key, "%ld", aid); cfStr = CFStringCreateWithCString( kCFAllocatorDefault, key, kCFStringEncodingMacRoman ); keys [0] = CFSTR(kIOFBModeTMKey); values[0] = data; keys [1] = CFSTR(kIOFBModeAIDKey); values[1] = num; dict = CFDictionaryCreate( kCFAllocatorDefault, keys, values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); assert(dict); if (CFDictionaryGetValue( stdModes, cfStr )) printf("%ld timing id dup\n", aid); else { printf("ADDING\n"); CFDictionarySetValue( stdModes, cfStr, dict ); } CFRelease(dict); } CFDictionarySetValue(result, CFSTR("std-modes"), stdModes); CFDictionarySetValue(result, CFSTR("timing-ids"), timingIDs); data = CFPropertyListCreateXMLData( kCFAllocatorDefault, result ); if (data) { char * str = (char *) CFDataGetBytePtr(data); str[CFDataGetLength(data)] = 0; printf( str ); } } exit(0); return(0); }