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; } }
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); } }
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(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; }