Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/39310 )
Change subject: raiden_debug_spi.c: Implement retry mechanism
......................................................................
raiden_debug_spi.c: Implement retry mechanism
This overcomes a problem with the ServoMicro where USB packets can be
ack'd by the device without triggering interrupts or loading data into
the USB endpoints. The retry mechanism attempts the USB read 3 times
before reattempting the write call to avoid performing multiple SPI
transfers due to a USB problem. This process repeats 3 times before we
return the last error code. Intermediary problems are reported in the
status code.
Based off the downstream commit:
https://chromium-review.googlesource.com/c/chromiumos/third_party/flashrom/…
Change-Id: I76cde68852fa4963582d57c7dcb9f24de32c6da8
Signed-off-by: Edward O'Callaghan <quasisec(a)google.com>
---
M raiden_debug_spi.c
1 file changed, 42 insertions(+), 8 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/10/39310/1
diff --git a/raiden_debug_spi.c b/raiden_debug_spi.c
index 08f8928..1f30b6a 100644
--- a/raiden_debug_spi.c
+++ b/raiden_debug_spi.c
@@ -133,6 +133,16 @@
#define PAYLOAD_SIZE (MAX_PACKET_SIZE - PACKET_HEADER_SIZE)
/*
+ * Servo Micro has an error where it is capable of acknowledging USB packets
+ * without loading it into the USB endpoint buffers or triggering interrupts.
+ * See crbug.com/952494. Retry mechanisms have been implemented to recover
+ * from these rare failures allowing the process to continue.
+ */
+#define WRITE_RETY_ATTEMPTS (3)
+#define READ_RETY_ATTEMPTS (3)
+#define RETY_INTERVAL_US (100 * 1000)
+
+/*
* This timeout is so large because the Raiden SPI timeout is 800ms.
*/
#define TRANSFER_TIMEOUT_MS (200 + 800)
@@ -245,16 +255,40 @@
{
int status = -1;
- status = write_command(flash, write_count, read_count,
- write_buffer, read_buffer);
+ for (int write_attempt = 0; write_attempt < WRITE_RETY_ATTEMPTS;
+ write_attempt++) {
- if (status) {
- return status;
+ status = write_command(flash, write_count, read_count,
+ write_buffer, read_buffer);
+
+ if (status) {
+ /* Write operation failed. */
+ msg_perr("Raiden: Write command failed\n"
+ "Write attempt = %d\n"
+ "status = %d\n",
+ write_attempt + 1, status);
+ programmer_delay(RETY_INTERVAL_US);
+ continue;
+ }
+ for (int read_attempt = 0; read_attempt < READ_RETY_ATTEMPTS; read_attempt++) {
+
+ status = read_response(flash, write_count, read_count,
+ write_buffer, read_buffer);
+
+ if (status != 0) {
+ /* Read operation failed. */
+ msg_perr("Raiden: Read response failed\n"
+ "Write attempt = %d\n"
+ "Read attempt = %d\n"
+ "status = %d\n",
+ write_attempt + 1, read_attempt + 1, status);
+ programmer_delay(RETY_INTERVAL_US);
+ } else {
+ /* We were successful at performing the SPI transfer. */
+ return status;
+ }
+ }
}
-
- status = read_response(flash, write_count, read_count,
- write_buffer, read_buffer);
-
return status;
}
--
To view, visit https://review.coreboot.org/c/flashrom/+/39310
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I76cde68852fa4963582d57c7dcb9f24de32c6da8
Gerrit-Change-Number: 39310
Gerrit-PatchSet: 1
Gerrit-Owner: Edward O'Callaghan <quasisec(a)chromium.org>
Gerrit-MessageType: newchange
Samir Ibradžić has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/38705 )
Change subject: ft2232_spi: Enhance csgpiol parameter for FT2232
......................................................................
ft2232_spi: Enhance csgpiol parameter for FT2232
This allows multiple 'csgpiol' bits to be set to active state at the
same time. Previously, only one GPIOL could be activated. I have an
use-case such that FT4232H is wired to two different SPI chips, and in
order to select one of them two GPIOLs have to be set.
Now, one can enable any particular GPIOL, for example:
csgpiol=01
would activate GPIOL0 and GPIOL1 at the same time.
The change is backward-compatible with previous csgpiol formatting.
Signed-off-by: Samir Ibradzic <sibradzic(a)gmail.com>
Change-Id: I645ddaa9852e9995bd2a6764862fda2b2ef0c26b
---
M ft2232_spi.c
1 file changed, 26 insertions(+), 14 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/05/38705/1
diff --git a/ft2232_spi.c b/ft2232_spi.c
index 5bdc2a7..947050f 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -86,10 +86,17 @@
/* The variables cs_bits and pindir store the values for the "set data bits low byte" MPSSE command that
* sets the initial state and the direction of the I/O pins. The pin offsets are as follows:
- * SCK is bit 0.
- * DO is bit 1.
- * DI is bit 2.
- * CS is bit 3.
+ * TCK/SK is bit 0.
+ * TDI/DO is bit 1.
+ * TDO/DI is bit 2.
+ * TMS/CS is bit 3.
+ * GPIOL0 is bit 4.
+ * GPIOL1 is bit 5.
+ * GPIOL2 is bit 6.
+ * GPIOL3 is bit 7.
+ *
+ * The pin signal direction bit offsets follow the same order; 0 means that
+ * pin at the matching bit index is an input, 1 means pin is an output.
*
* The default values (set below) are used for most devices:
* value: 0x08 CS=high, DI=low, DO=low, SK=low
@@ -331,19 +338,24 @@
}
free(arg);
+ /* Allows setting multiple GPIOL states, for example: csgpiol=012 */
arg = extract_programmer_param("csgpiol");
if (arg) {
- char *endptr;
- unsigned int temp = strtoul(arg, &endptr, 10);
- if (*endptr || endptr == arg || temp > 3) {
- msg_perr("Error: Invalid GPIOL specified: \"%s\".\n"
- "Valid values are between 0 and 3.\n", arg);
- free(arg);
- return -2;
+ unsigned int ngpios = strlen(arg);
+ for (unsigned int i=0; i<=ngpios; i++) {
+ int temp = arg[i] - '0';
+ if (ngpios == 0 || (ngpios != i && (temp < 0 || temp > 3))) {
+ msg_perr("Error: Invalid GPIOLs specified: \"%s\".\n"
+ "Valid values are numbers between 0 and 3. "
+ "Multiple GPIOLs can be specified.\n", arg);
+ free(arg);
+ return -2;
+ } else {
+ unsigned int pin = temp + 4;
+ cs_bits |= 1 << pin;
+ pindir |= 1 << pin;
+ }
}
- unsigned int pin = temp + 4;
- cs_bits |= 1 << pin;
- pindir |= 1 << pin;
}
free(arg);
--
To view, visit https://review.coreboot.org/c/flashrom/+/38705
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I645ddaa9852e9995bd2a6764862fda2b2ef0c26b
Gerrit-Change-Number: 38705
Gerrit-PatchSet: 1
Gerrit-Owner: Samir Ibradžić <sibradzic(a)gmail.com>
Gerrit-MessageType: newchange
Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/38936 )
Change subject: raiden_debug: Upstream ChromiumOS usb_device helpers
......................................................................
raiden_debug: Upstream ChromiumOS usb_device helpers
These are helpful usb device accessors and helpers that
are later used for the so-called Raiden debugger programmer.
BUG=b:143389556
BRANCH=none
TEST=builds
Change-Id: Ic928220fc919fe4958c8150e61e11470dac88f13
Signed-off-by: Edward O'Callaghan <quasisec(a)google.com>
---
M Makefile
M meson.build
A usb_device.c
A usb_device.h
4 files changed, 559 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/36/38936/1
diff --git a/Makefile b/Makefile
index 7242b09..bfd4d1e 100644
--- a/Makefile
+++ b/Makefile
@@ -1088,7 +1088,7 @@
ifneq ($(NEED_LIBUSB1), )
CHECK_LIBUSB1 = yes
FEATURE_CFLAGS += -D'NEED_LIBUSB1=1'
-PROGRAMMER_OBJS += usbdev.o
+PROGRAMMER_OBJS += usbdev.o usb_device.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
diff --git a/meson.build b/meson.build
index 375089c..45a3681 100644
--- a/meson.build
+++ b/meson.build
@@ -84,6 +84,7 @@
# some programmers require libusb
if get_option('usb')
srcs += 'usbdev.c'
+ srcs += 'usb_device.c'
deps += dependency('libusb-1.0')
else
config_ch341a_spi = false
diff --git a/usb_device.c b/usb_device.c
new file mode 100644
index 0000000..48833fb
--- /dev/null
+++ b/usb_device.c
@@ -0,0 +1,393 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2020, Google Inc. All rights reserved.
+ *
+ * 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 "programmer.h"
+#include "spi.h"
+#include "usb_device.h"
+
+#include <assert.h>
+#include <libusb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Possibly extract a programmer parameter and use it to initialize the given
+ * match value structure.
+ */
+static void usb_match_value_init(struct usb_match_value *match,
+ char const *parameter)
+{
+ char *string = extract_programmer_param(parameter);
+
+ match->name = parameter;
+
+ if (string) {
+ match->set = 1;
+ match->value = strtol(string, NULL, 0);
+ } else {
+ match->set = 0;
+ }
+
+ free(string);
+}
+
+#define USB_MATCH_VALUE_INIT(NAME) \
+ usb_match_value_init(&match->NAME, #NAME)
+
+void usb_match_init(struct usb_match *match)
+{
+ USB_MATCH_VALUE_INIT(vid);
+ USB_MATCH_VALUE_INIT(pid);
+ USB_MATCH_VALUE_INIT(bus);
+ USB_MATCH_VALUE_INIT(address);
+ USB_MATCH_VALUE_INIT(config);
+ USB_MATCH_VALUE_INIT(interface);
+ USB_MATCH_VALUE_INIT(altsetting);
+ USB_MATCH_VALUE_INIT(class);
+ USB_MATCH_VALUE_INIT(subclass);
+ USB_MATCH_VALUE_INIT(protocol);
+}
+
+void usb_match_value_default(struct usb_match_value *value,
+ long int default_value)
+{
+ if (value->set)
+ return;
+
+ value->set = 1;
+ value->value = default_value;
+}
+
+/*
+ * Match the value against a possible user supplied parameter.
+ *
+ * Return:
+ * 0: The user supplied the given parameter and it did not match the value.
+ * 1: Either the user didn't supply the parameter, or they did and it
+ * matches the given value.
+ */
+static int check_match(struct usb_match_value const *match_value, int value)
+{
+ int reject = match_value->set && (match_value->value != value);
+
+ if (reject)
+ msg_pdbg("USB: Rejecting device because %s = %d != %d\n",
+ match_value->name,
+ value,
+ match_value->value);
+
+ return !reject;
+}
+
+/*
+ * Allocate a copy of device and add it to the head of the devices list.
+ */
+static void add_device(struct usb_device *device,
+ struct usb_device **devices)
+{
+ struct usb_device *copy = malloc(sizeof(struct usb_device));
+
+ assert(copy != NULL);
+
+ *copy = *device;
+
+ copy->next = *devices;
+ *devices = copy;
+
+ libusb_ref_device(copy->device);
+}
+
+/*
+ * Look through the interfaces of the current device config for a match. Stop
+ * looking after the first valid match is found.
+ *
+ * Return:
+ * 0: No matching interface was found.
+ * 1: A complete match was found and added to the devices list.
+ */
+static int find_interface(struct usb_match const *match,
+ struct usb_device *current,
+ struct usb_device **devices)
+{
+ int i, j;
+
+ for (i = 0; i < current->config_descriptor->bNumInterfaces; ++i) {
+ struct libusb_interface const *interface;
+
+ interface = ¤t->config_descriptor->interface[i];
+
+ for (j = 0; j < interface->num_altsetting; ++j) {
+ struct libusb_interface_descriptor const *descriptor;
+
+ descriptor = &interface->altsetting[j];
+
+ if (check_match(&match->interface,
+ descriptor->bInterfaceNumber) &&
+ check_match(&match->altsetting,
+ descriptor->bAlternateSetting) &&
+ check_match(&match->class,
+ descriptor->bInterfaceClass) &&
+ check_match(&match->subclass,
+ descriptor->bInterfaceSubClass) &&
+ check_match(&match->protocol,
+ descriptor->bInterfaceProtocol)) {
+ current->interface_descriptor = descriptor;
+ add_device(current, devices);
+ msg_pdbg("USB: Found matching device\n");
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Look through the configs of the current device for a match. Stop looking
+ * after the first valid match is found.
+ *
+ * Return:
+ * 0: All configurations successfully checked, one may have been added to
+ * the list.
+ * non-zero: There was a failure while checking for a match.
+ */
+static int find_config(struct usb_match const *match,
+ struct usb_device *current,
+ struct libusb_device_descriptor const *device_descriptor,
+ struct usb_device **devices)
+{
+ int i;
+
+ for (i = 0; i < device_descriptor->bNumConfigurations; ++i) {
+ int ret = LIBUSB(libusb_get_config_descriptor(
+ current->device, i,
+ ¤t->config_descriptor));
+ if (ret != 0) {
+ msg_perr("USB: Failed to get config descriptor");
+ return ret;
+ }
+
+ if (check_match(&match->config,
+ current->config_descriptor->
+ bConfigurationValue) &&
+ find_interface(match, current, devices))
+ break;
+
+ libusb_free_config_descriptor(current->config_descriptor);
+ }
+
+ return 0;
+}
+
+int usb_device_find(struct usb_match const *match, struct usb_device **devices)
+{
+ libusb_device **list;
+ ssize_t count;
+ ssize_t i;
+
+ *devices = NULL;
+
+ int ret = LIBUSB(count = libusb_get_device_list(NULL, &list));
+ if (ret != 0) {
+ msg_perr("USB: Failed to get device list");
+ return ret;
+ }
+
+ for (i = 0; i < count; ++i) {
+ struct libusb_device_descriptor descriptor;
+ struct usb_device current = {
+ .device = list[i],
+ .handle = NULL,
+ .next = NULL,
+ };
+
+ uint8_t bus = libusb_get_bus_number(list[i]);
+ uint8_t address = libusb_get_device_address(list[i]);
+
+ msg_pdbg("USB: Inspecting device (Bus %d, Address %d)\n",
+ bus,
+ address);
+
+ ret = LIBUSB(libusb_get_device_descriptor(list[i],
+ &descriptor));
+ if (ret != 0) {
+ msg_perr("USB: Failed to get device descriptor");
+ return ret;
+ }
+
+ if (check_match(&match->vid, descriptor.idVendor) &&
+ check_match(&match->pid, descriptor.idProduct) &&
+ check_match(&match->bus, bus) &&
+ check_match(&match->address, address)) {
+ ret = find_config(match,
+ ¤t,
+ &descriptor,
+ devices);
+ if (ret != 0) {
+ msg_perr("USB: Failed to find config");
+ return ret;
+ }
+ }
+ }
+
+ libusb_free_device_list(list, 1);
+
+ return (*devices == NULL);
+}
+
+/*
+ * If the underlying libusb device is not open, open it.
+ *
+ * Return:
+ * 0: The device was already open or was successfully opened.
+ * non-zero: There was a failure while opening the device.
+ */
+static int usb_device_open(struct usb_device *device)
+{
+ if (device->handle == NULL) {
+ int ret = LIBUSB(libusb_open(device->device, &device->handle));
+ if (ret != 0) {
+ msg_perr("USB: Failed to open device\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int usb_device_show(char const *prefix, struct usb_device *device)
+{
+ struct libusb_device_descriptor descriptor;
+ unsigned char product[256];
+ int ret;
+
+ ret = usb_device_open(device);
+ if (ret != 0) {
+ msg_perr("USB: Failed to open device\n");
+ return ret;
+ }
+
+ ret = LIBUSB(libusb_get_device_descriptor(device->device, &descriptor));
+ if (ret != 0) {
+ msg_perr("USB: Failed to get device descriptor\n");
+ return ret;
+ }
+
+ ret = LIBUSB(libusb_get_string_descriptor_ascii(
+ device->handle,
+ descriptor.iProduct,
+ product,
+ sizeof(product)));
+ if (ret != 0) {
+ msg_perr("USB: Failed to get device product string\n");
+ return ret;
+ }
+
+ product[255] = '\0';
+
+ msg_perr("%sbus=0x%02x,address=0x%02x | %s\n",
+ prefix,
+ libusb_get_bus_number(device->device),
+ libusb_get_device_address(device->device),
+ product);
+
+ return 0;
+}
+
+int usb_device_claim(struct usb_device *device)
+{
+ int current_config;
+
+ int ret = usb_device_open(device);
+ if (ret != 0) {
+ msg_perr("USB: Failed to open device\n");
+ return ret;
+ }
+
+ ret = LIBUSB(libusb_get_configuration(device->handle,
+ ¤t_config));
+ if (ret != 0) {
+ msg_perr("USB: Failed to get current device configuration\n");
+ return ret;
+ }
+
+ if (current_config != device->config_descriptor->bConfigurationValue) {
+ ret = LIBUSB(libusb_set_configuration(
+ device->handle,
+ device->
+ config_descriptor->
+ bConfigurationValue));
+ if (ret != 0) {
+ msg_perr("USB: Failed to set new configuration from %d to %d\n",
+ current_config,
+ device->config_descriptor->bConfigurationValue);
+ return ret;
+ }
+ }
+
+ ret = LIBUSB(libusb_set_auto_detach_kernel_driver(device->handle, 1));
+ if (ret != 0) {
+ msg_perr("USB: Failed to enable auto kernel driver detach\n");
+ return ret;
+ }
+
+ ret = LIBUSB(libusb_claim_interface(device->handle,
+ device->
+ interface_descriptor->
+ bInterfaceNumber));
+ if (ret != 0) {
+ msg_perr("USB: Could not claim device interface %d\n",
+ device->interface_descriptor->bInterfaceNumber);
+ return ret;
+ }
+
+ if (device->interface_descriptor->bAlternateSetting != 0) {
+ ret = LIBUSB(libusb_set_interface_alt_setting(
+ device->handle,
+ device->
+ interface_descriptor->
+ bInterfaceNumber,
+ device->
+ interface_descriptor->
+ bAlternateSetting));
+ if (ret != 0) {
+ msg_perr("USB: Failed to set alternate setting %d\n",
+ device->interface_descriptor->bAlternateSetting);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+struct usb_device *usb_device_free(struct usb_device *device)
+{
+ struct usb_device *next = device->next;
+
+ if (device->handle != NULL)
+ libusb_close(device->handle);
+
+ /*
+ * This unref balances the ref added in the add_device function.
+ */
+ libusb_unref_device(device->device);
+ libusb_free_config_descriptor(device->config_descriptor);
+
+ free(device);
+
+ return next;
+}
diff --git a/usb_device.h b/usb_device.h
new file mode 100644
index 0000000..d379675
--- /dev/null
+++ b/usb_device.h
@@ -0,0 +1,164 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2020, Google Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+#ifndef USB_DEVICE_H
+#define USB_DEVICE_H
+
+/*
+ * USB device matching framework
+ *
+ * This can be used to match a USB device by a number of different parameters.
+ * The parameters can be passed on the command line and defaults can be set
+ * by the programmer.
+ */
+
+#include <libusb.h>
+#include <stdint.h>
+
+/*
+ * The LIBUSB macro converts a libusb failure code into an error code that
+ * flashrom recognizes. It also displays additional libusb specific
+ * information about the failure.
+ */
+#define LIBUSB(expression) \
+ ({ \
+ int libusb_error__ = (expression); \
+ \
+ if (libusb_error__ < 0) { \
+ msg_perr("libusb error: %s:%d %s\n", \
+ __FILE__, \
+ __LINE__, \
+ libusb_error_name(libusb_error__)); \
+ libusb_error__ = 0x20000 | -libusb_error__; \
+ } else { \
+ libusb_error__ = 0; \
+ } \
+ \
+ libusb_error__; \
+ })
+
+/*
+ * A USB match and associated value struct are used to encode the information
+ * about a device against which we wish to match. If the value of a
+ * usb_match_value has been set then a device must match that value. The name
+ * of the usb_match_value is used to fetch the programmer parameter from the
+ * flashrom command line and is the same as the name of the corresponding
+ * field in usb_match.
+ */
+struct usb_match_value {
+ char const *name;
+ int value;
+ int set;
+};
+
+struct usb_match {
+ struct usb_match_value bus;
+ struct usb_match_value address;
+ struct usb_match_value vid;
+ struct usb_match_value pid;
+ struct usb_match_value serial;
+ struct usb_match_value config;
+ struct usb_match_value interface;
+ struct usb_match_value altsetting;
+ struct usb_match_value class;
+ struct usb_match_value subclass;
+ struct usb_match_value protocol;
+};
+
+/*
+ * Initialize a usb_match structure so that each value's name matches the
+ * values name in the usb_match structure (so bus.name == "bus"...), and
+ * look for each value in the flashrom command line via
+ * extract_programmer_param. If the value is found convert it to an integer
+ * using strtol, accepting hex, decimal and octal encoding.
+ */
+void usb_match_init(struct usb_match *match);
+
+/*
+ * Add a default value to a usb_match_value. This must be done after calling
+ * usb_match_init. If usb_match_init already set the value of a usb_match_value
+ * we do nothing, otherwise set the value to default_value. This ensures that
+ * parameters passed on the command line override defaults.
+ */
+void usb_match_value_default(struct usb_match_value *match,
+ long int default_value);
+
+/*
+ * The usb_device structure is an entry in a linked list of devices that were
+ * matched by usb_device_find.
+ */
+struct usb_device {
+ struct libusb_device *device;
+ struct libusb_config_descriptor *config_descriptor;
+ struct libusb_interface_descriptor const *interface_descriptor;
+
+ /*
+ * Initially NULL, the libusb_device_handle is only valid once the
+ * usb_device has been successfully passed to usb_device_show or
+ * usb_device_claim.
+ */
+ struct libusb_device_handle *handle;
+
+ /*
+ * Link to next device, or NULL
+ */
+ struct usb_device *next;
+};
+
+/*
+ * Find and return a list of all compatible devices. Each device is added to
+ * the list with its first valid configuration and interface. If an alternate
+ * configuration (config, interface, altsetting...) is desired the specifics
+ * can be supplied as programmer parameters.
+ *
+ * Return:
+ * 0: At least one matching device was found.
+ * 1: No matching devices were found.
+ */
+int usb_device_find(struct usb_match const *match, struct usb_device **devices);
+
+/*
+ * Display the devices bus and address as well as its product string. The
+ * underlying libusb device is opened if it is not already open.
+ *
+ * Return:
+ * 0: The device information was displayed.
+ * non-zero: There was a failure while displaying the device information.
+ */
+int usb_device_show(char const *prefix, struct usb_device *device);
+
+/*
+ * Open the underlying libusb device, set its config, claim the interface and
+ * select the correct alternate interface.
+ *
+ * Return:
+ * 0: The device was successfully claimed.
+ * non-zero: There was a failure while trying to claim the device.
+ */
+int usb_device_claim(struct usb_device *device);
+
+/*
+ * Free a usb_device structure.
+ *
+ * This ensures that the libusb device is closed and that all allocated
+ * handles and descriptors are freed.
+ *
+ * Return:
+ * The next device in the device list.
+ */
+struct usb_device *usb_device_free(struct usb_device *device);
+
+#endif /* USB_DEVICE_H */
--
To view, visit https://review.coreboot.org/c/flashrom/+/38936
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: Ic928220fc919fe4958c8150e61e11470dac88f13
Gerrit-Change-Number: 38936
Gerrit-PatchSet: 1
Gerrit-Owner: Edward O'Callaghan <quasisec(a)chromium.org>
Gerrit-MessageType: newchange