1// cc -o /tmp/modesuck -g modesuck.c -framework ApplicationServices -framework IOKit -Wall 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 <math.h> 9#include <unistd.h> 10#include <string.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <assert.h> 14 15#include <IOKit/IOKitLib.h> 16#include <IOKit/graphics/IOGraphicsTypesPrivate.h> 17#include <ApplicationServices/ApplicationServices.h> 18 19 20__private_extern__ IOReturn 21readFile(const char *path, vm_offset_t * objAddr, vm_size_t * objSize) 22{ 23 int fd; 24 int err; 25 struct stat stat_buf; 26 27 *objAddr = 0; 28 *objSize = 0; 29 30 if((fd = open(path, O_RDONLY)) == -1) 31 return errno; 32 33 do { 34 if(fstat(fd, &stat_buf) == -1) { 35 err = errno; 36 continue; 37 } 38 if (0 == (stat_buf.st_mode & S_IFREG)) 39 { 40 *objAddr = 0; 41 *objSize = 0; 42 err = kIOReturnNotReadable; 43 continue; 44 } 45 *objSize = stat_buf.st_size; 46 47 if( KERN_SUCCESS != map_fd(fd, 0, objAddr, TRUE, *objSize)) { 48 *objAddr = 0; 49 *objSize = 0; 50 err = errno; 51 continue; 52 } 53 54 err = kIOReturnSuccess; 55 56 } while( false ); 57 58 close(fd); 59 60 return( err ); 61} 62 63__private_extern__ CFMutableDictionaryRef 64readPlist( const char * path, UInt32 key ) 65{ 66 IOReturn err; 67 vm_offset_t bytes; 68 vm_size_t byteLen; 69 CFDataRef data; 70 CFMutableDictionaryRef obj = 0; 71 72 err = readFile( path, &bytes, &byteLen ); 73 74 if( kIOReturnSuccess != err) 75 return (0); 76 77 data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, 78 (const UInt8 *) bytes, byteLen, kCFAllocatorNull ); 79 if( data) { 80 obj = (CFMutableDictionaryRef) CFPropertyListCreateFromXMLData( kCFAllocatorDefault, data, 81 kCFPropertyListMutableContainers, 82 (CFStringRef *) NULL ); 83 CFRelease( data ); 84 } 85 vm_deallocate( mach_task_self(), bytes, byteLen ); 86 87 return (obj); 88} 89 90int main(int argc, char * argv[]) 91{ 92 io_service_t framebuffer; 93 CGError err; 94 int i; 95 CGDisplayCount max; 96 CGDirectDisplayID displayIDs[8]; 97 IODisplayModeInformation * modeInfo; 98 IODetailedTimingInformationV2 *timingInfo; 99 100 CFDictionaryRef dict; 101 CFArrayRef modes; 102 CFIndex count; 103 CFDictionaryRef mode; 104 CFMutableDictionaryRef result, stdModes, timingIDs; 105 CFDataRef data; 106 CFNumberRef num; 107 CFStringRef cfStr; 108 char key[64]; 109 const void * keys[2]; 110 const void * values[2]; 111 112 err = CGGetOnlineDisplayList(8, displayIDs, &max); 113 if(err != kCGErrorSuccess) 114 exit(1); 115 if(max > 8) 116 max = 8; 117 118 for(i = 0; i < max; i++ ) { 119 120 framebuffer = CGDisplayIOServicePort(displayIDs[i]); 121 122 dict = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBConfigKey), 123 kCFAllocatorDefault, kNilOptions); 124 assert(dict); 125 126 modes = CFDictionaryGetValue(dict, CFSTR(kIOFBModesKey)); 127 assert(modes); 128 129 130 result = readPlist("/System/Library/Frameworks/IOKit.framework/" 131 "Resources/IOGraphicsProperties.plist", 0); 132 133 if (result) 134 { 135 stdModes = (CFMutableDictionaryRef) CFDictionaryGetValue(result, CFSTR("std-modes")); 136 assert(stdModes); 137 timingIDs = (CFMutableDictionaryRef) CFDictionaryGetValue(result, CFSTR("timing-ids")); 138 assert(timingIDs); 139 140 data = CFDictionaryGetValue(result, CFSTR("apple-edid")); 141 if (data) 142 { 143 UInt32 ids[24] = { 0 }; 144 145 UInt32 * p = (UInt32 *) CFDataGetBytePtr(data); 146 int i; 147 148 for( i = 0; i < (CFDataGetLength(data)/4); i+=2) 149 { 150 UInt32 bit, id; 151 id = p[i]; 152 bit = p[i + 1] >> 16; 153 if( bit < 24) 154 { 155 bit = (0x10 - (bit & 0xf8)) | (bit & 7); 156 157 if( ids[bit]) 158 printf("bit %ld, id %ld dup\n", bit, id); 159 else 160 ids[bit] = id; 161 } 162 } 163 164 data = CFDataCreate( kCFAllocatorDefault, 165 (const UInt8 *) ids, sizeof(ids) ); 166 CFDictionarySetValue( result, CFSTR("established-ids"), data); 167 CFRelease(data); 168 } 169 } 170 else 171 { 172 result = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, 173 &kCFTypeDictionaryKeyCallBacks, 174 &kCFTypeDictionaryValueCallBacks ); 175 assert(result); 176 177 stdModes = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, 178 &kCFTypeDictionaryKeyCallBacks, 179 &kCFTypeDictionaryValueCallBacks ); 180 assert(stdModes); 181 timingIDs = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, 182 &kCFTypeDictionaryKeyCallBacks, 183 &kCFTypeDictionaryValueCallBacks ); 184 assert(timingIDs); 185 } 186 187 count = CFArrayGetCount(modes); 188 for (i = 0; i < count; i++) 189 { 190 SInt32 aid; 191 192 mode = CFArrayGetValueAtIndex(modes, i); 193 194 num = CFDictionaryGetValue(mode, CFSTR(kIOFBModeAIDKey)); 195 if (num) 196 CFNumberGetValue( num, kCFNumberSInt32Type, &aid ); 197 else 198 aid = timingInvalid; 199 200 data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeDMKey)); 201 if (!data) 202 continue; 203 modeInfo = (IODisplayModeInformation *) CFDataGetBytePtr(data); 204 205 data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeTMKey)); 206 if (!data) 207 continue; 208 timingInfo = (IODetailedTimingInformationV2 *) CFDataGetBytePtr(data); 209 210 printf("%ldx%ld@%ld, %ld\n", modeInfo->nominalWidth, modeInfo->nominalHeight, ((modeInfo->refreshRate + 0x8000) >> 16), aid); 211 212if( timingInfo->horizontalActive & 7) printf("horizontalActive & 7\n"); 213if( timingInfo->horizontalBlanking & 7) printf("horizontalBlanking & 7\n"); 214if( timingInfo->horizontalSyncOffset & 7) printf("horizontalSyncOffset & 7\n"); 215if( timingInfo->horizontalSyncPulseWidth & 7) printf("horizontalSyncPulseWidth & 7\n"); 216 217 218 if( (aid == timingInvalid) 219 || (aid == timingInvalid_SM_T24) 220 || (aid == timingApple_FixedRateLCD) 221 || (aid == timingGTF_640x480_120hz) 222 || (aid == timingAppleNTSC_ST) 223 || (aid == timingAppleNTSC_FF) 224 || (aid == timingAppleNTSC_STconv) 225 || (aid == timingAppleNTSC_FFconv) 226 || (aid == timingApplePAL_ST) 227 || (aid == timingApplePAL_FF) 228 || (aid == timingApplePAL_STconv) 229 || (aid == timingApplePAL_FFconv) 230 || (aid == timingSMPTE240M_60hz) 231 || (aid == timingFilmRate_48hz) 232 || (aid == timingApple_0x0_0hz_Offline)) 233 continue; 234 235if(modeInfo->flags & (1<<kModeShowNever)) 236{ 237 printf("nv!\n"); 238 continue; 239} 240 241 if( true 242 && (aid != timingApple_1024x768_75hz) 243 ) 244 { 245 246 if( aid == timingVESA_640x480_72hz) 247 modeInfo->refreshRate = 72 << 16; // from 72.8 248 249 sprintf(key, "%ld", ((modeInfo->nominalWidth << 20) | (modeInfo->nominalHeight << 8) | ((modeInfo->refreshRate + 0x8000) >> 16))); 250 251 cfStr = CFStringCreateWithCString( kCFAllocatorDefault, key, 252 kCFStringEncodingMacRoman ); 253 if (CFDictionaryGetValue( timingIDs, cfStr )) 254 printf("%ld timing id dup\n", aid); 255 else 256 { 257 printf("ADDING\n"); 258 CFDictionarySetValue( timingIDs, cfStr, num ); 259 } 260 } 261 262 sprintf(key, "%ld", aid); 263 264 cfStr = CFStringCreateWithCString( kCFAllocatorDefault, key, 265 kCFStringEncodingMacRoman ); 266 267 keys [0] = CFSTR(kIOFBModeTMKey); 268 values[0] = data; 269 keys [1] = CFSTR(kIOFBModeAIDKey); 270 values[1] = num; 271 272 dict = CFDictionaryCreate( kCFAllocatorDefault, keys, values, 1, 273 &kCFTypeDictionaryKeyCallBacks, 274 &kCFTypeDictionaryValueCallBacks ); 275 276 assert(dict); 277 278 if (CFDictionaryGetValue( stdModes, cfStr )) 279 printf("%ld timing id dup\n", aid); 280 else 281 { 282 printf("ADDING\n"); 283 CFDictionarySetValue( stdModes, cfStr, dict ); 284 } 285 CFRelease(dict); 286 287 } 288 289 CFDictionarySetValue(result, CFSTR("std-modes"), stdModes); 290 CFDictionarySetValue(result, CFSTR("timing-ids"), timingIDs); 291 292 data = CFPropertyListCreateXMLData( kCFAllocatorDefault, result ); 293 if (data) 294 { 295 char * str = (char *) CFDataGetBytePtr(data); 296 str[CFDataGetLength(data)] = 0; 297 printf( str ); 298 } 299 300 } 301 302 exit(0); 303 return(0); 304} 305