diff options
Diffstat (limited to 'utils/regtools/qeditor/backend.cpp')
-rw-r--r-- | utils/regtools/qeditor/backend.cpp | 317 |
1 files changed, 290 insertions, 27 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 |