/*
* This file is part of the libCEC(R) library.
*
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
* libCEC(R) is an original work, containing original code.
*
* libCEC(R) is a trademark of Pulse-Eight Limited.
#elif defined(__WINDOWS__)
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "setupapi.lib")
+#pragma comment(lib, "cfgmgr32.lib")
#include <setupapi.h>
+#include <cfgmgr32.h>
// the virtual COM port only shows up when requesting devices with the raw device guid!
-static GUID USB_RAW_GUID = { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
+static GUID USB_RAW_GUID = { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
+static GUID USB_CDC_GUID = { 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } };
+
#elif defined(HAVE_LIBUDEV)
#include <dirent.h>
#include <poll.h>
#elif defined(__FreeBSD__)
#include <stdio.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
#endif
-#define CEC_VID 0x2548
-#define CEC_PID 0x1001
+#define CEC_VID 0x2548
+#define CEC_PID 0x1001
+#define CEC_PID2 0x1002
using namespace CEC;
using namespace std;
#endif
}
-uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
+#if defined(__WINDOWS__)
+static bool GetComPortFromHandle(HDEVINFO hDevHandle, PSP_DEVINFO_DATA devInfoData, char* strPortName, unsigned int iSize)
+{
+ bool bReturn(false);
+ TCHAR strRegPortName[256];
+ strRegPortName[0] = _T('\0');
+ DWORD dwSize = sizeof(strRegPortName);
+ DWORD dwType = 0;
+
+ HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevHandle, devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
+ if (!hDeviceKey)
+ return bReturn;
+
+ // locate the PortName
+ if ((RegQueryValueEx(hDeviceKey, _T("PortName"), NULL, &dwType, reinterpret_cast<LPBYTE>(strRegPortName), &dwSize) == ERROR_SUCCESS) &&
+ (dwType == REG_SZ) &&
+ _tcslen(strRegPortName) > 3 &&
+ _tcsnicmp(strRegPortName, _T("COM"), 3) == 0 &&
+ _ttoi(&(strRegPortName[3])) > 0)
+ {
+ // return the port name
+ snprintf(strPortName, iSize, "%s", strRegPortName);
+ bReturn = true;
+ }
+
+ RegCloseKey(hDeviceKey);
+
+ return bReturn;
+}
+
+static bool FindComPortForComposite(const char* strLocation, char* strPortName, unsigned int iSize)
+{
+ bool bReturn(false);
+
+ // find all devices of the CDC class
+ HDEVINFO hDevHandle = SetupDiGetClassDevs(&USB_CDC_GUID, NULL, NULL, DIGCF_PRESENT);
+ if (hDevHandle == INVALID_HANDLE_VALUE)
+ return bReturn;
+
+ // check all devices, whether they match the location or not
+ char strId[512];
+ bool bGetNext(true);
+ for (int iPtr = 0; !bReturn && bGetNext && iPtr < 1024 ; iPtr++)
+ {
+ strId[0] = 0;
+
+ SP_DEVINFO_DATA devInfoData;
+ devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+
+ // no more devices
+ if (!SetupDiEnumDeviceInfo(hDevHandle, iPtr, &devInfoData))
+ bGetNext = false;
+ else
+ {
+ // check if the location of the _parent_ device matches
+ DEVINST parentDevInst;
+ if (CM_Get_Parent(&parentDevInst, devInfoData.DevInst, 0) == CR_SUCCESS)
+ {
+ CM_Get_Device_ID(parentDevInst, strId, 512, 0);
+
+ // match
+ if (!strncmp(strId, strLocation, strlen(strLocation)))
+ bReturn = GetComPortFromHandle(hDevHandle, &devInfoData, strPortName, iSize);
+ }
+ }
+ }
+
+ SetupDiDestroyDeviceInfoList(hDevHandle);
+ return bReturn;
+}
+#endif
+
+uint8_t CUSBCECAdapterDetection::FindAdapters(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
{
uint8_t iFound(0);
kresult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent);
IOObjectRelease(oldparent);
}
- if (strlen(bsdPath) && iVendor == CEC_VID && iProduct == CEC_PID)
+ if (strlen(bsdPath) && iVendor == CEC_VID && (iProduct == CEC_PID || iProduct == CEC_PID2))
{
if (!strDevicePath || !strcmp(bsdPath, strDevicePath))
{
// on darwin, the device path is the same as the comm path.
- snprintf(deviceList[iFound ].path, sizeof(deviceList[iFound].path), "%s", bsdPath);
- snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", bsdPath);
+ if (iFound == 0 || strcmp(deviceList[iFound-1].strComName, bsdPath))
+ {
+ snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", bsdPath);
+ snprintf(deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName), "%s", bsdPath);
+ 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++;
+ }
}
}
}
- IOObjectRelease(serialService);
+ IOObjectRelease(serialService);
}
}
IOObjectRelease(serialPortIterator);
int iVendor, iProduct;
sscanf(udev_device_get_sysattr_value(pdev, "idVendor"), "%x", &iVendor);
sscanf(udev_device_get_sysattr_value(pdev, "idProduct"), "%x", &iProduct);
- if (iVendor == CEC_VID && iProduct == CEC_PID)
+ if (iVendor == CEC_VID && (iProduct == CEC_PID || iProduct == CEC_PID2))
{
CStdString strPath(udev_device_get_syspath(pdev));
if (!strDevicePath || !strcmp(strPath.c_str(), strDevicePath))
{
CStdString strComm(strPath);
- if (FindComPort(strComm))
+ if (FindComPort(strComm) && (iFound == 0 || strcmp(deviceList[iFound-1].strComName, strComm.c_str())))
{
- snprintf(deviceList[iFound ].path, sizeof(deviceList[iFound].path), "%s", strPath.c_str());
- snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", strComm.c_str());
+ snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", strPath.c_str());
+ snprintf(deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName), "%s", strComm.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++;
}
}
}
SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+ // find all devices
if ((hDevHandle = SetupDiGetClassDevs(&USB_RAW_GUID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) == INVALID_HANDLE_VALUE)
return iFound;
if(!bResult)
{
+ // no (more) results
SetupDiDestroyDeviceInfoList(hDevHandle);
delete []buffer;
buffer = NULL;
if(!bDetailResult)
continue;
+ // check whether the path matches, if a path was given
if (strDevicePath && strcmp(strDevicePath, devicedetailData->DevicePath) != 0)
continue;
+ // get the vid and pid
CStdString strVendorId;
CStdString strProductId;
CStdString strTmp(devicedetailData->DevicePath);
int iVendor, iProduct;
sscanf(strVendorId, "%x", &iVendor);
sscanf(strProductId, "%x", &iProduct);
- if (iVendor != CEC_VID || iProduct != CEC_PID)
- continue;
- HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevHandle, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
- if (!hDeviceKey)
+ // no match
+ if (iVendor != CEC_VID || (iProduct != CEC_PID && iProduct != CEC_PID2))
continue;
- TCHAR strPortName[256];
- strPortName[0] = _T('\0');
- DWORD dwSize = sizeof(strPortName);
- DWORD dwType = 0;
- /* search the registry */
- if ((RegQueryValueEx(hDeviceKey, _T("PortName"), NULL, &dwType, reinterpret_cast<LPBYTE>(strPortName), &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ))
+ if (iProduct == CEC_PID2)
{
- if (_tcslen(strPortName) > 3 && _tcsnicmp(strPortName, _T("COM"), 3) == 0 &&
- _ttoi(&(strPortName[3])) > 0)
+ // the 1002 pid indicates a composite device, that needs special treatment
+ char strId[512];
+ CM_Get_Device_ID(devInfoData.DevInst, strId, 512, 0);
+ if (FindComPortForComposite(strId, deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName)))
{
- snprintf(deviceList[iFound ].path, sizeof(deviceList[iFound].path), "%s", devicedetailData->DevicePath);
- snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", strPortName);
+ snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", devicedetailData->DevicePath);
+ deviceList[iFound].iVendorId = (uint16_t)iVendor;
+ deviceList[iFound].iProductId = (uint16_t)iProduct;
+ deviceList[iFound].adapterType = ADAPTERTYPE_P8_EXTERNAL; // will be overridden when not doing a "quick scan" by the actual type
+ iFound++;
}
}
-
- RegCloseKey(hDeviceKey);
+ else if (GetComPortFromHandle(hDevHandle, &devInfoData, deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName)))
+ {
+ snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", devicedetailData->DevicePath);
+ deviceList[iFound].iVendorId = (uint16_t)iVendor;
+ deviceList[iFound].iProductId = (uint16_t)iProduct;
+ deviceList[iFound].adapterType = ADAPTERTYPE_P8_EXTERNAL; // will be overridden when not doing a "quick scan" by the actual type
+ iFound++;
+ }
}
#elif defined(__FreeBSD__)
char devicePath[PATH_MAX + 1];
+ char infos[512];
+ char sysctlname[32];
+ char ttyname[8];
+ char *pos;
+ size_t infos_size = sizeof(infos);
int i;
- for (i = 0; i < 8; ++i)
+ for (i = 0; ; ++i)
{
- (void)snprintf(devicePath, sizeof(devicePath), "/dev/ttyU%d", i);
- if (!access(devicePath, 0))
- {
- snprintf(deviceList[iFound ].path, sizeof(deviceList[iFound].path), "%s", devicePath);
- snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", devicePath);
- }
+ memset(infos, 0, sizeof(infos));
+ (void)snprintf(sysctlname, sizeof(sysctlname),
+ "dev.umodem.%d.%%pnpinfo", i);
+ if (sysctlbyname(sysctlname, infos, &infos_size,
+ NULL, 0) != 0)
+ break;
+ if (strstr(infos, "vendor=0x2548") == NULL)
+ continue;
+ if (strstr(infos, "product=0x1001") == NULL
+ && strstr(infos, "product=0x1002") == NULL)
+ continue;
+ pos = strstr(infos, "ttyname=");
+ if (pos == NULL)
+ continue;
+ sscanf(pos, "ttyname=%s ", ttyname);
+
+ (void)snprintf(devicePath, sizeof(devicePath),
+ "/dev/tty%s", ttyname);
+
+ if (strDevicePath &&
+ strcmp(devicePath, strDevicePath) != 0)
+ continue;
+ snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", devicePath);
+ snprintf(deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName), "%s", devicePath);
+ deviceList[iFound].iVendorId = CEC_VID;
+ deviceList[iFound].iProductId = CEC_VID;
+ deviceList[iFound].adapterType = ADAPTERTYPE_P8_EXTERNAL; // will be overridden when not doing a "quick scan" by the actual type
+ iFound++;
}
#else
//silence "unused" warnings
- void *tmp = (void*)deviceList;
- tmp = (void *)strDevicePath;
+ ((void)deviceList);
+ ((void) strDevicePath);
#endif
- iBufSize = 0; /* silence "unused" warning on linux/osx */
+ iBufSize = 0; if(!iBufSize){} /* silence "unused" warning on linux/osx */
return iFound;
}