diff options
| author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2019-01-10 13:59:34 +0200 | 
|---|---|---|
| committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2019-01-14 09:27:28 +0200 | 
| commit | f63f1b1a16269ddcce75a61d540429fe3d41cfc8 (patch) | |
| tree | 33208ee6969537d7c4d732ba5f052699bdf185e9 /kms++/src | |
| parent | 21c70a626cef72804f0ea270ffbae803e76e5b71 (diff) | |
Card: improve DRM card selection
Add new Card constructor:
Card(const std::string& driver, uint32_t idx)
which can be used to open Nth card for the given driver.
The default constructor behavior is:
- If KMSXX_DEVICE env variable is set, the card device with that path is
  opened.
- If KMSXX_DRIVER env variable is set, the card with the given driver
  name and index is opened. The format is either "drvname" or
  "drvname:idx".
- If neither env variable is given, open /dev/dri/card0
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'kms++/src')
| -rw-r--r-- | kms++/src/card.cpp | 91 | 
1 files changed, 85 insertions, 6 deletions
| diff --git a/kms++/src/card.cpp b/kms++/src/card.cpp index a5c6d53..5d6a597 100644 --- a/kms++/src/card.cpp +++ b/kms++/src/card.cpp @@ -6,6 +6,7 @@  #include <string.h>  #include <algorithm>  #include <cerrno> +#include <algorithm>  #include <xf86drm.h>  #include <xf86drmMode.h> @@ -17,19 +18,97 @@ using namespace std;  namespace kms  { +static int open_device_by_path(string path) +{ +	int fd = open(path.c_str(), O_RDWR | O_CLOEXEC); +	if (fd < 0) +		throw invalid_argument(string(strerror(errno)) + " opening device " + path); +	return fd; +} + +// open Nth DRM card with the given driver name +static int open_device_by_driver(string name, uint32_t idx) +{ +	uint32_t matches = 0; + +	transform(name.begin(), name.end(), name.begin(), ::tolower); + +	for (uint32_t i = 0; ; ++i) { +		string path = "/dev/dri/card" + to_string(i); + +		int fd = open(path.c_str(), O_RDWR | O_CLOEXEC); +		if (fd < 0) { +			// presume no more card nodes +			throw invalid_argument("no card found for " + name + ":" + to_string(idx)); +		} + +		drmVersionPtr ver = drmGetVersion(fd); +		string drv_name = string(ver->name, ver->name_len); +		drmFreeVersion(ver); + +		transform(drv_name.begin(), drv_name.end(), drv_name.begin(), ::tolower); + +		if (name == drv_name) { +			if (idx == matches) +				return fd; +			matches++; +		} + +		close(fd); +	} +} +  Card::Card() -	: Card("/dev/dri/card0")  { +	const char* drv_p = getenv("KMSXX_DRIVER"); +	const char* dev_p = getenv("KMSXX_DEVICE"); + +	if (dev_p) { +		string dev(dev_p); +		m_fd = open_device_by_path(dev); +	} else if (drv_p) { +		string drv(drv_p); + +		auto isplit = find(drv.begin(), drv.end(), ':'); + +		if (isplit == drv.begin()) +			throw runtime_error("Invalid KMSXX_DRIVER"); + +		string name; +		uint32_t num = 0; + +		if (isplit == drv.end()) { +			name = drv; +		} else { +			name = string(drv.begin(), isplit); +			string numstr = string(isplit + 1, drv.end()); +			num = stoul(numstr); +		} + +		m_fd = open_device_by_driver(name, num); +	} else { +		m_fd = open_device_by_path("/dev/dri/card0"); +	} + +	setup();  } +Card::Card(const std::string& driver, uint32_t idx) +{ +	m_fd = open_device_by_driver(driver, idx); + +	setup(); +} -Card::Card(const std::string& device) +Card::Card(const std::string& dev_path)  { -	int fd = open(device.c_str(), O_RDWR | O_CLOEXEC); -	if (fd < 0) -		throw invalid_argument(string(strerror(errno)) + " opening " + device); -	m_fd = fd; +	m_fd = open_device_by_path(dev_path); + +	setup(); +} +void Card::setup() +{  	drmVersionPtr ver = drmGetVersion(m_fd);  	m_version_major = ver->version_major;  	m_version_minor = ver->version_minor; | 
