summaryrefslogtreecommitdiffstats
path: root/heimdall/source/BridgeManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'heimdall/source/BridgeManager.cpp')
-rw-r--r--heimdall/source/BridgeManager.cpp330
1 files changed, 216 insertions, 114 deletions
diff --git a/heimdall/source/BridgeManager.cpp b/heimdall/source/BridgeManager.cpp
index 00bdf29..db522ec 100644
--- a/heimdall/source/BridgeManager.cpp
+++ b/heimdall/source/BridgeManager.cpp
@@ -27,13 +27,14 @@
// Heimdall
#include "BeginDumpPacket.h"
#include "BridgeManager.h"
-#include "DeviceInfoPacket.h"
-#include "DeviceInfoResponse.h"
+#include "SetupSessionPacket.h"
+#include "SetupSessionResponse.h"
#include "DumpPartFileTransferPacket.h"
#include "DumpPartPitFilePacket.h"
#include "DumpResponse.h"
#include "EndModemFileTransferPacket.h"
#include "EndPhoneFileTransferPacket.h"
+#include "EndPitFileTransferPacket.h"
#include "EndSessionPacket.h"
#include "FileTransferPacket.h"
#include "FlashPartFileTransferPacket.h"
@@ -66,6 +67,159 @@ enum
kMaxSequenceLength = 800
};
+bool BridgeManager::CheckProtocol(void) const
+{
+ Interface::Print("Checking if protocol is initialised...\n");
+
+ SetupSessionPacket deviceInfoPacket(SetupSessionPacket::kDeviceInfo);
+
+ if (!SendPacket(&deviceInfoPacket, 100, false))
+ {
+ Interface::Print("Protocol is not initialised.\n");
+ return (false);
+ }
+
+ SetupSessionResponse deviceInfoResponse;
+
+ if (!ReceivePacket(&deviceInfoResponse, 100, false))
+ {
+ Interface::Print("Protocol is not initialised.\n");
+ return (false);
+ }
+
+ Interface::Print("Protocol is initialised.\n");
+ return (true);
+}
+
+bool BridgeManager::InitialiseProtocol(void) const
+{
+ Interface::Print("Initialising protocol...\n");
+
+ unsigned char *dataBuffer = new unsigned char[7];
+
+ int result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x3, 0, nullptr, 0, 1000);
+
+ if (result < 0)
+ {
+ Interface::PrintError("Failed to initialise protocol!\n");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ memset(dataBuffer, 0, 7);
+ dataBuffer[1] = 0xC2;
+ dataBuffer[2] = 0x01;
+ dataBuffer[6] = 0x07;
+
+ result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x20, 0x0, 0, dataBuffer, 7, 1000);
+ if (result < 0)
+ {
+ Interface::PrintError("Failed to initialise protocol!\n");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x3, 0, nullptr, 0, 1000);
+ if (result < 0)
+ {
+ Interface::PrintError("Failed to initialise protocol!\n");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x2, 0, nullptr, 0, 1000);
+ if (result < 0)
+ {
+ Interface::PrintError("Failed to initialise protocol!\n");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ memset(dataBuffer, 0, 7);
+ dataBuffer[1] = 0xC2;
+ dataBuffer[2] = 0x01;
+ dataBuffer[6] = 0x08;
+
+ result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x20, 0x0, 0, dataBuffer, 7, 1000);
+ if (result < 0)
+ {
+ Interface::PrintError("Failed to initialise protocol!\n");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x2, 0, nullptr, 0, 1000);
+ if (result < 0)
+ {
+ Interface::PrintError("Failed to initialise protocol!\n");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ Interface::Print("Handshaking with Loke...\n");
+
+ int dataTransferred;
+
+ // Send "ODIN"
+ strcpy((char *)dataBuffer, "ODIN");
+
+ result = libusb_bulk_transfer(deviceHandle, outEndpoint, dataBuffer, 4, &dataTransferred, 1000);
+ if (result < 0)
+ {
+ if (verbose)
+ Interface::PrintError("Failed to send data: \"%s\"\n", dataBuffer);
+ else
+ Interface::PrintError("Failed to send data!");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ if (dataTransferred != 4)
+ {
+ if (verbose)
+ Interface::PrintError("Failed to complete sending of data: \"%s\"\n", dataBuffer);
+ else
+ Interface::PrintError("Failed to complete sending of data!");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ // Expect "LOKE"
+ memset(dataBuffer, 0, 7);
+
+ result = libusb_bulk_transfer(deviceHandle, inEndpoint, dataBuffer, 7, &dataTransferred, 1000);
+ if (result < 0)
+ {
+ Interface::PrintError("Failed to receive response!\n");
+
+ delete [] dataBuffer;
+ return (false);;
+ }
+
+ if (dataTransferred != 4 || memcmp(dataBuffer, "LOKE", 4) != 0)
+ {
+ Interface::PrintError("Unexpected communication!\n");
+
+ if (verbose)
+ Interface::PrintError("Expected: \"%s\"\nReceived: \"%s\"\n", "LOKE", dataBuffer);
+
+ Interface::PrintError("Handshake failed!\n");
+
+ delete [] dataBuffer;
+ return (false);
+ }
+
+ return (true);
+}
+
BridgeManager::BridgeManager(bool verbose, int communicationDelay)
{
this->verbose = verbose;
@@ -339,6 +493,14 @@ int BridgeManager::Initialise(void)
Interface::Print("\n");
+ if (!CheckProtocol())
+ {
+ if (!InitialiseProtocol())
+ return (BridgeManager::kInitialiseFailed);
+ }
+
+ Interface::Print("\n");
+
return (BridgeManager::kInitialiseSucceeded);
}
@@ -346,130 +508,53 @@ bool BridgeManager::BeginSession(void) const
{
Interface::Print("Beginning session...\n");
- unsigned char *dataBuffer = new unsigned char[7];
-
- int result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x3, 0, nullptr, 0, 1000);
+ SetupSessionPacket beginSessionPacket(SetupSessionPacket::kBeginSession);
- if (result < 0)
+ if (!SendPacket(&beginSessionPacket))
{
Interface::PrintError("Failed to begin session!\n");
-
- delete [] dataBuffer;
return (false);
}
- memset(dataBuffer, 0, 7);
- dataBuffer[1] = 0xC2;
- dataBuffer[2] = 0x01;
- dataBuffer[6] = 0x07;
-
- result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x20, 0x0, 0, dataBuffer, 7, 1000);
- if (result < 0)
- {
- Interface::PrintError("Failed to begin session!\n");
-
- delete [] dataBuffer;
+ SetupSessionResponse setupSessionResponse;
+ if (!ReceivePacket(&setupSessionResponse))
return (false);
- }
- result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x3, 0, nullptr, 0, 1000);
- if (result < 0)
- {
- Interface::PrintError("Failed to begin session!\n");
+ int result = setupSessionResponse.GetUnknown();
- delete [] dataBuffer;
- return (false);
- }
-
- result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x2, 0, nullptr, 0, 1000);
- if (result < 0)
- {
- Interface::PrintError("Failed to begin session!\n");
-
- delete [] dataBuffer;
- return (false);
- }
-
- memset(dataBuffer, 0, 7);
- dataBuffer[1] = 0xC2;
- dataBuffer[2] = 0x01;
- dataBuffer[6] = 0x08;
-
- result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x20, 0x0, 0, dataBuffer, 7, 1000);
- if (result < 0)
- {
- Interface::PrintError("Failed to begin session!\n");
-
- delete [] dataBuffer;
- return (false);
- }
-
- result = libusb_control_transfer(deviceHandle, LIBUSB_REQUEST_TYPE_CLASS, 0x22, 0x2, 0, nullptr, 0, 1000);
- if (result < 0)
+ // 131072 for Galaxy S II, 0 for other devices.
+ if (result != 0 && result != 131072)
{
- Interface::PrintError("Failed to begin session!\n");
-
- delete [] dataBuffer;
+ Interface::PrintError("Unexpected device info response!\nExpected: 0\nReceived:%d\n", result);
return (false);
}
- Interface::Print("Handshaking with Loke...\n");
-
- int dataTransferred;
+ // -------------------- KIES DOESN'T DO THIS --------------------
- // Send "ODIN"
- strcpy((char *)dataBuffer, "ODIN");
+ SetupSessionPacket deviceTypePacket(SetupSessionPacket::kDeviceInfo);
- result = libusb_bulk_transfer(deviceHandle, outEndpoint, dataBuffer, 4, &dataTransferred, 1000);
- if (result < 0)
+ if (!SendPacket(&deviceTypePacket))
{
- if (verbose)
- Interface::PrintError("Failed to send data: \"%s\"\n", dataBuffer);
- else
- Interface::PrintError("Failed to send data!");
-
- delete [] dataBuffer;
+ Interface::PrintError("Failed to request device type!\n");
return (false);
}
- if (dataTransferred != 4)
- {
- if (verbose)
- Interface::PrintError("Failed to complete sending of data: \"%s\"\n", dataBuffer);
- else
- Interface::PrintError("Failed to complete sending of data!");
-
- delete [] dataBuffer;
+ if (!ReceivePacket(&setupSessionResponse))
return (false);
- }
- // Expect "LOKE"
- memset(dataBuffer, 0, 7);
+ int deviceType = setupSessionResponse.GetUnknown();
- result = libusb_bulk_transfer(deviceHandle, inEndpoint, dataBuffer, 7, &dataTransferred, 1000);
- if (result < 0)
+ // TODO: Work out what this value is... it has been either 180 or 0 for Galaxy S phones, 3 on the Galaxy Tab, 190 for SHW-M110S.
+ if (deviceType != 180 && deviceType != 0 && deviceType != 3 && deviceType != 190)
{
- Interface::PrintError("Failed to receive response!\n");
-
- delete [] dataBuffer;
- return (false);;
+ Interface::PrintError("Unexpected device info response!\nExpected: 180, 0 or 3\nReceived:%d\n", deviceType);
+ return (false);
}
-
- if (dataTransferred != 4 || memcmp(dataBuffer, "LOKE", 4) != 0)
+ else
{
- Interface::PrintError("Unexpected communication!\n");
-
- if (verbose)
- Interface::PrintError("Expected: \"%s\"\nReceived: \"%s\"\n", "LOKE", dataBuffer);
-
- Interface::PrintError("Handshake failed!\n");
-
- delete [] dataBuffer;
- return (false);
+ Interface::Print("Session begun with device of type: %d\n\n", result);
}
- Interface::Print("\n");
-
return (true);
}
@@ -529,7 +614,7 @@ bool BridgeManager::EndSession(bool reboot) const
return (true);
}
-bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout) const
+bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, bool retry) const
{
packet->Pack();
@@ -537,7 +622,7 @@ bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout) const
int result = libusb_bulk_transfer(deviceHandle, outEndpoint, packet->GetData(), packet->GetSize(),
&dataTransferred, timeout);
- if (result < 0)
+ if (result < 0 && retry)
{
// max(250, communicationDelay)
int retryDelay = (communicationDelay > 250) ? communicationDelay : 250;
@@ -577,13 +662,13 @@ bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout) const
return (true);
}
-bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const
+bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout, bool retry) const
{
int dataTransferred;
int result = libusb_bulk_transfer(deviceHandle, inEndpoint, packet->GetData(), packet->GetSize(),
&dataTransferred, timeout);
- if (result < 0)
+ if (result < 0 && retry)
{
// max(250, communicationDelay)
int retryDelay = (communicationDelay > 250) ? communicationDelay : 250;
@@ -608,12 +693,6 @@ bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const
if (verbose)
Interface::PrintError("libusb error %d whilst receiving packet.", result);
-
- if (i >= 3)
- {
- int breakHere = 0;
- breakHere++;
- }
}
if (verbose)
@@ -633,8 +712,8 @@ bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const
bool BridgeManager::RequestDeviceInfo(unsigned int request, int *result) const
{
- DeviceInfoPacket deviceInfoPacket(request);
- bool success = SendPacket(&deviceInfoPacket);
+ SetupSessionPacket beginSessionPacket(request);
+ bool success = SendPacket(&beginSessionPacket);
if (!success)
{
@@ -646,8 +725,10 @@ bool BridgeManager::RequestDeviceInfo(unsigned int request, int *result) const
return (false);
}
- DeviceInfoResponse deviceInfoResponse;
- success = ReceivePacket(&deviceInfoResponse);
+ SetupSessionResponse deviceInfoResponse;
+ if (!ReceivePacket(&deviceInfoResponse))
+ return (false);
+
*result = deviceInfoResponse.GetUnknown();
return (true);
@@ -718,7 +799,28 @@ bool BridgeManager::SendPitFile(FILE *file) const
if (!success)
{
- Interface::PrintError("Failed to receive PIT file transfer count!\n");
+ Interface::PrintError("Failed to receive PIT file part response!\n");
+ return (false);
+ }
+
+ // End pit file transfer
+ EndPitFileTransferPacket *endPitFileTransferPacket = new EndPitFileTransferPacket(fileSize);
+ success = SendPacket(endPitFileTransferPacket);
+ delete endPitFileTransferPacket;
+
+ if (!success)
+ {
+ Interface::PrintError("Failed to send end PIT file transfer packet!\n");
+ return (false);
+ }
+
+ pitFileResponse = new PitFileResponse();
+ success = ReceivePacket(pitFileResponse);
+ delete pitFileResponse;
+
+ if (!success)
+ {
+ Interface::PrintError("Failed to confirm end of PIT file transfer!\n");
return (false);
}