summaryrefslogtreecommitdiff
path: root/utils/regtools/qeditor/backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/qeditor/backend.cpp')
-rw-r--r--utils/regtools/qeditor/backend.cpp317
1 files changed, 290 insertions, 27 deletions
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp
index e011965..d2b75be 100644
--- a/utils/regtools/qeditor/backend.cpp
+++ b/utils/regtools/qeditor/backend.cpp
@@ -3,6 +3,10 @@
#include <QDebug>
#include "backend.h"
+/**
+ * Backend
+ */
+
Backend::Backend()
{
}
@@ -43,9 +47,16 @@ IoBackend *Backend::CreateDummyIoBackend()
return new DummyIoBackend();
}
-IoBackend::IoBackend()
+#ifdef HAVE_HWSTUB
+IoBackend *Backend::CreateHWStubIoBackend(HWStubDevice *dev)
{
+ return new HWStubIoBackend(dev);
}
+#endif
+
+/**
+ * FileIoBackend
+ */
FileIoBackend::FileIoBackend(const QString& filename)
{
@@ -91,27 +102,230 @@ bool FileIoBackend::Reload()
return true;
}
-DummyIoBackend::DummyIoBackend()
+#ifdef HAVE_HWSTUB
+/**
+ * HWStubDevice
+ */
+HWStubDevice::HWStubDevice(struct libusb_device *dev)
{
+ libusb_ref_device(dev);
+ m_dev = dev;
+ m_handle = 0;
+ m_hwdev = 0;
+ m_valid = Probe();
}
-QString DummyIoBackend::GetSocName()
+HWStubDevice::~HWStubDevice()
{
- return "";
+ Close();
+ libusb_unref_device(m_dev);
}
-bool DummyIoBackend::ReadRegister(const QString& name, soc_word_t& value)
+int HWStubDevice::GetBusNumber()
{
- (void) name;
- (void) value;
+ return libusb_get_bus_number(m_dev);
+}
+
+int HWStubDevice::GetDevAddress()
+{
+ return libusb_get_device_address(m_dev);
+}
+
+bool HWStubDevice::Probe()
+{
+ struct libusb_device_descriptor desc;
+ if(libusb_get_device_descriptor(m_dev, &desc))
+ return false;
+ if(desc.idVendor != HWSTUB_USB_VID || desc.idProduct != HWSTUB_USB_PID)
+ return false;
+ if(!Open())
+ return false;
+ int ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_VERSION, &m_hwdev_ver, sizeof(m_hwdev_ver));
+ if(ret != sizeof(m_hwdev_ver))
+ goto Lerr;
+ if(m_hwdev_ver.bMajor != HWSTUB_VERSION_MAJOR || m_hwdev_ver.bMinor < HWSTUB_VERSION_MINOR)
+ goto Lerr;
+ // get target
+ ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_TARGET, &m_hwdev_target, sizeof(m_hwdev_target));
+ if(ret != sizeof(m_hwdev_target))
+ goto Lerr;
+ // get STMP information
+ if(m_hwdev_target.dID == HWSTUB_TARGET_STMP)
+ {
+ ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_STMP, &m_hwdev_stmp, sizeof(m_hwdev_stmp));
+ if(ret != sizeof(m_hwdev_stmp))
+ goto Lerr;
+ }
+ Close();
+ return true;
+
+ Lerr:
+ Close();
return false;
}
-bool DummyIoBackend::Reload()
+bool HWStubDevice::Open()
+{
+ if(libusb_open(m_dev, &m_handle))
+ return false;
+ m_hwdev = hwstub_open(m_handle);
+ if(m_hwdev == 0)
+ {
+ libusb_close(m_handle);
+ return false;
+ }
+ return true;
+}
+
+void HWStubDevice::Close()
+{
+ if(m_hwdev)
+ hwstub_release(m_hwdev);
+ m_hwdev = 0;
+ if(m_handle)
+ libusb_close(m_handle);
+ m_handle = 0;
+}
+
+bool HWStubDevice::ReadMem(soc_addr_t addr, size_t length, void *buffer)
+{
+ if(!m_hwdev)
+ return false;
+ int ret = hwstub_rw_mem(m_hwdev, 1, addr, buffer, length);
+ return ret >= 0 && (size_t)ret == length;
+}
+
+bool HWStubDevice::IsValid()
+{
+ return m_valid;
+}
+
+
+/**
+ * HWStubIoBackend
+ */
+
+HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev)
+{
+ m_dev = dev;
+ m_dev->Open();
+ struct hwstub_target_desc_t target = m_dev->GetTargetInfo();
+ if(target.dID == HWSTUB_TARGET_STMP)
+ {
+ struct hwstub_stmp_desc_t stmp = m_dev->GetSTMPInfo();
+ if(stmp.wChipID == 0x3780)
+ m_soc = "imx233";
+ else if(stmp.wChipID >= 0x3700 && stmp.wChipID < 0x3780)
+ m_soc = "stmp3700";
+ else if(stmp.wChipID >= 0x3600 && stmp.wChipID < 0x3700)
+ m_soc = "stmp3600";
+ else
+ m_soc = QString("stmp%1").arg(stmp.wChipID, 4, 16, QChar('0'));
+ }
+ else if(target.dID == HWSTUB_TARGET_RK27)
+ m_soc = "rk27x";
+ else
+ m_soc = target.bName;
+}
+
+QString HWStubIoBackend::GetSocName()
+{
+ return m_soc;
+}
+
+HWStubIoBackend::~HWStubIoBackend()
+{
+ m_dev->Close();
+}
+
+bool HWStubIoBackend::ReadRegister(soc_addr_t addr, soc_word_t& value)
+{
+ return m_dev->ReadMem(addr, sizeof(value), &value);
+}
+
+bool HWStubIoBackend::Reload()
{
return true;
}
+/**
+ * HWStubBackendHelper
+ */
+HWStubBackendHelper::HWStubBackendHelper()
+{
+ libusb_init(NULL);
+#ifdef LIBUSB_NO_HOTPLUG
+ m_hotplug = false;
+#else
+ m_hotplug = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG);
+ if(m_hotplug)
+ {
+ m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback(
+ NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
+ LIBUSB_HOTPLUG_ENUMERATE, HWSTUB_USB_VID, HWSTUB_USB_PID, HWSTUB_CLASS,
+ &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this), &m_hotplug_handle);
+ }
+#endif
+}
+
+HWStubBackendHelper::~HWStubBackendHelper()
+{
+#ifndef LIBUSB_NO_HOTPLUG
+ if(m_hotplug)
+ libusb_hotplug_deregister_callback(NULL, m_hotplug_handle);
+#endif
+}
+
+QList< HWStubDevice* > HWStubBackendHelper::GetDevList()
+{
+ QList< HWStubDevice* > list;
+ libusb_device **dev_list;
+ ssize_t cnt = libusb_get_device_list(NULL, &dev_list);
+ for(int i = 0; i < cnt; i++)
+ {
+ HWStubDevice *dev = new HWStubDevice(dev_list[i]);
+ /* filter out non-hwstub devices */
+ if(dev->IsValid())
+ list.push_back(dev);
+ else
+ delete dev;
+ }
+ libusb_free_device_list(dev_list, 1);
+ return list;
+}
+
+#ifndef LIBUSB_NO_HOTPLUG
+void HWStubBackendHelper::OnHotPlug(bool arrived, struct libusb_device *dev)
+{
+ /* signal it */
+ emit OnDevListChanged(arrived, dev);
+}
+
+int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev,
+ libusb_hotplug_event event, void *user_data)
+{
+ HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data);
+ switch(event)
+ {
+ case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: helper->OnHotPlug(true, dev); break;
+ case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: helper->OnHotPlug(false, dev); break;
+ default: break;
+ }
+ return 0;
+}
+#endif
+
+bool HWStubBackendHelper::HasHotPlugSupport()
+{
+ return m_hotplug;
+}
+
+#endif
+
+/**
+ * BackendHelper
+ */
+
BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc)
:m_io_backend(io_backend), m_soc(soc)
{
@@ -119,38 +333,87 @@ BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc)
bool BackendHelper::ReadRegister(const QString& dev, const QString& reg, soc_word_t& v)
{
- return m_io_backend->ReadRegister("HW." + dev + "." + reg, v);
+ if(m_io_backend->SupportAccess(IoBackend::ByName))
+ return m_io_backend->ReadRegister("HW." + dev + "." + reg, v);
+ if(m_io_backend->SupportAccess(IoBackend::ByAddress))
+ {
+ soc_addr_t addr;
+ if(GetRegisterAddress(dev, reg, addr))
+ return m_io_backend->ReadRegister(addr, v);
+ }
+ return false;
}
-bool BackendHelper::ReadRegisterField(const QString& dev, const QString& reg,
- const QString& field, soc_word_t& v)
+
+bool BackendHelper::GetDeviceDesc(const QString& dev, soc_dev_t& dev_desc, size_t& index)
{
- soc_dev_t *sdev = 0;
for(size_t i = 0; i < m_soc.dev.size(); i++)
{
for(size_t j = 0; j < m_soc.dev[i].addr.size(); j++)
if(m_soc.dev[i].addr[j].name.c_str() == dev)
- sdev = &m_soc.dev[i];
+ {
+ dev_desc = m_soc.dev[i];
+ index = j;
+ return true;
+ }
}
- if(sdev == 0)
- return false;
- soc_reg_t *sreg = 0;
- for(size_t i = 0; i < sdev->reg.size(); i++)
+ return false;
+}
+
+bool BackendHelper::GetRegisterDesc(const soc_dev_t& dev, const QString& reg,
+ soc_reg_t& reg_desc, size_t& index)
+{
+ for(size_t i = 0; i < dev.reg.size(); i++)
{
- for(size_t j = 0; j < sdev->reg[i].addr.size(); j++)
- if(sdev->reg[i].addr[j].name.c_str() == reg)
- sreg = &sdev->reg[i];
+ for(size_t j = 0; j < dev.reg[i].addr.size(); j++)
+ if(dev.reg[i].addr[j].name.c_str() == reg)
+ {
+ index = j;
+ reg_desc = dev.reg[i];
+ return true;
+ }
}
- if(sreg == 0)
+ return false;
+}
+
+bool BackendHelper::GetFieldDesc(const soc_reg_t& reg_desc, const QString& field,
+ soc_reg_field_t& field_desc)
+{
+ for(size_t i = 0; i < reg_desc.field.size(); i++)
+ if(reg_desc.field[i].name.c_str() == field)
+ field_desc = reg_desc.field[i];
+ return false;
+}
+
+bool BackendHelper::GetRegisterAddress(const QString& dev, const QString& reg,
+ soc_addr_t& addr)
+{
+ size_t dev_index, reg_index;
+ soc_dev_t dev_desc;
+ soc_reg_t reg_desc;
+ if(!GetDeviceDesc(dev, dev_desc, dev_index))
+ return false;
+ if(!GetRegisterDesc(dev_desc, reg, reg_desc, reg_index))
+ return false;
+ addr = dev_desc.addr[dev_index].addr + reg_desc.addr[reg_index].addr;
+ return true;
+}
+
+bool BackendHelper::ReadRegisterField(const QString& dev, const QString& reg,
+ const QString& field, soc_word_t& v)
+{
+ size_t dev_index, reg_index;
+ soc_dev_t dev_desc;
+ soc_reg_t reg_desc;
+ soc_reg_field_t field_desc;
+ if(!GetDeviceDesc(dev, dev_desc, dev_index))
+ return false;
+ if(!GetRegisterDesc(dev_desc, reg, reg_desc, reg_index))
return false;
- soc_reg_field_t *sfield = 0;
- for(size_t i = 0; i < sreg->field.size(); i++)
- if(sreg->field[i].name.c_str() == field)
- sfield = &sreg->field[i];
- if(sfield == 0)
+ if(!GetFieldDesc(reg_desc, field, field_desc))
return false;
if(!ReadRegister(dev, reg, v))
return false;
- v = (v & sfield->bitmask()) >> sfield->first_bit;
+ v = (v & field_desc.bitmask()) >> field_desc.first_bit;
return true;
} \ No newline at end of file