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;
}
Пример #2
0
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;
  }
}
Пример #3
0
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;
}
Пример #4
0
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);
  }
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
    }
  }
}
Пример #8
0
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;
    }
  }
Пример #9
0
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;
}
Пример #10
0
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;
}