bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) { bool rtn = false; struct usb_bus *bus; usb_find_devices(); for (bus = m_busses; bus; bus = bus->next) { struct usb_device *dev; for (dev = bus->devices; dev; dev = dev->next) { PeripheralScanResult result; result.m_iVendorId = dev->descriptor.idVendor; result.m_iProductId = dev->descriptor.idProduct; result.m_type = (dev->descriptor.bDeviceClass == USB_CLASS_PER_INTERFACE && dev->descriptor.bNumConfigurations > 0 && dev->config[0].bNumInterfaces > 0 && dev->config[0].interface[0].num_altsetting > 0) ? GetType(dev->config[0].interface[0].altsetting[0].bInterfaceClass) : GetType(dev->descriptor.bDeviceClass); result.m_strLocation.Format("/bus%s/dev%s", bus->dirname, dev->filename); if (!results.ContainsResult(result)) results.m_results.push_back(result); } } // quick check if number of entries changed. if (m_results.m_results.size() != results.m_results.size()) { m_results = results; rtn = true; } else { // number of entried are the same, so we have to compare each one. for (unsigned int iDevicePtr = 0; iDevicePtr < m_results.m_results.size(); iDevicePtr++) { if (!results.ContainsResult(m_results.m_results.at(iDevicePtr))) { // if anything changes, we flag a new PeripheralScanResults m_results = results; rtn = true; break; } } } #if defined(HAS_LINUX_EVENTS) if (rtn) CWinEvents::RefreshDevices(); #endif return rtn; }
void CPeripheralBus::UnregisterRemovedDevices(const PeripheralScanResults &results) { CSingleLock lock(m_critSection); std::vector<CPeripheral *> removedPeripherals; for (int iDevicePtr = (int) m_peripherals.size() - 1; iDevicePtr >= 0; iDevicePtr--) { CPeripheral *peripheral = m_peripherals.at(iDevicePtr); PeripheralScanResult updatedDevice(m_type); if (!results.GetDeviceOnLocation(peripheral->Location(), &updatedDevice) || *peripheral != updatedDevice) { /* device removed */ removedPeripherals.push_back(peripheral); m_peripherals.erase(m_peripherals.begin() + iDevicePtr); } } lock.Leave(); for (unsigned int iDevicePtr = 0; iDevicePtr < removedPeripherals.size(); iDevicePtr++) { CPeripheral *peripheral = removedPeripherals.at(iDevicePtr); std::vector<PeripheralFeature> features; peripheral->GetFeatures(features); bool peripheralHasFeatures = features.size() > 1 || (features.size() == 1 && features.at(0) != FEATURE_UNKNOWN); if (peripheral->Type() != PERIPHERAL_UNKNOWN || peripheralHasFeatures) { CLog::Log(LOGNOTICE, "%s - device removed from %s/%s: %s (%s:%s)", __FUNCTION__, PeripheralTypeTranslator::TypeToString(peripheral->Type()), peripheral->Location().c_str(), peripheral->DeviceName().c_str(), peripheral->VendorIdAsString(), peripheral->ProductIdAsString()); peripheral->OnDeviceRemoved(); } m_manager->OnDeviceDeleted(*this, *peripheral); delete peripheral; } }
bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) { struct usb_bus *bus; usb_find_devices(); for (bus = m_busses; bus; bus = bus->next) { struct usb_device *dev; for (dev = bus->devices; dev; dev = dev->next) { PeripheralScanResult result(m_type); result.m_iVendorId = dev->descriptor.idVendor; result.m_iProductId = dev->descriptor.idProduct; result.m_type = (dev->descriptor.bDeviceClass == USB_CLASS_PER_INTERFACE && dev->descriptor.bNumConfigurations > 0 && dev->config[0].bNumInterfaces > 0 && dev->config[0].interface[0].num_altsetting > 0) ? GetType(dev->config[0].interface[0].altsetting[0].bInterfaceClass) : GetType(dev->descriptor.bDeviceClass); #ifdef __FreeBSD__ result.m_strLocation.Format("%s", dev->filename); #else result.m_strLocation.Format("/bus%s/dev%s", bus->dirname, dev->filename); #endif result.m_iSequence = GetNumberOfPeripheralsWithId(result.m_iVendorId, result.m_iProductId); if (!results.ContainsResult(result)) results.m_results.push_back(result); } } return true; }
void CPeripheralAddon::UnregisterRemovedDevices(const PeripheralScanResults &results, PeripheralVector& removedPeripherals) { CSingleLock lock(m_critSection); std::vector<unsigned int> removedIndexes; for (auto& it : m_peripherals) { const PeripheralPtr& peripheral = it.second; PeripheralScanResult updatedDevice(PERIPHERAL_BUS_ADDON); if (!results.GetDeviceOnLocation(peripheral->Location(), &updatedDevice) || *peripheral != updatedDevice) { // Device removed removedIndexes.push_back(it.first); } } lock.Leave(); for (auto index : removedIndexes) { auto it = m_peripherals.find(index); const PeripheralPtr& peripheral = it->second; CLog::Log(LOGNOTICE, "%s - device removed from %s/%s: %s (%s:%s)", __FUNCTION__, PeripheralTypeTranslator::TypeToString(peripheral->Type()), peripheral->Location().c_str(), peripheral->DeviceName().c_str(), peripheral->VendorIdAsString(), peripheral->ProductIdAsString()); UnregisterButtonMap(peripheral.get()); peripheral->OnDeviceRemoved(); removedPeripherals.push_back(peripheral); m_peripherals.erase(it); } }
bool CPeripheralBusRPi::PerformDeviceScan(PeripheralScanResults &results) { if (FindAdapter()) { PeripheralScanResult result; result.m_iVendorId = RPI_PERIPHERAL_BUS_VID; result.m_iProductId = RPI_PERIPHERAL_CEC_PID; result.m_type = PERIPHERAL_CEC; result.m_strLocation = "RPI/CEC"; if (!results.ContainsResult(result)) results.m_results.push_back(result); } return true; }
bool CPeripheralAddon::PerformDeviceScan(PeripheralScanResults &results) { unsigned int peripheralCount; PERIPHERAL_INFO* pScanResults; PERIPHERAL_ERROR retVal; try { LogError(retVal = m_pStruct->PerformDeviceScan(&peripheralCount, &pScanResults), "PerformDeviceScan()"); } catch (std::exception &e) { LogException(e, "PerformDeviceScan()"); return false; } if (retVal == PERIPHERAL_NO_ERROR) { for (unsigned int i = 0; i < peripheralCount; i++) { ADDON::Peripheral peripheral(pScanResults[i]); PeripheralScanResult result(PERIPHERAL_BUS_ADDON); switch (peripheral.Type()) { case PERIPHERAL_TYPE_JOYSTICK: result.m_type = PERIPHERAL_JOYSTICK; break; default: continue; } result.m_strDeviceName = peripheral.Name(); result.m_strLocation = StringUtils::Format("%s/%d", ID().c_str(), peripheral.Index()); result.m_iVendorId = peripheral.VendorID(); result.m_iProductId = peripheral.ProductID(); result.m_mappedType = PERIPHERAL_JOYSTICK; result.m_mappedBusType = PERIPHERAL_BUS_ADDON; result.m_iSequence = 0; if (!results.ContainsResult(result)) results.m_results.push_back(result); } try { m_pStruct->FreeScanResults(peripheralCount, pScanResults); } catch (std::exception &e) { LogException(e, "FreeJoysticks()"); } return true; } return false; }
void CPeripheralBus::UnregisterRemovedDevices(const PeripheralScanResults &results) { CSingleLock lock(m_critSection); for (int iDevicePtr = (int) m_peripherals.size() - 1; iDevicePtr >= 0; iDevicePtr--) { CPeripheral *peripheral = m_peripherals.at(iDevicePtr); PeripheralScanResult updatedDevice; if (!results.GetDeviceOnLocation(peripheral->Location(), &updatedDevice) || updatedDevice != *peripheral) { /* device removed */ if (peripheral->Type() != PERIPHERAL_UNKNOWN) CLog::Log(LOGNOTICE, "%s - device removed from %s/%s: %s (%s:%s)", __FUNCTION__, PeripheralTypeTranslator::TypeToString(peripheral->Type()), peripheral->Location().c_str(), peripheral->DeviceName().c_str(), peripheral->VendorIdAsString(), peripheral->ProductIdAsString()); m_peripherals.erase(m_peripherals.begin() + iDevicePtr); lock.Leave(); m_manager->OnDeviceDeleted(*this, peripheral->FileLocation()); delete peripheral; } } }
bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) { struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev(NULL), *parent(NULL); enumerate = udev_enumerate_new(m_udev); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); bool bContinue(true); std::string strPath, strClass; udev_list_entry_foreach(dev_list_entry, devices) { strPath = udev_list_entry_get_name(dev_list_entry); if (strPath.empty()) bContinue = false; if (bContinue) { if (!(parent = udev_device_new_from_syspath(m_udev, strPath.c_str()))) bContinue = false; } if (bContinue) { dev = udev_device_get_parent(udev_device_get_parent(parent)); if (!dev || !udev_device_get_sysattr_value(dev,"idVendor") || !udev_device_get_sysattr_value(dev, "idProduct")) bContinue = false; } if (bContinue) { strClass = udev_device_get_sysattr_value(dev, "bDeviceClass"); if (strClass.empty()) bContinue = false; } if (bContinue) { int iClass = PeripheralTypeTranslator::HexStringToInt(strClass.c_str()); if (iClass == USB_CLASS_PER_INTERFACE) { //TODO just assume this is a HID device for now, since the only devices that we're currently // interested in are HID devices iClass = USB_CLASS_HID; } PeripheralScanResult result(m_type); result.m_iVendorId = PeripheralTypeTranslator::HexStringToInt(udev_device_get_sysattr_value(dev, "idVendor")); result.m_iProductId = PeripheralTypeTranslator::HexStringToInt(udev_device_get_sysattr_value(dev, "idProduct")); result.m_type = GetType(iClass); result.m_strLocation = udev_device_get_syspath(dev); result.m_iSequence = GetNumberOfPeripheralsWithId(result.m_iVendorId, result.m_iProductId); if (!results.ContainsResult(result)) results.m_results.push_back(result); } bContinue = true; if (parent) { /* unref the _parent_ device */ udev_device_unref(parent); parent = NULL; } }
bool CPeripheralBusUSB::PerformDeviceScan(const GUID *guid, const PeripheralType type, PeripheralScanResults &results) { bool bReturn(false); HDEVINFO hDevHandle; DWORD required = 0, iMemberIndex = 0; int nBufferSize = 0; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); SP_DEVINFO_DATA devInfoData; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if ((hDevHandle = SetupDiGetClassDevs(guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) == INVALID_HANDLE_VALUE) { CLog::Log(LOGWARNING, "%s - cannot query USB devices: invalid handle", __FUNCTION__); return bReturn; } bReturn = true; BOOL bResult = true; PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData = NULL; while(bResult) { bResult = SetupDiEnumDeviceInfo(hDevHandle, iMemberIndex, &devInfoData); if (bResult) bResult = SetupDiEnumDeviceInterfaces(hDevHandle, 0, guid, iMemberIndex, &deviceInterfaceData); if (bResult) { iMemberIndex++; BOOL bDetailResult = false; { // As per MSDN, Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a // NULL DeviceInterfaceDetailData pointer, a DeviceInterfaceDetailDataSize of zero, // and a valid RequiredSize variable. In response to such a call, this function returns // the required buffer size at RequiredSize and fails with GetLastError returning // ERROR_INSUFFICIENT_BUFFER. // Allocate an appropriately sized buffer and call the function again to get the interface details. SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, NULL, 0, &required, NULL); devicedetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(required * sizeof(TCHAR)); devicedetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); nBufferSize = required; } bDetailResult = SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, devicedetailData, nBufferSize , &required, NULL); if (bDetailResult) { CStdString strVendorId(StringUtils::EmptyString); CStdString strProductId(StringUtils::EmptyString); CStdString strTmp(devicedetailData->DevicePath); strVendorId = strTmp.substr(strTmp.Find("vid_") + 4, 4); strProductId = strTmp.substr(strTmp.Find("pid_") + 4, 4); if ((strTmp.Find("&mi_") < 0) || (strTmp.Find("&mi_00") >= 0)) { PeripheralScanResult prevDevice; if (!results.GetDeviceOnLocation(devicedetailData->DevicePath, &prevDevice)) { PeripheralScanResult result; result.m_strLocation = devicedetailData->DevicePath; result.m_type = type; result.m_iVendorId = PeripheralTypeTranslator::HexStringToInt(strVendorId.c_str()); result.m_iProductId = PeripheralTypeTranslator::HexStringToInt(strProductId.c_str()); if (!results.ContainsResult(result)) results.m_results.push_back(result); } } } if (devicedetailData) { free(devicedetailData); devicedetailData = NULL; } } else { SetupDiDestroyDeviceInfoList(hDevHandle); return bReturn; } } return bReturn; }
bool CPeripheralBusUSB::PerformDeviceScan(const GUID *guid, const PeripheralType defaultType, PeripheralScanResults &results) { using KODI::PLATFORM::WINDOWS::FromW; bool bReturn(false); DWORD required = 0, iMemberIndex = 0; int nBufferSize = 200; // Just initial guess, will be increased if required SP_DEVICE_INTERFACE_DATA deviceInterfaceData; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); SP_DEVINFO_DATA devInfoData; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); HDEVINFO const hDevHandle = SetupDiGetClassDevs(guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (hDevHandle == INVALID_HANDLE_VALUE) { CLog::Log(LOGWARNING, "%s - cannot query USB devices: invalid handle", __FUNCTION__); return bReturn; } PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(nBufferSize); int nPropertyBufferSize = 100; // Just initial guess, will be increased if required char* deviceProperty = (char*)malloc(nPropertyBufferSize); if (!devicedetailData || !deviceProperty) { free(devicedetailData); free(deviceProperty); CLog::Log(LOGSEVERE, "%s: memory allocation failed", __FUNCTION__); return false; } SP_DEVINFO_DATA deviceInfo; bReturn = true; for (iMemberIndex = 0; bReturn && iMemberIndex < MAX_BUS_DEVICES; iMemberIndex++) { bReturn = SetupDiEnumDeviceInfo(hDevHandle, iMemberIndex, &devInfoData) == TRUE; if (bReturn) bReturn = SetupDiEnumDeviceInterfaces(hDevHandle, 0, guid, iMemberIndex, &deviceInterfaceData) == TRUE; else { bReturn = true; if (GetLastError() == ERROR_NO_MORE_ITEMS) break; // no more USB devices, nothing more to scan else continue; // try to get other USB devices } if (bReturn) { devicedetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); deviceInfo.cbSize = sizeof(SP_DEVINFO_DATA); BOOL bDetailResult = SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, devicedetailData, nBufferSize , &required, &deviceInfo); if (!bDetailResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { free(devicedetailData); devicedetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(required * sizeof(TCHAR)); if (!devicedetailData) { free(deviceProperty); CLog::Log(LOGSEVERE, "%s: memory allocation failed", __FUNCTION__); return false; } devicedetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); nBufferSize = required; bDetailResult = SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, devicedetailData, nBufferSize , &required, &deviceInfo); } if (bDetailResult) { bDetailResult = SetupDiGetDeviceRegistryProperty(hDevHandle, &deviceInfo, SPDRP_HARDWAREID, NULL, (PBYTE)deviceProperty, nPropertyBufferSize, &required); if (!bDetailResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { free(deviceProperty); deviceProperty = (char*)malloc(required); if (!deviceProperty) { free(devicedetailData); CLog::Log(LOGSEVERE, "%s: memory allocation failed", __FUNCTION__); return false; } nPropertyBufferSize = required; bDetailResult = SetupDiGetDeviceRegistryProperty(hDevHandle, &deviceInfo, SPDRP_HARDWAREID, NULL, (PBYTE)deviceProperty, nPropertyBufferSize, &required); } } if (bDetailResult) { std::string strTmp(deviceProperty); StringUtils::ToLower(strTmp); size_t posVid, posPid; if (((posVid=strTmp.find("\\vid_")) != std::string::npos || (posVid=strTmp.find("&vid_")) != std::string::npos) && ((posPid=strTmp.find("\\pid_")) != std::string::npos || (posPid=strTmp.find("&pid_")) != std::string::npos)) { std::string strVendorId(strTmp, posVid + 5, 4); std::string strProductId(strTmp, posPid + 5, 4); PeripheralScanResult prevDevice(m_type); if (!results.GetDeviceOnLocation(FromW(devicedetailData->DevicePath), &prevDevice)) { PeripheralScanResult result(m_type); result.m_strLocation = FromW(devicedetailData->DevicePath); result.m_iVendorId = PeripheralTypeTranslator::HexStringToInt(strVendorId.c_str()); result.m_iProductId = PeripheralTypeTranslator::HexStringToInt(strProductId.c_str()); result.m_iSequence = GetNumberOfPeripheralsWithId(result.m_iVendorId, result.m_iProductId); // Assume that buffer is more then enough (we need only 8 chars, initial allocation is 100 chars). If not - just skip type detection. if (SetupDiGetDeviceRegistryProperty(hDevHandle, &devInfoData, SPDRP_CLASS, NULL, (PBYTE)deviceProperty, nPropertyBufferSize, &required) && strcmp("HIDClass", deviceProperty) == 0) result.m_type = PERIPHERAL_HID; else result.m_type = defaultType; if (!results.ContainsResult(result)) results.m_results.push_back(result); } } } } } SetupDiDestroyDeviceInfoList(hDevHandle); if (devicedetailData) free(devicedetailData); if (deviceProperty) free(deviceProperty); return bReturn; }