Skip to content

Commit

Permalink
tools: Adds script to detect Espressif devkits connected to the host
Browse files Browse the repository at this point in the history
  • Loading branch information
gerekon committed Aug 20, 2024
1 parent 858373d commit 03c73b3
Show file tree
Hide file tree
Showing 13 changed files with 582 additions and 16 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ install(TARGETS openocd DESTINATION ${bindir})
install(DIRECTORY tcl/ DESTINATION ${pkgdatadir}/scripts)
install(FILES contrib/60-openocd.rules DESTINATION ${pkgdatadir}/contrib)
install(DIRECTORY contrib/libdcc DESTINATION ${pkgdatadir}/contrib)
install(FILES tools/esp_detect_config.py DESTINATION ${pkgdatadir}/tools)
get_property(ulink_firmware TARGET ocdjtagdrivers PROPERTY ULINK_FIRMWARE)
if(BUILD_JLINK)
install(FILES ${ulink_firmware} DESTINATION ${pkgdatadir}/OpenULINK)
Expand Down
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ nobase_dist_pkgdata_DATA = \
contrib/libdcc/README \
contrib/60-openocd.rules

esptoolsdir = $(pkgdatadir)/espressif/tools
dist_esptools_DATA = \
tools/esp_detect_config.py

SUBDIRS =
DIST_SUBDIRS =
bin_PROGRAMS =
Expand Down
12 changes: 12 additions & 0 deletions src/jtag/adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ static const struct gpio_map {
[ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
};

#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
static void adapter_usb_set_location(const char *location);
#endif

bool is_adapter_initialized(void)
{
return adapter_config.adapter_initialized;
Expand Down Expand Up @@ -146,6 +150,14 @@ int adapter_init(struct command_context *cmd_ctx)
return ERROR_JTAG_INIT_FAILED;
}

#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
char *loc = getenv("OPENOCD_USB_ADAPTER_LOCATION");
if (loc) {
LOG_INFO("use USB location specified via env var '%s'", loc);
adapter_usb_set_location(loc);
}
#endif

retval = adapter_driver->init();
if (retval != ERROR_OK)
return retval;
Expand Down
47 changes: 40 additions & 7 deletions src/jtag/drivers/esp_usb_jtag.c
Original file line number Diff line number Diff line change
Expand Up @@ -915,11 +915,37 @@ COMMAND_HANDLER(esp_usb_jtag_chip_id)
return ERROR_OK;
}

extern void libusb_list_devices(void);
COMMAND_HANDLER(esp_usb_jtag_get_location)
{
char dev_loc[128];

if (!priv->usb_device) {
command_print(CMD, "Can not get device location! No open device.");
return ERROR_FAIL;
}

if (jtag_libusb_get_dev_location_by_handle(priv->usb_device, dev_loc, sizeof(dev_loc)) != ERROR_OK) {
command_print(CMD, "Cannot get location for open usb device!");
return ERROR_FAIL;
}

command_print(CMD, "%s", dev_loc);
return ERROR_OK;
}

COMMAND_HANDLER(esp_usb_jtag_list)
COMMAND_HANDLER(esp_usb_jtag_dev_list)
{
libusb_list_devices();
const uint16_t vids[] = { esp_usb_vid, 0 }; /* must be null terminated */
const uint16_t pids[] = { esp_usb_pid, 0 }; /* must be null terminated */
int cnt, i;
char **locations;

cnt = jtag_libusb_get_devs_locations(vids, pids, &locations);
for (i = 0; i < cnt; i++)
command_print(CMD, "%s", locations[i]);

jtag_libusb_free_devs_locations(locations, cnt);

return ERROR_OK;
}

Expand Down Expand Up @@ -967,11 +993,18 @@ static const struct command_registration esp_usb_jtag_subcommands[] = {
.usage = "chip_id",
},
{
.name = "list",
.handler = &esp_usb_jtag_list,
.name = "list_devs",
.handler = &esp_usb_jtag_dev_list,
.mode = COMMAND_ANY,
.help = "list devices",
.usage = "list_devs",
},
{
.name = "get_location",
.handler = &esp_usb_jtag_get_location,
.mode = COMMAND_ANY,
.help = "list",
.usage = "list",
.help = "get device location",
.usage = "get_location",
},
COMMAND_REGISTRATION_DONE
};
Expand Down
49 changes: 49 additions & 0 deletions src/jtag/drivers/ftdi.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
/* FTDI access library includes */
#include "mpsse.h"

#include "libusb_helper.h"

#define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
#define JTAG_MODE_ALT (LSB_FIRST | NEG_EDGE_IN | NEG_EDGE_OUT)
#define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT)
Expand Down Expand Up @@ -918,6 +920,39 @@ COMMAND_HANDLER(ftdi_handle_tdo_sample_edge_command)
return ERROR_OK;
}

COMMAND_HANDLER(ftdi_handle_get_location)
{
char dev_loc[128];

struct libusb_device_handle *usb_dev = mpsse_get_usb_device(mpsse_ctx);
if (!usb_dev) {
command_print(CMD, "Can not get device location! No open device.");
return ERROR_FAIL;
}

if (jtag_libusb_get_dev_location_by_handle(usb_dev, dev_loc, sizeof(dev_loc)) != ERROR_OK) {
command_print(CMD, "Cannot get location for open usb device!");
return ERROR_FAIL;
}

command_print(CMD, "%s", dev_loc);
return ERROR_OK;
}

COMMAND_HANDLER(ftdi_handle_dev_list)
{
int cnt, i;
char **locations;

cnt = jtag_libusb_get_devs_locations(ftdi_vid, ftdi_pid, &locations);
for (i = 0; i < cnt; i++)
command_print(CMD, "%s", locations[i]);

jtag_libusb_free_devs_locations(locations, cnt);

return ERROR_OK;
}

static const struct command_registration ftdi_subcommand_handlers[] = {
{
.name = "device_desc",
Expand Down Expand Up @@ -979,6 +1014,20 @@ static const struct command_registration ftdi_subcommand_handlers[] = {
"allow signalling speed increase)",
.usage = "(rising|falling)",
},
{
.name = "list_devs",
.handler = &ftdi_handle_dev_list,
.mode = COMMAND_ANY,
.help = "list devices",
.usage = "list_devs",
},
{
.name = "get_location",
.handler = &ftdi_handle_get_location,
.mode = COMMAND_ANY,
.help = "get device location",
.usage = "get_location",
},
COMMAND_REGISTRATION_DONE
};

Expand Down
98 changes: 98 additions & 0 deletions src/jtag/drivers/libusb_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,104 @@ static bool jtag_libusb_match_serial(struct libusb_device_handle *device,
return match;
}

static int jtag_libusb_get_dev_location(struct libusb_device *dev, char *loc, int loc_len)
{
int k, len, wr;
uint8_t dev_bus = 0;
uint8_t port_path[MAX_USB_PORTS];
int path_len = 0;

#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
path_len = libusb_get_port_numbers(dev, port_path, MAX_USB_PORTS);
if (path_len == LIBUSB_ERROR_OVERFLOW) {
LOG_WARNING("cannot determine path to usb device! (more than %i ports in path)", MAX_USB_PORTS);
return ERROR_FAIL;
}
dev_bus = libusb_get_bus_number(dev);
#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */

len = snprintf(loc, loc_len, "%d", dev_bus);
if (len < 0 || len >= (loc_len - len)) {
*loc = 0;
return ERROR_FAIL;
}

for (k = 0; k < path_len; k++) {
wr = snprintf(&loc[len], loc_len - len, k == 0 ? "-%d" : ".%d", port_path[k]);
if (wr < 0 || wr >= (loc_len - len)) {
*loc = 0;
return ERROR_FAIL;
}
len += wr;
}
return ERROR_OK;
}

int jtag_libusb_get_dev_location_by_handle(struct libusb_device_handle *dev, char *loc, int loc_len)
{
return jtag_libusb_get_dev_location(libusb_get_device(dev), loc, loc_len);
}

int jtag_libusb_get_devs_locations(const uint16_t vids[], const uint16_t pids[], char ***locations)
{
int cnt, idx, devs_cnt = 0;
struct libusb_device **list;
struct libusb_device_descriptor desc;
char **locs;
/* <bus>-<port>[.<port>]... */
#define MAX_DEV_LOCATION_LEN 128

cnt = libusb_get_device_list(jtag_libusb_context, &list);
if (cnt <= 0) {
LOG_WARNING("Cannot get devices list (%d)!", cnt);
return 0;
}

locs = calloc(cnt, sizeof(char *));
if (!locs) {
LOG_ERROR("Unable to allocate space USB devices list!");
libusb_free_device_list(list, 1);
return 0;
}
for (idx = 0; idx < cnt; idx++) {
if (libusb_get_device_descriptor(list[idx], &desc) != 0)
continue;
if (!jtag_libusb_match_ids(&desc, vids, pids))
continue;

locs[devs_cnt] = calloc(1, MAX_DEV_LOCATION_LEN);
if (!locs[devs_cnt]) {
LOG_ERROR("Unable to allocate space USB device location!");
jtag_libusb_free_devs_locations(locs, devs_cnt);
libusb_free_device_list(list, true);
return 0;
}
if (jtag_libusb_get_dev_location(list[idx], locs[devs_cnt], MAX_DEV_LOCATION_LEN) != ERROR_OK)
LOG_WARNING("Cannot get location for usb device!");

devs_cnt++;
}
*locations = locs;

libusb_free_device_list(list, true);

return devs_cnt;
}

void jtag_libusb_free_devs_locations(char *locations[], int cnt)
{
int i;

if (!locations || cnt == 0)
return;

for (i = 0; i < cnt; i++) {
if (locations[i])
free(locations[i]);
}
free(locations);
}

int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *product, struct libusb_device_handle **out,
adapter_get_alternate_serial_fn adapter_get_alternate_serial)
Expand Down
5 changes: 5 additions & 0 deletions src/jtag/drivers/libusb_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,9 @@ uint8_t *oocd_libusb_dev_mem_alloc(libusb_device_handle *devh,
int oocd_libusb_dev_mem_free(libusb_device_handle *devh,
uint8_t *buffer, size_t length);

int jtag_libusb_get_dev_location_by_handle(struct libusb_device_handle *dev, char *loc, int loc_len);
int jtag_libusb_get_devs_locations(const uint16_t vids[], const uint16_t pids[], char ***locations);
void jtag_libusb_free_devs_locations(char *locations[], int cnt);


#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H */
5 changes: 5 additions & 0 deletions src/jtag/drivers/mpsse.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ bool mpsse_is_high_speed(struct mpsse_ctx *ctx)
return ctx->type != TYPE_FT2232C;
}

struct libusb_device_handle *mpsse_get_usb_device(struct mpsse_ctx *ctx)
{
return ctx->usb_dev;
}

void mpsse_purge(struct mpsse_ctx *ctx)
{
int err;
Expand Down
1 change: 1 addition & 0 deletions src/jtag/drivers/mpsse.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const cha
const char *serial, const char *location, int channel);
void mpsse_close(struct mpsse_ctx *ctx);
bool mpsse_is_high_speed(struct mpsse_ctx *ctx);
struct libusb_device_handle *mpsse_get_usb_device(struct mpsse_ctx *ctx);

/* Command queuing. These correspond to the MPSSE commands with the same names, but no need to care
* about bit/byte transfer or data length limitation. Read data is guaranteed to be available only
Expand Down
42 changes: 42 additions & 0 deletions tcl/esp-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
"$ref": "#/definitions/targetsInfo"
}
},
"interfaces": {
"description": "List of debug interfaces",
"type": "array",
"items": {
"$ref": "#/definitions/interfacesInfo"
}
},
"boards": {
"description": "List of boards",
"type": "array",
Expand Down Expand Up @@ -49,13 +56,39 @@
"name": {
"description": "Name of the target e.g. 'ESP32'",
"type": "string"
},
"idcode": {
"description": "JTAG IDCODE of the chip",
"type": "string"
},
"ocdid": {
"description": "OCDID of Xtensa chip",
"type": "string"
}
},
"required": [
"id",
"name"
]
},
"interfacesInfo": {
"type": "object",
"description": "Information about debug interface",
"properties": {
"id": {
"description": "Interface ID. Actually this is OpenOCD debug adapter driver name.",
"type": "string"
},
"config_file": {
"description": "Config file of debug interface e.g. 'ftdi/esp32_devkitj_v1.cfg'. Path relative to 'interface' sub-dir.",
"type": "string"
},
"command": {
"description": "Command for the debug interface driver, e.g. 'ftdi'",
"type": "string"
}
}
},
"boardsInfo": {
"type": "object",
"description": "Information about a board",
Expand All @@ -78,6 +111,15 @@
"items": {
"type": "string"
}
},
"interface": {
"description": "Interface ID. Actually this is OpenOCD debug adapter driver name.",
"type": "string",
"$ref": "#/definitions/interfacesInfo/properties/id"
},
"location": {
"description": "Location of the board, e.g. for USB it will look like 'usb://<bus>-<port>[.<port>]...'.",
"type": "string"
}
},
"required": [
Expand Down
Loading

0 comments on commit 03c73b3

Please sign in to comment.