Patchwork [2/5] dediprog: Tidy up commands and remove dead nonsense code.

login
register
about
Submitter David Woodhouse
Date 2015-07-09 15:59:15
Message ID <1436457555.15083.84.camel@infradead.org>
Download mbox | patch
Permalink /patch/4311/
State Superseded
Headers show

Comments

David Woodhouse - 2015-07-09 15:59:15
On Sun, 2015-07-05 at 19:09 +0200, Stefan Tauner wrote:
> On Sun, 28 Jun 2015 16:52:51 -0700
> David Hendricks <david.hendricks@gmail.com> wrote:
> 
> > Sounds good to me.
> > 
> > Acked-by: David Hendricks <dhendrix@chromium.org>
> 
> Thanks, r1896.

Here's an updated version of the next patch in the sequence. I've
tested this with an SF100 V:5.2.00 and a Winbind W25Q128.V in an Intel
Skylake board, and it seems to be working.

Have we now resolved the issue discussed at
http://www.flashrom.org/pipermail/flashrom/2013-June/011074.html which
was preventing us from enabling dediprog (SF100) support by default?


-----
From: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Date: Mon, 22 Jun 2015 03:37:23 +0200
Subject: [PATCH] dediprog: Support new communication protocol.

There are some changed commands, so adjust the code to support
these. Use helper functions to reduce duplication in libusb calls.

Based on the following chromiumos change:
Change-Id: Ibd1e27d9e8273ba879b9b5d95675b99596255c89

Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
---
 dediprog.c | 125 +++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 84 insertions(+), 41 deletions(-)
David Woodhouse - 2015-07-09 16:24:25
On Thu, 2015-07-09 at 16:59 +0100, David Woodhouse wrote:
> 
> Here's an updated version of the next patch in the sequence.

> ...

> From: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
> Date: Mon, 22 Jun 2015 03:37:23 +0200
> Subject: [PATCH] dediprog: Support new communication protocol.

On top of that, I tried the patch at 
http://git.infradead.org/users/dwmw2/flashrom.git/commitdiff/81ad0cc50
to attempt to enable SF600 support. I got someone to test it for me on
an SF600Plus with firmware 7.1.1. It doesn't work.

Firstly, whatever dediprog_device_init() is doing is not covered by the
recently-provided documentation for *either* the old or the new
protocol, and the SF600 doesn't like it:

     Unexpected response to init!
     Error: Programmer initialization failed.

If we just comment that out, and also make it accept firmware v7, then
we can successfully identify a W25Q64.W chip and read sane-looking
contents from it. Writes fail, though:

Calibrating delay loop... OS timer resolution is 1 usecs, 3206M loops per second, delay more than 10% too short (got 84% of expected delay), recalculating... 3512M loops per second, 10 myus = 15 us, 100 myus = 175 us, 1000 myus = 1643 us, 10000 myus = 16156 us, 4 myus = 16 us, OK.
Initializing dediprog programmer
dediprog_init
Setting voltage to 1800 mV
Found USB device (0483:dada).
ANDY: stubbing dediprog_device_init
Found a SF600   V:7.1.1
Unexpected firmware version 7.1.1!
SPI speed is 12MHz
Setting SPI voltage to 1.800 V
The following protocols are supported: SPI.
Probing for AMIC A25L05PT, 64 kB: programmer_map_flash_region: mapping A25L05PT from 0x00000000ffff0000 to 0x0000000000000000
dediprog_spi_send_command, writecnt=1, readcnt=4
RDID returned 0xef 0x60 0x17 0x00. probe_spi_rdid_generic: id1 0xef, id2 0x6017
programmer_unmap_flash_region: unmapped 0x0000000000000000
...
Probing for Generic unknown SPI chip (REMS), 0 kB: dediprog_spi_send_command, writecnt=4, readcnt=2
REMS returned 0xef 0x16. probe_spi_rems: id1 0xef, id2 0x16
Found Winbond flash chip "W25Q64.W" (8192 kB, SPI).
This chip may contain one-time programmable memory. flashrom cannot read
and may never be able to write it, hence it may not be able to completely
clone the contents of this chip (see man page for details).
programmer_map_flash_region: mapping W25Q64.W from 0x00000000ff800000 to 0x0000000000000000
dediprog_spi_send_command, writecnt=1, readcnt=2
Block protection is disabled.
Reading old flash chip contents... done.
Erasing and writing flash chip... Trying erase function 0... 0x000000-0x000fff:Edediprog_spi_send_command, writecnt=1, readcnt=0
dediprog_spi_send_command, writecnt=4, readcnt=0
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
FAILED at 0x00000226! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x00000fff: 0x1da
ERASE FAILED!
Reading current flash chip contents... done. Looking for another erase function.
Trying erase function 1... 0x000000-0x007fff:Edediprog_spi_send_command, writecnt=1, readcnt=0
dediprog_spi_send_command, writecnt=4, readcnt=0
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
FAILED at 0x0000089d! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x00007fff: 0x356
ERASE FAILED!
Reading current flash chip contents... done. Looking for another erase function.
Trying erase function 2... 0x000000-0x00ffff:Edediprog_spi_send_command, writecnt=1, readcnt=0
dediprog_spi_send_command, writecnt=4, readcnt=0
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
FAILED at 0x00000e0e! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x0000ffff: 0x5d5
ERASE FAILED!
Reading current flash chip contents... done. Looking for another erase function.
Trying erase function 3... 0x000000-0x7fffff:Edediprog_spi_send_command, writecnt=1, readcnt=0
dediprog_spi_send_command, writecnt=1, readcnt=0
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
FAILED at 0x000009ee! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x007fffff: 0x26fb4
ERASE FAILED!
Reading current flash chip contents... done. Looking for another erase function.
Trying erase function 4... 0x000000-0x7fffff:Edediprog_spi_send_command, writecnt=1, readcnt=0
dediprog_spi_send_command, writecnt=1, readcnt=0
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
dediprog_spi_send_command, writecnt=1, readcnt=2
FAILED at 0x00001a0f! Expected=0xff, Found=0x00, failed byte count from 0x00000000-0x007fffff: 0x26f6b
ERASE FAILED!
Looking for another erase function.
No usable erase functions left.
FAILED!
Uh oh. Erase/write failed. Checking if anything has changed.
Reading current flash chip contents... done.
Apparently at least some data has changed.
Your flash chip is in an unknown state.
Please report this on IRC at chat.freenode.net (channel #flashrom) or
mail flashrom@flashrom.org, thanks!
programmer_unmap_flash_region: unmapped 0x0000000000000000
dediprog_shutdown
Setting SPI voltage to 0.000 V
David Hendricks - 2015-07-12 23:48:58
On Thu, Jul 9, 2015 at 9:24 AM, David Woodhouse <dwmw2@infradead.org> wrote:
> On Thu, 2015-07-09 at 16:59 +0100, David Woodhouse wrote:
>>
>> Here's an updated version of the next patch in the sequence.
>
>> ...
>
>> From: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
>> Date: Mon, 22 Jun 2015 03:37:23 +0200
>> Subject: [PATCH] dediprog: Support new communication protocol.
>
> On top of that, I tried the patch at
> http://git.infradead.org/users/dwmw2/flashrom.git/commitdiff/81ad0cc50
> to attempt to enable SF600 support. I got someone to test it for me on
> an SF600Plus with firmware 7.1.1. It doesn't work.
>
> Firstly, whatever dediprog_device_init() is doing is not covered by the
> recently-provided documentation for *either* the old or the new
> protocol, and the SF600 doesn't like it:
>
>      Unexpected response to init!
>      Error: Programmer initialization failed.
>
> If we just comment that out, and also make it accept firmware v7, then
> we can successfully identify a W25Q64.W chip and read sane-looking
> contents from it. Writes fail, though:

I tried this out on an SF600 Plus (FW 7.1.4) and got the same result.
Though if we comment it out, then subsequent commands on the SF100 (FW
5.1.5) fail :-/

Attempting to write using the SF600 gives me:
flashrom v0.9.8-r1896 on Linux 4.0.4-gentoo (x86_64)
flashrom is free software, get the source code at http://www.flashrom.org

flashrom was built with libpci 3.3.1, GCC 4.7.3, little endian
Command line (5 args): ./flashrom -V -p dediprog -w /tmp/random_2M.bin
Calibrating delay loop... OS timer resolution is 1 usecs, 1299M loops
per second, 10 myus = 11 us, 100 myus = 100 us, 1000 myus = 999 us,
10000 myus = 9999 us, 4 myus = 5 us, OK.
Initializing dediprog programmer
Found USB device (0483:dada).
Found a SF600   V:7.1.4
SPI speed is 12MHz
Setting SPI voltage to 3.500 V
The following protocols are supported: SPI.
Probing for AMIC A25L05PT, 64 kB: probe_spi_rdid_generic: id1 0xef, id2 0x4015
...
Found Winbond flash chip "W25Q16.V" (2048 kB, SPI).
This chip may contain one-time programmable memory. flashrom cannot read
and may never be able to write it, hence it may not be able to completely
clone the contents of this chip (see man page for details).
Reading old flash chip contents... done.
Erasing and writing flash chip... Trying erase function 0...
0x000000-0x000fff:WSPI bulk write failed, expected 512, got -5
Input/output error!
Command Set LED 0x4 failed (Connection timed out)!
Reading current flash chip contents... Command Set LED 0x2 failed
(Connection timed out)!
Command Read SPI Bulk failed, -110 Connection timed out!
Command Set LED 0x4 failed (Connection timed out)!
Can't read anymore! Aborting.
FAILED!
Uh oh. Erase/write failed. Checking if anything has changed.
Reading current flash chip contents... Command Set LED 0x2 failed
(Connection timed out)!
Command Read SPI Bulk failed, -110 Connection timed out!
Command Set LED 0x4 failed (Connection timed out)!
Can't even read anymore!
Your flash chip is in an unknown state.
Please report this on IRC at chat.freenode.net (channel #flashrom) or
mail flashrom@flashrom.org, thanks!
Setting SPI voltage to 0.000 V
Command Set SPI Voltage 0x0 failed!

Patch

diff --git a/dediprog.c b/dediprog.c
index 996d2d7..7ccac12 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -141,6 +141,27 @@  static void print_hex(void *buf, size_t len)
 }
 #endif
 
+/* Returns true if firmware (and thus hardware) supports the "new" protocol */
+static bool is_new_prot(void)
+{
+	/* if (SF100) */
+	return dediprog_firmwareversion >= FIRMWARE_VERSION(5, 5, 0);
+	/* else if (SF600)
+	return dediprog_firmwareversion >= FIRMWARE_VERSION(6, 9, 0); */
+}
+
+static int dediprog_read(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, uint8_t *bytes, size_t size)
+{
+	return usb_control_msg(dediprog_handle, REQTYPE_EP_IN, cmd, value, idx,
+			       (char *)bytes, size, DEFAULT_TIMEOUT);
+}
+
+static int dediprog_write(enum dediprog_cmds cmd, unsigned int value, unsigned int idx, const uint8_t *bytes, size_t size)
+{
+	return usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, cmd, value, idx,
+			       (char *)bytes, size, DEFAULT_TIMEOUT);
+}
+
 /* Might be useful for other USB devices as well. static for now. */
 /* device parameter allows user to specify one device of multiple installed */
 static struct usb_device *get_device_by_vid_pid(uint16_t vid, uint16_t pid, unsigned int device)
@@ -166,24 +187,30 @@  static int dediprog_set_leds(int leds)
 	if (leds < LED_NONE || leds > LED_ALL)
 		leds = LED_ALL;
 
-	/* Older Dediprogs with 2.x.x and 3.x.x firmware only had
-	 * two LEDs, and they were reversed. So map them around if 
-	 * we have an old device. On those devices the LEDs map as
-	 * follows:
+	/* Older Dediprogs with 2.x.x and 3.x.x firmware only had two LEDs, assigned to different bits. So map
+	 * them around if we have an old device. On those devices the LEDs map as follows:
 	 *   bit 2 == 0: green light is on.
-	 *   bit 0 == 0: red light is on. 
+	 *   bit 0 == 0: red light is on.
+	 *
+	 * Additionally, the command structure has changed with the "new" protocol.
+	 *
+	 * FIXME: take IO pins into account
 	 */
-	int target_leds;
-	if (dediprog_firmwareversion < FIRMWARE_VERSION(5,0,0)) {
-		target_leds = ((leds & LED_ERROR) >> 2) |
-			((leds & LED_PASS) << 2);
+	int target_leds, ret;
+	if (is_new_prot()) {
+		target_leds = (leds ^ 7) << 8;
+		ret = dediprog_write(CMD_SET_IO_LED, target_leds, 0, NULL, 0);
 	} else {
-		target_leds = leds;
+		if (dediprog_firmwareversion < FIRMWARE_VERSION(5, 0, 0)) {
+			target_leds = ((leds & LED_ERROR) >> 2) | ((leds & LED_PASS) << 2);
+		} else {
+			target_leds = leds;
+		}
+		target_leds ^= 7;
+
+		ret = dediprog_write(CMD_SET_IO_LED, 0x9, target_leds, NULL, 0);
 	}
 
-	target_leds ^= 7;
-	int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_SET_IO_LED, 0x09, target_leds,
-				  NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
 		msg_perr("Command Set LED 0x%x failed (%s)!\n", leds, usb_strerror());
 		return 1;
@@ -222,8 +249,7 @@  static int dediprog_set_spi_voltage(int millivolt)
 		/* Wait some time as the original driver does. */
 		programmer_delay(200 * 1000);
 	}
-	ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_SET_VCC, voltage_selector, 0,
-			      NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = dediprog_write(CMD_SET_VCC, voltage_selector, 0, NULL, 0);
 	if (ret != 0x0) {
 		msg_perr("Command Set SPI Voltage 0x%x failed!\n",
 			 voltage_selector);
@@ -263,8 +289,7 @@  static int dediprog_set_spi_speed(unsigned int spispeed_idx)
 	const struct dediprog_spispeeds *spispeed = &spispeeds[spispeed_idx];
 	msg_pdbg("SPI speed is %sHz\n", spispeed->name);
 
-	int ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_SET_SPI_CLK, spispeed->speed, 0xff,
-				  NULL, 0x0, DEFAULT_TIMEOUT);
+	int ret = dediprog_write(CMD_SET_SPI_CLK, spispeed->speed, 0, NULL, 0);
 	if (ret != 0x0) {
 		msg_perr("Command Set SPI Speed 0x%x failed!\n", spispeed->speed);
 		return 1;
@@ -285,10 +310,7 @@  static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf,
 	/* chunksize must be 512, other sizes will NOT work at all. */
 	const unsigned int chunksize = 0x200;
 	const unsigned int count = len / chunksize;
-	const char count_and_chunk[] = {count & 0xff,
-					(count >> 8) & 0xff,
-					chunksize & 0xff,
-					(chunksize >> 8) & 0xff};
+	unsigned int cmd_len;
 
 	if ((start % chunksize) || (len % chunksize)) {
 		msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug "
@@ -299,15 +321,34 @@  static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf,
 	/* No idea if the hardware can handle empty reads, so chicken out. */
 	if (!len)
 		return 0;
-	/* Command Read SPI Bulk. No idea which read command is used on the
-	 * SPI side.
-	 */
-	ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_READ, start % 0x10000,
-			      start / 0x10000, (char *)count_and_chunk,
-			      sizeof(count_and_chunk), DEFAULT_TIMEOUT);
-	if (ret != sizeof(count_and_chunk)) {
-		msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret,
-			 usb_strerror());
+	/* Command Read SPI Bulk. */
+	if (is_new_prot()) {
+		const uint8_t read_cmd[] = {
+			count & 0xff,
+			(count >> 8) & 0xff,
+			0,
+			READ_MODE_FAST,
+			0,
+			0,
+			start & 0xff,
+			(start >> 8) & 0xff,
+			(start >> 16) & 0xff,
+			(start >> 24) & 0xff,
+			};
+
+		cmd_len = sizeof(read_cmd);
+		ret = dediprog_write(CMD_READ, 0, 0, read_cmd, cmd_len);
+	} else {
+		const uint8_t read_cmd[] = {count & 0xff,
+					(count >> 8) & 0xff,
+					chunksize & 0xff,
+					(chunksize >> 8) & 0xff};
+
+		cmd_len = sizeof(read_cmd);
+		ret = dediprog_write(CMD_READ, start % 0x10000, start / 0x10000, read_cmd, cmd_len);
+	}
+	if (ret != cmd_len) {
+		msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, usb_strerror());
 		return 1;
 	}
 
@@ -515,8 +556,12 @@  static int dediprog_spi_send_command(struct flashctx *flash,
 		return 1;
 	}
 	
-	ret = usb_control_msg(dediprog_handle, REQTYPE_EP_OUT, CMD_TRANSCEIVE, 0, readcnt ? 0x1 : 0x0,
-			      (char *)writearr, writecnt, DEFAULT_TIMEOUT);
+	/* New protocol has the read flag as value while the old protocol had it in the index field. */
+	if (is_new_prot()) {
+		ret = dediprog_write(CMD_TRANSCEIVE, readcnt ? 1 : 0, 0, writearr, writecnt);
+	} else {
+		ret = dediprog_write(CMD_TRANSCEIVE, 0, readcnt ? 1 : 0, writearr, writecnt);
+	}
 	if (ret != writecnt) {
 		msg_perr("Send SPI failed, expected %i, got %i %s!\n",
 			 writecnt, ret, usb_strerror());
@@ -525,8 +570,7 @@  static int dediprog_spi_send_command(struct flashctx *flash,
 	if (readcnt == 0)
 		return 0;
 
-	ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_TRANSCEIVE, 0, 0,
-			     (char *)readarr, readcnt, DEFAULT_TIMEOUT);
+	ret = dediprog_read(CMD_TRANSCEIVE, 0, 0, readarr, readcnt);
 	if (ret != readcnt) {
 		msg_perr("Receive SPI failed, expected %i, got %i %s!\n",
 			 readcnt, ret, usb_strerror());
@@ -553,8 +597,7 @@  static int dediprog_check_devicestring(void)
 	}
 #endif
 	/* Command Receive Device String. */
-	ret = usb_control_msg(dediprog_handle, REQTYPE_EP_IN, CMD_READ_PROG_INFO, 0, 0,
-			      buf, 0x10, DEFAULT_TIMEOUT);
+	ret = dediprog_read(CMD_READ_PROG_INFO, 0, 0, (uint8_t *)buf, 0x10);
 	if (ret != 0x10) {
 		msg_perr("Incomplete/failed Command Receive Device String!\n");
 		return 1;
@@ -566,16 +609,16 @@  static int dediprog_check_devicestring(void)
 		return 1;
 	}
 	if (sscanf(buf, "SF100 V:%d.%d.%d ", &fw[0], &fw[1], &fw[2]) != 3) {
-		msg_perr("Unexpected firmware version string!\n");
+		msg_perr("Unexpected firmware version string '%s'\n", buf);
 		return 1;
 	}
-	/* Only these versions were tested. */
-	if (fw[0] < 2 || fw[0] > 5) {
-		msg_perr("Unexpected firmware version %d.%d.%d!\n", fw[0],
-			 fw[1], fw[2]);
+	/* Only these major versions were tested. */
+	if (fw[0] < 2 || fw[0] > 6) {
+		msg_perr("Unexpected firmware version %d.%d.%d!\n", fw[0], fw[1], fw[2]);
 		return 1;
 	}
 	dediprog_firmwareversion = FIRMWARE_VERSION(fw[0], fw[1], fw[2]);
+
 	return 0;
 }