Support hla_serial command for ST-LINK adapters.
The hla_serial command allows for a programming device serial number to be specified in addition to USB VID/PID. This allows for multiple ST-LINK/V2 programmers to be attached to a single machine and operated using openocd. Change-Id: I350654bf676eb26ba3a90450acfa55d2a5d2d791 Signed-off-by: Austin Phillips <austin_phillips@hotmail.com> Reviewed-on: http://openocd.zylin.com/2198 Tested-by: jenkins Reviewed-by: Martin Glunz <mg@wunderkis.de> Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
parent
3a4ec66b24
commit
7568a91c8e
|
@ -3079,13 +3079,17 @@ This type of adapter does not expose some of the lower level api's
|
||||||
that OpenOCD would normally use to access the target.
|
that OpenOCD would normally use to access the target.
|
||||||
|
|
||||||
Currently supported adapters include the ST STLINK and TI ICDI.
|
Currently supported adapters include the ST STLINK and TI ICDI.
|
||||||
|
STLINK firmware version >= V2.J21.S4 recommended due to issues with earlier
|
||||||
|
versions of firmware where serial number is reset after first use. Suggest
|
||||||
|
using ST firmware update utility to upgrade STLINK firmware even if current
|
||||||
|
version reported is V2.J21.S4.
|
||||||
|
|
||||||
@deffn {Config Command} {hla_device_desc} description
|
@deffn {Config Command} {hla_device_desc} description
|
||||||
Currently Not Supported.
|
Currently Not Supported.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Config Command} {hla_serial} serial
|
@deffn {Config Command} {hla_serial} serial
|
||||||
Currently Not Supported.
|
Specifies the serial number of the adapter.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Config Command} {hla_layout} (@option{stlink}|@option{icdi})
|
@deffn {Config Command} {hla_layout} (@option{stlink}|@option{icdi})
|
||||||
|
|
|
@ -2099,7 +2099,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
|
||||||
const uint16_t pids[] = { param->pid, 0 };
|
const uint16_t pids[] = { param->pid, 0 };
|
||||||
struct jtag_libusb_device_handle *devh;
|
struct jtag_libusb_device_handle *devh;
|
||||||
|
|
||||||
if (jtag_libusb_open(vids, pids, &devh) != ERROR_OK)
|
if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
/* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
|
/* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
|
||||||
|
@ -2123,7 +2123,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
|
||||||
/* reopen jlink after usb_reset
|
/* reopen jlink after usb_reset
|
||||||
* on win32 this may take a second or two to re-enumerate */
|
* on win32 this may take a second or two to re-enumerate */
|
||||||
int retval;
|
int retval;
|
||||||
while ((retval = jtag_libusb_open(vids, pids, &devh)) != ERROR_OK) {
|
while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
timeout--;
|
timeout--;
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
|
|
|
@ -1699,7 +1699,7 @@ static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *ds
|
||||||
static struct jlink *jlink_usb_open()
|
static struct jlink *jlink_usb_open()
|
||||||
{
|
{
|
||||||
struct jtag_libusb_device_handle *devh;
|
struct jtag_libusb_device_handle *devh;
|
||||||
if (jtag_libusb_open(vids, pids, &devh) != ERROR_OK)
|
if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
|
/* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
|
||||||
|
@ -1723,7 +1723,7 @@ static struct jlink *jlink_usb_open()
|
||||||
/* reopen jlink after usb_reset
|
/* reopen jlink after usb_reset
|
||||||
* on win32 this may take a second or two to re-enumerate */
|
* on win32 this may take a second or two to re-enumerate */
|
||||||
int retval;
|
int retval;
|
||||||
while ((retval = jtag_libusb_open(vids, pids, &devh)) != ERROR_OK) {
|
while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
timeout--;
|
timeout--;
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
|
|
|
@ -37,9 +37,40 @@ static bool jtag_libusb_match(struct jtag_libusb_device *dev,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns true if the string descriptor indexed by str_index in device matches string */
|
||||||
|
static bool string_descriptor_equal(usb_dev_handle *device, uint8_t str_index,
|
||||||
|
const char *string)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
bool matched;
|
||||||
|
char desc_string[256+1]; /* Max size of string descriptor */
|
||||||
|
|
||||||
|
if (str_index == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
retval = usb_get_string_simple(device, str_index,
|
||||||
|
desc_string, sizeof(desc_string)-1);
|
||||||
|
if (retval < 0) {
|
||||||
|
LOG_ERROR("usb_get_string_simple() failed with %d", retval);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Null terminate descriptor string in case it needs to be logged. */
|
||||||
|
desc_string[sizeof(desc_string)-1] = '\0';
|
||||||
|
|
||||||
|
matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
|
||||||
|
if (!matched)
|
||||||
|
LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
|
||||||
|
desc_string, string);
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
|
const char *serial,
|
||||||
struct jtag_libusb_device_handle **out)
|
struct jtag_libusb_device_handle **out)
|
||||||
{
|
{
|
||||||
|
int retval = -ENODEV;
|
||||||
|
struct jtag_libusb_device_handle *libusb_handle;
|
||||||
usb_init();
|
usb_init();
|
||||||
|
|
||||||
usb_find_busses();
|
usb_find_busses();
|
||||||
|
@ -52,13 +83,24 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
if (!jtag_libusb_match(dev, vids, pids))
|
if (!jtag_libusb_match(dev, vids, pids))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
*out = usb_open(dev);
|
libusb_handle = usb_open(dev);
|
||||||
if (NULL == *out)
|
if (NULL == libusb_handle) {
|
||||||
return -errno;
|
retval = -errno;
|
||||||
return 0;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Device must be open to use libusb_get_string_descriptor_ascii. */
|
||||||
|
if (serial != NULL &&
|
||||||
|
!string_descriptor_equal(libusb_handle, dev->descriptor.iSerialNumber, serial)) {
|
||||||
|
usb_close(libusb_handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*out = libusb_handle;
|
||||||
|
retval = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -ENODEV;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void jtag_libusb_close(jtag_libusb_device_handle *dev)
|
void jtag_libusb_close(jtag_libusb_device_handle *dev)
|
||||||
|
|
|
@ -54,6 +54,7 @@ static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
|
||||||
}
|
}
|
||||||
|
|
||||||
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
|
const char *serial,
|
||||||
struct jtag_libusb_device_handle **out);
|
struct jtag_libusb_device_handle **out);
|
||||||
void jtag_libusb_close(jtag_libusb_device_handle *dev);
|
void jtag_libusb_close(jtag_libusb_device_handle *dev);
|
||||||
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
|
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
|
||||||
|
|
|
@ -28,25 +28,53 @@
|
||||||
static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
|
static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
|
||||||
static libusb_device **devs; /**< The usb device list **/
|
static libusb_device **devs; /**< The usb device list **/
|
||||||
|
|
||||||
static bool jtag_libusb_match(struct jtag_libusb_device *dev,
|
static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
|
||||||
const uint16_t vids[], const uint16_t pids[])
|
const uint16_t vids[], const uint16_t pids[])
|
||||||
{
|
{
|
||||||
struct libusb_device_descriptor dev_desc;
|
|
||||||
|
|
||||||
for (unsigned i = 0; vids[i]; i++) {
|
for (unsigned i = 0; vids[i]; i++) {
|
||||||
if (libusb_get_device_descriptor(dev, &dev_desc) == 0) {
|
if (dev_desc->idVendor == vids[i] &&
|
||||||
if (dev_desc.idVendor == vids[i] &&
|
dev_desc->idProduct == pids[i]) {
|
||||||
dev_desc.idProduct == pids[i])
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns true if the string descriptor indexed by str_index in device matches string */
|
||||||
|
static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index,
|
||||||
|
const char *string)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
bool matched;
|
||||||
|
char desc_string[256+1]; /* Max size of string descriptor */
|
||||||
|
|
||||||
|
if (str_index == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
retval = libusb_get_string_descriptor_ascii(device, str_index,
|
||||||
|
(unsigned char *)desc_string, sizeof(desc_string)-1);
|
||||||
|
if (retval < 0) {
|
||||||
|
LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Null terminate descriptor string in case it needs to be logged. */
|
||||||
|
desc_string[sizeof(desc_string)-1] = '\0';
|
||||||
|
|
||||||
|
matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
|
||||||
|
if (!matched)
|
||||||
|
LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
|
||||||
|
desc_string, string);
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
|
const char *serial,
|
||||||
struct jtag_libusb_device_handle **out)
|
struct jtag_libusb_device_handle **out)
|
||||||
{
|
{
|
||||||
int cnt, idx, errCode;
|
int cnt, idx, errCode;
|
||||||
|
int retval = -ENODEV;
|
||||||
|
struct jtag_libusb_device_handle *libusb_handle = NULL;
|
||||||
|
|
||||||
if (libusb_init(&jtag_libusb_context) < 0)
|
if (libusb_init(&jtag_libusb_context) < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -54,22 +82,37 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
cnt = libusb_get_device_list(jtag_libusb_context, &devs);
|
cnt = libusb_get_device_list(jtag_libusb_context, &devs);
|
||||||
|
|
||||||
for (idx = 0; idx < cnt; idx++) {
|
for (idx = 0; idx < cnt; idx++) {
|
||||||
if (!jtag_libusb_match(devs[idx], vids, pids))
|
struct libusb_device_descriptor dev_desc;
|
||||||
|
|
||||||
|
if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
errCode = libusb_open(devs[idx], out);
|
if (!jtag_libusb_match(&dev_desc, vids, pids))
|
||||||
|
continue;
|
||||||
|
|
||||||
/** Free the device list **/
|
errCode = libusb_open(devs[idx], &libusb_handle);
|
||||||
libusb_free_device_list(devs, 1);
|
|
||||||
|
|
||||||
if (errCode) {
|
if (errCode) {
|
||||||
LOG_ERROR("libusb_open() failed with %s",
|
LOG_ERROR("libusb_open() failed with %s",
|
||||||
libusb_error_name(errCode));
|
libusb_error_name(errCode));
|
||||||
return errCode;
|
continue;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
/* Device must be open to use libusb_get_string_descriptor_ascii. */
|
||||||
|
if (serial != NULL &&
|
||||||
|
!string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) {
|
||||||
|
libusb_close(libusb_handle);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return -ENODEV;
|
|
||||||
|
/* Success. */
|
||||||
|
*out = libusb_handle;
|
||||||
|
retval = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cnt >= 0)
|
||||||
|
libusb_free_device_list(devs, 1);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void jtag_libusb_close(jtag_libusb_device_handle *dev)
|
void jtag_libusb_close(jtag_libusb_device_handle *dev)
|
||||||
|
|
|
@ -48,6 +48,7 @@ static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
|
||||||
}
|
}
|
||||||
|
|
||||||
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
|
const char *serial,
|
||||||
struct jtag_libusb_device_handle **out);
|
struct jtag_libusb_device_handle **out);
|
||||||
void jtag_libusb_close(jtag_libusb_device_handle *dev);
|
void jtag_libusb_close(jtag_libusb_device_handle *dev);
|
||||||
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
|
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
|
||||||
|
|
|
@ -709,7 +709,7 @@ struct opendous_jtag *opendous_usb_open(void)
|
||||||
struct opendous_jtag *result;
|
struct opendous_jtag *result;
|
||||||
|
|
||||||
struct jtag_libusb_device_handle *devh;
|
struct jtag_libusb_device_handle *devh;
|
||||||
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, &devh) != ERROR_OK)
|
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh) != ERROR_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
jtag_libusb_set_configuration(devh, 0);
|
jtag_libusb_set_configuration(devh, 0);
|
||||||
|
|
|
@ -375,7 +375,7 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
|
||||||
static int osbdm_open(struct osbdm *osbdm)
|
static int osbdm_open(struct osbdm *osbdm)
|
||||||
{
|
{
|
||||||
(void)memset(osbdm, 0, sizeof(*osbdm));
|
(void)memset(osbdm, 0, sizeof(*osbdm));
|
||||||
if (jtag_libusb_open(osbdm_vid, osbdm_pid, &osbdm->devh) != ERROR_OK)
|
if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
|
if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
|
||||||
|
|
|
@ -1600,9 +1600,11 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
|
||||||
|
|
||||||
const uint16_t vids[] = { param->vid, 0 };
|
const uint16_t vids[] = { param->vid, 0 };
|
||||||
const uint16_t pids[] = { param->pid, 0 };
|
const uint16_t pids[] = { param->pid, 0 };
|
||||||
|
const char *serial = param->serial;
|
||||||
|
|
||||||
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport,
|
LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
|
||||||
param->vid, param->pid);
|
param->transport, param->vid, param->pid,
|
||||||
|
param->serial ? param->serial : "");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
On certain host USB configurations(e.g. MacBook Air)
|
On certain host USB configurations(e.g. MacBook Air)
|
||||||
|
@ -1614,7 +1616,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
|
||||||
in order to become operational.
|
in order to become operational.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
if (jtag_libusb_open(vids, pids, &h->fd) != ERROR_OK) {
|
if (jtag_libusb_open(vids, pids, serial, &h->fd) != ERROR_OK) {
|
||||||
LOG_ERROR("open failed");
|
LOG_ERROR("open failed");
|
||||||
goto error_open;
|
goto error_open;
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
|
||||||
bool renumeration = false;
|
bool renumeration = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (jtag_libusb_open(vids, pids, &temp) == ERROR_OK) {
|
if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) {
|
||||||
LOG_INFO("Altera USB-Blaster II (uninitialized) found");
|
LOG_INFO("Altera USB-Blaster II (uninitialized) found");
|
||||||
LOG_INFO("Loading firmware...");
|
LOG_INFO("Loading firmware...");
|
||||||
ret = load_usb_blaster_firmware(temp, low);
|
ret = load_usb_blaster_firmware(temp, low);
|
||||||
|
@ -200,13 +200,13 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
|
||||||
const uint16_t pids_renum[] = { low->ublast_pid, 0 };
|
const uint16_t pids_renum[] = { low->ublast_pid, 0 };
|
||||||
|
|
||||||
if (renumeration == false) {
|
if (renumeration == false) {
|
||||||
if (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev) != ERROR_OK) {
|
if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) {
|
||||||
LOG_ERROR("Altera USB-Blaster II not found");
|
LOG_ERROR("Altera USB-Blaster II not found");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int retry = 10;
|
int retry = 10;
|
||||||
while (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev) != ERROR_OK && retry--) {
|
while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) {
|
||||||
usleep(1000000);
|
usleep(1000000);
|
||||||
LOG_INFO("Waiting for renumerate...");
|
LOG_INFO("Waiting for renumerate...");
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,3 +7,10 @@ hla_layout stlink
|
||||||
hla_device_desc "ST-LINK/V2-1"
|
hla_device_desc "ST-LINK/V2-1"
|
||||||
hla_vid_pid 0x0483 0x374b
|
hla_vid_pid 0x0483 0x374b
|
||||||
|
|
||||||
|
# Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2
|
||||||
|
# devices seem to have serial numbers with unreadable characters. ST-LINK/V2
|
||||||
|
# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial
|
||||||
|
# number reset issues.
|
||||||
|
# eg.
|
||||||
|
#hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f"
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,10 @@ hla_layout stlink
|
||||||
hla_device_desc "ST-LINK/V2"
|
hla_device_desc "ST-LINK/V2"
|
||||||
hla_vid_pid 0x0483 0x3748
|
hla_vid_pid 0x0483 0x3748
|
||||||
|
|
||||||
|
# Optionally specify the serial number of ST-LINK/V2 usb device. ST-LINK/V2
|
||||||
|
# devices seem to have serial numbers with unreadable characters. ST-LINK/V2
|
||||||
|
# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial
|
||||||
|
# number reset issues.
|
||||||
|
# eg.
|
||||||
|
#hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue