diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-02-04 00:18:51 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-02-10 23:14:25 +0100 |
commit | 0e0c610df0d3d4044d0b21ddc1752a5dacd7f86e (patch) | |
tree | aca4cf3c5dd86384ee8018d9049e2c3469d597ea /utils | |
parent | 81dfed27cf7ca1008b9cf21c084310eaeae082ac (diff) | |
download | rockbox-0e0c610df0d3d4044d0b21ddc1752a5dacd7f86e.tar.gz rockbox-0e0c610df0d3d4044d0b21ddc1752a5dacd7f86e.zip |
utils/regtools: make qeditor able to poke directly at a hwstub device
This commit add the very handy feature of being able to read registers
directly from a device using hwstub. This is mostly trivial using the hwstub
library and the biggest change here is actually:
- being able to read registers by name and/or addresses
- being able to enumerate devives
The UI code currently doesn't handle hotplug but the backend does so it should
be trivial to add in the future. It also opens up the possibility the write
registers from hwstub or save the register values to a file.
Since it relies on both hwstub and libusb, a switch has been introduced in
qmake to disable it (use -config nohwstub).
Change-Id: I5d7d7a2a7c97ecd7407227357c8553c2773ea6cc
Diffstat (limited to 'utils')
-rw-r--r-- | utils/regtools/qeditor/backend.cpp | 317 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.h | 113 | ||||
-rw-r--r-- | utils/regtools/qeditor/main.cpp | 7 | ||||
-rw-r--r-- | utils/regtools/qeditor/qeditor.pro | 14 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.cpp | 65 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.h | 11 |
6 files changed, 486 insertions, 41 deletions
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp index e011965bd2..d2b75be701 100644 --- a/utils/regtools/qeditor/backend.cpp +++ b/utils/regtools/qeditor/backend.cpp | |||
@@ -3,6 +3,10 @@ | |||
3 | #include <QDebug> | 3 | #include <QDebug> |
4 | #include "backend.h" | 4 | #include "backend.h" |
5 | 5 | ||
6 | /** | ||
7 | * Backend | ||
8 | */ | ||
9 | |||
6 | Backend::Backend() | 10 | Backend::Backend() |
7 | { | 11 | { |
8 | } | 12 | } |
@@ -43,9 +47,16 @@ IoBackend *Backend::CreateDummyIoBackend() | |||
43 | return new DummyIoBackend(); | 47 | return new DummyIoBackend(); |
44 | } | 48 | } |
45 | 49 | ||
46 | IoBackend::IoBackend() | 50 | #ifdef HAVE_HWSTUB |
51 | IoBackend *Backend::CreateHWStubIoBackend(HWStubDevice *dev) | ||
47 | { | 52 | { |
53 | return new HWStubIoBackend(dev); | ||
48 | } | 54 | } |
55 | #endif | ||
56 | |||
57 | /** | ||
58 | * FileIoBackend | ||
59 | */ | ||
49 | 60 | ||
50 | FileIoBackend::FileIoBackend(const QString& filename) | 61 | FileIoBackend::FileIoBackend(const QString& filename) |
51 | { | 62 | { |
@@ -91,27 +102,230 @@ bool FileIoBackend::Reload() | |||
91 | return true; | 102 | return true; |
92 | } | 103 | } |
93 | 104 | ||
94 | DummyIoBackend::DummyIoBackend() | 105 | #ifdef HAVE_HWSTUB |
106 | /** | ||
107 | * HWStubDevice | ||
108 | */ | ||
109 | HWStubDevice::HWStubDevice(struct libusb_device *dev) | ||
95 | { | 110 | { |
111 | libusb_ref_device(dev); | ||
112 | m_dev = dev; | ||
113 | m_handle = 0; | ||
114 | m_hwdev = 0; | ||
115 | m_valid = Probe(); | ||
96 | } | 116 | } |
97 | 117 | ||
98 | QString DummyIoBackend::GetSocName() | 118 | HWStubDevice::~HWStubDevice() |
99 | { | 119 | { |
100 | return ""; | 120 | Close(); |
121 | libusb_unref_device(m_dev); | ||
101 | } | 122 | } |
102 | 123 | ||
103 | bool DummyIoBackend::ReadRegister(const QString& name, soc_word_t& value) | 124 | int HWStubDevice::GetBusNumber() |
104 | { | 125 | { |
105 | (void) name; | 126 | return libusb_get_bus_number(m_dev); |
106 | (void) value; | 127 | } |
128 | |||
129 | int HWStubDevice::GetDevAddress() | ||
130 | { | ||
131 | return libusb_get_device_address(m_dev); | ||
132 | } | ||
133 | |||
134 | bool HWStubDevice::Probe() | ||
135 | { | ||
136 | struct libusb_device_descriptor desc; | ||
137 | if(libusb_get_device_descriptor(m_dev, &desc)) | ||
138 | return false; | ||
139 | if(desc.idVendor != HWSTUB_USB_VID || desc.idProduct != HWSTUB_USB_PID) | ||
140 | return false; | ||
141 | if(!Open()) | ||
142 | return false; | ||
143 | int ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_VERSION, &m_hwdev_ver, sizeof(m_hwdev_ver)); | ||
144 | if(ret != sizeof(m_hwdev_ver)) | ||
145 | goto Lerr; | ||
146 | if(m_hwdev_ver.bMajor != HWSTUB_VERSION_MAJOR || m_hwdev_ver.bMinor < HWSTUB_VERSION_MINOR) | ||
147 | goto Lerr; | ||
148 | // get target | ||
149 | ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_TARGET, &m_hwdev_target, sizeof(m_hwdev_target)); | ||
150 | if(ret != sizeof(m_hwdev_target)) | ||
151 | goto Lerr; | ||
152 | // get STMP information | ||
153 | if(m_hwdev_target.dID == HWSTUB_TARGET_STMP) | ||
154 | { | ||
155 | ret = hwstub_get_desc(m_hwdev, HWSTUB_DT_STMP, &m_hwdev_stmp, sizeof(m_hwdev_stmp)); | ||
156 | if(ret != sizeof(m_hwdev_stmp)) | ||
157 | goto Lerr; | ||
158 | } | ||
159 | Close(); | ||
160 | return true; | ||
161 | |||
162 | Lerr: | ||
163 | Close(); | ||
107 | return false; | 164 | return false; |
108 | } | 165 | } |
109 | 166 | ||
110 | bool DummyIoBackend::Reload() | 167 | bool HWStubDevice::Open() |
168 | { | ||
169 | if(libusb_open(m_dev, &m_handle)) | ||
170 | return false; | ||
171 | m_hwdev = hwstub_open(m_handle); | ||
172 | if(m_hwdev == 0) | ||
173 | { | ||
174 | libusb_close(m_handle); | ||
175 | return false; | ||
176 | } | ||
177 | return true; | ||
178 | } | ||
179 | |||
180 | void HWStubDevice::Close() | ||
181 | { | ||
182 | if(m_hwdev) | ||
183 | hwstub_release(m_hwdev); | ||
184 | m_hwdev = 0; | ||
185 | if(m_handle) | ||
186 | libusb_close(m_handle); | ||
187 | m_handle = 0; | ||
188 | } | ||
189 | |||
190 | bool HWStubDevice::ReadMem(soc_addr_t addr, size_t length, void *buffer) | ||
191 | { | ||
192 | if(!m_hwdev) | ||
193 | return false; | ||
194 | int ret = hwstub_rw_mem(m_hwdev, 1, addr, buffer, length); | ||
195 | return ret >= 0 && (size_t)ret == length; | ||
196 | } | ||
197 | |||
198 | bool HWStubDevice::IsValid() | ||
199 | { | ||
200 | return m_valid; | ||
201 | } | ||
202 | |||
203 | |||
204 | /** | ||
205 | * HWStubIoBackend | ||
206 | */ | ||
207 | |||
208 | HWStubIoBackend::HWStubIoBackend(HWStubDevice *dev) | ||
209 | { | ||
210 | m_dev = dev; | ||
211 | m_dev->Open(); | ||
212 | struct hwstub_target_desc_t target = m_dev->GetTargetInfo(); | ||
213 | if(target.dID == HWSTUB_TARGET_STMP) | ||
214 | { | ||
215 | struct hwstub_stmp_desc_t stmp = m_dev->GetSTMPInfo(); | ||
216 | if(stmp.wChipID == 0x3780) | ||
217 | m_soc = "imx233"; | ||
218 | else if(stmp.wChipID >= 0x3700 && stmp.wChipID < 0x3780) | ||
219 | m_soc = "stmp3700"; | ||
220 | else if(stmp.wChipID >= 0x3600 && stmp.wChipID < 0x3700) | ||
221 | m_soc = "stmp3600"; | ||
222 | else | ||
223 | m_soc = QString("stmp%1").arg(stmp.wChipID, 4, 16, QChar('0')); | ||
224 | } | ||
225 | else if(target.dID == HWSTUB_TARGET_RK27) | ||
226 | m_soc = "rk27x"; | ||
227 | else | ||
228 | m_soc = target.bName; | ||
229 | } | ||
230 | |||
231 | QString HWStubIoBackend::GetSocName() | ||
232 | { | ||
233 | return m_soc; | ||
234 | } | ||
235 | |||
236 | HWStubIoBackend::~HWStubIoBackend() | ||
237 | { | ||
238 | m_dev->Close(); | ||
239 | } | ||
240 | |||
241 | bool HWStubIoBackend::ReadRegister(soc_addr_t addr, soc_word_t& value) | ||
242 | { | ||
243 | return m_dev->ReadMem(addr, sizeof(value), &value); | ||
244 | } | ||
245 | |||
246 | bool HWStubIoBackend::Reload() | ||
111 | { | 247 | { |
112 | return true; | 248 | return true; |
113 | } | 249 | } |
114 | 250 | ||
251 | /** | ||
252 | * HWStubBackendHelper | ||
253 | */ | ||
254 | HWStubBackendHelper::HWStubBackendHelper() | ||
255 | { | ||
256 | libusb_init(NULL); | ||
257 | #ifdef LIBUSB_NO_HOTPLUG | ||
258 | m_hotplug = false; | ||
259 | #else | ||
260 | m_hotplug = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG); | ||
261 | if(m_hotplug) | ||
262 | { | ||
263 | m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback( | ||
264 | NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, | ||
265 | LIBUSB_HOTPLUG_ENUMERATE, HWSTUB_USB_VID, HWSTUB_USB_PID, HWSTUB_CLASS, | ||
266 | &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this), &m_hotplug_handle); | ||
267 | } | ||
268 | #endif | ||
269 | } | ||
270 | |||
271 | HWStubBackendHelper::~HWStubBackendHelper() | ||
272 | { | ||
273 | #ifndef LIBUSB_NO_HOTPLUG | ||
274 | if(m_hotplug) | ||
275 | libusb_hotplug_deregister_callback(NULL, m_hotplug_handle); | ||
276 | #endif | ||
277 | } | ||
278 | |||
279 | QList< HWStubDevice* > HWStubBackendHelper::GetDevList() | ||
280 | { | ||
281 | QList< HWStubDevice* > list; | ||
282 | libusb_device **dev_list; | ||
283 | ssize_t cnt = libusb_get_device_list(NULL, &dev_list); | ||
284 | for(int i = 0; i < cnt; i++) | ||
285 | { | ||
286 | HWStubDevice *dev = new HWStubDevice(dev_list[i]); | ||
287 | /* filter out non-hwstub devices */ | ||
288 | if(dev->IsValid()) | ||
289 | list.push_back(dev); | ||
290 | else | ||
291 | delete dev; | ||
292 | } | ||
293 | libusb_free_device_list(dev_list, 1); | ||
294 | return list; | ||
295 | } | ||
296 | |||
297 | #ifndef LIBUSB_NO_HOTPLUG | ||
298 | void HWStubBackendHelper::OnHotPlug(bool arrived, struct libusb_device *dev) | ||
299 | { | ||
300 | /* signal it */ | ||
301 | emit OnDevListChanged(arrived, dev); | ||
302 | } | ||
303 | |||
304 | int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev, | ||
305 | libusb_hotplug_event event, void *user_data) | ||
306 | { | ||
307 | HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data); | ||
308 | switch(event) | ||
309 | { | ||
310 | case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: helper->OnHotPlug(true, dev); break; | ||
311 | case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: helper->OnHotPlug(false, dev); break; | ||
312 | default: break; | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | #endif | ||
317 | |||
318 | bool HWStubBackendHelper::HasHotPlugSupport() | ||
319 | { | ||
320 | return m_hotplug; | ||
321 | } | ||
322 | |||
323 | #endif | ||
324 | |||
325 | /** | ||
326 | * BackendHelper | ||
327 | */ | ||
328 | |||
115 | BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc) | 329 | BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc) |
116 | :m_io_backend(io_backend), m_soc(soc) | 330 | :m_io_backend(io_backend), m_soc(soc) |
117 | { | 331 | { |
@@ -119,38 +333,87 @@ BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc) | |||
119 | 333 | ||
120 | bool BackendHelper::ReadRegister(const QString& dev, const QString& reg, soc_word_t& v) | 334 | bool BackendHelper::ReadRegister(const QString& dev, const QString& reg, soc_word_t& v) |
121 | { | 335 | { |
122 | return m_io_backend->ReadRegister("HW." + dev + "." + reg, v); | 336 | if(m_io_backend->SupportAccess(IoBackend::ByName)) |
337 | return m_io_backend->ReadRegister("HW." + dev + "." + reg, v); | ||
338 | if(m_io_backend->SupportAccess(IoBackend::ByAddress)) | ||
339 | { | ||
340 | soc_addr_t addr; | ||
341 | if(GetRegisterAddress(dev, reg, addr)) | ||
342 | return m_io_backend->ReadRegister(addr, v); | ||
343 | } | ||
344 | return false; | ||
123 | } | 345 | } |
124 | 346 | ||
125 | bool BackendHelper::ReadRegisterField(const QString& dev, const QString& reg, | 347 | |
126 | const QString& field, soc_word_t& v) | 348 | bool BackendHelper::GetDeviceDesc(const QString& dev, soc_dev_t& dev_desc, size_t& index) |
127 | { | 349 | { |
128 | soc_dev_t *sdev = 0; | ||
129 | for(size_t i = 0; i < m_soc.dev.size(); i++) | 350 | for(size_t i = 0; i < m_soc.dev.size(); i++) |
130 | { | 351 | { |
131 | for(size_t j = 0; j < m_soc.dev[i].addr.size(); j++) | 352 | for(size_t j = 0; j < m_soc.dev[i].addr.size(); j++) |
132 | if(m_soc.dev[i].addr[j].name.c_str() == dev) | 353 | if(m_soc.dev[i].addr[j].name.c_str() == dev) |
133 | sdev = &m_soc.dev[i]; | 354 | { |
355 | dev_desc = m_soc.dev[i]; | ||
356 | index = j; | ||
357 | return true; | ||
358 | } | ||
134 | } | 359 | } |
135 | if(sdev == 0) | 360 | return false; |
136 | return false; | 361 | } |
137 | soc_reg_t *sreg = 0; | 362 | |
138 | for(size_t i = 0; i < sdev->reg.size(); i++) | 363 | bool BackendHelper::GetRegisterDesc(const soc_dev_t& dev, const QString& reg, |
364 | soc_reg_t& reg_desc, size_t& index) | ||
365 | { | ||
366 | for(size_t i = 0; i < dev.reg.size(); i++) | ||
139 | { | 367 | { |
140 | for(size_t j = 0; j < sdev->reg[i].addr.size(); j++) | 368 | for(size_t j = 0; j < dev.reg[i].addr.size(); j++) |
141 | if(sdev->reg[i].addr[j].name.c_str() == reg) | 369 | if(dev.reg[i].addr[j].name.c_str() == reg) |
142 | sreg = &sdev->reg[i]; | 370 | { |
371 | index = j; | ||
372 | reg_desc = dev.reg[i]; | ||
373 | return true; | ||
374 | } | ||
143 | } | 375 | } |
144 | if(sreg == 0) | 376 | return false; |
377 | } | ||
378 | |||
379 | bool BackendHelper::GetFieldDesc(const soc_reg_t& reg_desc, const QString& field, | ||
380 | soc_reg_field_t& field_desc) | ||
381 | { | ||
382 | for(size_t i = 0; i < reg_desc.field.size(); i++) | ||
383 | if(reg_desc.field[i].name.c_str() == field) | ||
384 | field_desc = reg_desc.field[i]; | ||
385 | return false; | ||
386 | } | ||
387 | |||
388 | bool BackendHelper::GetRegisterAddress(const QString& dev, const QString& reg, | ||
389 | soc_addr_t& addr) | ||
390 | { | ||
391 | size_t dev_index, reg_index; | ||
392 | soc_dev_t dev_desc; | ||
393 | soc_reg_t reg_desc; | ||
394 | if(!GetDeviceDesc(dev, dev_desc, dev_index)) | ||
395 | return false; | ||
396 | if(!GetRegisterDesc(dev_desc, reg, reg_desc, reg_index)) | ||
397 | return false; | ||
398 | addr = dev_desc.addr[dev_index].addr + reg_desc.addr[reg_index].addr; | ||
399 | return true; | ||
400 | } | ||
401 | |||
402 | bool BackendHelper::ReadRegisterField(const QString& dev, const QString& reg, | ||
403 | const QString& field, soc_word_t& v) | ||
404 | { | ||
405 | size_t dev_index, reg_index; | ||
406 | soc_dev_t dev_desc; | ||
407 | soc_reg_t reg_desc; | ||
408 | soc_reg_field_t field_desc; | ||
409 | if(!GetDeviceDesc(dev, dev_desc, dev_index)) | ||
410 | return false; | ||
411 | if(!GetRegisterDesc(dev_desc, reg, reg_desc, reg_index)) | ||
145 | return false; | 412 | return false; |
146 | soc_reg_field_t *sfield = 0; | 413 | if(!GetFieldDesc(reg_desc, field, field_desc)) |
147 | for(size_t i = 0; i < sreg->field.size(); i++) | ||
148 | if(sreg->field[i].name.c_str() == field) | ||
149 | sfield = &sreg->field[i]; | ||
150 | if(sfield == 0) | ||
151 | return false; | 414 | return false; |
152 | if(!ReadRegister(dev, reg, v)) | 415 | if(!ReadRegister(dev, reg, v)) |
153 | return false; | 416 | return false; |
154 | v = (v & sfield->bitmask()) >> sfield->first_bit; | 417 | v = (v & field_desc.bitmask()) >> field_desc.first_bit; |
155 | return true; | 418 | return true; |
156 | } \ No newline at end of file | 419 | } \ No newline at end of file |
diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h index 536eb8cec5..55f31cce52 100644 --- a/utils/regtools/qeditor/backend.h +++ b/utils/regtools/qeditor/backend.h | |||
@@ -4,16 +4,29 @@ | |||
4 | #include <QObject> | 4 | #include <QObject> |
5 | #include <QStringList> | 5 | #include <QStringList> |
6 | #include <QMap> | 6 | #include <QMap> |
7 | #include <QVector> | ||
7 | #include "soc_desc.hpp" | 8 | #include "soc_desc.hpp" |
9 | #ifdef HAVE_HWSTUB | ||
10 | #include "hwstub.h" | ||
11 | #endif | ||
8 | 12 | ||
9 | class IoBackend : public QObject | 13 | class IoBackend : public QObject |
10 | { | 14 | { |
11 | Q_OBJECT | 15 | Q_OBJECT |
12 | public: | 16 | public: |
13 | IoBackend(); | 17 | IoBackend() {} |
18 | virtual ~IoBackend() {} | ||
14 | 19 | ||
20 | enum AccessType | ||
21 | { | ||
22 | ByName, | ||
23 | ByAddress, | ||
24 | }; | ||
25 | |||
26 | virtual bool SupportAccess(AccessType type) = 0; | ||
15 | virtual QString GetSocName() = 0; | 27 | virtual QString GetSocName() = 0; |
16 | virtual bool ReadRegister(const QString& name, soc_word_t& value) = 0; | 28 | virtual bool ReadRegister(const QString& name, soc_word_t& value) = 0; |
29 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) = 0; | ||
17 | virtual bool Reload() = 0; | 30 | virtual bool Reload() = 0; |
18 | }; | 31 | }; |
19 | 32 | ||
@@ -21,11 +34,15 @@ class DummyIoBackend : public IoBackend | |||
21 | { | 34 | { |
22 | Q_OBJECT | 35 | Q_OBJECT |
23 | public: | 36 | public: |
24 | DummyIoBackend(); | 37 | DummyIoBackend() {} |
25 | 38 | ||
26 | virtual QString GetSocName(); | 39 | virtual bool SupportAccess(AccessType type) { (void) type; return false; } |
27 | virtual bool ReadRegister(const QString& name, soc_word_t& value); | 40 | virtual QString GetSocName() { return ""; } |
28 | virtual bool Reload(); | 41 | virtual bool ReadRegister(const QString& name, soc_word_t& value) |
42 | { (void) name; (void) value; return false; } | ||
43 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) | ||
44 | { (void) addr; (void) value; return false; } | ||
45 | virtual bool Reload() { return false; } | ||
29 | }; | 46 | }; |
30 | 47 | ||
31 | class FileIoBackend : public IoBackend | 48 | class FileIoBackend : public IoBackend |
@@ -34,8 +51,11 @@ class FileIoBackend : public IoBackend | |||
34 | public: | 51 | public: |
35 | FileIoBackend(const QString& filename); | 52 | FileIoBackend(const QString& filename); |
36 | 53 | ||
54 | virtual bool SupportAccess(AccessType type) { return type == ByName; } | ||
37 | virtual QString GetSocName(); | 55 | virtual QString GetSocName(); |
38 | virtual bool ReadRegister(const QString& name, soc_word_t& value); | 56 | virtual bool ReadRegister(const QString& name, soc_word_t& value); |
57 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) | ||
58 | { (void) addr; (void) value; return false; } | ||
39 | virtual bool Reload(); | 59 | virtual bool Reload(); |
40 | 60 | ||
41 | protected: | 61 | protected: |
@@ -44,6 +64,82 @@ protected: | |||
44 | QMap< QString, soc_word_t > m_map; | 64 | QMap< QString, soc_word_t > m_map; |
45 | }; | 65 | }; |
46 | 66 | ||
67 | #ifdef HAVE_HWSTUB | ||
68 | class HWStubDevice | ||
69 | { | ||
70 | public: | ||
71 | HWStubDevice(struct libusb_device *dev); | ||
72 | ~HWStubDevice(); | ||
73 | bool IsValid(); | ||
74 | bool Open(); | ||
75 | void Close(); | ||
76 | int GetBusNumber(); | ||
77 | int GetDevAddress(); | ||
78 | /* Calls below are cached and do not require the device to be opened */ | ||
79 | inline struct hwstub_version_desc_t GetVersionInfo() { return m_hwdev_ver; } | ||
80 | inline struct hwstub_target_desc_t GetTargetInfo() { return m_hwdev_target; } | ||
81 | inline struct hwstub_stmp_desc_t GetSTMPInfo() { return m_hwdev_stmp; } | ||
82 | /* Calls below require the device to be opened */ | ||
83 | bool ReadMem(soc_addr_t addr, size_t length, void *buffer); | ||
84 | |||
85 | protected: | ||
86 | bool Probe(); | ||
87 | |||
88 | bool m_valid; | ||
89 | struct libusb_device *m_dev; | ||
90 | libusb_device_handle *m_handle; | ||
91 | struct hwstub_device_t *m_hwdev; | ||
92 | struct hwstub_version_desc_t m_hwdev_ver; | ||
93 | struct hwstub_target_desc_t m_hwdev_target; | ||
94 | struct hwstub_stmp_desc_t m_hwdev_stmp; | ||
95 | }; | ||
96 | |||
97 | class HWStubIoBackend : public IoBackend | ||
98 | { | ||
99 | Q_OBJECT | ||
100 | public: | ||
101 | HWStubIoBackend(HWStubDevice *dev); | ||
102 | virtual ~HWStubIoBackend(); | ||
103 | |||
104 | virtual bool SupportAccess(AccessType type) { return type == ByAddress; } | ||
105 | virtual QString GetSocName(); | ||
106 | virtual bool ReadRegister(const QString& name, soc_word_t& value) | ||
107 | { (void) name; (void) value; return false; } | ||
108 | virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); | ||
109 | virtual bool Reload(); | ||
110 | |||
111 | protected: | ||
112 | QString m_soc; | ||
113 | HWStubDevice *m_dev; | ||
114 | }; | ||
115 | |||
116 | #if LIBUSB_API_VERSION < 0x01000102 | ||
117 | #define LIBUSB_NO_HOTPLUG | ||
118 | #endif | ||
119 | |||
120 | class HWStubBackendHelper : public QObject | ||
121 | { | ||
122 | Q_OBJECT | ||
123 | public: | ||
124 | HWStubBackendHelper(); | ||
125 | ~HWStubBackendHelper(); | ||
126 | bool HasHotPlugSupport(); | ||
127 | QList< HWStubDevice* > GetDevList(); | ||
128 | |||
129 | signals: | ||
130 | void OnDevListChanged(bool arrived, struct libusb_device *dev); | ||
131 | |||
132 | protected: | ||
133 | #ifndef LIBUSB_NO_HOTPLUG | ||
134 | void OnHotPlug(bool arrived, struct libusb_device *dev); | ||
135 | static int HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev, | ||
136 | libusb_hotplug_event event, void *user_data); | ||
137 | libusb_hotplug_callback_handle m_hotplug_handle; | ||
138 | #endif | ||
139 | bool m_hotplug; | ||
140 | }; | ||
141 | #endif | ||
142 | |||
47 | class Backend : public QObject | 143 | class Backend : public QObject |
48 | { | 144 | { |
49 | Q_OBJECT | 145 | Q_OBJECT |
@@ -55,6 +151,9 @@ public: | |||
55 | bool GetSocByName(const QString& name, soc_t& s); | 151 | bool GetSocByName(const QString& name, soc_t& s); |
56 | IoBackend *CreateDummyIoBackend(); | 152 | IoBackend *CreateDummyIoBackend(); |
57 | IoBackend *CreateFileIoBackend(const QString& filename); | 153 | IoBackend *CreateFileIoBackend(const QString& filename); |
154 | #ifdef HAVE_HWSTUB | ||
155 | IoBackend *CreateHWStubIoBackend(HWStubDevice *dev); | ||
156 | #endif | ||
58 | 157 | ||
59 | signals: | 158 | signals: |
60 | void OnSocListChanged(); | 159 | void OnSocListChanged(); |
@@ -69,6 +168,10 @@ public: | |||
69 | bool ReadRegister(const QString& dev, const QString& reg, soc_word_t& v); | 168 | bool ReadRegister(const QString& dev, const QString& reg, soc_word_t& v); |
70 | bool ReadRegisterField(const QString& dev, const QString& reg, | 169 | bool ReadRegisterField(const QString& dev, const QString& reg, |
71 | const QString& field, soc_word_t& v); | 170 | const QString& field, soc_word_t& v); |
171 | bool GetDeviceDesc(const QString& dev, soc_dev_t& dev_desc, size_t& index); | ||
172 | bool GetRegisterDesc(const soc_dev_t& dev, const QString& reg, soc_reg_t& reg_desc, size_t& index); | ||
173 | bool GetFieldDesc(const soc_reg_t& reg_desc, const QString& field, soc_reg_field_t& field_desc); | ||
174 | bool GetRegisterAddress(const QString& dev, const QString& reg, soc_addr_t& addr); | ||
72 | private: | 175 | private: |
73 | IoBackend *m_io_backend; | 176 | IoBackend *m_io_backend; |
74 | soc_t m_soc; | 177 | soc_t m_soc; |
diff --git a/utils/regtools/qeditor/main.cpp b/utils/regtools/qeditor/main.cpp index 0e4e67bfb7..576d3a16fc 100644 --- a/utils/regtools/qeditor/main.cpp +++ b/utils/regtools/qeditor/main.cpp | |||
@@ -6,25 +6,24 @@ int main(int argc, char *argv[]) | |||
6 | { | 6 | { |
7 | QApplication app(argc, argv); | 7 | QApplication app(argc, argv); |
8 | 8 | ||
9 | Backend *backend = new Backend; | 9 | Backend backend;; |
10 | QDir dir(QCoreApplication::applicationDirPath()); | 10 | QDir dir(QCoreApplication::applicationDirPath()); |
11 | dir.cdUp(); | 11 | dir.cdUp(); |
12 | dir.cd("desc"); | 12 | dir.cd("desc"); |
13 | dir.setFilter(QDir::Files); | 13 | dir.setFilter(QDir::Files); |
14 | printf("%s\n", dir.absolutePath().toStdString().c_str()); | ||
15 | QFileInfoList list = dir.entryInfoList(); | 14 | QFileInfoList list = dir.entryInfoList(); |
16 | for(int i = 0; i < list.size(); i++) | 15 | for(int i = 0; i < list.size(); i++) |
17 | { | 16 | { |
18 | QFileInfo fileInfo = list.at(i); | 17 | QFileInfo fileInfo = list.at(i); |
19 | if(fileInfo.fileName().right(4) != ".xml" || fileInfo.fileName().left(5) != "regs-") | 18 | if(fileInfo.fileName().right(4) != ".xml" || fileInfo.fileName().left(5) != "regs-") |
20 | continue; | 19 | continue; |
21 | backend->LoadSocDesc(fileInfo.absoluteFilePath()); | 20 | backend.LoadSocDesc(fileInfo.absoluteFilePath()); |
22 | } | 21 | } |
23 | 22 | ||
24 | QCoreApplication::setOrganizationName("Rockbox"); | 23 | QCoreApplication::setOrganizationName("Rockbox"); |
25 | QCoreApplication::setApplicationName("Register Editor"); | 24 | QCoreApplication::setApplicationName("Register Editor"); |
26 | QCoreApplication::setOrganizationDomain("rockbox.org"); | 25 | QCoreApplication::setOrganizationDomain("rockbox.org"); |
27 | MainWindow win(backend); | 26 | MainWindow win(&backend); |
28 | win.show(); | 27 | win.show(); |
29 | return app.exec(); | 28 | return app.exec(); |
30 | } | 29 | } |
diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro index 4e25a48d89..5604fe9d41 100644 --- a/utils/regtools/qeditor/qeditor.pro +++ b/utils/regtools/qeditor/qeditor.pro | |||
@@ -3,6 +3,16 @@ QT += widgets | |||
3 | HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h | 3 | HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h |
4 | SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp | 4 | SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp |
5 | LIBS += -L../lib/ -lsocdesc -lxml2 | 5 | LIBS += -L../lib/ -lsocdesc -lxml2 |
6 | INCLUDEPATH += ../lib/ | 6 | INCLUDEPATH += ../lib/ ../../hwstub/lib |
7 | 7 | ||
8 | CONFIG += debug \ No newline at end of file | 8 | unix { |
9 | !nohwstub { | ||
10 | message("Use 'qmake -config nohwstub' if you want to disable hwstub support") | ||
11 | LIBS += -L../../hwstub/lib -lhwstub | ||
12 | DEFINES += HAVE_HWSTUB | ||
13 | CONFIG += link_pkgconfig | ||
14 | PKGCONFIG += libusb-1.0 | ||
15 | } | ||
16 | } | ||
17 | |||
18 | CONFIG += debug | ||
diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp index 4f7a73cffc..8f64bbf48a 100644 --- a/utils/regtools/qeditor/regtab.cpp +++ b/utils/regtools/qeditor/regtab.cpp | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <QTableWidget> | 13 | #include <QTableWidget> |
14 | #include <QHeaderView> | 14 | #include <QHeaderView> |
15 | #include <QFileDialog> | 15 | #include <QFileDialog> |
16 | #include <QDebug> | ||
16 | #include "backend.h" | 17 | #include "backend.h" |
17 | #include "analyser.h" | 18 | #include "analyser.h" |
18 | 19 | ||
@@ -65,6 +66,9 @@ RegTab::RegTab(Backend *backend, QTabWidget *parent) | |||
65 | m_data_selector = new QComboBox; | 66 | m_data_selector = new QComboBox; |
66 | m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing)); | 67 | m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing)); |
67 | m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile)); | 68 | m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile)); |
69 | #ifdef HAVE_HWSTUB | ||
70 | m_data_selector->addItem(QIcon::fromTheme("multimedia-player"), "Device...", QVariant(DataSelDevice)); | ||
71 | #endif | ||
68 | m_data_sel_edit = new QLineEdit; | 72 | m_data_sel_edit = new QLineEdit; |
69 | m_data_sel_edit->setReadOnly(true); | 73 | m_data_sel_edit->setReadOnly(true); |
70 | m_data_soc_label = new QLabel; | 74 | m_data_soc_label = new QLabel; |
@@ -72,6 +76,10 @@ RegTab::RegTab(Backend *backend, QTabWidget *parent) | |||
72 | data_sel_reload->setIcon(QIcon::fromTheme("view-refresh")); | 76 | data_sel_reload->setIcon(QIcon::fromTheme("view-refresh")); |
73 | data_sel_layout->addWidget(m_data_selector); | 77 | data_sel_layout->addWidget(m_data_selector); |
74 | data_sel_layout->addWidget(m_data_sel_edit); | 78 | data_sel_layout->addWidget(m_data_sel_edit); |
79 | #ifdef HAVE_HWSTUB | ||
80 | m_dev_selector = new QComboBox; | ||
81 | data_sel_layout->addWidget(m_dev_selector, 1); | ||
82 | #endif | ||
75 | data_sel_layout->addWidget(m_data_soc_label); | 83 | data_sel_layout->addWidget(m_data_soc_label); |
76 | data_sel_layout->addWidget(data_sel_reload); | 84 | data_sel_layout->addWidget(data_sel_reload); |
77 | data_sel_group->setLayout(data_sel_layout); | 85 | data_sel_group->setLayout(data_sel_layout); |
@@ -107,6 +115,10 @@ RegTab::RegTab(Backend *backend, QTabWidget *parent) | |||
107 | this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *))); | 115 | this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *))); |
108 | connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this, | 116 | connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this, |
109 | SLOT(OnAnalyserClicked(QListWidgetItem *))); | 117 | SLOT(OnAnalyserClicked(QListWidgetItem *))); |
118 | #ifdef HAVE_HWSTUB | ||
119 | connect(m_dev_selector, SIGNAL(currentIndexChanged(int)), | ||
120 | this, SLOT(OnDevChanged(int))); | ||
121 | #endif | ||
110 | 122 | ||
111 | OnSocListChanged(); | 123 | OnSocListChanged(); |
112 | OnDataSelChanged(DataSelNothing); | 124 | OnDataSelChanged(DataSelNothing); |
@@ -141,6 +153,10 @@ void RegTab::OnDataSelChanged(int index) | |||
141 | QVariant var = m_data_selector->itemData(index); | 153 | QVariant var = m_data_selector->itemData(index); |
142 | if(var == DataSelFile) | 154 | if(var == DataSelFile) |
143 | { | 155 | { |
156 | m_data_sel_edit->show(); | ||
157 | #ifdef HAVE_HWSTUB | ||
158 | m_dev_selector->hide(); | ||
159 | #endif | ||
144 | QFileDialog *fd = new QFileDialog(m_data_selector); | 160 | QFileDialog *fd = new QFileDialog(m_data_selector); |
145 | fd->setFilter("Textual files (*.txt);;All files (*)"); | 161 | fd->setFilter("Textual files (*.txt);;All files (*)"); |
146 | fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString()); | 162 | fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString()); |
@@ -155,8 +171,20 @@ void RegTab::OnDataSelChanged(int index) | |||
155 | } | 171 | } |
156 | Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath()); | 172 | Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath()); |
157 | } | 173 | } |
174 | #ifdef HAVE_HWSTUB | ||
175 | else if(var == DataSelDevice) | ||
176 | { | ||
177 | m_data_sel_edit->hide(); | ||
178 | m_dev_selector->show(); | ||
179 | OnDevListChanged(); | ||
180 | } | ||
181 | #endif | ||
158 | else | 182 | else |
159 | { | 183 | { |
184 | m_data_sel_edit->show(); | ||
185 | #ifdef HAVE_HWSTUB | ||
186 | m_dev_selector->hide(); | ||
187 | #endif | ||
160 | delete m_io_backend; | 188 | delete m_io_backend; |
161 | m_io_backend = m_backend->CreateDummyIoBackend(); | 189 | m_io_backend = m_backend->CreateDummyIoBackend(); |
162 | SetDataSocName(""); | 190 | SetDataSocName(""); |
@@ -204,7 +232,7 @@ void RegTab::OnAnalyserClicked(QListWidgetItem *current) | |||
204 | delete m_right_content; | 232 | delete m_right_content; |
205 | AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text()); | 233 | AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text()); |
206 | m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget(); | 234 | m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget(); |
207 | m_right_panel->addWidget(m_right_content); | 235 | m_right_panel->addWidget(m_right_content, 1); |
208 | } | 236 | } |
209 | 237 | ||
210 | void RegTab::DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr, | 238 | void RegTab::DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr, |
@@ -256,8 +284,8 @@ void RegTab::DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr, | |||
256 | top_layout->addStretch(); | 284 | top_layout->addStretch(); |
257 | 285 | ||
258 | soc_word_t value; | 286 | soc_word_t value; |
259 | bool has_value = m_io_backend->ReadRegister(QString().sprintf("HW.%s.%s", | 287 | BackendHelper helper(m_io_backend, m_cur_soc); |
260 | dev_addr.name.c_str(), reg_addr.name.c_str()), value); | 288 | bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value); |
261 | 289 | ||
262 | QHBoxLayout *raw_val_layout = 0; | 290 | QHBoxLayout *raw_val_layout = 0; |
263 | if(has_value) | 291 | if(has_value) |
@@ -348,6 +376,37 @@ void RegTab::OnSocListChanged() | |||
348 | m_soc_selector->addItem(socs[i]); | 376 | m_soc_selector->addItem(socs[i]); |
349 | } | 377 | } |
350 | 378 | ||
379 | #ifdef HAVE_HWSTUB | ||
380 | void RegTab::OnDevListChanged() | ||
381 | { | ||
382 | m_dev_selector->clear(); | ||
383 | QList< HWStubDevice* > list = m_hwstub_helper.GetDevList(); | ||
384 | foreach(HWStubDevice *dev, list) | ||
385 | { | ||
386 | QString name = QString("Bus %1 Device %2: %3").arg(dev->GetBusNumber()) | ||
387 | .arg(dev->GetDevAddress()).arg(dev->GetTargetInfo().bName); | ||
388 | m_dev_selector->addItem(QIcon::fromTheme("multimedia-player"), name, | ||
389 | QVariant::fromValue((void *)dev)); | ||
390 | } | ||
391 | if(list.size() > 0) | ||
392 | m_dev_selector->setCurrentIndex(0); | ||
393 | else | ||
394 | SetDataSocName(""); | ||
395 | } | ||
396 | |||
397 | void RegTab::OnDevChanged(int index) | ||
398 | { | ||
399 | if(index == -1) | ||
400 | return; | ||
401 | HWStubDevice *dev = reinterpret_cast< HWStubDevice* >(m_dev_selector->itemData(index).value< void* >()); | ||
402 | delete m_io_backend; | ||
403 | m_io_backend = m_backend->CreateHWStubIoBackend(dev); | ||
404 | SetDataSocName(m_io_backend->GetSocName()); | ||
405 | OnDataSocActivated(m_io_backend->GetSocName()); | ||
406 | OnDataChanged(); | ||
407 | } | ||
408 | #endif | ||
409 | |||
351 | void RegTab::FillDevSubTree(RegTreeItem *item) | 410 | void RegTab::FillDevSubTree(RegTreeItem *item) |
352 | { | 411 | { |
353 | soc_dev_t& sd = m_cur_soc.dev[item->GetDevIndex()]; | 412 | soc_dev_t& sd = m_cur_soc.dev[item->GetDevIndex()]; |
diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h index 7ec8c9009f..d570eb6f90 100644 --- a/utils/regtools/qeditor/regtab.h +++ b/utils/regtools/qeditor/regtab.h | |||
@@ -25,6 +25,9 @@ enum | |||
25 | { | 25 | { |
26 | DataSelNothing, | 26 | DataSelNothing, |
27 | DataSelFile, | 27 | DataSelFile, |
28 | #ifdef HAVE_HWSTUB | ||
29 | DataSelDevice, | ||
30 | #endif | ||
28 | }; | 31 | }; |
29 | 32 | ||
30 | class RegTreeItem : public QTreeWidgetItem | 33 | class RegTreeItem : public QTreeWidgetItem |
@@ -56,6 +59,10 @@ protected: | |||
56 | soc_reg_t& reg, soc_reg_addr_t& reg_addr); | 59 | soc_reg_t& reg, soc_reg_addr_t& reg_addr); |
57 | void SetDataSocName(const QString& socname); | 60 | void SetDataSocName(const QString& socname); |
58 | QComboBox *m_soc_selector; | 61 | QComboBox *m_soc_selector; |
62 | #ifdef HAVE_HWSTUB | ||
63 | QComboBox *m_dev_selector; | ||
64 | HWStubBackendHelper m_hwstub_helper; | ||
65 | #endif | ||
59 | Backend *m_backend; | 66 | Backend *m_backend; |
60 | QTreeWidget *m_reg_tree; | 67 | QTreeWidget *m_reg_tree; |
61 | soc_t m_cur_soc; | 68 | soc_t m_cur_soc; |
@@ -71,6 +78,10 @@ protected: | |||
71 | QListWidget *m_analysers_list; | 78 | QListWidget *m_analysers_list; |
72 | 79 | ||
73 | private slots: | 80 | private slots: |
81 | #ifdef HAVE_HWSTUB | ||
82 | void OnDevListChanged(); | ||
83 | void OnDevChanged(int index); | ||
84 | #endif | ||
74 | void OnSocChanged(const QString& text); | 85 | void OnSocChanged(const QString& text); |
75 | void OnSocListChanged(); | 86 | void OnSocListChanged(); |
76 | void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); | 87 | void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); |