Skip to content

Commit

Permalink
added: P8 adapter discovery via Linux sysfs
Browse files Browse the repository at this point in the history
On Linux, dynamic device discovery is currently implemented via libudev,
which may not be available on more minimal systems. Thus, we implement a
new device discovery that directly uses sysfs to scan through available
USB devices for supported ones without any additional dependencies.
  • Loading branch information
pks-t authored and opdenkamp committed Mar 27, 2020
1 parent aceadfe commit 70d71cb
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
75 changes: 73 additions & 2 deletions src/libcec/adapter/Pulse-Eight/USBCECAdapterDetection.cpp
Expand Up @@ -68,6 +68,12 @@ extern "C" {
#include <unistd.h>
#endif

#if defined(__linux__)
#include <dirent.h>
#include <ios>
#include <fstream>
#endif

#include <string>
#include <algorithm>
#include <stdio.h>
Expand All @@ -79,7 +85,7 @@ extern "C" {

using namespace CEC;

#if defined(HAVE_LIBUDEV)
#if defined(HAVE_LIBUDEV) || defined(__linux__)
bool TranslateComPort(std::string& strString)
{
std::string strTmp(strString);
Expand Down Expand Up @@ -130,7 +136,7 @@ bool FindComPort(std::string& strLocation)

bool CUSBCECAdapterDetection::CanAutodetect(void)
{
#if defined(__APPLE__) || defined(HAVE_LIBUDEV) || defined(__WINDOWS__) || defined(__FreeBSD__)
#if defined(__APPLE__) || defined(HAVE_LIBUDEV) || defined(__WINDOWS__) || defined(__FreeBSD__) || defined(__linux__)
return true;
#else
return false;
Expand Down Expand Up @@ -413,6 +419,69 @@ uint8_t CUSBCECAdapterDetection::FindAdaptersUdev(cec_adapter_descriptor *device
return iFound;
}

uint8_t CUSBCECAdapterDetection::FindAdaptersLinux(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
{
uint8_t iFound(0);

#if defined(__linux__)
std::string strSysfsPath("/sys/bus/usb/devices");
DIR *dir;

if ((dir = opendir(strSysfsPath.c_str())) != NULL)
{
struct dirent *dent;

while ((dent = readdir(dir)) != NULL)
{
std::string strDevice = StringUtils::Format("%s/%s", strSysfsPath.c_str(), dent->d_name);
unsigned int iVendor, iProduct;

if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
continue;

std::ifstream fVendor(StringUtils::Format("%s/idVendor", strDevice.c_str()));
if (!fVendor)
continue;
fVendor >> std::hex >> iVendor;

std::ifstream fProduct(StringUtils::Format("%s/idProduct", strDevice.c_str()));
if (!fProduct)
continue;
fProduct >> std::hex >> iProduct;

if (iVendor != CEC_VID || (iProduct != CEC_PID && iProduct != CEC_PID2))
continue;

if (strDevicePath && strcmp(strDevice.c_str(), strDevicePath))
continue;

std::string strPort(strDevice);
if (FindComPort(strPort) && (iFound == 0 || strcmp(deviceList[iFound - 1].strComName, strPort.c_str())))
{
snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", strDevice.c_str());
snprintf(deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName), "%s", strPort.c_str());
deviceList[iFound].iVendorId = iVendor;
deviceList[iFound].iProductId = iProduct;
deviceList[iFound].adapterType = ADAPTERTYPE_P8_EXTERNAL; // will be overridden when not doing a "quick scan" by the actual type
iFound++;
}

if (iFound >= iBufSize)
break;
}

closedir(dir);
}

#else
(void)deviceList;
(void)iBufSize;
(void)strDevicePath;
#endif

return iFound;
}

uint8_t CUSBCECAdapterDetection::FindAdaptersFreeBSD(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
{
uint8_t iFound(0);
Expand Down Expand Up @@ -508,6 +577,8 @@ uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter_descriptor *deviceList
iFound = FindAdaptersFreeBSD(deviceList, iBufSize, strDevicePath);
if (iFound == 0)
iFound = FindAdaptersUdev(deviceList, iBufSize, strDevicePath);
if (iFound == 0)
iFound = FindAdaptersLinux(deviceList, iBufSize, strDevicePath);
if (iFound == 0)
iFound = FindAdaptersWindows(deviceList, iBufSize, strDevicePath);
return iFound;
Expand Down
1 change: 1 addition & 0 deletions src/libcec/adapter/Pulse-Eight/USBCECAdapterDetection.h
Expand Up @@ -50,6 +50,7 @@ namespace CEC
static uint8_t FindAdaptersWindows(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
static uint8_t FindAdaptersApple(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
static uint8_t FindAdaptersUdev(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
static uint8_t FindAdaptersLinux(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
static uint8_t FindAdaptersFreeBSD(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
};
};

0 comments on commit 70d71cb

Please sign in to comment.