diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | dediprog.c | 46 | ||||
-rw-r--r-- | developerbox_spi.c | 64 | ||||
-rw-r--r-- | programmer.h | 8 | ||||
-rw-r--r-- | usbdev.c | 130 |
5 files changed, 141 insertions, 108 deletions
@@ -1023,6 +1023,7 @@ endif ifneq ($(NEED_LIBUSB1), ) CHECK_LIBUSB1 = yes FEATURE_CFLAGS += -D'NEED_LIBUSB1=1' +PROGRAMMER_OBJS += usbdev.o # FreeBSD and DragonflyBSD use a reimplementation of libusb-1.0 that is simply called libusb ifeq ($(TARGET_OS),$(filter $(TARGET_OS),FreeBSD DragonFlyBSD)) USB1LIBS += -lusb @@ -242,50 +242,6 @@ static int dediprog_write(enum dediprog_cmds cmd, unsigned int value, unsigned i } -/* Might be useful for other USB devices as well. static for now. - * num parameter allows user to specify one device of multiple installed */ -static struct libusb_device_handle *get_device_by_vid_pid_number(uint16_t vid, uint16_t pid, unsigned int num) -{ - struct libusb_device **list; - ssize_t count = libusb_get_device_list(usb_ctx, &list); - if (count < 0) { - msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count)); - return NULL; - } - - struct libusb_device_handle *handle = NULL; - ssize_t i = 0; - for (i = 0; i < count; i++) { - struct libusb_device *dev = list[i]; - struct libusb_device_descriptor desc; - int 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 %04"PRIx16":%04"PRIx16" at address %d-%d.\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 handle; -} - /* This function sets the GPIOs connected to the LEDs as well as IO1-IO4. */ static int dediprog_set_leds(int leds) { @@ -1102,7 +1058,7 @@ int dediprog_init(void) const uint16_t vid = devs_dediprog[0].vendor_id; const uint16_t pid = devs_dediprog[0].device_id; - dediprog_handle = get_device_by_vid_pid_number(vid, pid, (unsigned int) usedevice); + dediprog_handle = usb_dev_get_by_vid_pid_number(usb_ctx, vid, pid, (unsigned int) usedevice); if (!dediprog_handle) { msg_perr("Could not find a Dediprog programmer on USB.\n"); libusb_exit(usb_ctx); diff --git a/developerbox_spi.c b/developerbox_spi.c index 8482dea1..4ad966ec 100644 --- a/developerbox_spi.c +++ b/developerbox_spi.c @@ -34,7 +34,6 @@ #include "platform.h" #include <stdlib.h> -#include <string.h> #include <libusb.h> #include "programmer.h" #include "spi.h" @@ -130,67 +129,6 @@ static const struct bitbang_spi_master bitbang_spi_master_cp210x = { .set_sck_set_mosi = cp210x_bitbang_set_sck_set_mosi, }; -static struct libusb_device_handle *get_device_by_vid_pid_serial(uint16_t vid, uint16_t pid, - const char *serialno) -{ - struct libusb_device **list; - ssize_t count = libusb_get_device_list(usb_ctx, &list); - if (count < 0) { - msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count)); - return NULL; - } - - ssize_t i = 0; - for (i = 0; i < count; i++) { - struct libusb_device *dev = list[i]; - struct libusb_device_descriptor desc; - struct libusb_device_handle *handle; - - int res = libusb_get_device_descriptor(dev, &desc); - if (res != 0) { - msg_perr("Reading the USB device descriptor failed (%s)!\n", libusb_error_name(res)); - continue; - } - - if ((desc.idVendor != vid) && (desc.idProduct != pid)) - continue; - - msg_pdbg("Found USB device %04"PRIx16":%04"PRIx16" at address %d-%d.\n", - desc.idVendor, desc.idProduct, - libusb_get_bus_number(dev), libusb_get_device_address(dev)); - - res = libusb_open(dev, &handle); - if (res != 0) { - msg_perr("Opening the USB device failed (%s)!\n", libusb_error_name(res)); - continue; - } - - if (serialno) { - unsigned char myserial[64]; - res = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, myserial, - sizeof(myserial)); - if (res < 0) { - msg_perr("Reading the USB serialno failed (%s)!\n", libusb_error_name(res)); - libusb_close(handle); - continue; - } - msg_pdbg("Serial number is %s\n", myserial); - - /* Filter out any serial number that does not commence with serialno */ - if (0 != strncmp(serialno, (char *) myserial, strlen(serialno))) { - libusb_close(handle); - continue; - } - } - - libusb_free_device_list(list, 1); - return handle; - } - - libusb_free_device_list(list, 1); - return NULL; -} - static int developerbox_spi_shutdown(void *data) { libusb_close(cp210x_handle); @@ -210,7 +148,7 @@ int developerbox_spi_init(void) char *serialno = extract_programmer_param("serial"); if (serialno) msg_pdbg("Looking for serial number commencing %s\n", serialno); - cp210x_handle = get_device_by_vid_pid_serial( + cp210x_handle = usb_dev_get_by_vid_pid_serial(usb_ctx, devs_developerbox_spi[0].vendor_id, devs_developerbox_spi[0].device_id, serialno); free(serialno); if (!cp210x_handle) { diff --git a/programmer.h b/programmer.h index 300cf5f1..311992a0 100644 --- a/programmer.h +++ b/programmer.h @@ -841,4 +841,12 @@ static inline bool spi_master_4ba(const struct flashctx *const flash) flash->mst->spi.features & SPI_MASTER_4BA; } +/* usbdev.c */ +struct libusb_device_handle; +struct libusb_context; +struct libusb_device_handle *usb_dev_get_by_vid_pid_serial( + struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, const char *serialno); +struct libusb_device_handle *usb_dev_get_by_vid_pid_number( + struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, unsigned int num); + #endif /* !__PROGRAMMER_H__ */ diff --git a/usbdev.c b/usbdev.c new file mode 100644 index 00000000..5c34ba12 --- /dev/null +++ b/usbdev.c @@ -0,0 +1,130 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2016 secunet Security Networks AG + * Copyright (C) 2018 Linaro Limited + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <string.h> +#include <libusb.h> +#include "programmer.h" + +struct libusb_device_handle *usb_dev_get_by_vid_pid_serial( + struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, const char *serialno) +{ + struct libusb_device **list; + ssize_t count = libusb_get_device_list(usb_ctx, &list); + if (count < 0) { + msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count)); + return NULL; + } + + ssize_t i = 0; + for (i = 0; i < count; i++) { + struct libusb_device *dev = list[i]; + struct libusb_device_descriptor desc; + struct libusb_device_handle *handle; + + int res = libusb_get_device_descriptor(dev, &desc); + if (res != 0) { + msg_perr("Reading the USB device descriptor failed (%s)!\n", libusb_error_name(res)); + continue; + } + + if ((desc.idVendor != vid) && (desc.idProduct != pid)) + continue; + + msg_pdbg("Found USB device %04"PRIx16":%04"PRIx16" at address %d-%d.\n", + desc.idVendor, desc.idProduct, + libusb_get_bus_number(dev), libusb_get_device_address(dev)); + + res = libusb_open(dev, &handle); + if (res != 0) { + msg_perr("Opening the USB device failed (%s)!\n", libusb_error_name(res)); + continue; + } + + if (serialno) { + unsigned char myserial[64]; + res = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, myserial, + sizeof(myserial)); + if (res < 0) { + msg_perr("Reading the USB serialno failed (%s)!\n", libusb_error_name(res)); + libusb_close(handle); + continue; + } + msg_pdbg("Serial number is %s\n", myserial); + + /* Reject any serial number that does not commence with serialno */ + if (0 != strncmp(serialno, (char *)myserial, strlen(serialno))) { + libusb_close(handle); + continue; + } + } + + libusb_free_device_list(list, 1); + return handle; + } + + libusb_free_device_list(list, 1); + return NULL; +} + +/* + * This function allows different devices to be targeted based on enumeration order. Different + * hotplug sequencing (or simply a reboot) may change the enumeration order. This function should + * only be used if a programmers does not provide an alternative way to identify itself uniquely + * (such as a unique serial number). + */ +struct libusb_device_handle *usb_dev_get_by_vid_pid_number( + struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, unsigned int num) +{ + struct libusb_device **list; + ssize_t count = libusb_get_device_list(usb_ctx, &list); + if (count < 0) { + msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count)); + return NULL; + } + + struct libusb_device_handle *handle = NULL; + ssize_t i = 0; + for (i = 0; i < count; i++) { + struct libusb_device *dev = list[i]; + struct libusb_device_descriptor desc; + int 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 %04"PRIx16":%04"PRIx16" at address %d-%d.\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 handle; +} |