summaryrefslogtreecommitdiff
path: root/utils/regtools/qeditor/backend.cpp
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2016-02-07 21:48:40 +0000
committerAmaury Pouly <amaury.pouly@gmail.com>2016-04-08 18:46:46 +0100
commit5ac0166388ac9a493491a30fbc3570f23950dc51 (patch)
tree8fe2019a8d3376042d1f92b7a2127bd73d3c97e3 /utils/regtools/qeditor/backend.cpp
parentcc4c9b70bcac048fc388d0f553b7621f52449526 (diff)
downloadrockbox-5ac0166388ac9a493491a30fbc3570f23950dc51.tar.gz
rockbox-5ac0166388ac9a493491a30fbc3570f23950dc51.zip
qeditor: port to the new hwstub library and add features
This commit adds support for the version of the hwstub library, which requires a lot of changes. It also adds some editing features, such as register access and much better editing of fields using the mouse (double click on a field to be able to resize and move it). Change-Id: I3c4e4cc855cb44911c72bc8127bad841b68efe52
Diffstat (limited to 'utils/regtools/qeditor/backend.cpp')
-rw-r--r--utils/regtools/qeditor/backend.cpp553
1 files changed, 401 insertions, 152 deletions
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp
index 5f006b0aa7..a8264c6e50 100644
--- a/utils/regtools/qeditor/backend.cpp
+++ b/utils/regtools/qeditor/backend.cpp
@@ -22,6 +22,7 @@
22#include <QTextStream> 22#include <QTextStream>
23#include <QDebug> 23#include <QDebug>
24#include <QFileInfo> 24#include <QFileInfo>
25#include <QFont>
25#include "backend.h" 26#include "backend.h"
26 27
27/** 28/**
@@ -337,110 +338,436 @@ QString FileIoBackend::GetFileName()
337 338
338#ifdef HAVE_HWSTUB 339#ifdef HAVE_HWSTUB
339/** 340/**
340 * HWStubDevice 341 * HWStubManager
341 */ 342 */
342HWStubDevice::HWStubDevice(struct libusb_device *dev) 343HWStubManager *HWStubManager::g_inst = nullptr;
344
345HWStubManager::HWStubManager()
343{ 346{
344 Init(dev); 347 Add("Default", QString::fromStdString(hwstub::uri::default_uri().full_uri()));
345} 348}
346 349
347HWStubDevice::HWStubDevice(const HWStubDevice *dev) 350HWStubManager::~HWStubManager()
348{ 351{
349 Init(dev->m_dev);
350} 352}
351 353
352void HWStubDevice::Init(struct libusb_device *dev) 354HWStubManager *HWStubManager::Get()
353{ 355{
354 libusb_ref_device(dev); 356 if(g_inst == nullptr)
355 m_dev = dev; 357 g_inst = new HWStubManager();
356 m_handle = 0; 358 return g_inst;
357 m_hwdev = 0;
358 m_valid = Probe();
359} 359}
360 360
361HWStubDevice::~HWStubDevice() 361bool HWStubManager::Add(const QString& name, const QString& uri)
362{
363 struct Context ctx;
364 ctx.name = name;
365 ctx.uri = uri;
366 ctx.context = hwstub::uri::create_context(uri.toStdString());
367 if(!ctx.context)
368 return false;
369 ctx.context->start_polling();
370 beginInsertRows(QModelIndex(), m_list.size(), m_list.size());
371 m_list.push_back(ctx);
372 endInsertRows();
373 return true;
374}
375
376void HWStubManager::Clear()
362{ 377{
363 Close(); 378 m_list.clear();
364 libusb_unref_device(m_dev);
365} 379}
366 380
367int HWStubDevice::GetBusNumber() 381int HWStubManager::rowCount(const QModelIndex& parent) const
368{ 382{
369 return libusb_get_bus_number(m_dev); 383 Q_UNUSED(parent);
384 return m_list.size();
370} 385}
371 386
372int HWStubDevice::GetDevAddress() 387int HWStubManager::columnCount(const QModelIndex& parent) const
373{ 388{
374 return libusb_get_device_address(m_dev); 389 Q_UNUSED(parent);
390 return 2;
375} 391}
376 392
377bool HWStubDevice::Probe() 393std::shared_ptr< hwstub::context > HWStubManager::GetContext(int row)
378{ 394{
379 if(!Open()) 395 if(row < 0 || (size_t)row >= m_list.size())
380 return false; 396 return std::shared_ptr< hwstub::context >();
381 // get target 397 else
382 int ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_TARGET, &m_hwdev_target, sizeof(m_hwdev_target)); 398 return m_list[row].context;
383 if(ret != sizeof(m_hwdev_target)) 399}
384 goto Lerr; 400
385 // get STMP information 401QVariant HWStubManager::data(const QModelIndex& index, int role) const
386 if(m_hwdev_target.dID == HWSTUB_TARGET_STMP) 402{
403 if(index.row() < 0 || (size_t)index.row() >= m_list.size())
404 return QVariant();
405 int section = index.column();
406 const Context& ctx = m_list[index.row()];
407 if(section == GetNameColumn())
387 { 408 {
388 ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_STMP, &m_hwdev_stmp, sizeof(m_hwdev_stmp)); 409 if(role == Qt::DisplayRole || role == Qt::EditRole)
389 if(ret != sizeof(m_hwdev_stmp)) 410 return QVariant(ctx.name);
390 goto Lerr;
391 } 411 }
392 else if(m_hwdev_target.dID == HWSTUB_TARGET_PP) 412 else if(section == GetUriColumn())
393 { 413 {
394 ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_PP, &m_hwdev_pp, sizeof(m_hwdev_pp)); 414 if(role == Qt::DisplayRole)
395 if(ret != sizeof(m_hwdev_pp)) 415 return QVariant(ctx.uri);
396 goto Lerr;
397 } 416 }
398 Close(); 417 return QVariant();
399 return true; 418}
400 419
401 Lerr: 420QVariant HWStubManager::headerData(int section, Qt::Orientation orientation, int role) const
402 Close(); 421{
403 return false; 422 if(orientation == Qt::Vertical)
423 return QVariant();
424 if(role != Qt::DisplayRole)
425 return QVariant();
426 if(section == GetNameColumn())
427 return QVariant("Name");
428 else if(section == GetUriColumn())
429 return QVariant("URI");
430 return QVariant();
431}
432
433Qt::ItemFlags HWStubManager::flags(const QModelIndex& index) const
434{
435 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
436 int section = index.column();
437 if(section == GetNameColumn())
438 flags |= Qt::ItemIsEditable;
439 return flags;
404} 440}
405 441
406bool HWStubDevice::Open() 442bool HWStubManager::setData(const QModelIndex& index, const QVariant& value, int role)
407{ 443{
408 if(libusb_open(m_dev, &m_handle)) 444 if(role != Qt::EditRole)
409 return false; 445 return false;
410 m_hwdev = hwstub_open(m_handle); 446 if(index.row() < 0 || (size_t)index.row() >= m_list.size())
411 if(m_hwdev == 0)
412 {
413 libusb_close(m_handle);
414 m_handle = 0;
415 return false; 447 return false;
416 } 448 if(index.column() != GetNameColumn())
449 return false;
450 m_list[index.row()].name = value.toString();
451 emit dataChanged(index, index);
417 return true; 452 return true;
418} 453}
419 454
420void HWStubDevice::Close() 455int HWStubManager::GetNameColumn() const
421{ 456{
422 if(m_hwdev) 457 return 0;
423 hwstub_release(m_hwdev);
424 m_hwdev = 0;
425 if(m_handle)
426 libusb_close(m_handle);
427 m_handle = 0;
428} 458}
429 459
430bool HWStubDevice::ReadMem(soc_addr_t addr, size_t length, void *buffer) 460int HWStubManager::GetUriColumn() const
461{
462 return 1;
463}
464
465QString HWStubManager::GetFriendlyName(std::shared_ptr< hwstub::device > device)
466{
467 /* try to open the device */
468 std::shared_ptr< hwstub::handle > handle;
469 hwstub::error err = device->open(handle);
470 if(err != hwstub::error::SUCCESS)
471 goto Lfallback;
472 /* get target descriptor */
473 struct hwstub_target_desc_t target_desc;
474 err = handle->get_target_desc(target_desc);
475 if(err != hwstub::error::SUCCESS)
476 goto Lfallback;
477 return QString::fromStdString(target_desc.bName);
478
479 /* fallback: don't open the device */
480Lfallback:
481 hwstub::usb::device *udev = dynamic_cast< hwstub::usb::device* >(device.get());
482 if(udev)
483 {
484 return QString("USB Bus %1 Device %2: ID %3:%4")
485 .arg(udev->get_bus_number()).arg(udev->get_address(), 3, 10, QChar('0'))
486 .arg(udev->get_vid(), 4, 16, QChar('0')).arg(udev->get_pid(), 4, 16, QChar('0'));
487 }
488 else
489 return QString("<Unknown device>");
490}
491
492/**
493 * HWStubContextModel
494 */
495HWStubContextModel::HWStubContextModel(QObject *parent)
496 :QAbstractTableModel(parent), m_has_dummy(false)
497{
498}
499
500HWStubContextModel::~HWStubContextModel()
501{
502 SetContext(std::shared_ptr< hwstub::context >());
503}
504
505void HWStubContextModel::SetContext(std::shared_ptr< hwstub::context > context)
506{
507 int first_row = m_has_dummy ? 1: 0;
508 /* clear previous model if any */
509 if(m_list.size() > 0)
510 {
511 beginRemoveRows(QModelIndex(), first_row, first_row + m_list.size() - 1);
512 m_list.clear();
513 endRemoveRows();
514 }
515 /* don't forget to unregister callback if context still exists */
516 std::shared_ptr< hwstub::context > ctx = m_context.lock();
517 if(ctx)
518 ctx->unregister_callback(m_callback_ref);
519 /* get new context */
520 m_context = context;
521 if(context)
522 {
523 /* register new callback */
524 m_callback_ref = context->register_callback(
525 std::bind(&HWStubContextModel::OnDevChangeLow, this, std::placeholders::_1,
526 std::placeholders::_2, std::placeholders::_3));
527 /* get dev list */
528 std::vector< std::shared_ptr< hwstub::device > > list;
529 hwstub::error err = context->get_device_list(list);
530 if(err == hwstub::error::SUCCESS)
531 {
532 beginInsertRows(QModelIndex(), first_row, first_row + list.size() - 1);
533 for(auto& d : list)
534 {
535 Device dev;
536 dev.name = GetFriendlyName(d);
537 dev.device = d;
538 m_list.push_back(dev);
539 }
540 endInsertRows();
541 }
542 }
543}
544
545void HWStubContextModel::EnableDummy(bool en, const QString& text)
546{
547 /* if needed, create/remove raw */
548 if(m_has_dummy && !en)
549 {
550 /* remove row */
551 beginRemoveRows(QModelIndex(), 0, 0);
552 m_has_dummy = false;
553 endRemoveRows();
554 }
555 else if(!m_has_dummy && en)
556 {
557 /* add row */
558 beginInsertRows(QModelIndex(), 0, 0);
559 m_has_dummy = true;
560 m_dummy_text = text;
561 endInsertRows();
562 }
563 else if(en)
564 {
565 /* text change only */
566 emit dataChanged(index(0, GetNameColumn()), index(0, GetNameColumn()));
567 }
568}
569
570int HWStubContextModel::rowCount(const QModelIndex& parent) const
571{
572 Q_UNUSED(parent);
573 return m_list.size() + (m_has_dummy ? 1 : 0);
574}
575
576int HWStubContextModel::columnCount(const QModelIndex& parent) const
577{
578 Q_UNUSED(parent);
579 return 1;
580}
581
582QVariant HWStubContextModel::data(const QModelIndex& index, int role) const
583{
584 int first_row = m_has_dummy ? 1: 0;
585 /* special case for dummy */
586 if(m_has_dummy && index.row() == 0)
587 {
588 int section = index.column();
589 if(section == GetNameColumn())
590 {
591 if(role == Qt::DisplayRole)
592 return QVariant(m_dummy_text);
593 else if(role == Qt::FontRole)
594 {
595 QFont font;
596 font.setItalic(true);
597 return QVariant(font);
598 }
599 }
600 return QVariant();
601 }
602
603 if(index.row() < first_row || (size_t)index.row() >= first_row + m_list.size())
604 return QVariant();
605 int section = index.column();
606 if(section == GetNameColumn())
607 {
608 if(role == Qt::DisplayRole)
609 return QVariant(m_list[index.row() - first_row].name);
610 }
611 return QVariant();
612}
613
614QVariant HWStubContextModel::headerData(int section, Qt::Orientation orientation, int role) const
615{
616 if(orientation == Qt::Vertical)
617 return QVariant();
618 if(role != Qt::DisplayRole)
619 return QVariant();
620 if(section == GetNameColumn())
621 return QVariant("Friendly name");
622 return QVariant();
623}
624
625Qt::ItemFlags HWStubContextModel::flags(const QModelIndex& index) const
626{
627 Q_UNUSED(index);
628 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
629}
630
631int HWStubContextModel::GetNameColumn() const
632{
633 return 0;
634}
635
636std::shared_ptr< hwstub::device > HWStubContextModel::GetDevice(int row)
637{
638 int first_row = m_has_dummy ? 1: 0;
639 /* special case for dummy */
640 if(row < first_row || (size_t)row >= first_row + m_list.size())
641 return std::shared_ptr< hwstub::device >();
642 else
643 return m_list[row - first_row].device;
644}
645
646QString HWStubContextModel::GetFriendlyName(std::shared_ptr< hwstub::device > device)
431{ 647{
432 if(!m_hwdev) 648 return HWStubManager::GetFriendlyName(device);
649}
650
651namespace
652{
653 struct dev_change_t
654 {
655 std::shared_ptr< hwstub::context > ctx;
656 bool arrived;
657 std::shared_ptr< hwstub::device > device;
658 };
659}
660
661void HWStubContextModel::OnDevChangeLow(std::shared_ptr< hwstub::context > ctx,
662 bool arrived, std::shared_ptr< hwstub::device > device)
663{
664 /* calling Qt function from non-Qt thread is unsafe. Since the polling thread
665 * is a pthread, the safest way to use Qt invoke mecanism to make it run
666 * on the event loop */
667 dev_change_t *evt = new dev_change_t;
668 evt->ctx = ctx;
669 evt->arrived = arrived;
670 evt->device = device;
671 QMetaObject::invokeMethod(this, "OnDevChangeUnsafe", Q_ARG(void *, (void *)evt));
672}
673
674void HWStubContextModel::OnDevChangeUnsafe(void *data)
675{
676 dev_change_t *evt = (dev_change_t *)data;
677 OnDevChange(evt->ctx, evt->arrived, evt->device);
678 delete evt;
679}
680
681void HWStubContextModel::OnDevChange(std::shared_ptr< hwstub::context > ctx, bool arrived,
682 std::shared_ptr< hwstub::device > device)
683{
684 int first_row = m_has_dummy ? 1: 0;
685 Q_UNUSED(ctx);
686 if(arrived)
687 {
688 Device dev;
689 dev.name = GetFriendlyName(device);
690 dev.device = device;
691 beginInsertRows(QModelIndex(), first_row + m_list.size(),
692 first_row + m_list.size());
693 m_list.push_back(dev);
694 endInsertRows();
695 }
696 else
697 {
698 /* find device in the list */
699 auto it = m_list.begin();
700 int idx = 0;
701 for(; it != m_list.end(); ++it, ++idx)
702 if(it->device == device)
703 break;
704 if(it == m_list.end())
705 return;
706 /* remove it */
707 beginRemoveRows(QModelIndex(), first_row + idx, first_row + idx);
708 m_list.erase(it);
709 endRemoveRows();
710 }
711}
712
713/**
714 * HWStubDevice
715 */
716HWStubDevice::HWStubDevice(std::shared_ptr< hwstub::device > device)
717{
718 m_valid = Probe(device);
719}
720
721HWStubDevice::~HWStubDevice()
722{
723}
724
725bool HWStubDevice::Probe(std::shared_ptr<hwstub::device> device)
726{
727 if(!device)
433 return false; 728 return false;
434 int ret = hwstub_rw_mem_atomic(m_hwdev, 1, addr, buffer, length); 729 hwstub::error err = device->open(m_handle);
435 return ret >= 0 && (size_t)ret == length; 730 if(err != hwstub::error::SUCCESS)
731 return false;
732 // get target information
733 err = m_handle->get_target_desc(m_hwdev_target);
734 if(err != hwstub::error::SUCCESS)
735 return false;
736 // get STMP/PP information
737 if(m_hwdev_target.dID == HWSTUB_TARGET_STMP)
738 {
739 err = m_handle->get_stmp_desc(m_hwdev_stmp);
740 if(err != hwstub::error::SUCCESS)
741 return false;
742 }
743 else if(m_hwdev_target.dID == HWSTUB_TARGET_PP)
744 {
745 err = m_handle->get_pp_desc(m_hwdev_pp);
746 if(err != hwstub::error::SUCCESS)
747 return false;
748 }
749 else if(m_hwdev_target.dID == HWSTUB_TARGET_JZ)
750 {
751 err = m_handle->get_jz_desc(m_hwdev_jz);
752 if(err != hwstub::error::SUCCESS)
753 return false;
754 }
755 m_name = HWStubManager::GetFriendlyName(device);
756 return true;
757}
758
759bool HWStubDevice::ReadMem(soc_addr_t addr, size_t length, void *buffer)
760{
761 size_t len = length;
762 hwstub::error err = m_handle->read(addr, buffer, len, true);
763 return err == hwstub::error::SUCCESS && len == length;
436} 764}
437 765
438bool HWStubDevice::WriteMem(soc_addr_t addr, size_t length, void *buffer) 766bool HWStubDevice::WriteMem(soc_addr_t addr, size_t length, void *buffer)
439{ 767{
440 if(!m_hwdev) 768 size_t len = length;
441 return false; 769 hwstub::error err = m_handle->write(addr, buffer, len, true);
442 int ret = hwstub_rw_mem_atomic(m_hwdev, 0, addr, buffer, length); 770 return err == hwstub::error::SUCCESS && len == length;
443 return ret >= 0 && (size_t)ret == length;
444} 771}
445 772
446bool HWStubDevice::IsValid() 773bool HWStubDevice::IsValid()
@@ -448,6 +775,10 @@ bool HWStubDevice::IsValid()
448 return m_valid; 775 return m_valid;
449} 776}
450 777
778QString HWStubDevice::GetFriendlyName()
779{
780 return m_name;
781}
451 782
452/** 783/**
453 * HWStubIoBackend 784 * HWStubIoBackend
@@ -456,7 +787,7 @@ bool HWStubDevice::IsValid()
456HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev) 787HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev)
457{ 788{
458 m_dev = dev; 789 m_dev = dev;
459 m_dev->Open(); 790
460 struct hwstub_target_desc_t target = m_dev->GetTargetInfo(); 791 struct hwstub_target_desc_t target = m_dev->GetTargetInfo();
461 if(target.dID == HWSTUB_TARGET_STMP) 792 if(target.dID == HWSTUB_TARGET_STMP)
462 { 793 {
@@ -470,6 +801,13 @@ HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev)
470 else 801 else
471 m_soc = QString("stmp%1").arg(stmp.wChipID, 4, 16, QChar('0')); 802 m_soc = QString("stmp%1").arg(stmp.wChipID, 4, 16, QChar('0'));
472 } 803 }
804 else if(target.dID == HWSTUB_TARGET_JZ)
805 {
806 struct hwstub_jz_desc_t jz = m_dev->GetJZInfo();
807 m_soc = QString("jz%1").arg(jz.wChipID, 4, 16, QChar('0'));
808 if(jz.bRevision != 0)
809 m_soc.append(QChar(jz.bRevision).toLower());
810 }
473 else if(target.dID == HWSTUB_TARGET_RK27) 811 else if(target.dID == HWSTUB_TARGET_RK27)
474 m_soc = "rk27x"; 812 m_soc = "rk27x";
475 else if(target.dID == HWSTUB_TARGET_PP) 813 else if(target.dID == HWSTUB_TARGET_PP)
@@ -549,95 +887,6 @@ bool HWStubIoBackend::Reload()
549 return true; 887 return true;
550} 888}
551 889
552/**
553 * HWStubBackendHelper
554 */
555HWStubBackendHelper::HWStubBackendHelper()
556{
557#ifdef LIBUSB_NO_HOTPLUG
558 m_hotplug = false;
559#else
560 m_hotplug = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG);
561 if(m_hotplug)
562 {
563 int evt = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
564 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT;
565 m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback(
566 NULL, (libusb_hotplug_event)evt, LIBUSB_HOTPLUG_ENUMERATE,
567 LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
568 &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this),
569 &m_hotplug_handle);
570 }
571#endif /* LIBUSB_NO_HOTPLUG */
572}
573
574HWStubBackendHelper::~HWStubBackendHelper()
575{
576#ifndef LIBUSB_NO_HOTPLUG
577 if(m_hotplug)
578 libusb_hotplug_deregister_callback(NULL, m_hotplug_handle);
579#endif /* LIBUSB_NO_HOTPLUG */
580}
581
582QList< HWStubDevice* > HWStubBackendHelper::GetDevList()
583{
584 QList< HWStubDevice* > list;
585 libusb_device **dev_list;
586 ssize_t cnt = hwstub_get_device_list(NULL, &dev_list);
587 for(int i = 0; i < cnt; i++)
588 {
589 HWStubDevice *dev = new HWStubDevice(dev_list[i]);
590 /* filter out non-hwstub devices */
591 if(dev->IsValid())
592 list.push_back(dev);
593 else
594 delete dev;
595 }
596 libusb_free_device_list(dev_list, 1);
597 return list;
598}
599
600#ifndef LIBUSB_NO_HOTPLUG
601void HWStubBackendHelper::OnHotPlug(bool arrived, struct libusb_device *dev)
602{
603 /* signal it */
604 emit OnDevListChanged(arrived, dev);
605}
606
607int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev,
608 libusb_hotplug_event event, void *user_data)
609{
610 Q_UNUSED(ctx);
611 HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data);
612 switch(event)
613 {
614 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: helper->OnHotPlug(true, dev); break;
615 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: helper->OnHotPlug(false, dev); break;
616 default: break;
617 }
618 return 0;
619}
620#endif /* LIBUSB_NO_HOTPLUG */
621
622bool HWStubBackendHelper::HasHotPlugSupport()
623{
624 return m_hotplug;
625}
626
627namespace
628{
629class lib_usb_init
630{
631public:
632 lib_usb_init()
633 {
634 libusb_init(NULL);
635 }
636};
637
638lib_usb_init __lib_usb_init;
639}
640
641#endif /* HAVE_HWSTUB */ 890#endif /* HAVE_HWSTUB */
642 891
643/** 892/**