Patchwork Bump dediprog driver to use libusb-1.0

login
register
about
Submitter Carl-Daniel Hailfinger
Date 2013-02-21 22:57:24
Message ID <5126A654.3030708@gmx.net>
Download mbox | patch
Permalink /patch/3856/
State Superseded
Headers show

Comments

Carl-Daniel Hailfinger - 2013-02-21 22:57:24
Am 21.02.2013 01:46 schrieb Carl-Daniel Hailfinger:
> Hi Nico,
>
> thanks for your patch.
>
> Am 16.11.2012 11:28 schrieb Nico Huber:
>> > This patch tracks the changes in the libusb interface. Nothing changed
>> > in the behaviour of the driver, so far.
>> >
>> > It will be used by a follow-up patch. It's based on "Enable spi clock
>> > setting in dediprog driver".
>> >
>> > Signed-off-by: Nico Huber <nico.huber@secunet.com>
> Review follows.
> The Makefile part checked for libusb 0.1, but it set the linker
> parameter for libusb 1.0.
> The code assumed that libusb_error_name() is always available, but that
> function was only introduced in libusb 1.0.9.
> There was a conflict between the added device parameter for multiple
> Dedipro SF100 devices on one PC (r1628) and the removal of
> get_device_by_vid_pid().
>
> I have fixed and forward ported the code, please check that it works and
> looks sane.
>
> This patch is completely untested, I only checked whether it compiles.
> If it works for you and looks sane, please tell me so I can commit.
>
> Signed-off-by: Nico Huber <nico.huber@secunet.com>

New version. Fixed error messages and incomplete cleanup in the error case.

libusb header file location is still something I have to fix in another
iteration.

Signed-off-by: Nico Huber <nico.huber@secunet.com>
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Nico Huber - 2013-02-22 10:56:03
Hello Carl-Daniel,
>> I have fixed and forward ported the code, please check that it works and
>> looks sane.
Thanks for your time. Current (your second) iteration works flawlessly
here.

> libusb header file location is still something I have to fix in another
> iteration.
I guess `#include <libusb.h>` would be right. But we'd have to ask
pkg-config for the includedir, then.

I'm not quite sure if I changed anything since my post, so I'll rebase,
test, and repost my pending changes.

Regards,
Nico
Stefan Tauner - 2013-03-27 10:51:55
On Fri, 22 Feb 2013 11:56:03 +0100
Nico Huber <nico.huber@secunet.com> wrote:

> I'm not quite sure if I changed anything since my post, so I'll rebase,
> test, and repost my pending changes.

Were there any pending changes or can we continue with what carldani
posted?
Nico Huber - 2013-03-27 11:11:47
Am 27.03.2013 11:51, schrieb Stefan Tauner:
> On Fri, 22 Feb 2013 11:56:03 +0100
> Nico Huber <nico.huber@secunet.com> wrote:
> 
>> I'm not quite sure if I changed anything since my post, so I'll rebase,
>> test, and repost my pending changes.
> 
> Were there any pending changes or can we continue with what carldani
> posted?
I'm happy with Carl-Daniel's version. What I meant to say was that I was
going to rebase other patches on his work. Which I did with
  [PATCH] dediprog: Use asynchronous bulk transfers for reading

So my patches on the mailing list are up to date.

Regards,
Nico
Kyösti Mälkki - 2013-03-30 18:16:31
On Wed, 2013-03-27 at 12:11 +0100, Nico Huber wrote:
> Am 27.03.2013 11:51, schrieb Stefan Tauner:
> > On Fri, 22 Feb 2013 11:56:03 +0100
> > Nico Huber <nico.huber@secunet.com> wrote:
> > 
> >> I'm not quite sure if I changed anything since my post, so I'll rebase,
> >> test, and repost my pending changes.
> > 
> > Were there any pending changes or can we continue with what carldani
> > posted?
> I'm happy with Carl-Daniel's version. What I meant to say was that I was
> going to rebase other patches on his work. Which I did with
>   [PATCH] dediprog: Use asynchronous bulk transfers for reading
> 
> So my patches on the mailing list are up to date.
> 
> Regards,
> Nico
> 

Well adding usbblaster_spi made it ouf-of-date. I have rebased it and
also changed the libusb-1.0 includes to use paths from pkg-config.

https://bitbucket.org/kmalkki/flashrom/commits/branch/usb-update


That branch also has version of libftdi-1.0 Makefile update and
usbblaster_spi update for asynchronous bulk transfers.

I noticed libusb-1.0-0_1.0.9~rc3-2ubuntu1_i386.deb on Ubuntu 12.04 LTS
segfaults on my asynchronous bulk transfers for usbblaster_spi, while
libusb-1.0-1.0.9rc3 compiled from git works fine.

Kyösti

Patch

Index: flashrom-dediprog_libusb1_nicohuber/Makefile
===================================================================
--- flashrom-dediprog_libusb1_nicohuber/Makefile	(Revision 1649)
+++ flashrom-dediprog_libusb1_nicohuber/Makefile	(Arbeitskopie)
@@ -117,7 +117,7 @@ 
 else
 override CONFIG_PONY_SPI = no
 endif
-# Dediprog and FT2232 are not supported under DOS (missing USB support).
+# Dediprog and FT2232 are not supported under DOS (missing libusb support).
 ifeq ($(CONFIG_DEDIPROG), yes)
 UNSUPPORTED_FEATURES += CONFIG_DEDIPROG=yes
 else
@@ -480,8 +480,9 @@ 
 FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "FT232H := yes" .features && printf "%s" "-D'HAVE_FT232H=1'")
 FEATURE_LIBS += $(shell LC_ALL=C grep -q "FTDISUPPORT := yes" .features && printf "%s" "$(FTDILIBS)")
 PROGRAMMER_OBJS += ft2232_spi.o
-# We can't set NEED_USB here because that would transform libftdi auto-enabling
+# We can't set NEED_LIBUSB1 here because that would transform libftdi auto-enabling
 # into a hard requirement for libusb, defeating the purpose of auto-enabling.
+# Besides that, the old libftdi requires libusb 0.1, not libusb 1.0.
 endif
 
 ifeq ($(CONFIG_DUMMY), yes)
@@ -534,7 +535,7 @@ 
 ifeq ($(CONFIG_DEDIPROG), yes)
 FEATURE_CFLAGS += -D'CONFIG_DEDIPROG=1'
 PROGRAMMER_OBJS += dediprog.o
-NEED_USB := yes
+NEED_LIBUSB1 := yes
 endif
 
 ifeq ($(CONFIG_SATAMV), yes)
@@ -589,10 +590,11 @@ 
 endif
 endif
 
-ifeq ($(NEED_USB), yes)
-CHECK_LIBUSB0 = yes
-FEATURE_CFLAGS += -D'NEED_USB=1'
-USBLIBS := $(shell pkg-config --libs libusb 2>/dev/null || printf "%s" "-lusb")
+ifeq ($(NEED_LIBUSB1), yes)
+CHECK_LIBUSB1 = yes
+FEATURE_CFLAGS += -D'NEED_LIBUSB1=1'
+USBLIBS := $(shell pkg-config --libs libusb-1.0 2>/dev/null || printf "%s" "-lusb-1.0")
+FEATURE_CFLAGS += $(shell LC_ALL=C grep -q "LIBUSB1_ERROR_NAME := yes" .features && printf "%s" "-D'LIBUSB_HAVE_ERROR_NAME=1'")
 endif
 
 ifeq ($(CONFIG_PRINT_WIKI), yes)
@@ -687,17 +689,17 @@ 
 endef
 export LIBPCI_TEST
 
-define LIBUSB0_TEST
-#include <usb.h>
+define LIBUSB1_TEST
+#include <libusb-1.0/libusb.h>
 int main(int argc, char **argv)
 {
 	(void) argc;
 	(void) argv;
-	usb_init();
+	libusb_init(NULL);
 	return 0;
 }
 endef
-export LIBUSB0_TEST
+export LIBUSB1_TEST
 
 hwlibs: compiler
 	@printf "" > .libdeps
@@ -720,18 +722,18 @@ 
 		rm -f .test.c .test.o .test$(EXEC_SUFFIX); exit 1) )
 	@rm -f .test.c .test.o .test$(EXEC_SUFFIX)
 endif
-ifeq ($(CHECK_LIBUSB0), yes)
-	@printf "Checking for libusb-0.1/libusb-compat headers... "
-	@echo "$$LIBUSB0_TEST" > .test.c
+ifeq ($(CHECK_LIBUSB1), yes)
+	@printf "Checking for libusb-1.0 headers... "
+	@echo "$$LIBUSB1_TEST" > .test.c
 	@$(CC) -c $(CPPFLAGS) $(CFLAGS) .test.c -o .test.o >/dev/null &&		\
 		echo "found." || ( echo "not found."; echo;				\
-		echo "Please install libusb-0.1 headers or libusb-compat headers.";	\
+		echo "Please install libusb-1.0 headers.";	\
 		echo "See README for more information."; echo;				\
 		rm -f .test.c .test.o; exit 1)
-	@printf "Checking if libusb-0.1 is usable... "
+	@printf "Checking if libusb-1.0 is usable... "
 	@$(CC) $(LDFLAGS) .test.o -o .test$(EXEC_SUFFIX) $(LIBS) $(USBLIBS) >/dev/null &&	\
 		echo "yes." || ( echo "no.";						\
-		echo "Please install libusb-0.1 or libusb-compat.";			\
+		echo "Please install libusb-1.0.";			\
 		echo "See README for more information."; echo;				\
 		rm -f .test.c .test.o .test$(EXEC_SUFFIX); exit 1)
 	@rm -f .test.c .test.o .test$(EXEC_SUFFIX)
@@ -753,6 +755,18 @@ 
 	@false
 endif
 
+define LIBUSB1_ERROR_NAME_TEST
+#include <libusb-1.0/libusb.h>
+int main(int argc, char **argv)
+{
+	(void) argc;
+	(void) argv;
+	libusb_error_name(0);
+	return 0;
+}
+endef
+export LIBUSB1_ERROR_NAME_TEST
+
 define FTDI_TEST
 #include <ftdi.h>
 struct ftdi_context *ftdic = NULL;
@@ -799,6 +813,13 @@ 
 
 features: compiler
 	@echo "FEATURES := yes" > .features.tmp
+ifeq ($(CHECK_LIBUSB1), yes)
+	@printf "Checking for libusb_error_name support in libusb-1.0... "
+	@echo "$$LIBUSB1_ERROR_NAME_TEST" >> .featuretest.c
+	@$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) .featuretest.c -o .featuretest$(EXEC_SUFFIX) $(USBLIBS) $(LIBS) >/dev/null 2>&1 &&	\
+		( echo "found."; echo "LIBUSB1_ERROR_NAME := yes" >> .features.tmp ) ||	\
+		( echo "not found." )
+endif
 ifeq ($(CONFIG_FT2232_SPI), yes)
 	@printf "Checking for FTDI support... "
 	@echo "$$FTDI_TEST" > .featuretest.c
Index: flashrom-dediprog_libusb1_nicohuber/dediprog.c
===================================================================
--- flashrom-dediprog_libusb1_nicohuber/dediprog.c	(Revision 1649)
+++ flashrom-dediprog_libusb1_nicohuber/dediprog.c	(Arbeitskopie)
@@ -2,6 +2,7 @@ 
  * This file is part of the flashrom project.
  *
  * Copyright (C) 2010 Carl-Daniel Hailfinger
+ *               2012 secunet Security Networks AG
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,7 +22,8 @@ 
 #include <string.h>
 #include <limits.h>
 #include <errno.h>
-#include <usb.h>
+#include <stdlib.h>
+#include <libusb-1.0/libusb.h>
 #include "flash.h"
 #include "chipdrivers.h"
 #include "programmer.h"
@@ -29,7 +31,8 @@ 
 
 #define FIRMWARE_VERSION(x,y,z) ((x << 16) | (y << 8) | z)
 #define DEFAULT_TIMEOUT 3000
-static usb_dev_handle *dediprog_handle;
+static libusb_context *usb_ctx;
+static libusb_device_handle *dediprog_handle;
 static int dediprog_firmwareversion;
 static int dediprog_endpoint;
 
@@ -47,27 +50,63 @@ 
 }
 #endif
 
+#ifndef LIBUSB_HAVE_ERROR_NAME
+/* Quick and dirty replacement for missing libusb_error_name in older libusb 1.0. */
+const char *libusb_error_name(int error_code)
+{
+	/* 18 chars for text, rest for number, sign, nullbyte. */
+	static char my_libusb_error[18 + 3 * sizeof(int) + 2];
+
+	sprintf(my_libusb_error, "libusb error code %i", error_code);
+	return my_libusb_error;
+}
+#endif
+
 /* 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)
+static struct libusb_device_handle *get_device_by_vid_pid_number(uint16_t vid, uint16_t pid, unsigned int num)
 {
-	struct usb_bus *bus;
-	struct usb_device *dev;
+	struct libusb_device **list;
+	ssize_t i = 0;
+	int err = 0;
+	struct libusb_device_handle *handle = NULL;
+	struct libusb_device_descriptor desc = {};
+	ssize_t count = libusb_get_device_list(usb_ctx, &list);
 
-	for (bus = usb_get_busses(); bus; bus = bus->next)
-		for (dev = bus->devices; dev; dev = dev->next)
-			if ((dev->descriptor.idVendor == vid) &&
-			    (dev->descriptor.idProduct == pid)) {
-				if (device == 0)
-					return dev;
-				device--;
+	if (count < 0) {
+		msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count));
+		return NULL;
+	}
+
+	for (i = 0; i < count; i++) {
+		struct libusb_device *dev = list[i];
+		err = libusb_get_device_descriptor(dev, &desc);
+		if (err != 0) {
+			msg_perr("Reading the USB device descriptor failed (%s)!\n", libusb_error_name(err));
+			libusb_free_device_list(list, 1);
+			return NULL;
+		}
+		if ((desc.idVendor == vid) && (desc.idProduct == pid)) {
+			msg_pdbg("Found USB device %04hx:%04hx at address %hhx-%hhx.\n", desc.idVendor,
+				 desc.idProduct, libusb_get_bus_number(dev), libusb_get_device_address(dev));
+			if (num == 0) {
+				err = libusb_open(dev, &handle);
+				if (err != 0) {
+					msg_perr("Opening the USB device failed (%s)!\n",
+						 libusb_error_name(err));
+					libusb_free_device_list(list, 1);
+					return NULL;
+				}
+				break;
 			}
+			num--;
+		}
+	}
+	libusb_free_device_list(list, 1);
 
-	return NULL;
+	return handle;
 }
 
-//int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
-
 /* Set/clear LEDs on dediprog */
 #define PASS_ON		(0 << 0)
 #define PASS_OFF	(1 << 0)
@@ -101,11 +140,10 @@ 
 		target_leds = leds;
 	}
 
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x07, 0x09, target_leds,
-			      NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x07, 0x09, target_leds,
+				      NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
-		msg_perr("Command Set LED 0x%x failed (%s)!\n",
-			 leds, usb_strerror());
+		msg_perr("Command Set LED 0x%x failed (%s)!\n", leds, libusb_error_name(ret));
 		return 1;
 	}
 
@@ -144,8 +182,8 @@ 
 		/* Wait some time as the original driver does. */
 		programmer_delay(200 * 1000);
 	}
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x9, voltage_selector,
-			      0xff, NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x9, voltage_selector,
+				      0xff, NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
 		msg_perr("Command Set SPI Voltage 0x%x failed!\n",
 			 voltage_selector);
@@ -188,8 +226,8 @@ 
 
 	msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed_idx].name);
 
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x61, spispeeds[spispeed_idx].speed, 0xff,
-			      NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x61, spispeeds[spispeed_idx].speed, 0xff,
+				      NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
 		msg_perr("Command Set SPI Speed 0x%x failed!\n", spispeeds[spispeed_idx].speed);
 		return 1;
@@ -205,15 +243,15 @@ 
 static int dediprog_spi_bulk_read(struct flashctx *flash, uint8_t *buf,
 				  unsigned int start, unsigned int len)
 {
-	int ret;
+	int ret, transferred;
 	unsigned int i;
 	/* 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};
+	const unsigned char count_and_chunk[] = {
+		count & 0xff,     (count >> 8) & 0xff,
+		chunksize & 0xff, (chunksize >> 8) & 0xff
+	};
 
 	if ((start % chunksize) || (len % chunksize)) {
 		msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug "
@@ -227,22 +265,20 @@ 
 	/* Command Read SPI Bulk. No idea which read command is used on the
 	 * SPI side.
 	 */
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x20, start % 0x10000,
-			      start / 0x10000, (char *)count_and_chunk,
-			      sizeof(count_and_chunk), DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x20, start % 0x10000, start / 0x10000,
+				      (unsigned 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());
+		msg_perr("Command Read SPI Bulk failed, %i %s!\n", ret, libusb_error_name(ret));
 		return 1;
 	}
 
 	for (i = 0; i < count; i++) {
-		ret = usb_bulk_read(dediprog_handle, 0x80 | dediprog_endpoint,
-				    (char *)buf + i * chunksize, chunksize,
-				    DEFAULT_TIMEOUT);
-		if (ret != chunksize) {
-			msg_perr("SPI bulk read %i failed, expected %i, got %i "
-				 "%s!\n", i, chunksize, ret, usb_strerror());
+		ret = libusb_bulk_transfer(dediprog_handle, 0x80 | dediprog_endpoint,
+					   buf + i * chunksize, chunksize, &transferred, DEFAULT_TIMEOUT);
+		if ((ret < 0) || (transferred != chunksize)) {
+			msg_perr("SPI bulk read %i failed, expected %i, got %i %s!\n",
+				 i, chunksize, ret, libusb_error_name(ret));
 			return 1;
 		}
 	}
@@ -306,7 +342,7 @@ 
 static int dediprog_spi_bulk_write(struct flashctx *flash, uint8_t *buf, unsigned int chunksize,
 				   unsigned int start, unsigned int len, uint8_t dedi_spi_cmd)
 {
-	int ret;
+	int ret, transferred;
 	unsigned int i;
 	/* USB transfer size must be 512, other sizes will NOT work at all.
 	 * chunksize is the real data size per USB bulk transfer. The remaining
@@ -314,7 +350,7 @@ 
 	 */
 	const unsigned int count = len / chunksize;
 	const char count_and_cmd[] = {count & 0xff, (count >> 8) & 0xff, 0x00, dedi_spi_cmd};
-	char usbbuf[512];
+	unsigned char usbbuf[512];
 
 	/*
 	 * We should change this check to
@@ -339,23 +375,21 @@ 
 	/* Command Write SPI Bulk. No idea which write command is used on the
 	 * SPI side.
 	 */
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x30, start % 0x10000, start / 0x10000,
-			      (char *)count_and_cmd, sizeof(count_and_cmd), DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x30, start % 0x10000, start / 0x10000,
+				      (unsigned char *)count_and_cmd, sizeof(count_and_cmd), DEFAULT_TIMEOUT);
 	if (ret != sizeof(count_and_cmd)) {
-		msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret,
-			 usb_strerror());
+		msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret, libusb_error_name(ret));
 		return 1;
 	}
 
 	for (i = 0; i < count; i++) {
 		memset(usbbuf, 0xff, sizeof(usbbuf));
 		memcpy(usbbuf, buf + i * chunksize, chunksize);
-		ret = usb_bulk_write(dediprog_handle, dediprog_endpoint,
-				    usbbuf, 512,
-				    DEFAULT_TIMEOUT);
-		if (ret != 512) {
-			msg_perr("SPI bulk write failed, expected %i, got %i "
-				 "%s!\n", 512, ret, usb_strerror());
+		ret = libusb_bulk_transfer(dediprog_handle, dediprog_endpoint,
+					   usbbuf, 512, &transferred, DEFAULT_TIMEOUT);
+		if ((ret < 0) || (transferred != 512)) {
+			msg_perr("SPI bulk write failed, expected %i, got %i %s!\n",
+				 512, ret, libusb_error_name(ret));
 			return 1;
 		}
 	}
@@ -444,23 +478,20 @@ 
 		msg_perr("Untested readcnt=%i, aborting.\n", readcnt);
 		return 1;
 	}
-	
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x1, 0xff,
-			      readcnt ? 0x1 : 0x0, (char *)writearr, writecnt,
-			      DEFAULT_TIMEOUT);
+
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x1, 0xff, readcnt ? 0x1 : 0x0,
+				      (unsigned char *)writearr, writecnt, DEFAULT_TIMEOUT);
 	if (ret != writecnt) {
-		msg_perr("Send SPI failed, expected %i, got %i %s!\n",
-			 writecnt, ret, usb_strerror());
+		msg_perr("Send SPI failed, expected %i, got %i %s!\n", writecnt, ret, libusb_error_name(ret));
 		return 1;
 	}
 	if (!readcnt)
 		return 0;
 	memset(readarr, 0, readcnt);
-	ret = usb_control_msg(dediprog_handle, 0xc2, 0x01, 0xbb8, 0x0000,
-			     (char *)readarr, readcnt, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0xc2, 0x01, 0xbb8, 0x0000,
+				      readarr, readcnt, DEFAULT_TIMEOUT);
 	if (ret != readcnt) {
-		msg_perr("Receive SPI failed, expected %i, got %i %s!\n",
-			 readcnt, ret, usb_strerror());
+		msg_perr("Receive SPI failed, expected %i, got %i %s!\n", readcnt, ret, libusb_error_name(ret));
 		return 1;
 	}
 	return 0;
@@ -470,22 +501,18 @@ 
 {
 	int ret;
 	int fw[3];
-	char buf[0x11];
+	unsigned char buf[0x11];
 
 	/* Command Prepare Receive Device String. */
 	memset(buf, 0, sizeof(buf));
-	ret = usb_control_msg(dediprog_handle, 0xc3, 0x7, 0x0, 0xef03, buf,
-			      0x1, DEFAULT_TIMEOUT);
-	/* The char casting is needed to stop gcc complaining about an always true comparison. */
-	if ((ret != 0x1) || (buf[0] != (char)0xff)) {
-		msg_perr("Unexpected response to Command Prepare Receive Device"
-			 " String!\n");
+	ret = libusb_control_transfer(dediprog_handle, 0xc3, 0x7, 0x0, 0xef03, buf, 0x1, DEFAULT_TIMEOUT);
+	if ((ret != 0x1) || (buf[0] != 0xff)) {
+		msg_perr("Unexpected response to Command Prepare Receive Device String!\n");
 		return 1;
 	}
 	/* Command Receive Device String. */
 	memset(buf, 0, sizeof(buf));
-	ret = usb_control_msg(dediprog_handle, 0xc2, 0x8, 0xff, 0xff, buf,
-			      0x10, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0xc2, 0x8, 0xff, 0xff, buf, 0x10, DEFAULT_TIMEOUT);
 	if (ret != 0x10) {
 		msg_perr("Incomplete/failed Command Receive Device String!\n");
 		return 1;
@@ -496,7 +523,7 @@ 
 		msg_perr("Device not a SF100!\n");
 		return 1;
 	}
-	if (sscanf(buf, "SF100 V:%d.%d.%d ", &fw[0], &fw[1], &fw[2]) != 3) {
+	if (sscanf((const char *)buf, "SF100 V:%d.%d.%d ", &fw[0], &fw[1], &fw[2]) != 3) {
 		msg_perr("Unexpected firmware version string!\n");
 		return 1;
 	}
@@ -517,13 +544,12 @@ 
 static int dediprog_command_a(void)
 {
 	int ret;
-	char buf[0x1];
+	unsigned char buf[0x1];
 
 	memset(buf, 0, sizeof(buf));
-	ret = usb_control_msg(dediprog_handle, 0xc3, 0xb, 0x0, 0x0, buf,
-			      0x1, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0xc3, 0xb, 0x0, 0x0, buf, 0x1, DEFAULT_TIMEOUT);
 	if (ret < 0) {
-		msg_perr("Command A failed (%s)!\n", usb_strerror());
+		msg_perr("Command A failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	if ((ret != 0x1) || (buf[0] != 0x6f)) {
@@ -541,13 +567,12 @@ 
 static int dediprog_command_b(void)
 {
 	int ret;
-	char buf[0x3];
+	unsigned char buf[0x3];
 
 	memset(buf, 0, sizeof(buf));
-	ret = usb_control_msg(dediprog_handle, 0xc3, 0x7, 0x0, 0xef00, buf,
-			      0x3, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0xc3, 0x7, 0x0, 0xef00, buf, 0x3, DEFAULT_TIMEOUT);
 	if (ret < 0) {
-		msg_perr("Command B failed (%s)!\n", usb_strerror());
+		msg_perr("Command B failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	if ((ret != 0x3) || (buf[0] != 0xff) || (buf[1] != 0xff) ||
@@ -569,10 +594,9 @@ 
 {
 	int ret;
 
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x4, 0x0, 0x0, NULL,
-			      0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x4, 0x0, 0x0, NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
-		msg_perr("Command C failed (%s)!\n", usb_strerror());
+		msg_perr("Command C failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	return 0;
@@ -587,17 +611,16 @@ 
 static int dediprog_command_f(int timeout)
 {
 	int ret;
-	char buf[0x1];
+	unsigned char buf[0x1];
 
 	memset(buf, 0, sizeof(buf));
-	ret = usb_control_msg(dediprog_handle, 0xc2, 0x11, 0xff, 0xff, buf,
-			      0x1, timeout);
+	ret = libusb_control_transfer(dediprog_handle, 0xc2, 0x11, 0xff, 0xff, buf, 0x1, timeout);
 	/* This check is most probably wrong. Command F always causes a timeout
 	 * in the logs, so we should check for timeout instead of checking for
 	 * success.
 	 */
 	if (ret != 0x1) {
-		msg_perr("Command F failed (%s)!\n", usb_strerror());
+		msg_perr("Command F failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	return 0;
@@ -611,9 +634,9 @@ 
 {
 	int ret;
 
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x07, 0x09, 0x03, NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x07, 0x09, 0x03, NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
-		msg_perr("Command G failed (%s)!\n", usb_strerror());
+		msg_perr("Command G failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	return 0;
@@ -628,9 +651,9 @@ 
 {
 	int ret;
 
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x07, 0x09, 0x05, NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x07, 0x09, 0x05, NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
-		msg_perr("Command H failed (%s)!\n", usb_strerror());
+		msg_perr("Command H failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	return 0;
@@ -645,9 +668,9 @@ 
 {
 	int ret;
 
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x07, 0x09, 0x06, NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x07, 0x09, 0x06, NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
-		msg_perr("Command I failed (%s)!\n", usb_strerror());
+		msg_perr("Command I failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	return 0;
@@ -665,9 +688,9 @@ 
 {
 	int ret;
 
-	ret = usb_control_msg(dediprog_handle, 0x42, 0x07, 0x09, 0x07, NULL, 0x0, DEFAULT_TIMEOUT);
+	ret = libusb_control_transfer(dediprog_handle, 0x42, 0x07, 0x09, 0x07, NULL, 0x0, DEFAULT_TIMEOUT);
 	if (ret != 0x0) {
-		msg_perr("Command J failed (%s)!\n", usb_strerror());
+		msg_perr("Command J failed (%s)!\n", libusb_error_name(ret));
 		return 1;
 	}
 	return 0;
@@ -770,21 +793,18 @@ 
 	if (dediprog_set_spi_voltage(0x0))
 		return 1;
 
-	if (usb_release_interface(dediprog_handle, 0)) {
+	if (libusb_release_interface(dediprog_handle, 0)) {
 		msg_perr("Could not release USB interface!\n");
 		return 1;
 	}
-	if (usb_close(dediprog_handle)) {
-		msg_perr("Could not close USB device!\n");
-		return 1;
-	}
+	libusb_close(dediprog_handle);
+	libusb_exit(usb_ctx);
 	return 0;
 }
 
 /* URB numbers refer to the first log ever captured. */
 int dediprog_init(void)
 {
-	struct usb_device *dev;
 	char *voltage, *device, *spispeed;
 	int spispeed_idx = 2;
 	int millivolt = 3500;
@@ -842,31 +862,29 @@ 
 	free(device);
 
 	/* Here comes the USB stuff. */
-	usb_init();
-	usb_find_busses();
-	usb_find_devices();
-	dev = get_device_by_vid_pid(0x0483, 0xdada, (unsigned int) usedevice);
-	if (!dev) {
+	libusb_init(&usb_ctx);
+	if (!usb_ctx) {
+		msg_perr("Could not initialize libusb!\n");
+		return 1;
+	}
+	dediprog_handle = get_device_by_vid_pid_number(0x0483, 0xdada, (unsigned int) usedevice);
+	if (!dediprog_handle) {
 		msg_perr("Could not find a Dediprog SF100 on USB!\n");
+		libusb_exit(usb_ctx);
 		return 1;
 	}
-	msg_pdbg("Found USB device (%04x:%04x).\n",
-		 dev->descriptor.idVendor, dev->descriptor.idProduct);
-	dediprog_handle = usb_open(dev);
-	ret = usb_set_configuration(dediprog_handle, 1);
-	if (ret < 0) {
-		msg_perr("Could not set USB device configuration: %i %s\n",
-			 ret, usb_strerror());
-		if (usb_close(dediprog_handle))
-			msg_perr("Could not close USB device!\n");
+	ret = libusb_set_configuration(dediprog_handle, 1);
+	if (ret != 0) {
+		msg_perr("Could not set USB device configuration: %i %s\n", ret, libusb_error_name(ret));
+		libusb_close(dediprog_handle);
+		libusb_exit(usb_ctx);
 		return 1;
 	}
-	ret = usb_claim_interface(dediprog_handle, 0);
+	ret = libusb_claim_interface(dediprog_handle, 0);
 	if (ret < 0) {
-		msg_perr("Could not claim USB device interface %i: %i %s\n",
-			 0, ret, usb_strerror());
-		if (usb_close(dediprog_handle))
-			msg_perr("Could not close USB device!\n");
+		msg_perr("Could not claim USB device interface %i: %i %s\n", 0, ret, libusb_error_name(ret));
+		libusb_close(dediprog_handle);
+		libusb_exit(usb_ctx);
 		return 1;
 	}
 	dediprog_endpoint = 2;