On Wed, May 20, 2015 at 11:32 AM, Linus Torvalds
<[email protected]> wrote:
>
> I'll try to figure out *why* those three dives fail to download. I
> suspect it's some issue where the length of the dive is just right to
> cause a packetization case that I don't handle right. I'll have to
> analyze those three cases more closely.

Yes.

The "receive_data()" function continues to try to read more data if
the previous packet was full - but in some cases the full packet
contained the final data, and receive_data() is just done and
shouldn't try to read any more.

The attached patch should fix it. Knock wood.

Dirk - can you make a nightly windows build with this, so that it can
get tested? The situation doesn't trigger with my dives, and while I
think I got it right...

                Linus
From 529ddffe87d877869fc3a30de8e07c295e95c13f Mon Sep 17 00:00:00 2001
From: Linus Torvalds <[email protected]>
Date: Wed, 20 May 2015 14:16:56 -0700
Subject: [PATCH] suunto eon steel: fix file reading special case

The "receive_data()" function would continue to try to read packets as
long as the previous packet was full-sized, but with just the right size
of file and the right chunking, the file might end at a packet boundary.
Then receive_data() would try to read more data, which fails - there are
no more packets, despite the last packet being full.

This never triggered for me, but Robert Helling forwarded a data dump of
a filure to read a dive due to this.

Since I don't trigger this case, I can't really test it, but I did check
that the new "stop early" logic works for me (ie never triggers ;).

Reported-by: Robert C. Helling <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
---
 src/suunto_eonsteel.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/suunto_eonsteel.c b/src/suunto_eonsteel.c
index ab090bfa29af..35249031a7dd 100644
--- a/src/suunto_eonsteel.c
+++ b/src/suunto_eonsteel.c
@@ -131,7 +131,7 @@ static int receive_data(suunto_eonsteel_device_t *eon, unsigned char *buffer, in
 	unsigned char buf[64];
 	int ret = 0;
 
-	for (;;) {
+	while (size > 0) {
 		int rc, transferred,  len;
 
 		rc = libusb_interrupt_transfer(eon->handle, InEndpoint, buf, sizeof(buf), &transferred, 5000);
@@ -233,12 +233,15 @@ static int send_receive(suunto_eonsteel_device_t *eon,
 	unsigned int len_out, const unsigned char *out,
 	unsigned int len_in, unsigned char *in)
 {
-	int len, actual;
+	int len, actual, max;
 	unsigned char buf[2048];
 
 	if (send_cmd(eon, cmd, len_out, out) < 0)
 		return -1;
-	len = receive_data(eon, buf, sizeof(buf));
+	max = len_in + 12;
+	if (max > sizeof(buf))
+		max = sizeof(buf);
+	len = receive_data(eon, buf, max);
 	if (len < 10) {
 		ERROR(eon->base.context, "short command reply (%d)", len);
 		return -1;
@@ -316,7 +319,7 @@ static int read_file(suunto_eonsteel_device_t *eon, const char *filename, dc_buf
 		put_le32(ask, cmdbuf+4);	// Size of read
 		rc = send_receive(eon, FILE_READ_CMD,
 			8, cmdbuf,
-			sizeof(result), result);
+			ask+8, result);
 		if (rc < 0) {
 			ERROR(eon->base.context, "unable to read %s", filename);
 			return -1;
-- 
2.4.0.53.g8440f74

_______________________________________________
subsurface mailing list
[email protected]
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to