hosted/libusb: Move platform.c libusb related functions to own file.
This commit is contained in:
parent
41788f923b
commit
32db38ecf2
|
@ -140,7 +140,9 @@ bool cmd_version(target *t, int argc, char **argv)
|
||||||
(void)argv;
|
(void)argv;
|
||||||
gdb_out(BOARD_IDENT);
|
gdb_out(BOARD_IDENT);
|
||||||
#if PC_HOSTED == 1
|
#if PC_HOSTED == 1
|
||||||
gdb_outf("\n for %s, %s\n", info.manufacturer, info.product);
|
char ident[256];
|
||||||
|
gdb_ident(ident, sizeof(ident));
|
||||||
|
gdb_outf("\n for %s\n", ident);
|
||||||
#else
|
#else
|
||||||
gdb_outf(", Hardware Version %d\n", platform_hwversion());
|
gdb_outf(", Hardware Version %d\n", platform_hwversion());
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,8 +42,8 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
VPATH += platforms/pc
|
VPATH += platforms/pc
|
||||||
SRC += timing.c cl_utils.c utils.c libusb_utils.c
|
SRC += timing.c cl_utils.c utils.c
|
||||||
SRC += stlinkv2.c
|
SRC += stlinkv2.c bmp_libusb.c
|
||||||
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
|
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
|
||||||
SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c
|
SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c
|
||||||
SRC += jlink.c jlink_adiv5_swdp.c jlink_jtagtap.c
|
SRC += jlink.c jlink_adiv5_swdp.c jlink_jtagtap.c
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#if !defined(__BMP_LIBUSB_H)
|
||||||
|
#define __BMP_LIBUSB_H
|
||||||
|
|
||||||
|
#include "cl_utils.h"
|
||||||
|
|
||||||
|
#if HOSTED_BMP_ONLY != 1
|
||||||
|
# include <libusb-1.0/libusb.h>
|
||||||
|
struct trans_ctx {
|
||||||
|
#define TRANS_FLAGS_IS_DONE (1 << 0)
|
||||||
|
#define TRANS_FLAGS_HAS_ERROR (1 << 1)
|
||||||
|
volatile unsigned long flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct usb_link_s {
|
||||||
|
libusb_context *ul_libusb_ctx;
|
||||||
|
libusb_device_handle *ul_libusb_device_handle;
|
||||||
|
unsigned char ep_tx;
|
||||||
|
unsigned char ep_rx;
|
||||||
|
struct libusb_transfer* req_trans;
|
||||||
|
struct libusb_transfer* rep_trans;
|
||||||
|
void *priv;
|
||||||
|
} usb_link_t;
|
||||||
|
|
||||||
|
int send_recv(usb_link_t *link, uint8_t *txbuf, size_t txsize,
|
||||||
|
uint8_t *rxbuf, size_t rxsize);
|
||||||
|
#endif
|
||||||
|
typedef struct bmp_info_s {
|
||||||
|
bmp_type_t bmp_type;
|
||||||
|
char dev;
|
||||||
|
char serial[64];
|
||||||
|
char manufacturer[128];
|
||||||
|
char product[128];
|
||||||
|
char version[128];
|
||||||
|
#if HOSTED_BMP_ONLY != 1
|
||||||
|
libusb_context *libusb_ctx;
|
||||||
|
struct ftdi_context *ftdic;
|
||||||
|
usb_link_t *usb_link;
|
||||||
|
unsigned int vid;
|
||||||
|
unsigned int pid;
|
||||||
|
#endif
|
||||||
|
} bmp_info_t;
|
||||||
|
|
||||||
|
extern bmp_info_t info;
|
||||||
|
void bmp_ident(bmp_info_t *info);
|
||||||
|
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info);
|
||||||
|
void libusb_exit_function(bmp_info_t *info);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,379 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
|
||||||
|
*
|
||||||
|
* 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 3 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Find all known usb connected debuggers */
|
||||||
|
#include "general.h"
|
||||||
|
#include "libusb-1.0/libusb.h"
|
||||||
|
#include "cl_utils.h"
|
||||||
|
#include "ftdi_bmp.h"
|
||||||
|
|
||||||
|
#define VENDOR_ID_STLINK 0x0483
|
||||||
|
#define PRODUCT_ID_STLINK_MASK 0xffe0
|
||||||
|
#define PRODUCT_ID_STLINK_GROUP 0x3740
|
||||||
|
#define PRODUCT_ID_STLINKV1 0x3744
|
||||||
|
#define PRODUCT_ID_STLINKV2 0x3748
|
||||||
|
#define PRODUCT_ID_STLINKV21 0x374b
|
||||||
|
#define PRODUCT_ID_STLINKV21_MSD 0x3752
|
||||||
|
#define PRODUCT_ID_STLINKV3 0x374f
|
||||||
|
#define PRODUCT_ID_STLINKV3E 0x374e
|
||||||
|
|
||||||
|
#define VENDOR_ID_SEGGER 0x1366
|
||||||
|
|
||||||
|
void libusb_exit_function(bmp_info_t *info)
|
||||||
|
{
|
||||||
|
if (!info->usb_link)
|
||||||
|
return;
|
||||||
|
libusb_free_transfer(info->usb_link->req_trans);
|
||||||
|
libusb_free_transfer(info->usb_link->rep_trans);
|
||||||
|
if (info->usb_link->ul_libusb_device_handle) {
|
||||||
|
libusb_release_interface (
|
||||||
|
info->usb_link->ul_libusb_device_handle, 0);
|
||||||
|
libusb_close(info->usb_link->ul_libusb_device_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
|
||||||
|
{
|
||||||
|
libusb_device **devs;
|
||||||
|
int res = libusb_init(&info->libusb_ctx);
|
||||||
|
if (res) {
|
||||||
|
DEBUG_WARN( "Fatal: Failed to get USB context: %s\n",
|
||||||
|
libusb_strerror(res));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
res = libusb_init(&info->libusb_ctx);
|
||||||
|
if (res) {
|
||||||
|
DEBUG_WARN( "Fatal: Failed to get USB context: %s\n",
|
||||||
|
libusb_strerror(res));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
if (cl_opts->opt_cable) {
|
||||||
|
if ((!strcmp(cl_opts->opt_cable, "list")) ||
|
||||||
|
(!strcmp(cl_opts->opt_cable, "l"))) {
|
||||||
|
cable_desc_t *cable = &cable_desc[0];
|
||||||
|
DEBUG_WARN("Available cables:\n");
|
||||||
|
for (; cable->name; cable++) {
|
||||||
|
DEBUG_WARN("\t%s\n", cable->name);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
info->bmp_type = BMP_TYPE_LIBFTDI;
|
||||||
|
}
|
||||||
|
int n_devs = libusb_get_device_list(info->libusb_ctx, &devs);
|
||||||
|
if (n_devs < 0) {
|
||||||
|
DEBUG_WARN( "WARN:libusb_get_device_list() failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bool report = false;
|
||||||
|
int found_debuggers;
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
char serial[64];
|
||||||
|
char manufacturer[128];
|
||||||
|
char product[128];
|
||||||
|
bmp_type_t type = BMP_TYPE_NONE;
|
||||||
|
bool access_problems = false;
|
||||||
|
char *active_cable = NULL;
|
||||||
|
bool ftdi_unknown = false;
|
||||||
|
rescan:
|
||||||
|
found_debuggers = 0;
|
||||||
|
for (int i = 0; devs[i]; i++) {
|
||||||
|
libusb_device *dev = devs[i];
|
||||||
|
int res = libusb_get_device_descriptor(dev, &desc);
|
||||||
|
if (res < 0) {
|
||||||
|
DEBUG_WARN( "WARN: libusb_get_device_descriptor() failed: %s",
|
||||||
|
libusb_strerror(res));
|
||||||
|
libusb_free_device_list(devs, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Exclude hubs from testing. Probably more classes could be excluded here!*/
|
||||||
|
if (desc.bDeviceClass == LIBUSB_CLASS_HUB) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
libusb_device_handle *handle;
|
||||||
|
res = libusb_open(dev, &handle);
|
||||||
|
if (res != LIBUSB_SUCCESS) {
|
||||||
|
if (!access_problems) {
|
||||||
|
DEBUG_INFO("INFO: Open USB %04x:%04x class %2x failed\n",
|
||||||
|
desc.idVendor, desc.idProduct, desc.bDeviceClass);
|
||||||
|
access_problems = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res = libusb_get_string_descriptor_ascii(
|
||||||
|
handle, desc.iSerialNumber, (uint8_t*)serial,
|
||||||
|
sizeof(serial));
|
||||||
|
if (res <= 0) {
|
||||||
|
/* This can fail for many devices. Continue silent!*/
|
||||||
|
libusb_close(handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) {
|
||||||
|
libusb_close(handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res = libusb_get_string_descriptor_ascii(
|
||||||
|
handle, desc.iManufacturer, (uint8_t*)manufacturer,
|
||||||
|
sizeof(manufacturer));
|
||||||
|
if (res > 0) {
|
||||||
|
res = libusb_get_string_descriptor_ascii(
|
||||||
|
handle, desc.iProduct, (uint8_t*)product,
|
||||||
|
sizeof(product));
|
||||||
|
if (res <= 0) {
|
||||||
|
DEBUG_WARN( "WARN:"
|
||||||
|
"libusb_get_string_descriptor_ascii "
|
||||||
|
"for ident_string failed: %s\n",
|
||||||
|
libusb_strerror(res));
|
||||||
|
libusb_close(handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libusb_close(handle);
|
||||||
|
if (cl_opts->opt_ident_string) {
|
||||||
|
char *match_manu = NULL;
|
||||||
|
char *match_product = NULL;
|
||||||
|
match_manu = strstr(manufacturer, cl_opts->opt_ident_string);
|
||||||
|
match_product = strstr(product, cl_opts->opt_ident_string);
|
||||||
|
if (!match_manu && !match_product) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Either serial and/or ident_string match or are not given.
|
||||||
|
* Check type.*/
|
||||||
|
if (desc.idVendor == VENDOR_ID_BMP) {
|
||||||
|
if (desc.idProduct == PRODUCT_ID_BMP) {
|
||||||
|
type = BMP_TYPE_BMP;
|
||||||
|
} else if (desc.idProduct == PRODUCT_ID_BMP_BL) {
|
||||||
|
DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) {
|
||||||
|
type = BMP_TYPE_CMSIS_DAP;
|
||||||
|
} else if (desc.idVendor == VENDOR_ID_STLINK) {
|
||||||
|
if ((desc.idProduct == PRODUCT_ID_STLINKV2) ||
|
||||||
|
(desc.idProduct == PRODUCT_ID_STLINKV21) ||
|
||||||
|
(desc.idProduct == PRODUCT_ID_STLINKV21_MSD) ||
|
||||||
|
(desc.idProduct == PRODUCT_ID_STLINKV3) ||
|
||||||
|
(desc.idProduct == PRODUCT_ID_STLINKV3E)) {
|
||||||
|
type = BMP_TYPE_STLINKV2;
|
||||||
|
} else {
|
||||||
|
if (desc.idProduct == PRODUCT_ID_STLINKV1)
|
||||||
|
DEBUG_WARN( "INFO: STLINKV1 not supported\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (desc.idVendor == VENDOR_ID_SEGGER) {
|
||||||
|
type = BMP_TYPE_JLINK;
|
||||||
|
} else {
|
||||||
|
cable_desc_t *cable = &cable_desc[0];
|
||||||
|
for (; cable->name; cable++) {
|
||||||
|
bool found = false;
|
||||||
|
if ((cable->vendor != desc.idVendor) || (cable->product != desc.idProduct))
|
||||||
|
continue; /* VID/PID do not match*/
|
||||||
|
if (cl_opts->opt_cable) {
|
||||||
|
if (strcmp(cable->name, cl_opts->opt_cable))
|
||||||
|
continue; /* cable names do not match*/
|
||||||
|
else
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (cable->description) {
|
||||||
|
if (strcmp(cable->description, product))
|
||||||
|
continue; /* discriptions do not match*/
|
||||||
|
else
|
||||||
|
found = true;
|
||||||
|
} else { /* VID/PID fits, but no cl_opts->opt_cable and no description*/
|
||||||
|
if ((cable->vendor == 0x0403) && /* FTDI*/
|
||||||
|
((cable->product == 0x6010) || /* FT2232C/D/H*/
|
||||||
|
(cable->product == 0x6011) || /* FT4232H Quad HS USB-UART/FIFO IC */
|
||||||
|
(cable->product == 0x6014))) { /* FT232H Single HS USB-UART/FIFO IC */
|
||||||
|
ftdi_unknown = true;
|
||||||
|
continue; /* Cable name is needed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
active_cable = cable->name;
|
||||||
|
type = BMP_TYPE_LIBFTDI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!cable->name)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (report) {
|
||||||
|
DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers + 1,
|
||||||
|
serial,
|
||||||
|
manufacturer,product);
|
||||||
|
}
|
||||||
|
info->vid = desc.idVendor;
|
||||||
|
info->pid = desc.idProduct;
|
||||||
|
info->bmp_type = type;
|
||||||
|
strncpy(info->serial, serial, sizeof(info->serial));
|
||||||
|
strncpy(info->product, product, sizeof(info->product));
|
||||||
|
strncpy(info->manufacturer, manufacturer, sizeof(info->manufacturer));
|
||||||
|
if (cl_opts->opt_position &&
|
||||||
|
(cl_opts->opt_position == (found_debuggers + 1))) {
|
||||||
|
found_debuggers = 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
found_debuggers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((found_debuggers == 0) && ftdi_unknown)
|
||||||
|
DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c <cable>\" !\n");
|
||||||
|
if ((found_debuggers == 1) && !cl_opts->opt_cable && (type == BMP_TYPE_LIBFTDI))
|
||||||
|
cl_opts->opt_cable = active_cable;
|
||||||
|
if (!found_debuggers && cl_opts->opt_list_only)
|
||||||
|
DEBUG_WARN("No usable debugger found\n");
|
||||||
|
if ((found_debuggers > 1) ||
|
||||||
|
((found_debuggers == 1) && (cl_opts->opt_list_only))) {
|
||||||
|
if (!report) {
|
||||||
|
if (found_debuggers > 1)
|
||||||
|
DEBUG_WARN("%d debuggers found!\nSelect with -P <pos>, "
|
||||||
|
"-s <(partial)serial no.> "
|
||||||
|
"and/or -S <(partial)description>\n",
|
||||||
|
found_debuggers);
|
||||||
|
report = true;
|
||||||
|
goto rescan;
|
||||||
|
} else {
|
||||||
|
if (found_debuggers > 0)
|
||||||
|
access_problems = false;
|
||||||
|
found_debuggers = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found_debuggers && access_problems)
|
||||||
|
DEBUG_WARN(
|
||||||
|
"No debugger found. Please check access rights to USB devices!\n");
|
||||||
|
libusb_free_device_list(devs, 1);
|
||||||
|
return (found_debuggers == 1) ? 0 : -1;
|
||||||
|
}
|
||||||
|
static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans)
|
||||||
|
{
|
||||||
|
struct trans_ctx * const ctx = trans->user_data;
|
||||||
|
|
||||||
|
if (trans->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("on_trans_done: ");
|
||||||
|
if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) {
|
||||||
|
DEBUG_WARN(" Timeout\n");
|
||||||
|
} else if (trans->status == LIBUSB_TRANSFER_CANCELLED) {
|
||||||
|
DEBUG_WARN(" cancelled\n");
|
||||||
|
} else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) {
|
||||||
|
DEBUG_WARN(" no device\n");
|
||||||
|
} else {
|
||||||
|
DEBUG_WARN(" unknown\n");
|
||||||
|
}
|
||||||
|
ctx->flags |= TRANS_FLAGS_HAS_ERROR;
|
||||||
|
}
|
||||||
|
ctx->flags |= TRANS_FLAGS_IS_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) {
|
||||||
|
struct trans_ctx trans_ctx;
|
||||||
|
enum libusb_error error;
|
||||||
|
|
||||||
|
trans_ctx.flags = 0;
|
||||||
|
|
||||||
|
/* brief intrusion inside the libusb interface */
|
||||||
|
trans->callback = on_trans_done;
|
||||||
|
trans->user_data = &trans_ctx;
|
||||||
|
|
||||||
|
if ((error = libusb_submit_transfer(trans))) {
|
||||||
|
DEBUG_WARN("libusb_submit_transfer(%d): %s\n", error,
|
||||||
|
libusb_strerror(error));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t start_time = platform_time_ms();
|
||||||
|
while (trans_ctx.flags == 0) {
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) {
|
||||||
|
DEBUG_WARN("libusb_handle_events()\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
uint32_t now = platform_time_ms();
|
||||||
|
if (now - start_time > 1000) {
|
||||||
|
libusb_cancel_transfer(trans);
|
||||||
|
DEBUG_WARN("libusb_handle_events() timeout\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) {
|
||||||
|
DEBUG_WARN("libusb_handle_events() | has_error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* One USB transaction */
|
||||||
|
int send_recv(usb_link_t *link,
|
||||||
|
uint8_t *txbuf, size_t txsize,
|
||||||
|
uint8_t *rxbuf, size_t rxsize)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
if( txsize) {
|
||||||
|
int txlen = txsize;
|
||||||
|
libusb_fill_bulk_transfer(link->req_trans,
|
||||||
|
link->ul_libusb_device_handle,
|
||||||
|
link->ep_tx | LIBUSB_ENDPOINT_OUT,
|
||||||
|
txbuf, txlen,
|
||||||
|
NULL, NULL, 0);
|
||||||
|
int i = 0;
|
||||||
|
DEBUG_WIRE(" Send (%3d): ", txlen);
|
||||||
|
for (; i < txlen; i++) {
|
||||||
|
DEBUG_WIRE("%02x", txbuf[i]);
|
||||||
|
if ((i & 7) == 7)
|
||||||
|
DEBUG_WIRE(".");
|
||||||
|
if ((i & 31) == 31)
|
||||||
|
DEBUG_WIRE("\n ");
|
||||||
|
}
|
||||||
|
if (!(i & 31))
|
||||||
|
DEBUG_WIRE("\n");
|
||||||
|
if (submit_wait(link, link->req_trans)) {
|
||||||
|
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* send_only */
|
||||||
|
if (rxsize != 0) {
|
||||||
|
/* read the response */
|
||||||
|
libusb_fill_bulk_transfer(link->rep_trans, link->ul_libusb_device_handle,
|
||||||
|
link->ep_rx | LIBUSB_ENDPOINT_IN,
|
||||||
|
rxbuf, rxsize, NULL, NULL, 0);
|
||||||
|
|
||||||
|
if (submit_wait(link, link->rep_trans)) {
|
||||||
|
DEBUG_WARN("clear 1\n");
|
||||||
|
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
res = link->rep_trans->actual_length;
|
||||||
|
if (res >0) {
|
||||||
|
int i;
|
||||||
|
uint8_t *p = rxbuf;
|
||||||
|
DEBUG_WIRE(" Rec (%zu/%d)", rxsize, res);
|
||||||
|
for (i = 0; i < res && i < 32 ; i++) {
|
||||||
|
if ( i && ((i & 7) == 0))
|
||||||
|
DEBUG_WIRE(".");
|
||||||
|
DEBUG_WIRE("%02x", p[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_WIRE("\n");
|
||||||
|
return res;
|
||||||
|
}
|
|
@ -34,6 +34,7 @@
|
||||||
#include <hidapi.h>
|
#include <hidapi.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include "bmp_hosted.h"
|
||||||
#include "dap.h"
|
#include "dap.h"
|
||||||
#include "cmsis_dap.h"
|
#include "cmsis_dap.h"
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "ftdi_bmp.h"
|
#include "ftdi_bmp.h"
|
||||||
|
#include <libftdi1/ftdi.h>
|
||||||
|
|
||||||
struct ftdi_context *ftdic;
|
struct ftdi_context *ftdic;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "swdptap.h"
|
#include "swdptap.h"
|
||||||
#include "jtagtap.h"
|
#include "jtagtap.h"
|
||||||
|
|
||||||
|
#include "bmp_hosted.h"
|
||||||
|
#include <libftdi1/ftdi.h>
|
||||||
|
|
||||||
typedef struct data_desc_s {
|
typedef struct data_desc_s {
|
||||||
int16_t data_low;
|
int16_t data_low;
|
||||||
int16_t ddr_low;
|
int16_t ddr_low;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#if !defined(__JLINK_H_)
|
#if !defined(__JLINK_H_)
|
||||||
#define __JLINK_H_
|
#define __JLINK_H_
|
||||||
|
|
||||||
|
#include "bmp_hosted.h"
|
||||||
#include "jtagtap.h"
|
#include "jtagtap.h"
|
||||||
|
|
||||||
/** @cond PRIVATE */
|
/** @cond PRIVATE */
|
||||||
|
|
|
@ -25,11 +25,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <libftdi1/ftdi.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "ftdi_bmp.h"
|
||||||
|
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "ftdi_bmp.h"
|
|
||||||
|
|
||||||
extern cable_desc_t *active_cable;
|
extern cable_desc_t *active_cable;
|
||||||
extern struct ftdi_context *ftdic;
|
extern struct ftdi_context *ftdic;
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
|
#include <libftdi1/ftdi.h>
|
||||||
|
#include "platform.h"
|
||||||
#include "ftdi_bmp.h"
|
#include "ftdi_bmp.h"
|
||||||
|
|
||||||
enum swdio_status{
|
enum swdio_status{
|
||||||
|
|
|
@ -32,40 +32,28 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "bmp_remote.h"
|
#include "bmp_remote.h"
|
||||||
|
#include "bmp_hosted.h"
|
||||||
#include "stlinkv2.h"
|
#include "stlinkv2.h"
|
||||||
#include "ftdi_bmp.h"
|
#include "ftdi_bmp.h"
|
||||||
#include "jlink.h"
|
#include "jlink.h"
|
||||||
#include "cmsis_dap.h"
|
#include "cmsis_dap.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "cl_utils.h"
|
||||||
#define VENDOR_ID_STLINK 0x0483
|
|
||||||
#define PRODUCT_ID_STLINK_MASK 0xffe0
|
|
||||||
#define PRODUCT_ID_STLINK_GROUP 0x3740
|
|
||||||
#define PRODUCT_ID_STLINKV1 0x3744
|
|
||||||
#define PRODUCT_ID_STLINKV2 0x3748
|
|
||||||
#define PRODUCT_ID_STLINKV21 0x374b
|
|
||||||
#define PRODUCT_ID_STLINKV21_MSD 0x3752
|
|
||||||
#define PRODUCT_ID_STLINKV3 0x374f
|
|
||||||
#define PRODUCT_ID_STLINKV3E 0x374e
|
|
||||||
|
|
||||||
#define VENDOR_ID_SEGGER 0x1366
|
|
||||||
|
|
||||||
bmp_info_t info;
|
bmp_info_t info;
|
||||||
|
|
||||||
swd_proc_t swd_proc;
|
swd_proc_t swd_proc;
|
||||||
jtag_proc_t jtag_proc;
|
jtag_proc_t jtag_proc;
|
||||||
|
|
||||||
|
void gdb_ident(char *p, int count)
|
||||||
|
{
|
||||||
|
snprintf(p, count, "\n for %s (%s), %s\n", info.manufacturer, info.product,
|
||||||
|
info.version);
|
||||||
|
}
|
||||||
|
|
||||||
static void exit_function(void)
|
static void exit_function(void)
|
||||||
{
|
{
|
||||||
if(info.usb_link) {
|
libusb_exit_function(&info);
|
||||||
libusb_free_transfer(info.usb_link->req_trans);
|
|
||||||
libusb_free_transfer(info.usb_link->rep_trans);
|
|
||||||
if (info.usb_link->ul_libusb_device_handle) {
|
|
||||||
libusb_release_interface (
|
|
||||||
info.usb_link->ul_libusb_device_handle, 0);
|
|
||||||
libusb_close(info.usb_link->ul_libusb_device_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (info.bmp_type) {
|
switch (info.bmp_type) {
|
||||||
case BMP_TYPE_CMSIS_DAP:
|
case BMP_TYPE_CMSIS_DAP:
|
||||||
dap_exit_function();
|
dap_exit_function();
|
||||||
|
@ -83,195 +71,6 @@ static void sigterm_handler(int sig)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
|
|
||||||
{
|
|
||||||
libusb_device **devs;
|
|
||||||
int n_devs = libusb_get_device_list(info->libusb_ctx, &devs);
|
|
||||||
if (n_devs < 0) {
|
|
||||||
DEBUG_WARN( "WARN:libusb_get_device_list() failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
bool report = false;
|
|
||||||
int found_debuggers;
|
|
||||||
struct libusb_device_descriptor desc;
|
|
||||||
char serial[64];
|
|
||||||
char manufacturer[128];
|
|
||||||
char product[128];
|
|
||||||
bmp_type_t type = BMP_TYPE_NONE;
|
|
||||||
bool access_problems = false;
|
|
||||||
char *active_cable = NULL;
|
|
||||||
bool ftdi_unknown = false;
|
|
||||||
rescan:
|
|
||||||
found_debuggers = 0;
|
|
||||||
for (int i = 0; devs[i]; i++) {
|
|
||||||
libusb_device *dev = devs[i];
|
|
||||||
int res = libusb_get_device_descriptor(dev, &desc);
|
|
||||||
if (res < 0) {
|
|
||||||
DEBUG_WARN( "WARN: libusb_get_device_descriptor() failed: %s",
|
|
||||||
libusb_strerror(res));
|
|
||||||
libusb_free_device_list(devs, 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Exclude hubs from testing. Probably more classes could be excluded here!*/
|
|
||||||
if (desc.bDeviceClass == LIBUSB_CLASS_HUB) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
libusb_device_handle *handle;
|
|
||||||
res = libusb_open(dev, &handle);
|
|
||||||
if (res != LIBUSB_SUCCESS) {
|
|
||||||
if (!access_problems) {
|
|
||||||
DEBUG_INFO("INFO: Open USB %04x:%04x class %2x failed\n",
|
|
||||||
desc.idVendor, desc.idProduct, desc.bDeviceClass);
|
|
||||||
access_problems = true;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
res = libusb_get_string_descriptor_ascii(
|
|
||||||
handle, desc.iSerialNumber, (uint8_t*)serial,
|
|
||||||
sizeof(serial));
|
|
||||||
if (res <= 0) {
|
|
||||||
/* This can fail for many devices. Continue silent!*/
|
|
||||||
libusb_close(handle);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) {
|
|
||||||
libusb_close(handle);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
res = libusb_get_string_descriptor_ascii(
|
|
||||||
handle, desc.iManufacturer, (uint8_t*)manufacturer,
|
|
||||||
sizeof(manufacturer));
|
|
||||||
if (res > 0) {
|
|
||||||
res = libusb_get_string_descriptor_ascii(
|
|
||||||
handle, desc.iProduct, (uint8_t*)product,
|
|
||||||
sizeof(product));
|
|
||||||
if (res <= 0) {
|
|
||||||
DEBUG_WARN( "WARN:"
|
|
||||||
"libusb_get_string_descriptor_ascii "
|
|
||||||
"for ident_string failed: %s\n",
|
|
||||||
libusb_strerror(res));
|
|
||||||
libusb_close(handle);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
libusb_close(handle);
|
|
||||||
if (cl_opts->opt_ident_string) {
|
|
||||||
char *match_manu = NULL;
|
|
||||||
char *match_product = NULL;
|
|
||||||
match_manu = strstr(manufacturer, cl_opts->opt_ident_string);
|
|
||||||
match_product = strstr(product, cl_opts->opt_ident_string);
|
|
||||||
if (!match_manu && !match_product) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Either serial and/or ident_string match or are not given.
|
|
||||||
* Check type.*/
|
|
||||||
if (desc.idVendor == VENDOR_ID_BMP) {
|
|
||||||
if (desc.idProduct == PRODUCT_ID_BMP) {
|
|
||||||
type = BMP_TYPE_BMP;
|
|
||||||
} else if (desc.idProduct == PRODUCT_ID_BMP_BL) {
|
|
||||||
DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) {
|
|
||||||
type = BMP_TYPE_CMSIS_DAP;
|
|
||||||
} else if (desc.idVendor == VENDOR_ID_STLINK) {
|
|
||||||
if ((desc.idProduct == PRODUCT_ID_STLINKV2) ||
|
|
||||||
(desc.idProduct == PRODUCT_ID_STLINKV21) ||
|
|
||||||
(desc.idProduct == PRODUCT_ID_STLINKV21_MSD) ||
|
|
||||||
(desc.idProduct == PRODUCT_ID_STLINKV3) ||
|
|
||||||
(desc.idProduct == PRODUCT_ID_STLINKV3E)) {
|
|
||||||
type = BMP_TYPE_STLINKV2;
|
|
||||||
} else {
|
|
||||||
if (desc.idProduct == PRODUCT_ID_STLINKV1)
|
|
||||||
DEBUG_WARN( "INFO: STLINKV1 not supported\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (desc.idVendor == VENDOR_ID_SEGGER) {
|
|
||||||
type = BMP_TYPE_JLINK;
|
|
||||||
} else {
|
|
||||||
cable_desc_t *cable = &cable_desc[0];
|
|
||||||
for (; cable->name; cable++) {
|
|
||||||
bool found = false;
|
|
||||||
if ((cable->vendor != desc.idVendor) || (cable->product != desc.idProduct))
|
|
||||||
continue; /* VID/PID do not match*/
|
|
||||||
if (cl_opts->opt_cable) {
|
|
||||||
if (strcmp(cable->name, cl_opts->opt_cable))
|
|
||||||
continue; /* cable names do not match*/
|
|
||||||
else
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
if (cable->description) {
|
|
||||||
if (strcmp(cable->description, product))
|
|
||||||
continue; /* discriptions do not match*/
|
|
||||||
else
|
|
||||||
found = true;
|
|
||||||
} else { /* VID/PID fits, but no cl_opts->opt_cable and no description*/
|
|
||||||
if ((cable->vendor == 0x0403) && /* FTDI*/
|
|
||||||
((cable->product == 0x6010) || /* FT2232C/D/H*/
|
|
||||||
(cable->product == 0x6011) || /* FT4232H Quad HS USB-UART/FIFO IC */
|
|
||||||
(cable->product == 0x6014))) { /* FT232H Single HS USB-UART/FIFO IC */
|
|
||||||
ftdi_unknown = true;
|
|
||||||
continue; /* Cable name is needed */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found) {
|
|
||||||
active_cable = cable->name;
|
|
||||||
type = BMP_TYPE_LIBFTDI;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!cable->name)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (report) {
|
|
||||||
DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers + 1,
|
|
||||||
serial,
|
|
||||||
manufacturer,product);
|
|
||||||
}
|
|
||||||
info->vid = desc.idVendor;
|
|
||||||
info->pid = desc.idProduct;
|
|
||||||
info->bmp_type = type;
|
|
||||||
strncpy(info->serial, serial, sizeof(info->serial));
|
|
||||||
strncpy(info->product, product, sizeof(info->product));
|
|
||||||
strncpy(info->manufacturer, manufacturer, sizeof(info->manufacturer));
|
|
||||||
if (cl_opts->opt_position &&
|
|
||||||
(cl_opts->opt_position == (found_debuggers + 1))) {
|
|
||||||
found_debuggers = 1;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
found_debuggers++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((found_debuggers == 0) && ftdi_unknown)
|
|
||||||
DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c <cable>\" !\n");
|
|
||||||
if ((found_debuggers == 1) && !cl_opts->opt_cable && (type == BMP_TYPE_LIBFTDI))
|
|
||||||
cl_opts->opt_cable = active_cable;
|
|
||||||
if (!found_debuggers && cl_opts->opt_list_only)
|
|
||||||
DEBUG_WARN("No usable debugger found\n");
|
|
||||||
if ((found_debuggers > 1) ||
|
|
||||||
((found_debuggers == 1) && (cl_opts->opt_list_only))) {
|
|
||||||
if (!report) {
|
|
||||||
if (found_debuggers > 1)
|
|
||||||
DEBUG_WARN("%d debuggers found!\nSelect with -P <pos>, "
|
|
||||||
"-s <(partial)serial no.> "
|
|
||||||
"and/or -S <(partial)description>\n",
|
|
||||||
found_debuggers);
|
|
||||||
report = true;
|
|
||||||
goto rescan;
|
|
||||||
} else {
|
|
||||||
if (found_debuggers > 0)
|
|
||||||
access_problems = false;
|
|
||||||
found_debuggers = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found_debuggers && access_problems)
|
|
||||||
DEBUG_WARN(
|
|
||||||
"No debugger found. Please check access rights to USB devices!\n");
|
|
||||||
libusb_free_device_list(devs, 1);
|
|
||||||
return (found_debuggers == 1) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BMP_CL_OPTIONS_t cl_opts;
|
static BMP_CL_OPTIONS_t cl_opts;
|
||||||
|
|
||||||
void platform_init(int argc, char **argv)
|
void platform_init(int argc, char **argv)
|
||||||
|
@ -281,25 +80,8 @@ void platform_init(int argc, char **argv)
|
||||||
atexit(exit_function);
|
atexit(exit_function);
|
||||||
signal(SIGTERM, sigterm_handler);
|
signal(SIGTERM, sigterm_handler);
|
||||||
signal(SIGINT, sigterm_handler);
|
signal(SIGINT, sigterm_handler);
|
||||||
int res = libusb_init(&info.libusb_ctx);
|
|
||||||
if (res) {
|
|
||||||
DEBUG_WARN( "Fatal: Failed to get USB context: %s\n",
|
|
||||||
libusb_strerror(res));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
if (cl_opts.opt_device) {
|
if (cl_opts.opt_device) {
|
||||||
info.bmp_type = BMP_TYPE_BMP;
|
info.bmp_type = BMP_TYPE_BMP;
|
||||||
} else if (cl_opts.opt_cable) {
|
|
||||||
if ((!strcmp(cl_opts.opt_cable, "list")) ||
|
|
||||||
(!strcmp(cl_opts.opt_cable, "l"))) {
|
|
||||||
cable_desc_t *cable = &cable_desc[0];
|
|
||||||
DEBUG_WARN("Available cables:\n");
|
|
||||||
for (; cable->name; cable++) {
|
|
||||||
DEBUG_WARN("\t%s\n", cable->name);
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
info.bmp_type = BMP_TYPE_LIBFTDI;
|
|
||||||
} else if (find_debuggers(&cl_opts, &info)) {
|
} else if (find_debuggers(&cl_opts, &info)) {
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
#ifndef __PLATFORM_H
|
#ifndef __PLATFORM_H
|
||||||
#define __PLATFORM_H
|
#define __PLATFORM_H
|
||||||
|
|
||||||
#include <libusb-1.0/libusb.h>
|
|
||||||
#include "libusb_utils.h"
|
|
||||||
#include <libftdi1/ftdi.h>
|
|
||||||
|
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
|
|
||||||
char *platform_ident(void);
|
char *platform_ident(void);
|
||||||
|
@ -27,19 +23,5 @@ typedef enum bmp_type_s {
|
||||||
BMP_TYPE_JLINK
|
BMP_TYPE_JLINK
|
||||||
} bmp_type_t;
|
} bmp_type_t;
|
||||||
|
|
||||||
typedef struct bmp_info_s {
|
void gdb_ident(char *p, int count);
|
||||||
bmp_type_t bmp_type;
|
|
||||||
libusb_context *libusb_ctx;
|
|
||||||
struct ftdi_context *ftdic;
|
|
||||||
usb_link_t *usb_link;
|
|
||||||
unsigned int vid;
|
|
||||||
unsigned int pid;
|
|
||||||
char dev;
|
|
||||||
char serial[64];
|
|
||||||
char manufacturer[128];
|
|
||||||
char product[128];
|
|
||||||
} bmp_info_t;
|
|
||||||
|
|
||||||
extern bmp_info_t info;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "gdb_if.h"
|
#include "gdb_if.h"
|
||||||
#include "adiv5.h"
|
#include "adiv5.h"
|
||||||
|
#include "bmp_hosted.h"
|
||||||
#include "stlinkv2.h"
|
#include "stlinkv2.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "jtag_devs.h"
|
#include "jtag_devs.h"
|
||||||
|
|
|
@ -1,138 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of the Black Magic Debug project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
|
|
||||||
*
|
|
||||||
* 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 3 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include "general.h"
|
|
||||||
#include "cl_utils.h"
|
|
||||||
|
|
||||||
static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans)
|
|
||||||
{
|
|
||||||
struct trans_ctx * const ctx = trans->user_data;
|
|
||||||
|
|
||||||
if (trans->status != LIBUSB_TRANSFER_COMPLETED)
|
|
||||||
{
|
|
||||||
DEBUG_WARN("on_trans_done: ");
|
|
||||||
if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) {
|
|
||||||
DEBUG_WARN(" Timeout\n");
|
|
||||||
} else if (trans->status == LIBUSB_TRANSFER_CANCELLED) {
|
|
||||||
DEBUG_WARN(" cancelled\n");
|
|
||||||
} else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) {
|
|
||||||
DEBUG_WARN(" no device\n");
|
|
||||||
} else {
|
|
||||||
DEBUG_WARN(" unknown\n");
|
|
||||||
}
|
|
||||||
ctx->flags |= TRANS_FLAGS_HAS_ERROR;
|
|
||||||
}
|
|
||||||
ctx->flags |= TRANS_FLAGS_IS_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) {
|
|
||||||
struct trans_ctx trans_ctx;
|
|
||||||
enum libusb_error error;
|
|
||||||
|
|
||||||
trans_ctx.flags = 0;
|
|
||||||
|
|
||||||
/* brief intrusion inside the libusb interface */
|
|
||||||
trans->callback = on_trans_done;
|
|
||||||
trans->user_data = &trans_ctx;
|
|
||||||
|
|
||||||
if ((error = libusb_submit_transfer(trans))) {
|
|
||||||
DEBUG_WARN("libusb_submit_transfer(%d): %s\n", error,
|
|
||||||
libusb_strerror(error));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t start_time = platform_time_ms();
|
|
||||||
while (trans_ctx.flags == 0) {
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec = 1;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) {
|
|
||||||
DEBUG_WARN("libusb_handle_events()\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uint32_t now = platform_time_ms();
|
|
||||||
if (now - start_time > 1000) {
|
|
||||||
libusb_cancel_transfer(trans);
|
|
||||||
DEBUG_WARN("libusb_handle_events() timeout\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) {
|
|
||||||
DEBUG_WARN("libusb_handle_events() | has_error\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One USB transaction */
|
|
||||||
int send_recv(usb_link_t *link,
|
|
||||||
uint8_t *txbuf, size_t txsize,
|
|
||||||
uint8_t *rxbuf, size_t rxsize)
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
if( txsize) {
|
|
||||||
int txlen = txsize;
|
|
||||||
libusb_fill_bulk_transfer(link->req_trans,
|
|
||||||
link->ul_libusb_device_handle,
|
|
||||||
link->ep_tx | LIBUSB_ENDPOINT_OUT,
|
|
||||||
txbuf, txlen,
|
|
||||||
NULL, NULL, 0);
|
|
||||||
int i = 0;
|
|
||||||
DEBUG_WIRE(" Send (%3d): ", txlen);
|
|
||||||
for (; i < txlen; i++) {
|
|
||||||
DEBUG_WIRE("%02x", txbuf[i]);
|
|
||||||
if ((i & 7) == 7)
|
|
||||||
DEBUG_WIRE(".");
|
|
||||||
if ((i & 31) == 31)
|
|
||||||
DEBUG_WIRE("\n ");
|
|
||||||
}
|
|
||||||
if (!(i & 31))
|
|
||||||
DEBUG_WIRE("\n");
|
|
||||||
if (submit_wait(link, link->req_trans)) {
|
|
||||||
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* send_only */
|
|
||||||
if (rxsize != 0) {
|
|
||||||
/* read the response */
|
|
||||||
libusb_fill_bulk_transfer(link->rep_trans, link->ul_libusb_device_handle,
|
|
||||||
link->ep_rx | LIBUSB_ENDPOINT_IN,
|
|
||||||
rxbuf, rxsize, NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (submit_wait(link, link->rep_trans)) {
|
|
||||||
DEBUG_WARN("clear 1\n");
|
|
||||||
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
res = link->rep_trans->actual_length;
|
|
||||||
if (res >0) {
|
|
||||||
int i;
|
|
||||||
uint8_t *p = rxbuf;
|
|
||||||
DEBUG_WIRE(" Rec (%zu/%d)", rxsize, res);
|
|
||||||
for (i = 0; i < res && i < 32 ; i++) {
|
|
||||||
if ( i && ((i & 7) == 0))
|
|
||||||
DEBUG_WIRE(".");
|
|
||||||
DEBUG_WIRE("%02x", p[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DEBUG_WIRE("\n");
|
|
||||||
return res;
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of the Black Magic Debug project.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
|
|
||||||
*
|
|
||||||
* 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 3 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#if !defined(__LIBUSB_UTILS_H)
|
|
||||||
#define __LIBUSB_UTILS_H
|
|
||||||
#include <libusb-1.0/libusb.h>
|
|
||||||
|
|
||||||
struct trans_ctx {
|
|
||||||
#define TRANS_FLAGS_IS_DONE (1 << 0)
|
|
||||||
#define TRANS_FLAGS_HAS_ERROR (1 << 1)
|
|
||||||
volatile unsigned long flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
libusb_context *ul_libusb_ctx;
|
|
||||||
libusb_device_handle *ul_libusb_device_handle;
|
|
||||||
unsigned char ep_tx;
|
|
||||||
unsigned char ep_rx;
|
|
||||||
struct libusb_transfer* req_trans;
|
|
||||||
struct libusb_transfer* rep_trans;
|
|
||||||
void *priv;
|
|
||||||
} usb_link_t;
|
|
||||||
|
|
||||||
int send_recv(usb_link_t *link, uint8_t *txbuf, size_t txsize,
|
|
||||||
uint8_t *rxbuf, size_t rxsize);
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue