Logo Search packages:      
Sourcecode: hdhomerun-config-gui version File versions  Download package

Devices.cpp

/*
 * Copyright © 2008 Silicondust USA Inc. <www.silicondust.com>.
 */

#include "AppInclude.h"

THDHomeRunDevice::THDHomeRunDevice(uint32_t DeviceID, uint8_t TunerIndex)
{
      this->DeviceID = DeviceID;
      this->TunerIndex = TunerIndex;

      char cName[16];
      memset(cName, 0, sizeof(cName));
      snprintf(cName, sizeof(cName), "%08lX-%d", (unsigned long)DeviceID, TunerIndex);
      Name = cName;

      Next = NULL;
      Discovered = false;

      hd = hdhomerun_device_create(DeviceID, 0, TunerIndex, dbg);
}

THDHomeRunDevice::~THDHomeRunDevice()
{
      if (hd) {
            hdhomerun_device_destroy(hd);
      }
}

THDHomeRunDeviceList::THDHomeRunDeviceList()
{
      g_static_rw_lock_init(&Lock);
      DeviceList = NULL;
      FFoundErrorCode = 0;
}

THDHomeRunDeviceList::~THDHomeRunDeviceList()
{
}

uint16_t THDHomeRunDeviceList::FoundErrorCode()
{
      g_static_rw_lock_reader_lock(&Lock);
      uint16_t Result = FFoundErrorCode;
      g_static_rw_lock_reader_unlock(&Lock);
      return Result;
}

guint32 THDHomeRunDeviceList::DiscoveredCount()
{
      try {
            int Count = 0;
            THDHomeRunDevice *Dev = IterateFirst();
            while (Dev) {
                  if (Dev->Discovered) {
                        Count++;
                  }
                  Dev = IterateNext(Dev);
            }
            IterateComplete();
            return Count;
      }
      catch(...) {
            IterateExceptionCleanup();
            return 0;
      }
}

string *THDHomeRunDeviceList::ModelCommon()
{
      string *Model = NULL;
      try {
            THDHomeRunDevice *Dev = IterateFirst();
            while (Dev) {
                  if (!Dev->Discovered || Dev->Model.empty()) {
                        Dev = IterateNext(Dev);
                        continue;
                  }

                  if (!Model) {
                        Model = &Dev->Model;
                        Dev = IterateNext(Dev);
                        continue;
                  }

                  if (Model != &Dev->Model) {
                        Model = NULL;
                        break;
                  }

                  Dev = IterateNext(Dev);
            }
            IterateComplete();
            return Model;
      }
      catch(...) {
            IterateExceptionCleanup();
            return NULL;
      }
}

THDHomeRunDevice *THDHomeRunDeviceList::Find(uint32_t DeviceID, uint8_t TunerIndex)
{
      try {
            THDHomeRunDevice *Dev = IterateFirst();
            while (Dev) {
                  if ((Dev->DeviceID == DeviceID) && (Dev->TunerIndex == TunerIndex)) {
                        break;
                  }
                  Dev = IterateNext(Dev);
            }

            IterateComplete();
            return Dev;
      }
      catch(...) {
            IterateExceptionCleanup();
            return NULL;
      }
}

THDHomeRunDevice *THDHomeRunDeviceList::Find(string * Name)
{
      try {
            THDHomeRunDevice *Dev = IterateFirst();
            while (Dev) {
                  if (Dev->Name == *Name) {
                        break;
                  }
                  Dev = IterateNext(Dev);
            }
            IterateComplete();
            return Dev;
      }
      catch(...) {
            IterateExceptionCleanup();
            return NULL;
      }
}

THDHomeRunDevice *THDHomeRunDeviceList::IterateFirst()
{
      g_static_rw_lock_writer_lock(&Lock);
      return DeviceList;
}

THDHomeRunDevice *THDHomeRunDeviceList::IterateNext(THDHomeRunDevice * Dev)
{
      return Dev->Next;
}

void THDHomeRunDeviceList::IterateComplete()
{
      g_static_rw_lock_writer_unlock(&Lock);
}

void THDHomeRunDeviceList::IterateExceptionCleanup()
{
      g_static_rw_lock_writer_unlock(&Lock);
}

THDHomeRunDevice *THDHomeRunDeviceList::AddDeviceInternal(uint32_t DeviceID, guint8 TunerIndex)
{
      THDHomeRunDevice *Prev = NULL;
      THDHomeRunDevice *P = DeviceList;

      while (P) {
            if (P->DeviceID < DeviceID) {
                  Prev = P;
                  P = P->Next;
                  continue;
            }
            if (P->DeviceID > DeviceID) {
                  break;
            }

            if (P->TunerIndex < TunerIndex) {
                  Prev = P;
                  P = P->Next;
                  continue;
            }
            if (P->TunerIndex > TunerIndex) {
                  break;
            }

            return P;
      }

      THDHomeRunDevice *Dev = new THDHomeRunDevice(DeviceID, TunerIndex);

      if (Prev) {
            Dev->Next = P;
            Prev->Next = Dev;
      } else {
            Dev->Next = DeviceList;
            DeviceList = Dev;
      }

      return Dev;
}

THDHomeRunDevice *THDHomeRunDeviceList::AddDevice(guint32 DeviceID, guint8 TunerIndex)
{
      if (DeviceID == HDHOMERUN_DEVICE_ID_WILDCARD) {
            hdhomerun_debug_printf(dbg, "devices: invalid DeviceID %08lx\n", DeviceID);
            FFoundErrorCode = 0x4001;
            return NULL;
      }
      if (!hdhomerun_discover_validate_device_id(DeviceID)) {
            hdhomerun_debug_printf(dbg, "devices: invalid DeviceID %08lx\n", DeviceID);
            FFoundErrorCode = 0x4002;
            return NULL;
      }

      g_static_rw_lock_writer_lock(&Lock);

      THDHomeRunDevice *Dev = NULL;
      try {
            Dev = AddDeviceInternal(DeviceID, TunerIndex);
      }
      catch(...) {
            hdhomerun_debug_printf(dbg, "devices: AddDevice exception!\n");
      }

      g_static_rw_lock_writer_unlock(&Lock);
      return Dev;
}

THDHomeRunDevice *THDHomeRunDeviceList::AddDevice(string * DeviceName)
{
      uint32_t DeviceID;
      uint8_t TunerIndex;

      if (sscanf(DeviceName->c_str(), "%x-%hhu", &DeviceID, &TunerIndex) != 2) {
            return NULL;
      }

      return AddDevice(DeviceID, TunerIndex);
}

void THDHomeRunDeviceList::DetectDiscoverTuners(uint32_t DeviceID)
{
      struct hdhomerun_device_t *hd = hdhomerun_device_create(DeviceID, 0, 0, dbg);
      if (!hd) {
            hdhomerun_debug_printf(dbg, "devices: %08lX: DetectDiscoverTuners failed to create device\n", DeviceID);
            return;
      }

      const char *cModel = hdhomerun_device_get_model_str(hd);
      if (!cModel) {
            hdhomerun_debug_printf(dbg, "devices: %08lX: DetectDiscoverTuners failed to connect\n", DeviceID);
            return;
      }

      hdhomerun_debug_printf(dbg, "devices: %08lX: model '%s'", DeviceID, cModel);

      char *cVer = NULL; 
      hdhomerun_device_get_var(hd, "/sys/version", &cVer, NULL);
      hdhomerun_debug_printf(dbg, "devices: %08lX: firmware '%s'", DeviceID, cVer ? cVer : "unknown");

      unsigned int TunerIndex = 0;
      while (1) {
            hdhomerun_device_set_tuner(hd, TunerIndex);

            char *Target;
            int ret = hdhomerun_device_get_tuner_target(hd, &Target);
            if (ret < 0) {
                  hdhomerun_debug_printf(dbg, "devices: %08lX: DetectDiscoverTuners communication error", DeviceID);
                  break;
            }
            if (ret == 0) {
                  break;
            }

            hdhomerun_debug_printf(dbg, "devices: %08lX: DetectDiscoverTuners found tuner %u", DeviceID, TunerIndex);

            THDHomeRunDevice *Dev = AddDevice(DeviceID, TunerIndex);
            if (!Dev) {
                  TunerIndex++;
                  continue;
            }

            Dev->Model = cModel;
            Dev->Discovered = true;

            TunerIndex++;
      }

      hdhomerun_device_destroy(hd);
}

void THDHomeRunDeviceList::DetectDiscover()
{
      struct hdhomerun_discover_device_t ResultList[64];
      int Count = hdhomerun_discover_find_devices_custom(0, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, ResultList, 64);
      if (Count < 0) {
            hdhomerun_debug_printf(dbg, "devices: DetectDiscover error finding devices\n");
            return;
      }
      if (Count == 0) {
            hdhomerun_debug_printf(dbg, "devices: DetectDiscover no devices found\n");
            return;
      }

      struct hdhomerun_discover_device_t *Result = ResultList;
      struct hdhomerun_discover_device_t *ResultEnd = ResultList + Count;
      while (Result < ResultEnd) {
            /* Detect the number of tuners and add a device record for each one. */
            DetectDiscoverTuners(Result->device_id);
            Result++;
      }
}


void THDHomeRunDeviceList::DetectEntry()
{
      g_static_rw_lock_writer_lock(&Lock);

      THDHomeRunDevice *Dev = DeviceList;
      while (Dev) {
            Dev->Discovered = false;
            Dev = Dev->Next;
      }

      FFoundErrorCode = 0;

      g_static_rw_lock_writer_unlock(&Lock);
}

void THDHomeRunDeviceList::DetectCleanup()
{
      g_static_rw_lock_writer_lock(&Lock);

      THDHomeRunDevice *Prev = NULL;
      THDHomeRunDevice *Dev = DeviceList;
      while (Dev) {
            if (Dev->Discovered) {
                  Prev = Dev;
                  Dev = Dev->Next;
                  continue;
            }

            if (Prev) {
                  Prev->Next = Dev->Next;
                  Dev = Dev->Next;
            } else {
                  DeviceList = Dev->Next;
                  Dev = Dev->Next;
            }
      }

      g_static_rw_lock_writer_unlock(&Lock);
}

void THDHomeRunDeviceList::Detect()
{
      DetectEntry();

      DetectDiscover();

      DetectCleanup();
}

Generated by  Doxygen 1.6.0   Back to index