More empty transfer craziness, this time when receving packets

It seems newer devices need more weird empty transfers in order to
function.
Esse commit está contido em:
Benjamin Dobell
2014-07-06 03:50:48 +10:00
commit d613a87cdb
2 arquivos alterados com 76 adições e 64 exclusões
+68 -57
Ver Arquivo
@@ -66,11 +66,6 @@ const DeviceIdentifier BridgeManager::supportedDevices[BridgeManager::kSupported
DeviceIdentifier(BridgeManager::kVidSamsung, BridgeManager::kPidDroidCharge)
};
enum
{
kDumpBufferSize = 4096,
};
enum
{
kFileTransferSequenceMaxLengthDefault = 800,
@@ -78,16 +73,6 @@ enum
kFileTransferSequenceTimeoutDefault = 30000 // 30 seconds
};
enum
{
kReceivePacketMaxAttempts = 5
};
enum
{
kPitSizeMultiplicand = 4096
};
int BridgeManager::FindDeviceInterface(void)
{
Interface::Print("Detecting device...\n");
@@ -661,13 +646,53 @@ bool BridgeManager::SendBulkTransfer(unsigned char *data, int length, int timeou
return (result == LIBUSB_SUCCESS && dataTransferred == length);
}
bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, int sendEmptyTransferFlags) const
int BridgeManager::ReceiveBulkTransfer(unsigned char *data, int length, int timeout, bool retry) const
{
int dataTransferred;
int result = libusb_bulk_transfer(deviceHandle, inEndpoint, data, length, &dataTransferred, timeout);
if (result != LIBUSB_SUCCESS && retry)
{
static const int retryDelay = 250;
if (verbose)
Interface::PrintError("libusb error %d whilst receiving bulk transfer.", result);
// Retry
for (int i = 0; i < 5; i++)
{
if (verbose)
Interface::PrintErrorSameLine(" Retrying...\n");
// Wait longer each retry
Sleep(retryDelay * (i + 1));
result = libusb_bulk_transfer(deviceHandle, inEndpoint, data, length, &dataTransferred, timeout);
if (result == LIBUSB_SUCCESS)
break;
if (verbose)
Interface::PrintError("libusb error %d whilst receiving bulk transfer.", result);
}
if (verbose)
Interface::PrintErrorSameLine("\n");
}
if (result != LIBUSB_SUCCESS)
return (result);
return (dataTransferred);
}
bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, int emptyTransferFlags) const
{
packet->Pack();
if (sendEmptyTransferFlags & kSendEmptyTransferBefore)
if (emptyTransferFlags & kEmptyTransferBefore)
{
if (!SendBulkTransfer(nullptr, 0, kDefaultTimeoutSendEmptyTransfer, false) && verbose)
if (!SendBulkTransfer(nullptr, 0, kDefaultTimeoutEmptyTransfer, false) && verbose)
{
Interface::PrintWarning("Empty bulk transfer before sending packet failed. Continuing anyway...\n");
}
@@ -676,9 +701,9 @@ bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, int sendEmpt
if (!SendBulkTransfer(packet->GetData(), packet->GetSize(), timeout))
return (false);
if (sendEmptyTransferFlags & kSendEmptyTransferAfter)
if (emptyTransferFlags & kEmptyTransferAfter)
{
if (!SendBulkTransfer(nullptr, 0, kDefaultTimeoutSendEmptyTransfer, false) && verbose)
if (!SendBulkTransfer(nullptr, 0, kDefaultTimeoutEmptyTransfer, false) && verbose)
{
Interface::PrintWarning("Empty bulk transfer after sending packet failed. Continuing anyway...\n");
}
@@ -687,59 +712,44 @@ bool BridgeManager::SendPacket(OutboundPacket *packet, int timeout, int sendEmpt
return (true);
}
bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout) const
bool BridgeManager::ReceivePacket(InboundPacket *packet, int timeout, int emptyTransferFlags) const
{
unsigned char *buffer = packet->GetData();
unsigned int bufferSize = packet->GetSize();
int dataTransferred;
int result;
unsigned int attempt = 0;
static const int retryDelay = 250;
for (; attempt < kReceivePacketMaxAttempts; attempt++)
if (emptyTransferFlags & kEmptyTransferBefore)
{
if (attempt > 0)
if (ReceiveBulkTransfer(nullptr, 0, kDefaultTimeoutEmptyTransfer, false) < 0 && verbose)
{
if (verbose)
Interface::PrintErrorSameLine(" Retrying...\n");
// Wait longer each retry
Sleep(retryDelay * (attempt + 1));
Interface::PrintWarning("Empty bulk transfer before receiving packet failed. Continuing anyway...\n");
}
result = libusb_bulk_transfer(deviceHandle, inEndpoint, buffer, bufferSize, &dataTransferred, timeout);
if (result >= 0)
break;
if (verbose)
Interface::PrintError("libusb error %d whilst receiving packet.", result);
}
if (verbose && attempt > 0)
Interface::PrintErrorSameLine("\n");
int receivedSize = ReceiveBulkTransfer(packet->GetData(), packet->GetSize(), timeout);
if (attempt == kReceivePacketMaxAttempts)
if (receivedSize < 0)
return (false);
if (dataTransferred != packet->GetSize() && !packet->IsSizeVariable())
if (receivedSize != packet->GetSize() && !packet->IsSizeVariable())
{
if (verbose)
Interface::PrintError("Incorrect packet size received - expected size = %d, received size = %d.\n", packet->GetSize(), dataTransferred);
Interface::PrintError("Incorrect packet size received - expected size = %d, received size = %d.\n", packet->GetSize(), receivedSize);
return (false);
}
packet->SetReceivedSize(dataTransferred);
packet->SetReceivedSize(receivedSize);
bool unpacked = packet->Unpack();
if (!unpacked && verbose)
Interface::PrintError("Failed to unpack received packet.\n");
if (emptyTransferFlags & kEmptyTransferAfter)
{
if (ReceiveBulkTransfer(nullptr, 0, kDefaultTimeoutEmptyTransfer, false) < 0 && verbose)
{
Interface::PrintWarning("Empty bulk transfer after receiving packet failed. Continuing anyway...\n");
}
}
return (unpacked);
}
@@ -903,7 +913,6 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const
unsigned char *buffer = new unsigned char[fileSize];
int offset = 0;
// NOTE: The PIT file appears to always be padded out to exactly 4 kilobytes.
for (unsigned int i = 0; i < transferCount; i++)
{
DumpPartPitFilePacket *requestPacket = new DumpPartPitFilePacket(i);
@@ -916,9 +925,11 @@ int BridgeManager::ReceivePitFile(unsigned char **pitBuffer) const
delete [] buffer;
return (0);
}
int receiveEmptyTransferFlags = (i == transferCount - 1) ? kEmptyTransferAfter : kEmptyTransferNone;
ReceiveFilePartPacket *receiveFilePartPacket = new ReceiveFilePartPacket();
success = ReceivePacket(receiveFilePartPacket);
success = ReceivePacket(receiveFilePartPacket, receiveEmptyTransferFlags);
if (!success)
{
@@ -1067,7 +1078,7 @@ bool BridgeManager::SendFile(FILE *file, unsigned int destination, unsigned int
for (unsigned int filePartIndex = 0; filePartIndex < sequenceSize; filePartIndex++)
{
// NOTE: This empty transfer thing is entirely ridiculous, but sadly it seems to be required.
int sendEmptyTransferFlags = (filePartIndex == 0) ? kSendEmptyTransferNone : kSendEmptyTransferBefore;
int sendEmptyTransferFlags = (filePartIndex == 0) ? kEmptyTransferNone : kEmptyTransferBefore;
// Send
SendFilePartPacket *sendFilePartPacket = new SendFilePartPacket(file, fileTransferPacketSize);
@@ -1171,7 +1182,7 @@ bool BridgeManager::SendFile(FILE *file, unsigned int destination, unsigned int
{
EndPhoneFileTransferPacket *endPhoneFileTransferPacket = new EndPhoneFileTransferPacket(sequenceEffectiveByteCount, 0, deviceType, fileIdentifier, isLastSequence);
success = SendPacket(endPhoneFileTransferPacket, kDefaultTimeoutSend, kSendEmptyTransferBeforeAndAfter);
success = SendPacket(endPhoneFileTransferPacket, kDefaultTimeoutSend, kEmptyTransferBeforeAndAfter);
delete endPhoneFileTransferPacket;
if (!success)
@@ -1185,7 +1196,7 @@ bool BridgeManager::SendFile(FILE *file, unsigned int destination, unsigned int
{
EndModemFileTransferPacket *endModemFileTransferPacket = new EndModemFileTransferPacket(sequenceEffectiveByteCount, 0, deviceType, isLastSequence);
success = SendPacket(endModemFileTransferPacket, kDefaultTimeoutSend, kSendEmptyTransferBeforeAndAfter);
success = SendPacket(endModemFileTransferPacket, kDefaultTimeoutSend, kEmptyTransferBeforeAndAfter);
delete endModemFileTransferPacket;
if (!success)
+8 -7
Ver Arquivo
@@ -82,7 +82,7 @@ namespace Heimdall
{
kDefaultTimeoutSend = 3000,
kDefaultTimeoutReceive = 3000,
kDefaultTimeoutSendEmptyTransfer = 100
kDefaultTimeoutEmptyTransfer = 100
};
enum class UsbLogLevel
@@ -98,10 +98,10 @@ namespace Heimdall
enum
{
kSendEmptyTransferNone = 0,
kSendEmptyTransferBefore = 1,
kSendEmptyTransferAfter = 1 << 1,
kSendEmptyTransferBeforeAndAfter = kSendEmptyTransferBefore | kSendEmptyTransferAfter
kEmptyTransferNone = 0,
kEmptyTransferBefore = 1,
kEmptyTransferAfter = 1 << 1,
kEmptyTransferBeforeAndAfter = kEmptyTransferBefore | kEmptyTransferAfter
};
private:
@@ -141,6 +141,7 @@ namespace Heimdall
bool InitialiseProtocol(void);
bool SendBulkTransfer(unsigned char *data, int length, int timeout, bool retry = true) const;
int ReceiveBulkTransfer(unsigned char *data, int length, int timeout, bool retry = true) const;
public:
@@ -153,8 +154,8 @@ namespace Heimdall
bool BeginSession(void);
bool EndSession(bool reboot) const;
bool SendPacket(OutboundPacket *packet, int timeout = kDefaultTimeoutSend, int sendEmptyTransferFlags = kSendEmptyTransferAfter) const;
bool ReceivePacket(InboundPacket *packet, int timeout = kDefaultTimeoutReceive) const;
bool SendPacket(OutboundPacket *packet, int timeout = kDefaultTimeoutSend, int emptyTransferFlags = kEmptyTransferAfter) const;
bool ReceivePacket(InboundPacket *packet, int timeout = kDefaultTimeoutReceive, int emptyTransferFlags = kEmptyTransferNone) const;
bool RequestDeviceType(unsigned int request, int *result) const;