dediprog: Parse USB endpoint addresses from descriptor
For real dediprog devices this shouldn't change anything. For devices
implementing the dediprog USB interface on a microcontroller like:
https://github.com/ArthurHeymans/dedipico
https://github.com/ArthurHeymans/dedich322
This allows them to put the dediprog endpoints on whathever addresses
they like.
Tested with SF100 and SF600Plus-G2
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Change-Id: I879ae10715207a44b4060d4c538965166a6a6964
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/516
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: Nico Huber <nico.h@gmx.de>
diff --git a/dediprog.c b/dediprog.c
index 8fb4a65..d8a452f 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -40,6 +40,7 @@
#define MAX_BLOCK_COUNT 65535
#define MAX_CMD_SIZE 15
#define DEDIPROG_ASYNC_TRANSFERS 8 /* at most 8 asynchronous transfers */
+#define DEDIPROG_INTERFACE 0
#define REQTYPE_OTHER_OUT (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0x43 */
#define REQTYPE_OTHER_IN (LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_OTHER) /* 0xC3 */
#define REQTYPE_EP_OUT (LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_ENDPOINT) /* 0x42 */
@@ -1183,6 +1184,68 @@
.probe_opcode = default_spi_probe_opcode,
};
+static int dediprog_find_bulk_endpoints(struct dediprog_data *dp_data)
+{
+ struct libusb_config_descriptor *config;
+ const struct libusb_interface_descriptor *interface = NULL;
+ int in_endpoint = 0;
+ int out_endpoint = 0;
+ int ret;
+ int i;
+
+ ret = libusb_get_active_config_descriptor(libusb_get_device(dp_data->handle), &config);
+ if (ret != 0) {
+ msg_perr("Could not read USB configuration descriptor: %i %s\n",
+ ret, libusb_error_name(ret));
+ return 1;
+ }
+
+ for (i = 0; i < config->bNumInterfaces; i++) {
+ const struct libusb_interface *const iface = &config->interface[i];
+ if (iface->num_altsetting > 0 && iface->altsetting[0].bInterfaceNumber == DEDIPROG_INTERFACE) {
+ interface = &iface->altsetting[0];
+ break;
+ }
+ }
+
+ if (!interface) {
+ msg_perr("Could not find USB interface %u in configuration descriptor.\n", DEDIPROG_INTERFACE);
+ libusb_free_config_descriptor(config);
+ return 1;
+ }
+
+ for (i = 0; i < interface->bNumEndpoints; i++) {
+ const struct libusb_endpoint_descriptor *const endpoint = &interface->endpoint[i];
+ const uint8_t type = endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK;
+ const uint8_t address = endpoint->bEndpointAddress;
+
+ if (type != LIBUSB_TRANSFER_TYPE_BULK)
+ continue;
+
+ if ((address & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) {
+ if (!in_endpoint)
+ in_endpoint = address;
+ } else if (!out_endpoint) {
+ out_endpoint = address;
+ }
+ }
+
+ libusb_free_config_descriptor(config);
+
+ if (!in_endpoint || !out_endpoint) {
+ msg_perr("Could not find required bulk endpoints (in=0x%02x, out=0x%02x).\n",
+ in_endpoint, out_endpoint);
+ return 1;
+ }
+
+ dp_data->in_endpoint = in_endpoint;
+ dp_data->out_endpoint = out_endpoint;
+
+ msg_pdbg("Using bulk endpoints in=0x%02x, out=0x%02x.\n",
+ dp_data->in_endpoint, dp_data->out_endpoint);
+ return 0;
+}
+
/*
* Open a dediprog_handle with the USB device at the given index.
* @index index of the USB device
@@ -1225,11 +1288,8 @@
goto unknown_dev;
}
- dp_data->in_endpoint = LIBUSB_ENDPOINT_IN | 2;
- if (dp_data->devicetype <= DEV_SF200)
- dp_data->out_endpoint = 2;
- else
- dp_data->out_endpoint = 1;
+ if (dediprog_find_bulk_endpoints(dp_data))
+ goto unknown_dev;
return 0;