summaryrefslogtreecommitdiffstats
path: root/src/usb-device.c
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2016-12-06 22:39:44 +0100
committerPali Rohár <pali.rohar@gmail.com>2016-12-06 22:39:44 +0100
commit676da477510cb1966a74273f89c8aa64654a1d49 (patch)
tree6b494e6129e9908f5e7ad33290f92f257560dd2d /src/usb-device.c
parentea7f2a441a68bc4496733a2fcabc6bf8d2962d04 (diff)
download0xFFFF-676da477510cb1966a74273f89c8aa64654a1d49.tar.bz2
all: Revert libusb-1.0 support
Listing of usb devices with libusb-1.0 is too slow and not usable for flashing or cold-flashing Nokia N900. Old libusb (0.1) does not have this problem and works perfectly. Problem for libusb-1.0 was reported at least two times into libusb-devel mailing list, but upstream developers are totally ignore it. One message is in archive: https://sourceforge.net/p/libusb/mailman/message/34985373/ Because of that there is just one option: use tested and working libusb 0.1 library instead some experimental and non-working libusb-1.0.
Diffstat (limited to 'src/usb-device.c')
-rw-r--r--src/usb-device.c148
1 files changed, 89 insertions, 59 deletions
diff --git a/src/usb-device.c b/src/usb-device.c
index 3ca4579..d3aa707 100644
--- a/src/usb-device.c
+++ b/src/usb-device.c
@@ -25,7 +25,13 @@
#include <ctype.h>
#include <signal.h>
-#include <libusb-1.0/libusb.h>
+#include <usb.h>
+
+#ifdef __linux__
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+#include <sys/ioctl.h>
+#endif
+#endif
#include "global.h"
#include "device.h"
@@ -76,34 +82,42 @@ static void usb_flash_device_info_print(const struct usb_flash_device * dev) {
}
-static void usb_reattach_kernel_driver(libusb_device_handle * udev, int interface) {
+static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
+
+#ifdef __linux__
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ struct {
+ int ifno;
+ int ioctl_code;
+ void * data;
+ } command = {
+ .ifno = interface,
+ .ioctl_code = _IO('U', 23),
+ .data = NULL,
+ };
if ( interface < 0 )
return;
PRINTF_LINE("Reattach kernel driver to USB interface...");
PRINTF_END();
- libusb_release_interface(udev, interface);
- libusb_attach_kernel_driver(udev, interface);
+ usb_release_interface(udev, interface);
+ ioctl(*((int *)udev), _IOWR('U', 18, command), &command);
+#endif
+#endif
}
-static void usb_descriptor_info_print(libusb_device_handle * udev, struct libusb_device * dev, char * product, size_t size) {
+static void usb_descriptor_info_print(usb_dev_handle * udev, struct usb_device * dev, char * product, size_t size) {
- struct libusb_device_descriptor desc;
char buf[1024];
char buf2[1024];
unsigned int x;
int ret;
int i;
- if ( libusb_get_device_descriptor(dev, &desc) < 0 ) {
- PRINTF_LINE("libusb_get_device_descriptor() failed");
- PRINTF_END();
- return;
- }
memset(buf, 0, sizeof(buf));
- libusb_get_string_descriptor_ascii(udev, desc.iProduct, (unsigned char *)buf, sizeof(buf));
+ usb_get_string_simple(udev, dev->descriptor.iProduct, buf, sizeof(buf));
PRINTF_LINE("USB device product string: %s", buf[0] ? buf : "(not detected)");
PRINTF_END();
@@ -112,7 +126,7 @@ static void usb_descriptor_info_print(libusb_device_handle * udev, struct libusb
memset(buf, 0, sizeof(buf));
memset(buf2, 0, sizeof(buf2));
- ret = libusb_get_string_descriptor_ascii(udev, desc.iSerialNumber, (unsigned char *)buf, sizeof(buf));
+ ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, buf, sizeof(buf));
if ( ! isalnum(buf[0]) )
buf[0] = 0;
for ( i = 0; i < ret; i+=2 ) {
@@ -131,23 +145,15 @@ static void usb_descriptor_info_print(libusb_device_handle * udev, struct libusb
}
-static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev) {
+static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
- int err, i;
+ int i;
char product[1024];
- libusb_device_handle * udev;
struct usb_device_info * ret = NULL;
- struct libusb_device_descriptor desc;
-
- if ( libusb_get_device_descriptor(dev, &desc) < 0 ) {
- PRINTF_LINE("libusb_get_device_descriptor failed");
- PRINTF_END();
- return NULL;
- }
for ( i = 0; usb_devices[i].vendor; ++i ) {
- if ( desc.idVendor == usb_devices[i].vendor && desc.idProduct == usb_devices[i].product ) {
+ if ( dev->descriptor.idVendor == usb_devices[i].vendor && dev->descriptor.idProduct == usb_devices[i].product ) {
printf("\b\b ");
PRINTF_END();
@@ -156,10 +162,9 @@ static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev)
PRINTF_END();
PRINTF_LINE("Opening USB...");
-
- err = libusb_open(dev, &udev);
- if ( err < 0 ) {
- PRINTF_ERROR("libusb_open failed");
+ usb_dev_handle * udev = usb_open(dev);
+ if ( ! udev ) {
+ PRINTF_ERROR("usb_open failed");
fprintf(stderr, "\n");
return NULL;
}
@@ -168,15 +173,17 @@ static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev)
if ( usb_devices[i].interface >= 0 ) {
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
PRINTF_LINE("Detaching kernel from USB interface...");
- libusb_detach_kernel_driver(udev, usb_devices[i].interface);
+ usb_detach_kernel_driver_np(udev, usb_devices[i].interface);
+#endif
PRINTF_LINE("Claiming USB interface...");
- if ( libusb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
- PRINTF_ERROR("libusb_claim_interface failed");
+ if ( usb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
+ PRINTF_ERROR("usb_claim_interface failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
- libusb_close(udev);
+ usb_close(udev);
return NULL;
}
@@ -184,22 +191,22 @@ static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev)
if ( usb_devices[i].alternate >= 0 ) {
PRINTF_LINE("Setting alternate USB interface...");
- if ( libusb_set_interface_alt_setting(udev, usb_devices[i].interface, usb_devices[i].alternate) < 0 ) {
- PRINTF_ERROR("libusb_claim_interface failed");
+ if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
+ PRINTF_ERROR("usb_claim_interface failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
- libusb_close(udev);
+ usb_close(udev);
return NULL;
}
}
if ( usb_devices[i].configuration >= 0 ) {
PRINTF_LINE("Setting USB configuration...");
- if ( libusb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
- PRINTF_ERROR("libusb_set_configuration failed");
+ if ( usb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
+ PRINTF_ERROR("usb_set_configuration failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
- libusb_close(udev);
+ usb_close(udev);
return NULL;
}
}
@@ -208,7 +215,7 @@ static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev)
if ( ! ret ) {
ALLOC_ERROR();
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
- libusb_close(udev);
+ usb_close(udev);
return NULL;
}
@@ -239,7 +246,7 @@ static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev)
ERROR("Device detection failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
- libusb_close(udev);
+ usb_close(udev);
free(ret);
return NULL;
}
@@ -253,7 +260,7 @@ static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev)
ERROR("Device mishmash");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
- libusb_close(udev);
+ usb_close(udev);
free(ret);
return NULL;
}
@@ -270,6 +277,28 @@ static struct usb_device_info * usb_device_is_valid(struct libusb_device * dev)
}
+static struct usb_device_info * usb_search_device(struct usb_device * dev, int level) {
+
+ int i;
+ struct usb_device_info * ret = NULL;
+
+ if ( ! dev )
+ return NULL;
+
+ ret = usb_device_is_valid(dev);
+ if ( ret )
+ return ret;
+
+ for ( i = 0; i < dev->num_children; i++ ) {
+ ret = usb_search_device(dev->children[i], level + 1);
+ if ( ret )
+ break;
+ }
+
+ return ret;
+
+}
+
static volatile sig_atomic_t signal_quit;
static void signal_handler(int signum) {
@@ -281,18 +310,14 @@ static void signal_handler(int signum) {
struct usb_device_info * usb_open_and_wait_for_device(void) {
- libusb_device **devs;
- libusb_device **dev;
+ struct usb_bus * bus;
struct usb_device_info * ret = NULL;
int i = 0;
void (*prev)(int);
static char progress[] = {'/','-','\\', '|'};
- if ( libusb_init(NULL) < 0 ) {
- PRINTF_LINE("libusb_init failed");
- PRINTF_END();
- return NULL;
- }
+ usb_init();
+ usb_find_busses();
PRINTF_BACK();
printf("\n");
@@ -305,19 +330,25 @@ struct usb_device_info * usb_open_and_wait_for_device(void) {
PRINTF_LINE("Waiting for USB device... %c", progress[++i%sizeof(progress)]);
- if ( libusb_get_device_list(NULL, &devs) < 0 ) {
- PRINTF_LINE("Listing USB devices failed");
- PRINTF_END();
- break;
- }
+ usb_find_devices();
+
+ for ( bus = usb_get_busses(); bus; bus = bus->next ) {
+
+ if ( bus->root_dev )
+ ret = usb_search_device(bus->root_dev, 0);
+ else {
+ struct usb_device *dev;
+ for ( dev = bus->devices; dev; dev = dev->next ) {
+ ret = usb_search_device(dev, 0);
+ if ( ret )
+ break;
+ }
+ }
- for ( dev = devs; *dev != NULL; ++dev ) {
- ret = usb_device_is_valid(*dev);
if ( ret )
break;
- }
- libusb_free_device_list(devs, 1);
+ }
if ( ret )
break;
@@ -342,8 +373,7 @@ struct usb_device_info * usb_open_and_wait_for_device(void) {
void usb_close_device(struct usb_device_info * dev) {
usb_reattach_kernel_driver(dev->udev, dev->flash_device->interface);
- libusb_close(dev->udev);
- libusb_exit(NULL);
+ usb_close(dev->udev);
free(dev);
}