Skip to content

Commit

Permalink
try to solve #35 and #38 as well as stalled upload
Browse files Browse the repository at this point in the history
Signed-off-by: Martin <[email protected]>
  • Loading branch information
Ho-Ro committed Nov 29, 2019
1 parent 76f075c commit 0b77b94
Show file tree
Hide file tree
Showing 11 changed files with 899 additions and 1,078 deletions.
2 changes: 1 addition & 1 deletion openhantek/src/OH_BUILD.h
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Do not edit, will be re-created at each commit!
#define OH_BUILD "20191125 build 562"
#define OH_BUILD "20191129 build 563"
34 changes: 23 additions & 11 deletions openhantek/src/hantekdso/models/modelDSO6022.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@

using namespace Hantek;

static ModelDSO2020 modelInstance_20;
static ModelDSO6022BE modelInstance_22;
static ModelDSO6022BL modelInstance_2a;
#ifdef LCSOFT_TEST_BOARD
// two test cases with simple EZUSB board (LCsoft) without EEPROM or with Saleae VID/PID EEPROM
static ModelEzUSB modelInstance4;
static ModelSaleae modelInstance5;
#endif
static ModelDSO6022BE modelInstance_6022be;
static ModelDSO6022BL modelInstance_6022bl;

static ModelDSO2020 modelInstance_2020;

static void initSpecifications(Dso::ControlSpecification& specification) {
// we drop 2K + 480 sample values due to unreliable start of stream
Expand Down Expand Up @@ -122,6 +118,9 @@ static void applyRequirements_(HantekDsoControl *dsoControl) {
dsoControl->addCommand(new ControlSetCalFreq()); // 0xE6
}


// Hantek DSO-6022BE (this is the base model)
//
// VID/PID active VID/PID no FW FW ver FW name Scope name
// |------------| |------------| |----| |---------| |----------|
ModelDSO6022BE::ModelDSO6022BE() : DSOModel(ID, 0x04b5, 0x6022, 0x04b4, 0x6022, 0x0204, "dso6022be", "DSO-6022BE",
Expand All @@ -133,6 +132,7 @@ void ModelDSO6022BE::applyRequirements(HantekDsoControl *dsoControl) const {
applyRequirements_(dsoControl);
}


// Hantek DSO-6022BL (scope or logic analyzer)
ModelDSO6022BL::ModelDSO6022BL() : DSOModel(ID, 0x04b5, 0x602a, 0x04b4, 0x602a, 0x0204, "dso6022bl", "DSO-6022BL",
Dso::ControlSpecification(2)) {
Expand All @@ -143,7 +143,8 @@ void ModelDSO6022BL::applyRequirements(HantekDsoControl *dsoControl) const {
applyRequirements_(dsoControl);
}

// Voltcraft DSO-2020 USB Oscilloscope

// Voltcraft DSO-2020 USB Oscilloscope (HW is identical to 6022)
// Scope starts up as model DS-2020 (VID/PID = 04b4/2020) but loads 6022BE firmware and looks like a 6022BE
ModelDSO2020::ModelDSO2020() : DSOModel(ID, 0x04b5, 0x6022, 0x04b4, 0x2020, 0x0204, "dso6022be", "DSO-2020",
Dso::ControlSpecification(2)) {
Expand All @@ -155,9 +156,18 @@ void ModelDSO2020::applyRequirements(HantekDsoControl *dsoControl) const {
}


#ifdef LCSOFT_TEST_BOARD
// two test cases with simple EZUSB board (LCsoft) without EEPROM or with Saleae VID/PID EEPROM

// two test cases with simple EZUSB board (LCsoft) without EEPROM or with Saleae VID/PID in EEPROM
// after loading the FW they look like a 6022BE (without useful sample values as Port B and D are left open)
// LCSOFT_TEST_BOARD is #defined/#undefined in modelDSO6022.h

#ifdef LCSOFT_TEST_BOARD

static ModelEzUSB modelInstance_EzUSB;
static ModelSaleae modelInstance_Saleae;


// LCSOFT without EEPROM reports EzUSB VID/PID
ModelEzUSB::ModelEzUSB() : DSOModel(ID, 0x04b5, 0x6022, 0x04b4, 0x8613, 0x0204, "dso6022be", "LCsoft-EzUSB",
Dso::ControlSpecification(2)) {
initSpecifications(specification);
Expand All @@ -167,6 +177,8 @@ void ModelEzUSB::applyRequirements(HantekDsoControl *dsoControl) const {
applyRequirements_(dsoControl);
}


// Saleae VID/PID in EEPROM
ModelSaleae::ModelSaleae() : DSOModel(ID, 0x04b5, 0x6022, 0x0925, 0x3881, 0x0204, "dso6022be", "LCsoft-Saleae",
Dso::ControlSpecification(2)) {
initSpecifications(specification);
Expand Down
8 changes: 7 additions & 1 deletion openhantek/src/hantekdso/models/modelDSO6022.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ struct ModelDSO2020 : public DSOModel {
};


// two test cases with simple EZUSB board (LCsoft) without EEPROM or with Saleae VID/PID in EEPROM
// after loading the FW they look like a 6022BE (without useful sample values as Port B and D are left open)
// LCSOFT_TEST_BOARD is also used in modelDSO6022.cpp

// #define LCSOFT_TEST_BOARD

#ifdef LCSOFT_TEST_BOARD
// two test cases with simple EZUSB board (LCsoft) without EEPROM or with Saleae VID/PID EEPROM

struct ModelEzUSB : public DSOModel {
static const int ID = 0x6022;
ModelEzUSB();
Expand All @@ -42,4 +47,5 @@ struct ModelSaleae : public DSOModel {
ModelSaleae();
void applyRequirements(HantekDsoControl* dsoControl) const override;
};

#endif
60 changes: 40 additions & 20 deletions openhantek/src/usb/finddevices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

#include "modelregistry.h"

FindDevices::FindDevices(libusb_context *context) : context(context) {}

// Iterate through all usb devices
FindDevices::FindDevices( libusb_context *context ) : context( context ) {}


// Iterate all devices on USB and keep track of all supported scopes
int FindDevices::updateDeviceList() {
libusb_device **deviceList;
ssize_t deviceCount = libusb_get_device_list(context, &deviceList);
Expand All @@ -31,50 +33,68 @@ int FindDevices::updateDeviceList() {
++findIteration;
int changes = 0;

for (ssize_t deviceIterator = 0; deviceIterator < deviceCount; ++deviceIterator) {
libusb_device *device = deviceList[deviceIterator];
for (ssize_t deviceIndex = 0; deviceIndex < deviceCount; ++deviceIndex ) {
libusb_device *device = deviceList[ deviceIndex ];
// Get device descriptor
struct libusb_device_descriptor descriptor;
libusb_get_device_descriptor(device, &descriptor);
DeviceList::const_iterator inList = devices.find(USBDevice::computeUSBdeviceID(device));
libusb_get_device_descriptor( device, &descriptor );

if ( inList != devices.end()) {
inList->second->setFindIteration(findIteration);
}
if ( 0x1d6b == descriptor.idVendor ) // skip linux foundation devices, e.g. usb root hubs
continue;

const UniqueUSBid USBid = USBDevice::computeUSBdeviceID( device );

DeviceList::const_iterator inList = devices.find( USBid );
if ( inList != devices.end()) { // already in list, update heartbeat only
inList->second->setFindIteration( findIteration );
continue;
}
// else check against all supported models for match
for (DSOModel* model : ModelRegistry::get()->models()) {
// Check VID and PID for firmware flashed devices
bool supported = descriptor.idVendor == model->vendorID && descriptor.idProduct == model->productID;
// Devices without firmware have different VID/PIDs
supported |= descriptor.idVendor == model->vendorIDnoFirmware && descriptor.idProduct == model->productIDnoFirmware;
if (supported) {
if (supported) { // put matching device into list
++changes;
devices[USBDevice::computeUSBdeviceID(device)] = std::unique_ptr<USBDevice>(new USBDevice(model, device, findIteration));
// printf( "+ %016lX %s\n", USBid, model->name.c_str() );
devices[ USBid ] = std::unique_ptr<USBDevice>(new USBDevice( model, device, findIteration ) );
break; // stop after 1st supported model (there can be more models with identical VID/PID)
}
}
}

// Remove non existing devices
for (DeviceList::iterator it=devices.begin();it!=devices.end();) {
if (it->second->getFindIteration() != findIteration) {
for ( DeviceList::iterator it=devices.begin(); it!=devices.end(); ) {
if ( it->second->getFindIteration() != findIteration ) { // heartbeat not up to date, no more on the bus
++changes;
it = devices.erase(it);
// printf( "- %016lX\n", it->first );
it = devices.erase( it ); // it points to next entry
} else {
++it;
}
}
libusb_free_device_list( deviceList, false );
return changes;
#ifdef __linux__
libusb_free_device_list( deviceList, true );
#else
// TODO check if this crashes on FreeBSD, MacOSX, Windows
// TODO check if change true -> false solves it
libusb_free_device_list( deviceList, true );
#endif
return changes; // report number of all detected bus changes (added + removed devices)
}


const FindDevices::DeviceList* FindDevices::getDevices()
{
return &devices;
}

std::unique_ptr<USBDevice> FindDevices::takeDevice(UniqueUSBid id)

std::unique_ptr<USBDevice> FindDevices::takeDevice( UniqueUSBid id )
{
DeviceList::iterator i = devices.find(id);
if (i==devices.end()) return nullptr;
return std::move(i->second);
DeviceList::iterator it = devices.find( id );
if ( it == devices.end() )
return nullptr;
return std::move( it->second );
}
13 changes: 7 additions & 6 deletions openhantek/src/usb/uploadFirmware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@ bool UploadFirmware::startUpload(USBDevice *device) {
if (!temp_firmware_path) return false;
temp_firmware_path->open();

#ifndef __FreeBSD__
// We need to claim the first interface, reported to give an error on FreeBSD
status = libusb_set_auto_detach_kernel_driver(handle, 1);
if (status != LIBUSB_SUCCESS) {
errorMessage = TR("libusb_set_auto_detach_kernel_driver() failed: %1").arg(libusb_error_name(status));
libusb_close(handle);
#ifdef __linux__
// Detach kernel driver, reported to lead to an error on FreeBSD, MacOSX and Windows
status = libusb_set_auto_detach_kernel_driver( handle, 1 );
if ( status != LIBUSB_SUCCESS && status != LIBUSB_ERROR_NOT_SUPPORTED ) {
errorMessage = TR( "libusb_set_auto_detach_kernel_driver() failed: %1" ).arg( libusb_error_name( status ) );
libusb_close( handle );
return false;
}
#endif

// We need to claim the first interface (num=0)
status = libusb_claim_interface(handle, 0);
if (status != LIBUSB_SUCCESS) {
errorMessage = TR("libusb_claim_interface() failed: %1").arg(libusb_error_name(status));
Expand Down
29 changes: 24 additions & 5 deletions openhantek/src/usb/usbdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,34 @@ QString libUsbErrorString(int error) {
}


UniqueUSBid USBDevice::computeUSBdeviceID(libusb_device *device) {
UniqueUSBid v = 0;
libusb_get_port_numbers(device, (uint8_t *)&v, sizeof(v));
return v;
UniqueUSBid USBDevice::computeUSBdeviceID(libusb_device *device ) {
// Returns a 64-bit value that uniquely identifies a device on the bus
// bbppVVVVPPPPFFFF
// ^^^^-- Firmware version
// ^^^^------ Product ID
// ^^^^---------- Vendor ID
// ^^-------------- USB port
// ^^---------------- USB bus

// Get device descriptor
struct libusb_device_descriptor descriptor;
libusb_get_device_descriptor(device, &descriptor);
// collect values and arrange them
UniqueUSBid uid = libusb_get_bus_number( device );
uid <<= 8;
uid |= libusb_get_port_number( device );
uid <<= 16;
uid |= descriptor.idVendor;
uid <<= 16;
uid |= descriptor.idProduct;
uid <<= 16;
uid |= descriptor.bcdDevice;
return uid;
}


USBDevice::USBDevice(DSOModel *model, libusb_device *device, unsigned findIteration)
: model(model), device(device), findIteration(findIteration), uniqueUSBdeviceID(computeUSBdeviceID(device)) {
: model(model), device(device), findIteration(findIteration), uniqueUSBdeviceID( computeUSBdeviceID( device ) ) {
libusb_ref_device(device);
libusb_get_device_descriptor(device, &descriptor);
}
Expand Down
14 changes: 5 additions & 9 deletions openhantek/src/usb/usbdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

class DSOModel;

typedef unsigned long UniqueUSBid;
typedef uint64_t UniqueUSBid;


/// \brief Returns string representation for libusb errors.
Expand Down Expand Up @@ -133,15 +133,11 @@ class USBDevice : public QObject {
/**
* @return Return the unique usb device id {@link USBDevice::computeUSBdeviceID()}.
*/
inline unsigned long getUniqueUSBDeviceID() const { return uniqueUSBdeviceID; }
inline UniqueUSBid getUniqueUSBDeviceID() const { return uniqueUSBdeviceID; }
/**
* The USB bus is organized in a tree hierarchy. A device is connected to a port on a bus device,
* which is connected to a port on another bus device etc up to the root usb device.
*
* The USB 3.0 standard allows up to 7 levels with 256 devices on each level (1 Byte). We generate
* a unique number for the connected device.
* ID built from bus, port, VID, PID and FW version
*/
static UniqueUSBid computeUSBdeviceID(libusb_device *device);
static UniqueUSBid computeUSBdeviceID( libusb_device *device );

/// \brief Get the oscilloscope model.
/// \return The ::Model of the connected Hantek DSO.
Expand All @@ -167,7 +163,7 @@ class USBDevice : public QObject {
libusb_device *device; ///< The USB handle for the oscilloscope
libusb_device_handle *handle = nullptr;
unsigned findIteration;
const unsigned long uniqueUSBdeviceID;
const UniqueUSBid uniqueUSBdeviceID;
int interface;
int outPacketLength; ///< Packet length for the OUT endpoint
int inPacketLength; ///< Packet length for the IN endpoint
Expand Down
Loading

0 comments on commit 0b77b94

Please sign in to comment.