diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-02-09 02:16:43 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-02-10 23:14:26 +0100 |
commit | a66a5af4db8249b5b86a8126e0fe7a60a6f6338a (patch) | |
tree | 2b9507b56b72da61ffdf90ef44ec44a862fcd0c1 | |
parent | 3d07706c05c46878533f55f26bbe02d7904efd75 (diff) | |
download | rockbox-a66a5af4db8249b5b86a8126e0fe7a60a6f6338a.tar.gz rockbox-a66a5af4db8249b5b86a8126e0fe7a60a6f6338a.zip |
regtools/qeditor: prepare support for register writing
Change-Id: Ifef36a3ddb1604db63ec974da2d6a77a5540ff42
-rw-r--r-- | utils/regtools/qeditor/backend.cpp | 43 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.h | 36 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.cpp | 117 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.h | 19 |
4 files changed, 207 insertions, 8 deletions
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp index 75c504a6f6..fa107ec26c 100644 --- a/utils/regtools/qeditor/backend.cpp +++ b/utils/regtools/qeditor/backend.cpp | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <QFile> | 1 | #include <QFile> |
2 | #include <QTextStream> | 2 | #include <QTextStream> |
3 | #include <QDebug> | 3 | #include <QDebug> |
4 | #include <QFileInfo> | ||
4 | #include "backend.h" | 5 | #include "backend.h" |
5 | 6 | ||
6 | /** | 7 | /** |
@@ -99,9 +100,38 @@ bool FileIoBackend::Reload() | |||
99 | else if(ok) | 100 | else if(ok) |
100 | m_map[key] = val; | 101 | m_map[key] = val; |
101 | } | 102 | } |
103 | |||
104 | m_readonly = !QFileInfo(file).isWritable(); | ||
105 | m_dirty = false; | ||
106 | return true; | ||
107 | } | ||
108 | |||
109 | bool FileIoBackend::WriteRegister(const QString& name, soc_word_t value) | ||
110 | { | ||
111 | m_dirty = true; | ||
112 | m_map[name] = value; | ||
102 | return true; | 113 | return true; |
103 | } | 114 | } |
104 | 115 | ||
116 | bool FileIoBackend::Commit() | ||
117 | { | ||
118 | if(!m_dirty) | ||
119 | return true; | ||
120 | QFile file(m_filename); | ||
121 | if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) | ||
122 | return false; | ||
123 | QTextStream out(&file); | ||
124 | out << "HW = " << m_soc << "\n"; | ||
125 | QMapIterator< QString, soc_word_t > it(m_map); | ||
126 | while(it.hasNext()) | ||
127 | { | ||
128 | it.next(); | ||
129 | out << it.key() << " = " << it.value() << "\n"; | ||
130 | } | ||
131 | out.flush(); | ||
132 | return file.flush(); | ||
133 | } | ||
134 | |||
105 | #ifdef HAVE_HWSTUB | 135 | #ifdef HAVE_HWSTUB |
106 | /** | 136 | /** |
107 | * HWStubDevice | 137 | * HWStubDevice |
@@ -195,6 +225,14 @@ bool HWStubDevice::ReadMem(soc_addr_t addr, size_t length, void *buffer) | |||
195 | return ret >= 0 && (size_t)ret == length; | 225 | return ret >= 0 && (size_t)ret == length; |
196 | } | 226 | } |
197 | 227 | ||
228 | bool HWStubDevice::WriteMem(soc_addr_t addr, size_t length, void *buffer) | ||
229 | { | ||
230 | if(!m_hwdev) | ||
231 | return false; | ||
232 | int ret = hwstub_rw_mem(m_hwdev, 0, addr, buffer, length); | ||
233 | return ret >= 0 && (size_t)ret == length; | ||
234 | } | ||
235 | |||
198 | bool HWStubDevice::IsValid() | 236 | bool HWStubDevice::IsValid() |
199 | { | 237 | { |
200 | return m_valid; | 238 | return m_valid; |
@@ -243,6 +281,11 @@ bool HWStubIoBackend::ReadRegister(soc_addr_t addr, soc_word_t& value) | |||
243 | return m_dev->ReadMem(addr, sizeof(value), &value); | 281 | return m_dev->ReadMem(addr, sizeof(value), &value); |
244 | } | 282 | } |
245 | 283 | ||
284 | bool HWStubIoBackend:: WriteRegister(soc_addr_t addr, soc_word_t value) | ||
285 | { | ||
286 | return m_dev->WriteMem(addr, sizeof(value), &value); | ||
287 | } | ||
288 | |||
246 | bool HWStubIoBackend::Reload() | 289 | bool HWStubIoBackend::Reload() |
247 | { | 290 | { |
248 | return true; | 291 | return true; |
diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h index 879b88c42c..72a19b6ec1 100644 --- a/utils/regtools/qeditor/backend.h +++ b/utils/regtools/qeditor/backend.h | |||
@@ -32,6 +32,17 @@ public: | |||
32 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) = 0; | 32 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) = 0; |
33 | /* reload content (if it makes sense) */ | 33 | /* reload content (if it makes sense) */ |
34 | virtual bool Reload() = 0; | 34 | virtual bool Reload() = 0; |
35 | /* check whether backend supports writing */ | ||
36 | virtual bool IsReadOnly() = 0; | ||
37 | /* write a register by name or address | ||
38 | * NOTE: even on a read-only backend, a write is allowed be successful as long | ||
39 | * as commit fails */ | ||
40 | virtual bool WriteRegister(const QString& name, soc_word_t value) = 0; | ||
41 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value) = 0; | ||
42 | /* check whether backend contains uncommitted (ie cached) writes */ | ||
43 | virtual bool IsDirty() = 0; | ||
44 | /* commit all writes */ | ||
45 | virtual bool Commit() = 0; | ||
35 | }; | 46 | }; |
36 | 47 | ||
37 | class DummyIoBackend : public IoBackend | 48 | class DummyIoBackend : public IoBackend |
@@ -47,8 +58,17 @@ public: | |||
47 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) | 58 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) |
48 | { (void) addr; (void) value; return false; } | 59 | { (void) addr; (void) value; return false; } |
49 | virtual bool Reload() { return false; } | 60 | virtual bool Reload() { return false; } |
61 | virtual bool IsReadOnly() { return true; } | ||
62 | virtual bool WriteRegister(const QString& name, soc_word_t value) | ||
63 | { (void) name; (void) value; return false; } | ||
64 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value) | ||
65 | { (void) addr; (void) value; return false; } | ||
66 | virtual bool IsDirty() { return false; } | ||
67 | virtual bool Commit() { return false; } | ||
50 | }; | 68 | }; |
51 | 69 | ||
70 | /** NOTE the File backend makes a difference between writes and commits: | ||
71 | * a write will *never* touch the underlying file unless it was committed. */ | ||
52 | class FileIoBackend : public IoBackend | 72 | class FileIoBackend : public IoBackend |
53 | { | 73 | { |
54 | Q_OBJECT | 74 | Q_OBJECT |
@@ -61,10 +81,18 @@ public: | |||
61 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) | 81 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) |
62 | { (void) addr; (void) value; return false; } | 82 | { (void) addr; (void) value; return false; } |
63 | virtual bool Reload(); | 83 | virtual bool Reload(); |
84 | virtual bool IsReadOnly() { return m_readonly; } | ||
85 | virtual bool WriteRegister(const QString& name, soc_word_t value); | ||
86 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value) | ||
87 | { (void) addr; (void) value; return false; } | ||
88 | virtual bool IsDirty() { return m_dirty; } | ||
89 | virtual bool Commit(); | ||
64 | 90 | ||
65 | protected: | 91 | protected: |
66 | QString m_filename; | 92 | QString m_filename; |
67 | QString m_soc; | 93 | QString m_soc; |
94 | bool m_readonly; | ||
95 | bool m_dirty; | ||
68 | QMap< QString, soc_word_t > m_map; | 96 | QMap< QString, soc_word_t > m_map; |
69 | }; | 97 | }; |
70 | 98 | ||
@@ -85,6 +113,7 @@ public: | |||
85 | inline struct hwstub_stmp_desc_t GetSTMPInfo() { return m_hwdev_stmp; } | 113 | inline struct hwstub_stmp_desc_t GetSTMPInfo() { return m_hwdev_stmp; } |
86 | /* Calls below require the device to be opened */ | 114 | /* Calls below require the device to be opened */ |
87 | bool ReadMem(soc_addr_t addr, size_t length, void *buffer); | 115 | bool ReadMem(soc_addr_t addr, size_t length, void *buffer); |
116 | bool WriteMem(soc_addr_t addr, size_t length, void *buffer); | ||
88 | 117 | ||
89 | protected: | 118 | protected: |
90 | bool Probe(); | 119 | bool Probe(); |
@@ -98,6 +127,7 @@ protected: | |||
98 | struct hwstub_stmp_desc_t m_hwdev_stmp; | 127 | struct hwstub_stmp_desc_t m_hwdev_stmp; |
99 | }; | 128 | }; |
100 | 129 | ||
130 | /** NOTE the HWStub backend is never dirty: all writes are immediately committed */ | ||
101 | class HWStubIoBackend : public IoBackend | 131 | class HWStubIoBackend : public IoBackend |
102 | { | 132 | { |
103 | Q_OBJECT | 133 | Q_OBJECT |
@@ -111,6 +141,12 @@ public: | |||
111 | { (void) name; (void) value; return false; } | 141 | { (void) name; (void) value; return false; } |
112 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); | 142 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); |
113 | virtual bool Reload(); | 143 | virtual bool Reload(); |
144 | virtual bool IsReadOnly() { return false; } | ||
145 | virtual bool WriteRegister(const QString& name, soc_word_t value) | ||
146 | { (void) name; (void) value; return false; } | ||
147 | virtual bool WriteRegister(soc_addr_t addr, soc_word_t value); | ||
148 | virtual bool IsDirty() { return false; } | ||
149 | virtual bool Commit() { return true; } | ||
114 | 150 | ||
115 | protected: | 151 | protected: |
116 | QString m_soc; | 152 | QString m_soc; |
diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp index e4adecf203..1e9846ef33 100644 --- a/utils/regtools/qeditor/regtab.cpp +++ b/utils/regtools/qeditor/regtab.cpp | |||
@@ -17,17 +17,100 @@ | |||
17 | #include "backend.h" | 17 | #include "backend.h" |
18 | #include "analyser.h" | 18 | #include "analyser.h" |
19 | 19 | ||
20 | RegTreeItem::RegTreeItem(const QString& string, int type) | 20 | SocFieldValidator::SocFieldValidator(QObject *parent) |
21 | :QTreeWidgetItem(QStringList(string), type) | 21 | :QValidator(parent) |
22 | { | 22 | { |
23 | m_field.first_bit = 0; | ||
24 | m_field.last_bit = 31; | ||
23 | } | 25 | } |
24 | 26 | ||
25 | void RegTreeItem::SetPath(int dev_idx, int dev_addr_idx, int reg_idx, int reg_addr_idx) | 27 | SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent) |
28 | :QValidator(parent), m_field(field) | ||
26 | { | 29 | { |
27 | m_dev_idx = dev_idx; | 30 | } |
28 | m_dev_addr_idx = dev_addr_idx; | 31 | |
29 | m_reg_idx = reg_idx; | 32 | void SocFieldValidator::fixup(QString& input) const |
30 | m_reg_addr_idx = reg_addr_idx; | 33 | { |
34 | input = input.trimmed(); | ||
35 | } | ||
36 | |||
37 | QValidator::State SocFieldValidator::validate(QString& input, int& pos) const | ||
38 | { | ||
39 | (void) pos; | ||
40 | soc_word_t val; | ||
41 | State state = parse(input, val); | ||
42 | qDebug() << "validate(" << input << "): " << state; | ||
43 | return state; | ||
44 | } | ||
45 | |||
46 | QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const | ||
47 | { | ||
48 | // the empty string is all alwats intermediate | ||
49 | if(input.size() == 0) | ||
50 | return Intermediate; | ||
51 | // first check named values | ||
52 | State state = Invalid; | ||
53 | foreach(const soc_reg_field_value_t& value, m_field.value) | ||
54 | { | ||
55 | QString name = QString::fromLocal8Bit(value.name.c_str()); | ||
56 | // cannot be a substring if too long or empty | ||
57 | if(input.size() > name.size()) | ||
58 | continue; | ||
59 | // check equal string | ||
60 | if(input == name) | ||
61 | { | ||
62 | state = Acceptable; | ||
63 | val = value.value; | ||
64 | break; | ||
65 | } | ||
66 | // check substring | ||
67 | if(name.startsWith(input)) | ||
68 | state = Intermediate; | ||
69 | } | ||
70 | // early return for exact match | ||
71 | if(state == Acceptable) | ||
72 | return state; | ||
73 | // do a few special cases for convenience | ||
74 | if(input.compare("0x", Qt::CaseInsensitive) == 0 || | ||
75 | input.compare("0b", Qt::CaseInsensitive) == 0) | ||
76 | return Intermediate; | ||
77 | // try by parsing | ||
78 | unsigned basis, pos; | ||
79 | if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive)) | ||
80 | { | ||
81 | basis = 16; | ||
82 | pos = 2; | ||
83 | } | ||
84 | else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive)) | ||
85 | { | ||
86 | basis = 2; | ||
87 | pos = 2; | ||
88 | } | ||
89 | else if(input.size() >= 2 && input.startsWith("0")) | ||
90 | { | ||
91 | basis = 8; | ||
92 | pos = 1; | ||
93 | } | ||
94 | else | ||
95 | { | ||
96 | basis = 10; | ||
97 | pos = 0; | ||
98 | } | ||
99 | bool ok = false; | ||
100 | unsigned long v = input.mid(pos).toULong(&ok, basis); | ||
101 | // if not ok, return result of name parsing | ||
102 | if(!ok) | ||
103 | return state; | ||
104 | // if ok, check if it fits in the number of bits | ||
105 | unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1; | ||
106 | unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1; | ||
107 | if(v <= max) | ||
108 | { | ||
109 | val = v; | ||
110 | return Acceptable; | ||
111 | } | ||
112 | |||
113 | return state; | ||
31 | } | 114 | } |
32 | 115 | ||
33 | RegTab::RegTab(Backend *backend) | 116 | RegTab::RegTab(Backend *backend) |
@@ -167,6 +250,7 @@ void RegTab::OnDataSelChanged(int index) | |||
167 | OnDataSocActivated(m_io_backend->GetSocName()); | 250 | OnDataSocActivated(m_io_backend->GetSocName()); |
168 | } | 251 | } |
169 | Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath()); | 252 | Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath()); |
253 | SetReadOnlyIndicator(); | ||
170 | } | 254 | } |
171 | #ifdef HAVE_HWSTUB | 255 | #ifdef HAVE_HWSTUB |
172 | else if(var == DataSelDevice) | 256 | else if(var == DataSelDevice) |
@@ -189,6 +273,10 @@ void RegTab::OnDataSelChanged(int index) | |||
189 | OnDataChanged(); | 273 | OnDataChanged(); |
190 | } | 274 | } |
191 | 275 | ||
276 | void RegTab::SetReadOnlyIndicator() | ||
277 | { | ||
278 | } | ||
279 | |||
192 | void RegTab::OnDataChanged() | 280 | void RegTab::OnDataChanged() |
193 | { | 281 | { |
194 | OnRegItemChanged(m_reg_tree->currentItem(), m_reg_tree->currentItem()); | 282 | OnRegItemChanged(m_reg_tree->currentItem(), m_reg_tree->currentItem()); |
@@ -230,6 +318,8 @@ void RegTab::DisplayRegister(const SocRegRef& ref) | |||
230 | { | 318 | { |
231 | delete m_right_content; | 319 | delete m_right_content; |
232 | 320 | ||
321 | bool read_only = m_io_backend->IsReadOnly(); | ||
322 | |||
233 | QVBoxLayout *right_layout = new QVBoxLayout; | 323 | QVBoxLayout *right_layout = new QVBoxLayout; |
234 | 324 | ||
235 | const soc_dev_addr_t& dev_addr = ref.GetDevAddr(); | 325 | const soc_dev_addr_t& dev_addr = ref.GetDevAddr(); |
@@ -286,9 +376,11 @@ void RegTab::DisplayRegister(const SocRegRef& ref) | |||
286 | QLabel *raw_val_name = new QLabel; | 376 | QLabel *raw_val_name = new QLabel; |
287 | raw_val_name->setText("Raw value:"); | 377 | raw_val_name->setText("Raw value:"); |
288 | QLineEdit *raw_val_edit = new QLineEdit; | 378 | QLineEdit *raw_val_edit = new QLineEdit; |
289 | raw_val_edit->setReadOnly(true); | 379 | raw_val_edit->setReadOnly(read_only); |
290 | raw_val_edit->setText(QString().sprintf("0x%08x", value)); | 380 | raw_val_edit->setText(QString().sprintf("0x%08x", value)); |
291 | raw_val_edit->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); | 381 | raw_val_edit->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); |
382 | raw_val_edit->setValidator(new SocFieldValidator(raw_val_edit)); | ||
383 | connect(raw_val_edit, SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed())); | ||
292 | raw_val_layout = new QHBoxLayout; | 384 | raw_val_layout = new QHBoxLayout; |
293 | raw_val_layout->addStretch(); | 385 | raw_val_layout->addStretch(); |
294 | raw_val_layout->addWidget(raw_val_name); | 386 | raw_val_layout->addWidget(raw_val_name); |
@@ -445,3 +537,12 @@ void RegTab::OnSocChanged(const QString& soc) | |||
445 | FillRegTree(); | 537 | FillRegTree(); |
446 | FillAnalyserList(); | 538 | FillAnalyserList(); |
447 | } | 539 | } |
540 | |||
541 | void RegTab::OnRawRegValueReturnPressed() | ||
542 | { | ||
543 | QObject *obj = sender(); | ||
544 | QLineEdit *edit = dynamic_cast< QLineEdit* >(obj); | ||
545 | const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator* >(edit->validator()); | ||
546 | soc_word_t val; | ||
547 | QValidator::State state = validator->parse(edit->text(), val); | ||
548 | } | ||
diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h index 107e4e3986..72f00a31a2 100644 --- a/utils/regtools/qeditor/regtab.h +++ b/utils/regtools/qeditor/regtab.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <QPushButton> | 11 | #include <QPushButton> |
12 | #include <QLabel> | 12 | #include <QLabel> |
13 | #include <QListWidget> | 13 | #include <QListWidget> |
14 | #include <QValidator> | ||
14 | #include <soc_desc.hpp> | 15 | #include <soc_desc.hpp> |
15 | #include "backend.h" | 16 | #include "backend.h" |
16 | #include "settings.h" | 17 | #include "settings.h" |
@@ -52,6 +53,22 @@ private: | |||
52 | SocRegRef m_ref; | 53 | SocRegRef m_ref; |
53 | }; | 54 | }; |
54 | 55 | ||
56 | class SocFieldValidator : public QValidator | ||
57 | { | ||
58 | Q_OBJECT | ||
59 | public: | ||
60 | SocFieldValidator(QObject *parent = 0); | ||
61 | SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0); | ||
62 | |||
63 | virtual void fixup(QString& input) const; | ||
64 | virtual State validate(QString& input, int& pos) const; | ||
65 | /* validate and return the interpreted value */ | ||
66 | State parse(const QString& input, soc_word_t& val) const; | ||
67 | |||
68 | protected: | ||
69 | soc_reg_field_t m_field; | ||
70 | }; | ||
71 | |||
55 | }; | 72 | }; |
56 | 73 | ||
57 | class RegTab : public QSplitter | 74 | class RegTab : public QSplitter |
@@ -90,6 +107,7 @@ private slots: | |||
90 | void OnDevListChanged(); | 107 | void OnDevListChanged(); |
91 | void OnDevChanged(int index); | 108 | void OnDevChanged(int index); |
92 | #endif | 109 | #endif |
110 | void SetReadOnlyIndicator(); | ||
93 | void OnSocChanged(const QString& text); | 111 | void OnSocChanged(const QString& text); |
94 | void OnSocListChanged(); | 112 | void OnSocListChanged(); |
95 | void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); | 113 | void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); |
@@ -99,6 +117,7 @@ private slots: | |||
99 | void OnDataSocActivated(const QString&); | 117 | void OnDataSocActivated(const QString&); |
100 | void OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous); | 118 | void OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous); |
101 | void OnAnalyserClicked(QListWidgetItem *clicked); | 119 | void OnAnalyserClicked(QListWidgetItem *clicked); |
120 | void OnRawRegValueReturnPressed(); | ||
102 | }; | 121 | }; |
103 | 122 | ||
104 | #endif /* REGTAB_H */ \ No newline at end of file | 123 | #endif /* REGTAB_H */ \ No newline at end of file |