#include "env.h"
#include "randr-edid.h"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>
#include <stdlib.h>
using namespace P8PLATFORM;
static const char * const edid_names[] =
{
#if (RANDR_MAJOR > 1) || (RANDR_MAJOR == 1 && RANDR_MINOR >2)
RR_PROPERTY_RANDR_EDID,
#else
"EDID",
#endif
"EDID_DATA",
"XFree86_DDC_EDID1_RAWDATA"
};
#define EDID_NAME_COUNT (sizeof(edid_names)/sizeof(*edid_names))
uint16_t CRandrEdidParser::GetPhysicalAddress(void)
{
uint16_t physical_address = 0;
Display *disp = XOpenDisplay(NULL);
if( disp )
{
int event_base, error_base;
int maj, min;
if( XRRQueryExtension(disp, &event_base, &error_base)
&& XRRQueryVersion(disp, &maj, &min) )
{
int version = (maj << 8) | min;
if( version >= 0x0102 )
{
size_t atom_avail = 0;
Atom edid_atoms[EDID_NAME_COUNT];
if( XInternAtoms(disp, (char **)edid_names, EDID_NAME_COUNT, True, edid_atoms) )
{
atom_avail = 0;
for(size_t atom_count=0; atom_count<EDID_NAME_COUNT; ++atom_count)
{
Atom edid_atom = edid_atoms[atom_count];
if( None != edid_atom )
{
if( atom_avail < atom_count )
{
edid_atoms[atom_avail] = edid_atom;
}
++atom_avail;
}
}
}
if( atom_avail > 0 )
{
int scr_count = ScreenCount(disp);
int screen;
for(screen=0; screen<scr_count; ++screen)
{
XRRScreenResources *rsrc = NULL;
Window root = RootWindow(disp, screen);
#if (RANDR_MAJOR > 1) || (RANDR_MAJOR == 1 && RANDR_MINOR >=3)
if( version >= 0x0103 )
{
rsrc = XRRGetScreenResourcesCurrent(disp, root);
}
if( NULL == rsrc )
#endif
rsrc = XRRGetScreenResources(disp, root);
if( NULL != rsrc )
{
int output_id;
for( output_id=0; 0 == physical_address && output_id < rsrc->noutput; ++output_id )
{
RROutput rr_output_id = rsrc->outputs[output_id];
XRROutputInfo *output_info = XRRGetOutputInfo(disp, rsrc, rr_output_id);
if( NULL != output_info )
{
if( RR_Connected == output_info->connection )
{
for(size_t atom_count=0; 0 == physical_address && atom_count<atom_avail; ++atom_count)
{
Atom actual_type;
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *data;
int status;
status = XRRGetOutputProperty(disp, rr_output_id, edid_atoms[atom_count], 0, 128, False, False,
AnyPropertyType, &actual_type, &actual_format,
&nitems, &bytes_after, &data);
if( Success == status )
{
if((actual_type == XA_INTEGER) && (actual_format == 8) )
{
physical_address = CEDIDParser::GetPhysicalAddressFromEDID(data, nitems);
}
XFree(data);
}
}
}
XRRFreeOutputInfo(output_info);
}
else
break;
}
XRRFreeScreenResources(rsrc);
}
}
}
}
}
XCloseDisplay(disp);
}
return physical_address;
}