BridgeManager: only libusb_reset_device on ubuntu

It seems that only ubuntu needs libusb_reset_device for successful
handshake. On most distros and device it works with or without, but
for some devices (like degaswifi/SM-T230 with a Marvell PXA 1088 SOC)
it causes handshake to fail.

Probably libusb_reset_device causes issues only for some devices, but
there seem to be no way to distinguish which ones from Heimdall (not
based on Odin protocol version or SOC at least).

Fixes commit 07a14d4aa8 ("InitialiseProtocol: reset device before
handshake").
This commit is contained in:
Henrik Grimler 2022-02-13 10:26:41 +01:00
parent 0f1843c93c
commit 62368adc7d
No known key found for this signature in database
GPG Key ID: B0076E490B71616B
2 changed files with 41 additions and 3 deletions

View File

@ -20,6 +20,7 @@
// C Standard Library
#include <cstdio>
#include <fstream>
// libusb
#include <libusb.h>
@ -311,10 +312,16 @@ bool BridgeManager::InitialiseProtocol(void)
memcpy(dataBuffer, "ODIN", 4);
memset(dataBuffer + 4, 0, 1);
if (libusb_reset_device(deviceHandle))
#ifdef OS_LINUX
if (IsUbuntu())
{
Interface::PrintError("Failed to reset device!\n");
Interface::Print("Resetting device...\n");
if (libusb_reset_device(deviceHandle))
{
Interface::PrintError("Failed to reset device!\n");
}
}
#endif
if (!SendBulkTransfer(dataBuffer, 4, 1000))
{
@ -1237,3 +1244,32 @@ void BridgeManager::SetUsbLogLevel(UsbLogLevel usbLogLevel)
}
}
}
#ifdef OS_LINUX
bool BridgeManager::IsUbuntu()
{
std::ifstream os_release("/etc/os-release");
std::string line, entry, os;
int pos;
while (std::getline(os_release, line))
{
pos = line.find("=");
entry = line.substr(0, pos);
if (entry == "ID")
{
os = line.substr(pos+1);
if (verbose)
{
Interface::Print("Linux distro ID: %s\n",
os.c_str());
}
if (os == "ubuntu")
{
return true;
}
break;
}
}
return false;
}
#endif

View File

@ -166,7 +166,9 @@ namespace Heimdall
bool SendFile(FILE *file, unsigned int destination, unsigned int deviceType, unsigned int fileIdentifier = 0xFFFFFFFF) const;
void SetUsbLogLevel(UsbLogLevel usbLogLevel);
#ifdef OS_LINUX
bool IsUbuntu(void);
#endif
UsbLogLevel GetUsbLogLevel(void) const
{
return usbLogLevel;