aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Dobell <benjamin.dobell+git@glassechidna.com.au>2014-04-30 03:49:19 +1000
committerBenjamin Dobell <benjamin.dobell+git@glassechidna.com.au>2014-05-06 21:39:05 +1000
commit1e345bcd7c6a82bbf0800781416d5df15b555da0 (patch)
tree6b514985d730ad52356df41c7e6b85dc177800ea
parenta934ad26086ef44563ef7813608e310c0f2dee08 (diff)
downloadexternal_heimdall-1e345bcd7c6a82bbf0800781416d5df15b555da0.zip
external_heimdall-1e345bcd7c6a82bbf0800781416d5df15b555da0.tar.gz
external_heimdall-1e345bcd7c6a82bbf0800781416d5df15b555da0.tar.bz2
Fix support for SGS4 (with empty bulk transfers)
After each bulk transfer sent containing an Odin/Loke protocol packet, we now send through a zero length bulk transfer. This is required for newer devices to function correctly.
-rw-r--r--heimdall/source/BridgeManager.cpp140
-rw-r--r--heimdall/source/BridgeManager.h2
2 files changed, 55 insertions, 87 deletions
diff --git a/heimdall/source/BridgeManager.cpp b/heimdall/source/BridgeManager.cpp
index 49dde7f..3e85a09 100644
--- a/heimdall/source/BridgeManager.cpp
+++ b/heimdall/source/BridgeManager.cpp
@@ -80,7 +80,6 @@ enum
enum
{
- kHandshakeMaxAttempts = 5,
kReceivePacketMaxAttempts = 5
};
@@ -384,7 +383,7 @@ bool BridgeManager::InitialiseProtocol(void)
{
Interface::Print("Initialising protocol...\n");
- LineCoding lineCoding;
+ /*LineCoding lineCoding;
lineCoding.dteRate = 115200;
lineCoding.charFormat = kLineCodingCharFormatZeroToOneStopBit;
@@ -399,93 +398,53 @@ bool BridgeManager::InitialiseProtocol(void)
lineCoding.dataBits = 8;
SetControlLineCoding(lineCoding);
- SetControlLineState(kLineStateControlSignalCarrierControl);
+ SetControlLineState(kLineStateControlSignalCarrierControl);*/
- unsigned int attempt = 0;
+ int dataTransferred = 0;
- // max(250, communicationDelay)
- int retryDelay = (communicationDelay > 250) ? communicationDelay : 250;
+ unsigned char dataBuffer[7];
- for (; attempt < kHandshakeMaxAttempts; attempt++)
- {
- if (attempt > 0)
- {
- if (verbose)
- Interface::PrintErrorSameLine(" Retrying...\n");
-
- // Wait longer each retry
- Sleep(retryDelay * (attempt + 1));
- }
+ // Send "ODIN"
+ memcpy(dataBuffer, "ODIN", 4);
+ memset(dataBuffer + 4, 0, 1);
- int dataTransferred = 0;
+ if (!SendBulkTransfer(dataBuffer, 4, 1000))
+ {
+ Interface::PrintError("Failed to send handshake!");
+ }
- unsigned char dataBuffer[7];
+ // Expect "LOKE"
+ memset(dataBuffer, 0, 7);
- // Send "ODIN"
- memcpy(dataBuffer, "ODIN", 4);
- memset(dataBuffer + 4, 0, 1);
+ int retry = 0;
+ dataTransferred = 0;
- if (libusb_bulk_transfer(deviceHandle, outEndpoint, dataBuffer, 4, &dataTransferred, 1000) != LIBUSB_SUCCESS)
- {
- if (verbose)
- Interface::PrintError("Failed to send data: \"%s\"\n", dataBuffer);
- else
- Interface::PrintError("Failed to send data!");
+ int result = libusb_bulk_transfer(deviceHandle, inEndpoint, dataBuffer, 7, &dataTransferred, 1000);
- return (false);
- }
-
- if (dataTransferred != 4)
+ if (result != LIBUSB_SUCCESS)
+ {
+ if (verbose)
+ Interface::PrintError("Failed to receive handshake response. Result: %d\n", result);
+ }
+ else
+ {
+ if (dataTransferred == 4 && memcmp(dataBuffer, "LOKE", 4) == 0)
{
- if (verbose)
- Interface::PrintError("Failed to complete sending of data: \"%s\"\n", dataBuffer);
- else
- Interface::PrintError("Failed to complete sending of data!");
-
- return (false);
- }
-
- // Expect "LOKE"
- memset(dataBuffer, 0, 7);
-
- int retry = 0;
- dataTransferred = 0;
-
- if (libusb_bulk_transfer(deviceHandle, inEndpoint, dataBuffer, 7, &dataTransferred, 1000) != LIBUSB_SUCCESS)
- {
- if (verbose)
- Interface::PrintError("Failed to receive handshake response.");
+ // Successfully received "LOKE"
+ Interface::Print("Protocol initialisation successful.\n\n");
+ return (true);
}
else
{
- if (dataTransferred == 4 && memcmp(dataBuffer, "LOKE", 4) == 0)
- {
- // Successfully received "LOKE"
- break;
- }
- else
- {
- if (verbose)
- Interface::PrintError("Expected: \"%s\"\nReceived: \"%s\"\n", "LOKE", dataBuffer);
+ if (verbose)
+ Interface::PrintError("Expected: \"LOKE\"\nReceived: \"%s\"\n", dataBuffer);
- Interface::PrintError("Unexpected handshake response!");
- }
+ Interface::PrintError("Unexpected handshake response!\n");
}
}
- if (attempt == kHandshakeMaxAttempts)
- {
- if (verbose)
- Interface::PrintErrorSameLine("\n");
-
- Interface::PrintError("Protocol initialisation failed!\n\n");
- return (false);
- }
- else
- {
- Interface::Print("Protocol initialisation successful.\n\n");
- return (true);
- }
+ Interface::PrintError("Protocol initialisation failed!\n\n");
+ return (false);
}
BridgeManager::BridgeManager(bool verbose, int communicationDelay)
@@ -759,21 +718,18 @@ bool BridgeManager::EndSession(bool reboot) const
return (true);
}
-bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, bool retry) const
+bool BridgeManager::SendBulkTransfer(unsigned char *data, int length, int timeout, bool retry) const
{
- packet->Pack();
-
int dataTransferred;
- int result = libusb_bulk_transfer(deviceHandle, outEndpoint, packet->GetData(), packet->GetSize(),
- &dataTransferred, timeout);
+ int result = libusb_bulk_transfer(deviceHandle, outEndpoint, data, length, &dataTransferred, timeout);
- if (result < 0 && retry)
+ if (result != LIBUSB_SUCCESS && retry)
{
// max(250, communicationDelay)
int retryDelay = (communicationDelay > 250) ? communicationDelay : 250;
if (verbose)
- Interface::PrintError("libusb error %d whilst sending packet.", result);
+ Interface::PrintError("libusb error %d whilst sending bulk transfer.", result);
// Retry
for (int i = 0; i < 5; i++)
@@ -784,26 +740,36 @@ bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, bool retry)
// Wait longer each retry
Sleep(retryDelay * (i + 1));
- result = libusb_bulk_transfer(deviceHandle, outEndpoint, packet->GetData(), packet->GetSize(),
- &dataTransferred, timeout);
+ result = libusb_bulk_transfer(deviceHandle, outEndpoint, data, length, &dataTransferred, timeout);
- if (result >= 0)
+ if (result == LIBUSB_SUCCESS)
break;
if (verbose)
- Interface::PrintError("libusb error %d whilst sending packet.", result);
+ Interface::PrintError("libusb error %d whilst sending bulk transfer.", result);
}
if (verbose)
Interface::PrintErrorSameLine("\n");
}
- if (communicationDelay != 0)
- Sleep(communicationDelay);
+ return (result == LIBUSB_SUCCESS && dataTransferred == length);
+}
- if (result < 0 || dataTransferred != packet->GetSize())
+bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, bool retry) const
+{
+ packet->Pack();
+
+ if (!SendBulkTransfer(packet->GetData(), packet->GetSize(), timeout, retry))
+ return (false);
+
+ // After each packet we send an empty bulk transfer... Hey! I'm just implementing the protocol, I didn't define it!
+ if (!SendBulkTransfer(nullptr, 0, timeout, retry))
return (false);
+ if (communicationDelay != 0)
+ Sleep(communicationDelay);
+
return (true);
}
diff --git a/heimdall/source/BridgeManager.h b/heimdall/source/BridgeManager.h
index 1f88cdc..6481de6 100644
--- a/heimdall/source/BridgeManager.h
+++ b/heimdall/source/BridgeManager.h
@@ -142,6 +142,8 @@ namespace Heimdall
bool SetControlLineState(unsigned short controlSignalFlags);
bool SetControlLineCoding(LineCoding lineCoding);
+ bool SendBulkTransfer(unsigned char *data, int length, int timeout = 3000, bool retry = true) const;
+
public:
BridgeManager(bool verbose, int communicationDelay = BridgeManager::kCommunicationDelayDefault);