Merge pull request #805 from UweBonnes/bmp_only
Provide a compile time option (HOSTED_BMP_ONLY=1) for easier compilation of hosted
This commit is contained in:
commit
3cec441833
|
@ -140,7 +140,9 @@ bool cmd_version(target *t, int argc, char **argv)
|
|||
(void)argv;
|
||||
gdb_out(BOARD_IDENT);
|
||||
#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
|
||||
gdb_outf(", Hardware Version %d\n", platform_hwversion());
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,14 @@ SYS = $(shell $(CC) -dumpmachine)
|
|||
CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG
|
||||
CFLAGS +=-I ./target -I./platforms/pc
|
||||
|
||||
# Define HOSTED_BMP_ONLY to '1' in order to build the hosted blackmagic
|
||||
# executable with support for native BMP probes only. This makes
|
||||
# linking against the libftdi and libusb libraries unnecessary. This can
|
||||
# be useful to minimize external dependencies, and make building on
|
||||
# windows systems easier.
|
||||
HOSTED_BMP_ONLY ?= 0
|
||||
CFLAGS += -DHOSTED_BMP_ONLY=$(HOSTED_BMP_ONLY)
|
||||
|
||||
ifneq (, $(findstring linux, $(SYS)))
|
||||
SRC += serial_unix.c
|
||||
ifeq ($(ASAN), 1)
|
||||
|
@ -9,10 +17,16 @@ CFLAGS += -fsanitize=address
|
|||
LDFLAGS += -lasan
|
||||
endif
|
||||
else ifneq (, $(findstring mingw, $(SYS)))
|
||||
# Build for windows versions Vista, and above, where the
|
||||
# 'SetupDiGetDevicePropertyW()' function is available
|
||||
CFLAGS += -D_WIN32_WINNT=0x600
|
||||
SRC += serial_win.c
|
||||
LDFLAGS += -lws2_32
|
||||
LDFLAGS += -lsetupapi
|
||||
else ifneq (, $(findstring cygwin, $(SYS)))
|
||||
# Build for windows versions Vista, and above, where the
|
||||
# 'SetupDiGetDevicePropertyW()' function is available
|
||||
CFLAGS += -D_WIN32_WINNT=0x600
|
||||
SRC += serial_win.c
|
||||
LDFLAGS += -lws2_32
|
||||
LDFLAGS += -lsetupapi
|
||||
|
@ -24,27 +38,32 @@ LDFLAGS += -framework CoreFoundation
|
|||
CFLAGS += -Ihidapi/hidapi
|
||||
endif
|
||||
|
||||
ifneq ($(HOSTED_BMP_ONLY), 1)
|
||||
LDFLAGS += -lusb-1.0
|
||||
CFLAGS += $(shell pkg-config --cflags libftdi1)
|
||||
LDFLAGS += $(shell pkg-config --libs libftdi1)
|
||||
CFLAGS += -Wno-missing-field-initializers
|
||||
endif
|
||||
|
||||
ifneq (, $(findstring mingw, $(SYS)))
|
||||
SRC += cmsis_dap.c dap.c hid.c
|
||||
CFLAGS += -DCMSIS_DAP
|
||||
else
|
||||
ifeq ($(shell pkg-config --exists hidapi-libusb && echo 0), 0)
|
||||
CFLAGS += $(shell pkg-config --cflags hidapi-libusb)
|
||||
LDFLAGS += $(shell pkg-config --libs hidapi-libusb)
|
||||
ifneq ($(HOSTED_BMP_ONLY), 1)
|
||||
CFLAGS += -DCMSIS_DAP
|
||||
SRC += cmsis_dap.c dap.c
|
||||
ifneq (, $(findstring mingw, $(SYS)))
|
||||
SRC += hid.c
|
||||
else
|
||||
CFLAGS += $(shell pkg-config --cflags hidapi-libusb)
|
||||
LDFLAGS += $(shell pkg-config --libs hidapi-libusb)
|
||||
endif
|
||||
endif
|
||||
|
||||
VPATH += platforms/pc
|
||||
SRC += timing.c cl_utils.c utils.c libusb_utils.c
|
||||
SRC += stlinkv2.c
|
||||
SRC += timing.c cl_utils.c utils.c
|
||||
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
|
||||
ifneq ($(HOSTED_BMP_ONLY), 1)
|
||||
SRC += bmp_libusb.c stlinkv2.c
|
||||
SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c
|
||||
SRC += jlink.c jlink_adiv5_swdp.c jlink_jtagtap.c
|
||||
else
|
||||
SRC += bmp_serial.c
|
||||
endif
|
||||
PC_HOSTED = 1
|
||||
|
|
|
@ -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,397 @@
|
|||
/*
|
||||
* 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"
|
||||
#include "version.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 bmp_ident(bmp_info_t *info)
|
||||
{
|
||||
DEBUG_INFO("BMP hosted %s\n for ST-Link V2/3, CMSIS_DAP, JLINK and "
|
||||
"LIBFTDI/MPSSE\n", FIRMWARE_VERSION);
|
||||
if (info && info->vid && info->pid)
|
||||
DEBUG_INFO("Using %04x:%04x %s %s\n %s\n", info->vid, info->pid,
|
||||
info->serial,
|
||||
info->manufacturer,
|
||||
info->product);
|
||||
}
|
||||
|
||||
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;
|
||||
bool access_problems = false;
|
||||
char *active_cable = NULL;
|
||||
bool ftdi_unknown = false;
|
||||
rescan:
|
||||
type = BMP_TYPE_NONE;
|
||||
found_debuggers = 0;
|
||||
serial[0] = 0;
|
||||
manufacturer[0] = 0;
|
||||
product[0] = 0;
|
||||
access_problems = false;
|
||||
active_cable = NULL;
|
||||
ftdi_unknown = false;
|
||||
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 (cl_opts->opt_serial && ((res <= 0) ||
|
||||
!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;
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* 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 serial connected debuggers */
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include "general.h"
|
||||
#include "platform.h"
|
||||
#include "bmp_hosted.h"
|
||||
#include "version.h"
|
||||
|
||||
void bmp_ident(bmp_info_t *info)
|
||||
{
|
||||
(void) info;
|
||||
DEBUG_INFO("BMP hosted (BMP Only) %s\n", FIRMWARE_VERSION);
|
||||
}
|
||||
|
||||
void libusb_exit_function(bmp_info_t *info) {(void)info;};
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
||||
{
|
||||
(void)cl_opts;
|
||||
(void)info;
|
||||
return -1;
|
||||
}
|
||||
#elif defined(__WIN32__) || defined(__CYGWIN__)
|
||||
|
||||
|
||||
/* This source has been used as an example:
|
||||
* https://stackoverflow.com/questions/3438366/setupdigetdeviceproperty-usage-example */
|
||||
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <cfgmgr32.h> // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpropdef.h */
|
||||
#ifdef DEFINE_DEVPROPKEY
|
||||
#undef DEFINE_DEVPROPKEY
|
||||
#endif
|
||||
#define DEFINE_DEVPROPKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) const DEVPROPKEY DECLSPEC_SELECTANY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
|
||||
|
||||
/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpkey.h */
|
||||
DEFINE_DEVPROPKEY(DEVPKEY_Device_BusReportedDeviceDesc, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 4); // DEVPROP_TYPE_STRING
|
||||
|
||||
/* List all USB devices with some additional information.
|
||||
* Unfortunately, this code is quite ugly. */
|
||||
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
||||
{
|
||||
unsigned i;
|
||||
DWORD dwSize;
|
||||
DEVPROPTYPE ulPropertyType;
|
||||
CONFIGRET status;
|
||||
HDEVINFO hDevInfo;
|
||||
SP_DEVINFO_DATA DeviceInfoData;
|
||||
TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN];
|
||||
WCHAR busReportedDeviceSesc[4096];
|
||||
int probes_found = 0;
|
||||
bool is_printing_probes_info = cl_opts->opt_list_only != 0;
|
||||
|
||||
info->bmp_type = BMP_TYPE_BMP;
|
||||
|
||||
hDevInfo = SetupDiGetClassDevs (0, "USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
print_probes_info:
|
||||
for (i = 0; ; i++) {
|
||||
char serial_number[sizeof info->serial];
|
||||
DeviceInfoData.cbSize = sizeof (DeviceInfoData);
|
||||
if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))
|
||||
break;
|
||||
|
||||
status = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID , MAX_PATH, 0);
|
||||
if (status != CR_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (!sscanf(szDeviceInstanceID, "USB\\VID_1D50&PID_6018\\%s", serial_number))
|
||||
continue;
|
||||
|
||||
if (SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,
|
||||
&ulPropertyType, (BYTE*)busReportedDeviceSesc, sizeof busReportedDeviceSesc, &dwSize, 0))
|
||||
{
|
||||
probes_found ++;
|
||||
if (is_printing_probes_info)
|
||||
{
|
||||
DEBUG_WARN("%2d: %s, %ls\n", probes_found,
|
||||
serial_number, busReportedDeviceSesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool probe_identified = true;
|
||||
if ((cl_opts->opt_serial && strstr(serial_number, cl_opts->opt_serial)) ||
|
||||
(cl_opts->opt_position && cl_opts->opt_position == probes_found) ||
|
||||
/* Special case for the very first probe found. */
|
||||
(probe_identified = false, probes_found == 1)) {
|
||||
|
||||
strncpy(info->serial, serial_number, sizeof info->serial);
|
||||
strncpy(info->manufacturer, "BMP", sizeof info->manufacturer);
|
||||
snprintf(info->product, sizeof info->product, "%ls", busReportedDeviceSesc);
|
||||
/* Don't bother to parse the version string. It is a part of the
|
||||
* product description string. It seems that at the moment it
|
||||
* is only being used to print a version string in response
|
||||
* to the 'monitor version' command, so it doesn't really matter
|
||||
* if the version string is printed as a part of the product string,
|
||||
* or as a separate string, the result is pretty much the same. */
|
||||
info->version[0] = 0;
|
||||
if (probe_identified)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_printing_probes_info)
|
||||
return 1;
|
||||
if (probes_found == 1)
|
||||
/* Exactly one probe found. Its information has already been filled
|
||||
* in the detection loop, so use this probe. */
|
||||
return 0;
|
||||
if (probes_found < 1) {
|
||||
DEBUG_WARN("No BMP probe found\n");
|
||||
return -1;
|
||||
}
|
||||
/* Otherwise, if this line is reached, then more than one probe has been found,
|
||||
* and no probe was identified as selected by the user.
|
||||
* Restart the identification loop, this time printing the probe information,
|
||||
* and then return. */
|
||||
DEBUG_WARN("%d debuggers found!\nSelect with -P <pos>, or "
|
||||
"-s <(partial)serial no.>\n",
|
||||
probes_found);
|
||||
probes_found = 0;
|
||||
is_printing_probes_info = true;
|
||||
goto print_probes_info;
|
||||
}
|
||||
|
||||
#else
|
||||
#define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe"
|
||||
#define DEVICE_BY_ID "/dev/serial/by-id/"
|
||||
|
||||
/*
|
||||
* Extract type, version and serial from /dev/serial/by_id
|
||||
* Return 0 on success
|
||||
*
|
||||
* Old versions have different strings. Try to cope!
|
||||
*/
|
||||
static int scan_linux_id(char *name, char *type, char *version, char *serial)
|
||||
{
|
||||
name += strlen(BMP_IDSTRING) + 1;
|
||||
while (*name == '_')
|
||||
name++;
|
||||
if (!*name) {
|
||||
DEBUG_WARN("Unexpected end\n");
|
||||
return -1;
|
||||
}
|
||||
char *p = strchr(name, '_');
|
||||
if (!p) {
|
||||
DEBUG_WARN("type not found\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(type, name, p - name);
|
||||
name = p;
|
||||
while (*name != 'v')
|
||||
name++;
|
||||
if (!*name) {
|
||||
DEBUG_WARN("Unexpected end after type\n");
|
||||
return -1;
|
||||
}
|
||||
p = strchr(name, '_');
|
||||
if (!p) {
|
||||
DEBUG_WARN("version not found\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(version, name, p - name);
|
||||
name = p;
|
||||
while (*name == '_')
|
||||
name++;
|
||||
if (!*name) {
|
||||
DEBUG_WARN("Unexpected end after version\n");
|
||||
return -1;
|
||||
}
|
||||
p = strchr(name, '-');
|
||||
if (!p) {
|
||||
DEBUG_WARN("Serial not found\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(serial, name, p - name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
||||
{
|
||||
char name[4096];
|
||||
if (cl_opts->opt_device)
|
||||
return 1;
|
||||
info->bmp_type = BMP_TYPE_BMP;
|
||||
DIR *dir = opendir(DEVICE_BY_ID);
|
||||
if (!dir) {
|
||||
DEBUG_WARN("Could not opendir %s: %s\n", name, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
int found_bmps = 0;
|
||||
struct dirent *dp;
|
||||
int i = 0;
|
||||
while ((dp = readdir(dir)) != NULL) {
|
||||
if ((strstr(dp->d_name, BMP_IDSTRING)) &&
|
||||
(strstr(dp->d_name, "-if00"))) {
|
||||
i++;
|
||||
char type[256], version[256], serial[256];
|
||||
if (scan_linux_id(dp->d_name, type, version, serial)) {
|
||||
DEBUG_WARN("Unexpected device name found \"%s\"\n",
|
||||
dp->d_name);
|
||||
}
|
||||
if ((cl_opts->opt_serial && strstr(serial, cl_opts->opt_serial)) ||
|
||||
(cl_opts->opt_position && cl_opts->opt_position == i)) {
|
||||
/* With serial number given and partial match, we are done!*/
|
||||
strncpy(info->serial, serial, sizeof(info->serial));
|
||||
strncpy(info->manufacturer, "BMP", sizeof(info->manufacturer));
|
||||
strncpy(info->product, type, sizeof(info->product));
|
||||
strncpy(info->version, version, sizeof(info->version));
|
||||
found_bmps = 1;
|
||||
break;
|
||||
} else {
|
||||
found_bmps++;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
if (found_bmps < 1) {
|
||||
DEBUG_WARN("No BMP probe found\n");
|
||||
return -1;
|
||||
} else if (found_bmps > 1) {
|
||||
DEBUG_INFO("Available Probes:\n");
|
||||
}
|
||||
dir = opendir(DEVICE_BY_ID);
|
||||
i = 0;
|
||||
while ((dp = readdir(dir)) != NULL) {
|
||||
if ((strstr(dp->d_name, BMP_IDSTRING)) &&
|
||||
(strstr(dp->d_name, "-if00"))) {
|
||||
i++;
|
||||
char type[256], version[256], serial[256];
|
||||
if (scan_linux_id(dp->d_name, type, version, serial)) {
|
||||
DEBUG_WARN("Unexpected device name found \"%s\"\n",
|
||||
dp->d_name);
|
||||
} else if (found_bmps == 1) {
|
||||
strncpy(info->serial, serial, sizeof(info->serial));
|
||||
found_bmps = 1;
|
||||
strncpy(info->serial, serial, sizeof(info->serial));
|
||||
strncpy(info->manufacturer, "BMP", sizeof(info->manufacturer));
|
||||
strncpy(info->product, type, sizeof(info->product));
|
||||
strncpy(info->version, version, sizeof(info->version));
|
||||
break;
|
||||
} else if (found_bmps > 1) {
|
||||
DEBUG_WARN("%2d: %s, Black Sphere Technologies, Black Magic "
|
||||
"Probe (%s), %s\n", i, serial, type, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return (found_bmps == 1) ? 0 : 1;
|
||||
}
|
||||
#endif
|
|
@ -34,6 +34,7 @@
|
|||
#include <hidapi.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "bmp_hosted.h"
|
||||
#include "dap.h"
|
||||
#include "cmsis_dap.h"
|
||||
|
||||
|
@ -55,18 +56,18 @@ int dap_init(bmp_info_t *info)
|
|||
if (hid_init())
|
||||
return -1;
|
||||
int size = strlen(info->serial);
|
||||
wchar_t serial[size + 1], *wc = serial;
|
||||
wchar_t serial[64] = {0}, *wc = serial;
|
||||
for (int i = 0; i < size; i++)
|
||||
*wc++ = info->serial[i];
|
||||
*wc = 0;
|
||||
/* Blacklist devices that do not wirk with 513 byte report length
|
||||
/* Blacklist devices that do not work with 513 byte report length
|
||||
* FIXME: Find a solution to decipher from the device.
|
||||
*/
|
||||
if ((info->vid == 0x1fc9) && (info->pid == 0x0132)) {
|
||||
DEBUG_WARN("Blacklist\n");
|
||||
report_size = 64 + 1;
|
||||
}
|
||||
handle = hid_open(info->vid, info->pid, serial);
|
||||
handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL);
|
||||
if (!handle)
|
||||
return -1;
|
||||
dap_disconnect();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <sys/time.h>
|
||||
|
||||
#include "ftdi_bmp.h"
|
||||
#include <libftdi1/ftdi.h>
|
||||
|
||||
struct ftdi_context *ftdic;
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include "swdptap.h"
|
||||
#include "jtagtap.h"
|
||||
|
||||
#include "bmp_hosted.h"
|
||||
#include <libftdi1/ftdi.h>
|
||||
|
||||
typedef struct data_desc_s {
|
||||
int16_t data_low;
|
||||
int16_t ddr_low;
|
||||
|
@ -103,8 +106,22 @@ extern cable_desc_t *active_cable;
|
|||
extern struct ftdi_context *ftdic;
|
||||
extern data_desc_t active_state;
|
||||
|
||||
#if HOSTED_BMP_ONLY == 1
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) {return -1;};
|
||||
int libftdi_swdptap_init(swd_proc_t *swd_proc) {return -1;};
|
||||
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc) {return 0;};
|
||||
void libftdi_buffer_flush(void) {};
|
||||
int libftdi_buffer_write(const uint8_t *data, int size) {return size;};
|
||||
int libftdi_buffer_read(uint8_t *data, int size) {return size;};
|
||||
const char *libftdi_target_voltage(void) {return "ERROR";};
|
||||
void libftdi_jtagtap_tdi_tdo_seq(
|
||||
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) {};
|
||||
bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd) {return false;};
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info);
|
||||
|
||||
int libftdi_swdptap_init(swd_proc_t *swd_proc);
|
||||
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc);
|
||||
void libftdi_buffer_flush(void);
|
||||
|
@ -114,6 +131,7 @@ const char *libftdi_target_voltage(void);
|
|||
void libftdi_jtagtap_tdi_tdo_seq(
|
||||
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
|
||||
bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd);
|
||||
#endif
|
||||
|
||||
#define MPSSE_SK 1
|
||||
#define PIN0 1
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#if !defined(__JLINK_H_)
|
||||
#define __JLINK_H_
|
||||
|
||||
#include "bmp_hosted.h"
|
||||
#include "jtagtap.h"
|
||||
|
||||
/** @cond PRIVATE */
|
||||
|
@ -43,7 +44,17 @@
|
|||
#define SELECT_IF_JTAG 0
|
||||
#define SELECT_IF_SWD 1
|
||||
|
||||
|
||||
#if HOSTED_BMP_ONLY == 1
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
int jlink_init(bmp_info_t *info) {return -1;};
|
||||
int jlink_swdp_scan(bmp_info_t *info) {return 0;};
|
||||
int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc) {return 0;};
|
||||
const char *jlink_target_voltage(bmp_info_t *info) {return "ERROR";};
|
||||
void jlink_srst_set_val(bmp_info_t *info, bool assert) {};
|
||||
bool jlink_srst_get_val(bmp_info_t *info) {return true;};
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
int jlink_init(bmp_info_t *info);
|
||||
int jlink_swdp_scan(bmp_info_t *info);
|
||||
int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc);
|
||||
|
@ -51,3 +62,4 @@ const char *jlink_target_voltage(bmp_info_t *info);
|
|||
void jlink_srst_set_val(bmp_info_t *info, bool assert);
|
||||
bool jlink_srst_get_val(bmp_info_t *info);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -25,11 +25,12 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <libftdi1/ftdi.h>
|
||||
#include "platform.h"
|
||||
#include "ftdi_bmp.h"
|
||||
|
||||
#include "general.h"
|
||||
#include "ftdi_bmp.h"
|
||||
|
||||
extern cable_desc_t *active_cable;
|
||||
extern struct ftdi_context *ftdic;
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include "general.h"
|
||||
#include <libftdi1/ftdi.h>
|
||||
#include "platform.h"
|
||||
#include "ftdi_bmp.h"
|
||||
|
||||
enum swdio_status{
|
||||
|
|
|
@ -32,40 +32,27 @@
|
|||
#include <signal.h>
|
||||
|
||||
#include "bmp_remote.h"
|
||||
#include "bmp_hosted.h"
|
||||
#include "stlinkv2.h"
|
||||
#include "ftdi_bmp.h"
|
||||
#include "jlink.h"
|
||||
#include "cmsis_dap.h"
|
||||
#include "version.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
|
||||
#include "cl_utils.h"
|
||||
|
||||
bmp_info_t info;
|
||||
|
||||
swd_proc_t swd_proc;
|
||||
jtag_proc_t jtag_proc;
|
||||
|
||||
void gdb_ident(char *p, int count)
|
||||
{
|
||||
snprintf(p, count, "%s (%s), %s", info.manufacturer, info.product,
|
||||
info.version);
|
||||
}
|
||||
|
||||
static void exit_function(void)
|
||||
{
|
||||
if(info.usb_link) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
libusb_exit_function(&info);
|
||||
switch (info.bmp_type) {
|
||||
case BMP_TYPE_CMSIS_DAP:
|
||||
dap_exit_function();
|
||||
|
@ -83,231 +70,20 @@ static void sigterm_handler(int sig)
|
|||
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;
|
||||
|
||||
void platform_init(int argc, char **argv)
|
||||
{
|
||||
cl_opts.opt_idstring = "Blackmagic PC-Hosted";
|
||||
cl_init(&cl_opts, argc, argv);
|
||||
atexit(exit_function);
|
||||
signal(SIGTERM, 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) {
|
||||
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)) {
|
||||
exit(-1);
|
||||
}
|
||||
DEBUG_INFO("BMP hosted %s\n for ST-Link V2/3, CMSIS_DAP, JLINK and "
|
||||
"LIBFTDI/MPSSE\n", FIRMWARE_VERSION);
|
||||
DEBUG_INFO("Using %04x:%04x %s %s\n %s\n", info.vid, info.pid, info.serial,
|
||||
info.manufacturer,
|
||||
info.product);
|
||||
bmp_ident(&info);
|
||||
switch (info.bmp_type) {
|
||||
case BMP_TYPE_BMP:
|
||||
if (serial_open(&cl_opts, info.serial))
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
#ifndef __PLATFORM_H
|
||||
#define __PLATFORM_H
|
||||
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#include "libusb_utils.h"
|
||||
#include <libftdi1/ftdi.h>
|
||||
|
||||
#include "timing.h"
|
||||
|
||||
char *platform_ident(void);
|
||||
|
@ -27,19 +23,5 @@ typedef enum bmp_type_s {
|
|||
BMP_TYPE_JLINK
|
||||
} bmp_type_t;
|
||||
|
||||
typedef struct bmp_info_s {
|
||||
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;
|
||||
|
||||
void gdb_ident(char *p, int count);
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "general.h"
|
||||
#include "gdb_if.h"
|
||||
#include "adiv5.h"
|
||||
#include "bmp_hosted.h"
|
||||
#include "stlinkv2.h"
|
||||
#include "exception.h"
|
||||
#include "jtag_devs.h"
|
||||
|
|
|
@ -24,16 +24,30 @@
|
|||
|
||||
#define STLINK_DEBUG_PORT_ACCESS 0xffff
|
||||
|
||||
#if HOSTED_BMP_ONLY == 1
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
int stlink_init(bmp_info_t *info) {return -1;};
|
||||
int stlink_hwversion(void) {return -1;};
|
||||
const char *stlink_target_voltage(bmp_info_t *info) {return "ERROR";};
|
||||
void stlink_srst_set_val(bmp_info_t *info, bool assert) {};
|
||||
bool stlink_srst_get_val(void) {return true;};
|
||||
int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp) {return -1;};
|
||||
void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp) {};
|
||||
int stlink_jtag_dp_init(ADIv5_DP_t *dp) {return false;};
|
||||
int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens) {return 0;};
|
||||
void stlink_exit_function(bmp_info_t *info) {};
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
int stlink_init(bmp_info_t *info);
|
||||
int stlink_hwversion(void);
|
||||
const char *stlink_target_voltage(bmp_info_t *info);
|
||||
void stlink_srst_set_val(bmp_info_t *info, bool assert);
|
||||
bool stlink_srst_get_val(void);
|
||||
int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp);
|
||||
|
||||
const char *stlink_target_voltage(bmp_info_t *info);
|
||||
void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp);
|
||||
int stlink_jtag_dp_init(ADIv5_DP_t *dp);
|
||||
int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens);
|
||||
void stlink_exit_function(bmp_info_t *info);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "target_internal.h"
|
||||
|
||||
#include "cl_utils.h"
|
||||
#include "bmp_hosted.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
|
@ -113,17 +114,20 @@ static void bmp_munmap(struct mmap_data *map)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
|
||||
static void cl_help(char **argv)
|
||||
{
|
||||
DEBUG_WARN("%s for: \n", opt->opt_idstring);
|
||||
DEBUG_WARN("\tBMP hosted %s\n\t\tfor ST-Link V2/3, CMSIS_DAP, JLINK and "
|
||||
"LIBFTDI/MPSSE\n\n", FIRMWARE_VERSION);
|
||||
bmp_ident(NULL);
|
||||
DEBUG_WARN("Usage: %s [options]\n", argv[0]);
|
||||
DEBUG_WARN("\t-h\t\t: This help.\n");
|
||||
DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n");
|
||||
DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n");
|
||||
DEBUG_WARN("Probe selection arguments:\n");
|
||||
DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at \"path\"(Deprecated)\n");
|
||||
DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at <path>");
|
||||
#if HOSTED_BMP_ONLY == 1 && defined(__APPLE__)
|
||||
DEBUG_WARN("\n");
|
||||
#else
|
||||
DEBUG_WARN(". Deprecated!\n");
|
||||
#endif
|
||||
DEBUG_WARN("\t-P <pos>\t: Use debugger found at position <pos>\n");
|
||||
DEBUG_WARN("\t-n <num>\t: Use target device found at position <num>\n");
|
||||
DEBUG_WARN("\t-s \"serial\"\t: Use dongle with (partial) "
|
||||
|
@ -166,7 +170,8 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||
opt->opt_cable = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
cl_help(argv, opt);
|
||||
cl_debuglevel = 3;
|
||||
cl_help(argv);
|
||||
break;
|
||||
case 'H':
|
||||
opt->opt_no_hl = true;
|
||||
|
@ -189,7 +194,6 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||
opt->external_resistor_swd = true;
|
||||
break;
|
||||
case 'd':
|
||||
DEBUG_WARN("Deprecated!\n");
|
||||
if (optarg)
|
||||
opt->opt_device = optarg;
|
||||
break;
|
||||
|
|
|
@ -54,7 +54,6 @@ typedef struct BMP_CL_OPTIONS_s {
|
|||
int opt_target_dev;
|
||||
uint32_t opt_flash_start;
|
||||
size_t opt_flash_size;
|
||||
char *opt_idstring;
|
||||
}BMP_CL_OPTIONS_t;
|
||||
|
||||
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
|
||||
|
|
|
@ -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
|
|
@ -67,7 +67,6 @@ static char *find_bmp_by_serial(const char *serial)
|
|||
|
||||
int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial)
|
||||
{
|
||||
(void) serial; /* FIXME: Does Windows allow open with USB serial no? */
|
||||
char device[256];
|
||||
if (!cl_opts->opt_device)
|
||||
cl_opts->opt_device = find_bmp_by_serial(serial);
|
||||
|
|
Loading…
Reference in New Issue