15ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson""" 25ff4624633a375231c052b38510f279c9f2bbc28Corbin SimpsonA wrapper around the Direct Rendering Manager (DRM) library, which itself is a 35ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonwrapper around the Direct Rendering Interface (DRI) between the kernel and 45ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonuserland. 55ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 65ff4624633a375231c052b38510f279c9f2bbc28Corbin SimpsonSince we are masochists, we use ctypes instead of cffi to load libdrm and 75ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonaccess several symbols within it. We use Python's file descriptor and mmap 85ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonwrappers. 95ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 105ff4624633a375231c052b38510f279c9f2bbc28Corbin SimpsonAt some point in the future, cffi could be used, for approximately the same 115ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsoncost in lines of code. 125ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson""" 135ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 145ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonfrom ctypes import * 155ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonimport mmap 165ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonimport os 175f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedelimport subprocess 185ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 19c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr# drmModeConnection enum 20c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTED = 1 21c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_DISCONNECTED = 2 22c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_UNKNOWNCONNECTION = 3 23c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 24c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_Unknown = 0 25c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_VGA = 1 26c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_DVII = 2 27c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_DVID = 3 28c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_DVIA = 4 29c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_Composite = 5 30c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_SVIDEO = 6 31c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_LVDS = 7 32c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_Component = 8 33c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_9PinDIN = 9 34c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_DisplayPort = 10 35c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_HDMIA = 11 36c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_HDMIB = 12 37c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_TV = 13 38c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_eDP = 14 39c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_VIRTUAL = 15 40c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik BehrDRM_MODE_CONNECTOR_DSI = 16 41c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 42557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss# This constant is not defined in any one header; it is the pieced-together 43557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss# incantation for the ioctl that performs dumb mappings. I would love for this 44557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss# to not have to be here, but it can't be imported from any header easily. 45557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe KnissDRM_IOCTL_MODE_MAP_DUMB = 0xc01064b3 46557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss 47557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss# This define should be equal to O_CLOEXEC, which should be available in 48557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss# python's os module, but isn't until version 3.3. If we version up, we can 49557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss# set this to os.O_CLOEXEC. 50557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe KnissDRM_CLOEXEC = 02000000 51557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss 525ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 535ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonclass DrmVersion(Structure): 545ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 555ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson The version of a DRM node. 565ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 575ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 585ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _fields_ = [ 595ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("version_major", c_int), 605ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("version_minor", c_int), 615ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("version_patchlevel", c_int), 625ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("name_len", c_int), 635ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("name", c_char_p), 645ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("date_len", c_int), 655ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("date", c_char_p), 665ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("desc_len", c_int), 675ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("desc", c_char_p), 685ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ] 695ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 705ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _l = None 715ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 725ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __repr__(self): 735f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel return "%s %d.%d.%d (%s) (%s)" % (self.name, 745f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.version_major, 755f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.version_minor, 765f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.version_patchlevel, 775f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.desc, 785f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.date,) 795ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 805ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __del__(self): 815ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self._l: 825ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._l.drmFreeVersion(self) 835ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 845ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 855ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonclass DrmModeResources(Structure): 865ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 875ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Resources associated with setting modes on a DRM node. 885ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 895ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 905ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _fields_ = [ 915ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("count_fbs", c_int), 925ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("fbs", POINTER(c_uint)), 935ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("count_crtcs", c_int), 945ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("crtcs", POINTER(c_uint)), 95d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("count_connectors", c_int), 96d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("connectors", POINTER(c_uint)), 97d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("count_encoders", c_int), 98d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("encoders", POINTER(c_uint)), 99d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("min_width", c_int), 100d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("max_width", c_int), 101d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("min_height", c_int), 102d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("max_height", c_int), 1035ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ] 1045ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1055ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _fd = None 1065ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _l = None 1075ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1085ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __repr__(self): 1095ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return "<DRM mode resources>" 1105ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1115ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __del__(self): 1125ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self._l: 1135ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._l.drmModeFreeResources(self) 1145ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1155f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel def _wakeup_screen(self): 1165f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel """ 1175f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel Send a synchronous dbus message to power on screen. 1185f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel """ 1195f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel # Get and process reply to make this synchronous. 1205f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel subprocess.check_output([ 1215f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel "dbus-send", "--type=method_call", "--system", "--print-reply", 1225f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel "--dest=org.chromium.PowerManager", "/org/chromium/PowerManager", 1235f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel "org.chromium.PowerManager.HandleUserActivity", "int32:0" 1245f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel ]) 1255f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel 126d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel def getValidCrtc(self): 127d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel for i in xrange(0, self.count_crtcs): 128d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel crtc_id = self.crtcs[i] 129d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel crtc = self._l.drmModeGetCrtc(self._fd, crtc_id).contents 130d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel if crtc.mode_valid: 131d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel return crtc 132d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel return None 133d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel 1345f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel def getCrtc(self, crtc_id): 1355ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 1365ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Obtain the CRTC at a given index. 1375ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 138c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang @param crtc_id: The CRTC to get. 1395ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 140d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel if crtc_id: 1415f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel return self._l.drmModeGetCrtc(self._fd, crtc_id).contents 1425f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel return self.getValidCrtc() 1435f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel 1445f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel def getCrtcRobust(self, crtc_id=None): 1455f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel crtc = self.getCrtc(crtc_id) 1465f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel if crtc is None: 1475f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self._wakeup_screen() 1485f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel crtc = self.getCrtc(crtc_id) 1495f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel if crtc is not None: 1505f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel crtc._fd = self._fd 1515f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel crtc._l = self._l 1525ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return crtc 1535ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1545ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 155c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behrclass DrmModeModeInfo(Structure): 156c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr """ 157c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr A DRM modesetting mode info. 158c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr """ 159c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 160c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _fields_ = [ 161c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("clock", c_uint), 162c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("hdisplay", c_ushort), 163c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("hsync_start", c_ushort), 164c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("hsync_end", c_ushort), 165c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("htotal", c_ushort), 166c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("hskew", c_ushort), 167c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("vdisplay", c_ushort), 168c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("vsync_start", c_ushort), 169c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("vsync_end", c_ushort), 170c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("vtotal", c_ushort), 171c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("vscan", c_ushort), 172c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("vrefresh", c_uint), 173c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("flags", c_uint), 174c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("type", c_uint), 175c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("name", c_char * 32), 176c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ] 177c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 178c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 1795ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonclass DrmModeCrtc(Structure): 1805ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 1815ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson A DRM modesetting CRTC. 1825ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 1835ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1845ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _fields_ = [ 1855ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("crtc_id", c_uint), 1865ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("buffer_id", c_uint), 187d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("x", c_uint), 188d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("y", c_uint), 189d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("width", c_uint), 190d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("height", c_uint), 191d2c9f442b031fc47f6196b92bb96ecbbd796c10cIlja H. Friedel ("mode_valid", c_int), 192c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("mode", DrmModeModeInfo), 193c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("gamma_size", c_int), 1945ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ] 1955ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1965ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _fd = None 1975ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _l = None 1985ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 1995ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __repr__(self): 2005ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return "<CRTC (%d)>" % self.crtc_id 2015ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 2025ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __del__(self): 2035ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self._l: 2045ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._l.drmModeFreeCrtc(self) 2055ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 2065ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def hasFb(self): 2075ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 2085ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Whether this CRTC has an associated framebuffer. 2095ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 2105ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 2115ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return self.buffer_id != 0 2125ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 2135ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def fb(self): 2145ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 2155ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Obtain the framebuffer, if one is associated. 2165ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 2175ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 2185ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self.hasFb(): 2195ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson fb = self._l.drmModeGetFB(self._fd, self.buffer_id).contents 2205ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson fb._fd = self._fd 2215ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson fb._l = self._l 2225ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return fb 223f2a4b9f6e2697ef7f6c82b7f276e9e102b61e62bCorbin Simpson else: 224f2a4b9f6e2697ef7f6c82b7f276e9e102b61e62bCorbin Simpson raise RuntimeError("CRTC %d doesn't have a framebuffer!" % 225d94feb65407b07bd2c17ffd94cfcace57f9d0650Ilja H. Friedel self.crtc_id) 2265ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 2275ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 228c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behrclass DrmModeEncoder(Structure): 229c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr """ 230c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr A DRM modesetting encoder. 231c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr """ 232c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 233c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _fields_ = [ 234c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("encoder_id", c_uint), 235c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("encoder_type", c_uint), 236c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("crtc_id", c_uint), 237c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("possible_crtcs", c_uint), 238c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("possible_clones", c_uint), 239c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ] 240c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 241c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _fd = None 242c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _l = None 243c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 244c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def __repr__(self): 245c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return "<Encoder (%d)>" % self.encoder_id 246c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 247c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def __del__(self): 248c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if self._l: 249c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr self._l.drmModeFreeEncoder(self) 250c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 251c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 252c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behrclass DrmModeConnector(Structure): 253c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr """ 254c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr A DRM modesetting connector. 255c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr """ 256c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 257c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _fields_ = [ 258c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("connector_id", c_uint), 259c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("encoder_id", c_uint), 260c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("connector_type", c_uint), 261c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("connector_type_id", c_uint), 262c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("connection", c_uint), # drmModeConnection enum 263c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("mmWidth", c_uint), 264c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("mmHeight", c_uint), 265c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("subpixel", c_uint), # drmModeSubPixel enum 266c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("count_modes", c_int), 267c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("modes", POINTER(DrmModeModeInfo)), 268c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("count_propts", c_int), 269c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("props", POINTER(c_uint)), 270c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("prop_values", POINTER(c_ulonglong)), 271c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("count_encoders", c_int), 272c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ("encoders", POINTER(c_uint)), 273c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ] 274c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 275c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _fd = None 276c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _l = None 277c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 278c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def __repr__(self): 279c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return "<Connector (%d)>" % self.connector_id 280c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 281c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def __del__(self): 282c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if self._l: 283c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr self._l.drmModeFreeConnector(self) 284c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 285c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def isInternal(self): 286c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return (self.connector_type == DRM_MODE_CONNECTOR_LVDS or 287c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr self.connector_type == DRM_MODE_CONNECTOR_eDP or 288c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr self.connector_type == DRM_MODE_CONNECTOR_DSI) 289c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 290c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def isConnected(self): 291c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return self.connection == DRM_MODE_CONNECTED 292c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 293c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 2945ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonclass drm_mode_map_dumb(Structure): 2955ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 2965ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Request a mapping of a modesetting buffer. 2975ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 2985ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson The map will be "dumb;" it will be accessible via mmap() but very slow. 2995ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3005ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3015ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _fields_ = [ 3025ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("handle", c_uint), 3035ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("pad", c_uint), 3045ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("offset", c_ulonglong), 3055ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ] 3065ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3075ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3085ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonclass DrmModeFB(Structure): 3095ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3105ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson A DRM modesetting framebuffer. 3115ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3125ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3135ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _fields_ = [ 3145ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("fb_id", c_uint), 3155ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("width", c_uint), 3165ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("height", c_uint), 3175ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("pitch", c_uint), 3185ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("bpp", c_uint), 3195ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("depth", c_uint), 3205ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ("handle", c_uint), 3215ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson ] 3225ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3235ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _l = None 3245ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson _map = None 3255ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3265ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __repr__(self): 3275ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson s = "<Framebuffer (%dx%d (pitch %d bytes), %d bits/pixel, depth %d)" 3285f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel vitals = s % (self.width, 3295f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.height, 3305f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.pitch, 3315f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.bpp, 3325f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self.depth,) 3335ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self._map: 3345ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson tail = " (mapped)>" 3355ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson else: 3365ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson tail = ">" 3375ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return vitals + tail 3385ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3395ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __del__(self): 3405ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self._l: 3415ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._l.drmModeFreeFB(self) 3425ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 343d0762edbad798a5203df727ddb9eab2d24fdc860Haixia Shi def map(self, size): 3445ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3455ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Map the framebuffer. 3465ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3475ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3485ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self._map: 3495ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return 3505ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3515ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson mapDumb = drm_mode_map_dumb() 3525ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson mapDumb.handle = self.handle 3535ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3545ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson rv = self._l.drmIoctl(self._fd, DRM_IOCTL_MODE_MAP_DUMB, 355d94feb65407b07bd2c17ffd94cfcace57f9d0650Ilja H. Friedel pointer(mapDumb)) 3565ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if rv: 3575ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson raise IOError(rv, os.strerror(rv)) 3585ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3595ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson # mmap.mmap() has a totally different order of arguments in Python 3605ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson # compared to C; check the documentation before altering this 3615ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson # incantation. 3625f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel self._map = mmap.mmap(self._fd, 3635f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel size, 3645f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel flags=mmap.MAP_SHARED, 3655f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel prot=mmap.PROT_READ, 3665f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel offset=mapDumb.offset) 3675ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3685ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def unmap(self): 3695ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3705ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Unmap the framebuffer. 3715ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3725ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3735ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson if self._map: 3745ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._map.close() 3755ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._map = None 3765ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 377557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss def getFD(self): 378557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss """ 379557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss Convert handle to a FD. 380557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss """ 381557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss prime_fd = c_int(0) 382557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss rv = self._l.drmPrimeHandleToFD(self._fd, self.handle, 383557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss DRM_CLOEXEC, byref(prime_fd)) 384557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss if rv: 385557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss raise RuntimeError("Failed to convert FB handle to FD. %d" % rv) 386557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss return prime_fd 3875ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3885ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsondef loadDRM(): 3895ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3905ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Load a handle to libdrm. 3915ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 3925ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson In addition to loading, this function also configures the argument and 3935ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return types of functions. 3945ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 3955ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 396c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l = None 397c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 398c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr try: 399c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l = cdll.LoadLibrary("libdrm.so") 400c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr except OSError: 401c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l = cdll.LoadLibrary("libdrm.so.2") # ubuntu doesn't have libdrm.so 4025ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4035ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmGetVersion.argtypes = [c_int] 4045ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmGetVersion.restype = POINTER(DrmVersion) 4055ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4065ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmFreeVersion.argtypes = [POINTER(DrmVersion)] 4075ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmFreeVersion.restype = None 4085ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4095ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeGetResources.argtypes = [c_int] 4105ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeGetResources.restype = POINTER(DrmModeResources) 4115ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4125ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeFreeResources.argtypes = [POINTER(DrmModeResources)] 4135ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeFreeResources.restype = None 4145ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4155ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeGetCrtc.argtypes = [c_int, c_uint] 4165ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeGetCrtc.restype = POINTER(DrmModeCrtc) 4175ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4185ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeFreeCrtc.argtypes = [POINTER(DrmModeCrtc)] 4195ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeFreeCrtc.restype = None 4205ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 421c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeGetEncoder.argtypes = [c_int, c_uint] 422c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeGetEncoder.restype = POINTER(DrmModeEncoder) 423c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 424c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeFreeEncoder.argtypes = [POINTER(DrmModeEncoder)] 425c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeFreeEncoder.restype = None 426c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 427c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeGetConnector.argtypes = [c_int, c_uint] 428c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeGetConnector.restype = POINTER(DrmModeConnector) 429c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 430c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeFreeConnector.argtypes = [POINTER(DrmModeConnector)] 431c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr l.drmModeFreeConnector.restype = None 432c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 4335ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeGetFB.argtypes = [c_int, c_uint] 4345ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeGetFB.restype = POINTER(DrmModeFB) 4355ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4365ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeFreeFB.argtypes = [POINTER(DrmModeFB)] 4375ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmModeFreeFB.restype = None 4385ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4395ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmIoctl.argtypes = [c_int, c_ulong, c_voidp] 4405ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson l.drmIoctl.restype = c_int 4415ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 442557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss l.drmPrimeHandleToFD.argtypes = [c_int, c_uint, c_uint, POINTER(c_int)] 443557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss l.drmPrimeHandleToFD.restype = c_int 444557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss 4455ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return l 4465ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4475ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4485ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpsonclass DRM(object): 4495ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4505ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson A DRM node. 4515ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4525ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4535ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __init__(self, library, fd): 4545ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._l = library 4555ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._fd = fd 4565ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4575ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def __repr__(self): 4585ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return "<DRM (FD %d)>" % self._fd 4595ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4605ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson @classmethod 4615ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def fromHandle(cls, handle): 4625ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4635ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Create a node from a file handle. 4645ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4655ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson @param handle: A file-like object backed by a file descriptor. 4665ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4675ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4685ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self = cls(loadDRM(), handle.fileno()) 4695ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson # We must keep the handle alive, and we cannot trust the caller to 4705ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson # keep it alive for us. 4715ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson self._handle = handle 4725ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return self 4735ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4745ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def version(self): 4755ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4765ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Obtain the version. 4775ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4785ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4795ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson v = self._l.drmGetVersion(self._fd).contents 4805ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson v._l = self._l 4815ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return v 4825ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 4835ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson def resources(self): 4845ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4855ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson Obtain the modesetting resources. 4865ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 4875ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 488c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang resources_ptr = self._l.drmModeGetResources(self._fd) 489c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang if resources_ptr: 490c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang r = resources_ptr.contents 491c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang r._fd = self._fd 492c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang r._l = self._l 493c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang return r 494c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang 495c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang return None 4965ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 497c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def getCrtc(self, crtc_id): 498c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c_ptr = self._l.drmModeGetCrtc(self._fd, crtc_id) 499c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if c_ptr: 500c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c = c_ptr.contents 501c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c._fd = self._fd 502c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c._l = self._l 503c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return c 504c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 505c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return None 506c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 507c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def getEncoder(self, encoder_id): 508c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr e_ptr = self._l.drmModeGetEncoder(self._fd, encoder_id) 509c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if e_ptr: 510c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr e = e_ptr.contents 511c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr e._fd = self._fd 512c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr e._l = self._l 513c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return e 514c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 515c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return None 516c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 517c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr def getConnector(self, connector_id): 518c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c_ptr = self._l.drmModeGetConnector(self._fd, connector_id) 519c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if c_ptr: 520c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c = c_ptr.contents 521c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c._fd = self._fd 522c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr c._l = self._l 523c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return c 524c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 525c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr return None 526c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 527c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 5285ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 529c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huangdef drmFromPath(path): 5305ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 531c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang Given a DRM node path, open the corresponding node. 5325ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 533c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang @param path: The path of the minor node to open. 5345ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 535557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss # Always open the device as RW (r+) so that mmap works later. 536557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss handle = open(path, "r+") 5375ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson return DRM.fromHandle(handle) 5385ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 5395ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson 540c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang_drm = None 541c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang 5425f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel 543557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Knissdef getCrtc(crtc_id=None): 5445ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 545557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss @param crtc_id: None for first found CRTC with mode set 546c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr or "internal" for crtc connected to internal LCD 547c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr or "external" for crtc connected to external display 548c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr or "usb" "evdi" or "udl" for crtc with valid mode on evdi or 549c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr udl display 550c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr or DRM integer crtc_id 5515ff4624633a375231c052b38510f279c9f2bbc28Corbin Simpson """ 552c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang global _drm 553c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 554c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang if not _drm: 555c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr paths = [ 556c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr "/dev/dri/" + n 557c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for n in filter(lambda x: x.startswith("card"), 558c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr os.listdir("/dev/dri")) 559c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr ] 560c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 561c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if crtc_id == "usb" or crtc_id == "evdi" or crtc_id == "udl": 562c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for p in paths: 563c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr d = drmFromPath(p) 564c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr v = d.version() 565c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 566c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if crtc_id == v.name: 567c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _drm = d 568c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 569c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 570c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if crtc_id == "usb" and (v.name == "evdi" or v.name == "udl"): 571c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _drm = d 572c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 573c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 574c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr elif crtc_id == "internal" or crtc_id == "external": 575c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr internal = crtc_id == "internal" 576c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for p in paths: 577c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr d = drmFromPath(p) 578c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if d.resources() is None: 579c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr continue 580c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if d.resources() and d.resources().count_connectors > 0: 581c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for c in xrange(0, d.resources().count_connectors): 582c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr connector = d.getConnector(d.resources().connectors[c]) 583c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if (internal == connector.isInternal() 584c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr and connector.isConnected() 585c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr and connector.encoder_id != 0): 586c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr e = d.getEncoder(connector.encoder_id) 587c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr crtc = d.getCrtc(e.crtc_id) 588c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if crtc.mode_valid: 589c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr crtc_id = crtc.crtc_id 590c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _drm = d 591c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 592c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if _drm: 593c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 594c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 595c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr elif crtc_id is None or crtc_id == 0: 596c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for p in paths: 597c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr d = drmFromPath(p) 598c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if d.resources() is None: 599c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr continue 600c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for c in xrange(0, d.resources().count_crtcs): 601c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr crtc = d.getCrtc(d.resources().crtcs[c]) 602c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if crtc.mode_valid: 603c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr crtc_id = d.resources().crtcs[c] 604c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _drm = d 605c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 606c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if _drm: 607c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 608c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr 609c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr else: 610c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for p in paths: 611c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr d = drmFromPath(p) 612c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if d.resources() is None: 613c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr continue 614c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr for c in xrange(0, d.resources().count_crtcs): 615c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if crtc_id == d.resources().crtcs[c]: 616c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr _drm = d 617c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 618c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr if _drm: 619c4d29ea43d5700dd9924e81d148384f5d63a09f1Dominik Behr break 620c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang 621c5c4cfb286ad25e89a9ab298c56d8e656b615fd0Yuli Huang if _drm: 622557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss return _drm.resources().getCrtcRobust(crtc_id) 6235f4922c627d9eb895f6fcf35e1e19b090a5894a8Ilja H. Friedel 624557946d18d625f8c14e0a1bf6a23d91b17d70f1dJoe Kniss return None 625