#endif
#include <jtag/interface.h>
+#include <jtag/swd.h>
#include <jtag/commands.h>
#include "libusb_common.h"
* pid = ( usb_address > 0x4) ? 0x0101 : (0x101 + usb_address)
*/
-#define VID 0x1366, 0x1366, 0x1366, 0x1366
-#define PID 0x0101, 0x0102, 0x0103, 0x0104
+#define JLINK_USB_INTERFACE_CLASS 0xff
+#define JLINK_USB_INTERFACE_SUBCLASS 0xff
+#define JLINK_USB_INTERFACE_PROTOCOL 0xff
-#define JLINK_WRITE_ENDPOINT 0x02
-#define JLINK_READ_ENDPOINT 0x81
-
-static unsigned int jlink_write_ep = JLINK_WRITE_ENDPOINT;
-static unsigned int jlink_read_ep = JLINK_READ_ENDPOINT;
+static unsigned int jlink_write_ep;
+static unsigned int jlink_read_ep;
static unsigned int jlink_hw_jtag_version = 2;
#define JLINK_USB_TIMEOUT 1000
/*#define JLINK_TAP_BUFFER_SIZE 256*/
/*#define JLINK_TAP_BUFFER_SIZE 384*/
-#define JLINK_IN_BUFFER_SIZE 2048
+#define JLINK_IN_BUFFER_SIZE (2048 + 1)
#define JLINK_OUT_BUFFER_SIZE (2*2048 + 4)
-#define JLINK_EMU_RESULT_BUFFER_SIZE 64
/* Global USB buffers */
static uint8_t usb_in_buffer[JLINK_IN_BUFFER_SIZE];
static uint8_t usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
-static uint8_t usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE];
/* Constants for JLink command */
#define EMU_CMD_VERSION 0x01
#define EMU_CMD_SET_SPEED 0x05
#define EMU_CMD_GET_STATE 0x07
#define EMU_CMD_SET_KS_POWER 0x08
+#define EMU_CMD_REGISTER 0x09
#define EMU_CMD_GET_SPEEDS 0xc0
#define EMU_CMD_GET_HW_INFO 0xc1
#define EMU_CMD_GET_COUNTERS 0xc2
#define EMU_CMD_WRITE_MEM_ARM79 0xf7
#define EMU_CMD_READ_MEM_ARM79 0xf8
+/* Register subcommands */
+#define REG_CMD_REGISTER 100
+#define REG_CMD_UNREGISTER 101
+
/* bits return from EMU_CMD_GET_CAPS */
#define EMU_CAP_RESERVED_1 0
#define EMU_CAP_GET_HW_VERSION 1
#define EMU_CAP_RAWTRACE 30
#define EMU_CAP_RESERVED_3 31
-static char *jlink_cap_str[] = {
+static const char * const jlink_cap_str[] = {
"Always 1.",
"Supports command EMU_CMD_GET_HARDWARE_VERSION",
"Supports command EMU_CMD_WRITE_DCC",
#define JLINK_MAX_SPEED 12000
/* J-Link hardware versions */
-#define JLINK_HW_TYPE_JLINK 0
-#define JLINK_HW_TYPE_JTRACE 1
-#define JLINK_HW_TYPE_FLASHER 2
-#define JLINK_HW_TYPE_JLINK_PRO 3
-#define JLINK_HW_TYPE_MAX 4
-
-static char *jlink_hw_type_str[] = {
- "J-Link",
- "J-Trace",
- "Flasher",
- "J-Link Pro",
-};
+#define JLINK_HW_TYPE_JLINK 0
+#define JLINK_HW_TYPE_JTRACE 1
+#define JLINK_HW_TYPE_FLASHER 2
+#define JLINK_HW_TYPE_JLINK_PRO 3
+#define JLINK_HW_TYPE_JLINK_LITE_ADI 5
+#define JLINK_HW_TYPE_LPCLINK2 18
+
+/* Interface selection */
+#define JLINK_TIF_JTAG 0
+#define JLINK_TIF_SWD 1
+#define JLINK_SWD_DIR_IN 0
+#define JLINK_SWD_DIR_OUT 1
/* Queue command functions */
static void jlink_end_state(tap_state_t state);
static void jlink_reset(int trst, int srst);
static void jlink_simple_command(uint8_t command);
static int jlink_get_status(void);
+static int jlink_swd_run_queue(struct adiv5_dap *dap);
+static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data);
+static int jlink_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq);
/* J-Link tap buffer functions */
static void jlink_tap_init(void);
static int jlink_usb_io(struct jlink *jlink, int out_length, int in_length);
static int jlink_usb_write(struct jlink *jlink, int out_length);
static int jlink_usb_read(struct jlink *jlink, int expected_size);
-static int jlink_usb_read_emu_result(struct jlink *jlink);
/* helper functions */
static int jlink_get_version_info(void);
static struct jlink *jlink_handle;
/* pid could be specified at runtime */
-static uint16_t vids[] = { VID, 0 };
-static uint16_t pids[] = { PID, 0 };
+static uint16_t vids[] = { 0x1366, 0x1366, 0x1366, 0x1366, 0x1366, 0 };
+static uint16_t pids[] = { 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0 };
+
+static char *jlink_serial;
static uint32_t jlink_caps;
static uint32_t jlink_hw_type;
+static int queued_retval;
+static bool swd_mode;
+
/* 256 byte non-volatile memory */
struct jlink_config {
uint8_t usb_address;
return ERROR_OK;
}
+static int jlink_register(void)
+{
+ int result;
+ usb_out_buffer[0] = EMU_CMD_REGISTER;
+ usb_out_buffer[1] = REG_CMD_REGISTER;
+ /* 2 - 11 is "additional parameter",
+ * 12 - 13 is connection handle, zero initially */
+ memset(&usb_out_buffer[2], 0, 10 + 2);
+
+ result = jlink_usb_write(jlink_handle, 14);
+ if (result != 14) {
+ LOG_ERROR("J-Link register write failed (%d)", result);
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+
+ /* Returns:
+ * 0 - 1 connection handle,
+ * 2 - 3 number of information entities,
+ * 4 - 5 size of a single information struct,
+ * 6 - 7 number of additional bytes,
+ * 8 - ... reply data
+ *
+ * Try to read the whole USB bulk packet
+ */
+ result = jtag_libusb_bulk_read(jlink_handle->usb_handle, jlink_read_ep,
+ (char *)usb_in_buffer, sizeof(usb_in_buffer),
+ JLINK_USB_TIMEOUT);
+ if (!result) {
+ LOG_ERROR("J-Link register read failed (0 bytes received)");
+ return ERROR_JTAG_DEVICE_ERROR;
+ }
+
+ return ERROR_OK;
+}
+
/*
* select transport interface
*
uint32_t iface_mask = buf_get_u32(usb_in_buffer, 0, 32);
if (!(iface_mask & (1<<iface))) {
- LOG_ERROR("J-Link requesting to select unsupported interface (%x)", iface_mask);
+ LOG_ERROR("J-Link requesting to select unsupported interface (%" PRIx32 ")", iface_mask);
return ERROR_JTAG_DEVICE_ERROR;
}
return ERROR_JTAG_INIT_FAILED;
}
- /*
- * The next three instructions were added after discovering a problem
- * while using an oscilloscope.
- * For the V8 SAM-ICE dongle (and likely other j-link device variants),
- * the reset line to the target microprocessor was found to cycle only
- * intermittently during emulator startup (even after encountering the
- * downstream reset instruction later in the code).
- * This was found to create two issues:
- * 1) In general it is a bad practice to not reset a CPU to a known
- * state when starting an emulator and
- * 2) something critical happens inside the dongle when it does the
- * first read following a new USB session.
- * Keeping the processor in reset during the first read collecting
- * version information seems to prevent errant
- * "J-Link command EMU_CMD_VERSION failed" issues.
- */
-
- LOG_INFO("J-Link initialization started / target CPU reset initiated");
- jlink_simple_command(EMU_CMD_HW_TRST0);
- jlink_simple_command(EMU_CMD_HW_RESET0);
- usleep(1000);
-
jlink_hw_jtag_version = 2;
if (jlink_get_version_info() == ERROR_OK) {
jlink_get_status();
}
+ /* Registration is sometimes necessary for SWD to work */
+ if (jlink_caps & (1<<EMU_CAP_REGISTER))
+ jlink_register();
+
/*
* Some versions of Segger's software do not select JTAG interface by default.
*
* Segger recommends to select interface necessarily as a part of init process,
* in case any previous session leaves improper interface selected.
- *
- * Until SWD implemented, select only JTAG interface here.
*/
+ int retval;
if (jlink_caps & (1<<EMU_CAP_SELECT_IF))
- jlink_select_interface(0);
+ retval = jlink_select_interface(swd_mode ? JLINK_TIF_SWD : JLINK_TIF_JTAG);
+ else
+ retval = swd_mode ? ERROR_JTAG_DEVICE_ERROR : ERROR_OK;
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Selected transport mode is not supported.");
+ return ERROR_JTAG_INIT_FAILED;
+ }
LOG_INFO("J-Link JTAG Interface ready");
jtag_sleep(3000);
jlink_tap_init();
- /* v5/6 jlink seems to have an issue if the first tap move
- * is not divisible by 8, so we send a TLR on first power up */
- for (i = 0; i < 8; i++)
- jlink_tap_append_step(1, 0);
- jlink_tap_execute();
+ jlink_speed(jtag_get_speed_khz());
+
+ if (!swd_mode) {
+ /* v5/6 jlink seems to have an issue if the first tap move
+ * is not divisible by 8, so we send a TLR on first power up */
+ for (i = 0; i < 8; i++)
+ jlink_tap_append_step(1, 0);
+ jlink_tap_execute();
+ }
return ERROR_OK;
}
if (!cfg)
return;
- jlink_dump_printf(ctx, "Kickstart power on JTAG-pin 19: 0x%x",
+ jlink_dump_printf(ctx, "Kickstart power on JTAG-pin 19: 0x%" PRIx32,
cfg->kickstart_power_on_jtag_pin_19);
}
LOG_INFO("J-Link hw version %i", (int)jlink_hw_version);
- if (jlink_hw_type >= JLINK_HW_TYPE_MAX)
- LOG_INFO("J-Link hw type uknown 0x%x", jlink_hw_type);
- else
- LOG_INFO("J-Link hw type %s", jlink_hw_type_str[jlink_hw_type]);
+ switch (jlink_hw_type) {
+ case JLINK_HW_TYPE_JLINK:
+ LOG_INFO("J-Link hw type J-Link");
+ break;
+ case JLINK_HW_TYPE_JTRACE:
+ LOG_INFO("J-Link hw type J-Trace");
+ break;
+ case JLINK_HW_TYPE_FLASHER:
+ LOG_INFO("J-Link hw type Flasher");
+ break;
+ case JLINK_HW_TYPE_JLINK_PRO:
+ LOG_INFO("J-Link hw type J-Link Pro");
+ break;
+ case JLINK_HW_TYPE_JLINK_LITE_ADI:
+ LOG_INFO("J-Link hw type J-Link Lite-ADI");
+ break;
+ case JLINK_HW_TYPE_LPCLINK2:
+ LOG_INFO("J-Link hw type J-Link on LPC-Link2");
+ break;
+ default:
+ LOG_INFO("J-Link hw type unknown 0x%" PRIx32, jlink_hw_type);
+ break;
+ }
}
if (jlink_caps & (1 << EMU_CAP_GET_MAX_BLOCK_SIZE)) {
return ERROR_OK;
}
+COMMAND_HANDLER(jlink_serial_command)
+{
+ if (CMD_ARGC != 1) {
+ LOG_ERROR("Need exactly one argument to jlink_serial");
+ return ERROR_FAIL;
+ }
+ if (jlink_serial)
+ free(jlink_serial);
+ jlink_serial = strdup(CMD_ARGV[0]);
+
+ return ERROR_OK;
+}
+
COMMAND_HANDLER(jlink_handle_jlink_info_command)
{
if (jlink_get_version_info() == ERROR_OK) {
.mode = COMMAND_CONFIG,
.help = "set the pid of the interface we want to use",
},
+ {
+ .name = "serial",
+ .handler = &jlink_serial_command,
+ .mode = COMMAND_CONFIG,
+ .help = "set the serial number of the J-Link adapter we want to use"
+ },
COMMAND_REGISTRATION_DONE
};
COMMAND_REGISTRATION_DONE
};
+static int jlink_swd_init(void)
+{
+ LOG_INFO("JLink SWD mode enabled");
+ swd_mode = true;
+
+ return ERROR_OK;
+}
+
+static void jlink_swd_write_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t value)
+{
+ assert(!(cmd & SWD_CMD_RnW));
+ jlink_swd_queue_cmd(dap, cmd, NULL, value);
+}
+
+static void jlink_swd_read_reg(struct adiv5_dap *dap, uint8_t cmd, uint32_t *value)
+{
+ assert(cmd & SWD_CMD_RnW);
+ jlink_swd_queue_cmd(dap, cmd, value, 0);
+}
+
+static int_least32_t jlink_swd_frequency(struct adiv5_dap *dap, int_least32_t hz)
+{
+ if (hz > 0)
+ jlink_speed(hz / 1000);
+
+ return hz;
+}
+
+static const struct swd_driver jlink_swd = {
+ .init = jlink_swd_init,
+ .frequency = jlink_swd_frequency,
+ .switch_seq = jlink_swd_switch_seq,
+ .read_reg = jlink_swd_read_reg,
+ .write_reg = jlink_swd_write_reg,
+ .run = jlink_swd_run_queue,
+};
+
+static const char * const jlink_transports[] = { "jtag", "swd", NULL };
+
struct jtag_interface jlink_interface = {
.name = "jlink",
.commands = jlink_command_handlers,
- .transports = jtag_only,
+ .transports = jlink_transports,
+ .swd = &jlink_swd,
.execute_queue = jlink_execute_queue,
.speed = jlink_speed,
static unsigned tap_length;
+/* In SWD mode use tms buffer for direction control */
static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE];
static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE];
static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE];
int first; /* First bit position in tdo_buffer to read */
int length; /* Number of bits to read */
struct scan_command *command; /* Corresponding scan command */
- uint8_t *buffer;
+ void *buffer;
};
#define MAX_PENDING_SCAN_RESULTS 256
{
int index_var = tap_length / 8;
- if (index_var >= JLINK_TAP_BUFFER_SIZE) {
- LOG_ERROR("jlink_tap_append_step: overflow");
- *(uint32_t *)0xFFFFFFFF = 0;
- exit(-1);
- }
+ assert(index_var < JLINK_TAP_BUFFER_SIZE);
int bit_index = tap_length % 8;
uint8_t bit = 1 << bit_index;
jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer,
tap_length, jlink_last_state);
- result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length, byte_length);
- if (result != byte_length) {
- LOG_ERROR("jlink_tap_execute, wrong result %d (expected %d)",
- result, byte_length);
+ result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length,
+ use_jtag3 ? byte_length + 1 : byte_length);
+ if (result != ERROR_OK) {
+ LOG_ERROR("jlink_tap_execute failed USB io (%d)", result);
+ jlink_tap_init();
+ return ERROR_JTAG_QUEUE_FAILED;
+ }
+
+ result = use_jtag3 ? usb_in_buffer[byte_length] : 0;
+ if (result != 0) {
+ LOG_ERROR("jlink_tap_execute failed, result %d (%s)", result,
+ result == 1 ? "adaptive clocking timeout" : "unknown");
jlink_tap_init();
return ERROR_JTAG_QUEUE_FAILED;
}
return ERROR_OK;
}
+static void fill_buffer(uint8_t *buf, uint32_t val, uint32_t len)
+{
+ unsigned int tap_pos = tap_length;
+
+ while (len > 32) {
+ buf_set_u32(buf, tap_pos, 32, val);
+ len -= 32;
+ tap_pos += 32;
+ }
+ if (len)
+ buf_set_u32(buf, tap_pos, len, val);
+}
+
+static void jlink_queue_data_out(const uint8_t *data, uint32_t len)
+{
+ const uint32_t dir_out = 0xffffffff;
+
+ if (data)
+ bit_copy(tdi_buffer, tap_length, data, 0, len);
+ else
+ fill_buffer(tdi_buffer, 0, len);
+ fill_buffer(tms_buffer, dir_out, len);
+ tap_length += len;
+}
+
+static void jlink_queue_data_in(uint32_t len)
+{
+ const uint32_t dir_in = 0;
+
+ fill_buffer(tms_buffer, dir_in, len);
+ tap_length += len;
+}
+
+static int jlink_swd_switch_seq(struct adiv5_dap *dap, enum swd_special_seq seq)
+{
+ const uint8_t *s;
+ unsigned int s_len;
+
+ switch (seq) {
+ case LINE_RESET:
+ LOG_DEBUG("SWD line reset");
+ s = swd_seq_line_reset;
+ s_len = swd_seq_line_reset_len;
+ break;
+ case JTAG_TO_SWD:
+ LOG_DEBUG("JTAG-to-SWD");
+ s = swd_seq_jtag_to_swd;
+ s_len = swd_seq_jtag_to_swd_len;
+ break;
+ case SWD_TO_JTAG:
+ LOG_DEBUG("SWD-to-JTAG");
+ s = swd_seq_swd_to_jtag;
+ s_len = swd_seq_swd_to_jtag_len;
+ break;
+ default:
+ LOG_ERROR("Sequence %d not supported", seq);
+ return ERROR_FAIL;
+ }
+
+ jlink_queue_data_out(s, s_len);
+
+ return ERROR_OK;
+}
+
+static int jlink_swd_run_queue(struct adiv5_dap *dap)
+{
+ LOG_DEBUG("Executing %d queued transactions", pending_scan_results_length);
+ int retval;
+
+ if (queued_retval != ERROR_OK) {
+ LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
+ goto skip;
+ }
+
+ /* A transaction must be followed by another transaction or at least 8 idle cycles to
+ * ensure that data is clocked through the AP. */
+ jlink_queue_data_out(NULL, 8);
+
+ size_t byte_length = DIV_ROUND_UP(tap_length, 8);
+
+ /* There's a comment in jlink_tap_execute saying JLink returns
+ * an extra NULL in packet when size of incoming message is a
+ * multiple of 64. Someone should verify if that's still the
+ * case with the current jlink firmware */
+
+ usb_out_buffer[0] = EMU_CMD_HW_JTAG3;
+ usb_out_buffer[1] = 0;
+ usb_out_buffer[2] = (tap_length >> 0) & 0xff;
+ usb_out_buffer[3] = (tap_length >> 8) & 0xff;
+ memcpy(usb_out_buffer + 4, tms_buffer, byte_length);
+ memcpy(usb_out_buffer + 4 + byte_length, tdi_buffer, byte_length);
+
+ retval = jlink_usb_message(jlink_handle, 4 + 2 * byte_length,
+ byte_length + 1);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("jlink_swd_run_queue failed USB io (%d)", retval);
+ goto skip;
+ }
+
+ retval = usb_in_buffer[byte_length];
+ if (retval) {
+ LOG_ERROR("jlink_swd_run_queue failed, result %d", retval);
+ goto skip;
+ }
+
+ for (int i = 0; i < pending_scan_results_length; i++) {
+ int ack = buf_get_u32(usb_in_buffer, pending_scan_results_buffer[i].first, 3);
+
+ if (ack != SWD_ACK_OK) {
+ LOG_DEBUG("SWD ack not OK: %d %s", ack,
+ ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
+ queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
+ goto skip;
+ } else if (pending_scan_results_buffer[i].length) {
+ uint32_t data = buf_get_u32(usb_in_buffer, 3 + pending_scan_results_buffer[i].first, 32);
+ int parity = buf_get_u32(usb_in_buffer, 3 + 32 + pending_scan_results_buffer[i].first, 1);
+
+ if (parity != parity_u32(data)) {
+ LOG_ERROR("SWD Read data parity mismatch");
+ queued_retval = ERROR_FAIL;
+ goto skip;
+ }
+
+ if (pending_scan_results_buffer[i].buffer)
+ *(uint32_t *)pending_scan_results_buffer[i].buffer = data;
+ }
+ }
+
+skip:
+ jlink_tap_init();
+ retval = queued_retval;
+ queued_retval = ERROR_OK;
+
+ return retval;
+}
+
+static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *dst, uint32_t data)
+{
+ uint8_t data_parity_trn[DIV_ROUND_UP(32 + 1, 8)];
+ if (tap_length + 46 + 8 + dap->memaccess_tck >= sizeof(tdi_buffer) * 8 ||
+ pending_scan_results_length == MAX_PENDING_SCAN_RESULTS) {
+ /* Not enough room in the queue. Run the queue. */
+ queued_retval = jlink_swd_run_queue(dap);
+ }
+
+ if (queued_retval != ERROR_OK)
+ return;
+
+ cmd |= SWD_CMD_START | SWD_CMD_PARK;
+
+ jlink_queue_data_out(&cmd, 8);
+
+ pending_scan_results_buffer[pending_scan_results_length].first = tap_length;
+
+ if (cmd & SWD_CMD_RnW) {
+ /* Queue a read transaction */
+ pending_scan_results_buffer[pending_scan_results_length].length = 32;
+ pending_scan_results_buffer[pending_scan_results_length].buffer = dst;
+
+ jlink_queue_data_in(1 + 3 + 32 + 1 + 1);
+ } else {
+ /* Queue a write transaction */
+ pending_scan_results_buffer[pending_scan_results_length].length = 0;
+ jlink_queue_data_in(1 + 3 + 1);
+
+ buf_set_u32(data_parity_trn, 0, 32, data);
+ buf_set_u32(data_parity_trn, 32, 1, parity_u32(data));
+
+ jlink_queue_data_out(data_parity_trn, 32 + 1);
+ }
+
+ pending_scan_results_length++;
+
+ /* Insert idle cycles after AP accesses to avoid WAIT */
+ if (cmd & SWD_CMD_APnDP)
+ jlink_queue_data_out(NULL, dap->memaccess_tck);
+}
+
/*****************************************************************************/
/* JLink USB low-level functions */
static struct jlink *jlink_usb_open()
{
struct jtag_libusb_device_handle *devh;
- if (jtag_libusb_open(vids, pids, &devh) != ERROR_OK)
+ if (jtag_libusb_open(vids, pids, jlink_serial, &devh) != ERROR_OK)
return NULL;
/* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
* committing them!
*/
-#if IS_WIN32 == 0
+/* This entire block can probably be removed. It was a workaround for
+ * libusb0.1 and old JLink firmware. It has already be removed for
+ * windows and causing problems (LPC Link-2 with JLink firmware) on
+ * Linux with libusb1.0.
+ *
+ * However, for now the behavior will be left unchanged for non-windows
+ * platforms using libusb0.1 due to lack of testing.
+ */
+#if IS_WIN32 == 0 && HAVE_LIBUSB1 == 0
jtag_libusb_reset_device(devh);
/* reopen jlink after usb_reset
* on win32 this may take a second or two to re-enumerate */
int retval;
- while ((retval = jtag_libusb_open(vids, pids, &devh)) != ERROR_OK) {
+ while ((retval = jtag_libusb_open(vids, pids, jlink_serial, &devh)) != ERROR_OK) {
usleep(1000);
timeout--;
if (!timeout)
#endif
- /* usb_set_configuration required under win32 */
- struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
+ /* usb_set_configuration is only required under win32
+ * with libusb 0.1 and libusb0.sys. For libusb 1.0 it is a no-op
+ * since the configuration is already set. */
jtag_libusb_set_configuration(devh, 0);
- jtag_libusb_claim_interface(devh, 0);
-
-#if 0
- /*
- * This makes problems under Mac OS X. And is not needed
- * under Windows. Hopefully this will not break a linux build
- */
- usb_set_altinterface(result->usb_handle, 0);
-#endif
- jtag_libusb_get_endpoints(udev, &jlink_read_ep, &jlink_write_ep);
+ jtag_libusb_choose_interface(devh, &jlink_read_ep, &jlink_write_ep,
+ JLINK_USB_INTERFACE_CLASS,
+ JLINK_USB_INTERFACE_SUBCLASS,
+ JLINK_USB_INTERFACE_PROTOCOL);
struct jlink *result = malloc(sizeof(struct jlink));
result->usb_handle = devh;
}
result = jlink_usb_read(jlink, in_length);
- if ((result != in_length) && (result != (in_length + 1))) {
+ if (result != in_length) {
LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)",
in_length, result);
return ERROR_JTAG_DEVICE_ERROR;
}
-
- if (jlink_hw_jtag_version < 3)
- return result;
-
- int result2 = ERROR_OK;
- if (result == in_length) {
- /* Must read the result from the EMU too */
- result2 = jlink_usb_read_emu_result(jlink);
- if (1 != result2) {
- LOG_ERROR("jlink_usb_read_emu_result retried requested = 1, "
- "result=%d, in_length=%i", result2, in_length);
- /* Try again once, should only happen if (in_length%64 == 0) */
- result2 = jlink_usb_read_emu_result(jlink);
- if (1 != result2) {
- LOG_ERROR("jlink_usb_read_emu_result failed "
- "(requested = 1, result=%d)", result2);
- return ERROR_JTAG_DEVICE_ERROR;
- }
- }
-
- /* Check the result itself */
- result2 = usb_emu_result_buffer[0];
- } else {
- /* Save the result, then remove it from return value */
- result2 = usb_in_buffer[result--];
- }
-
- if (result2) {
- LOG_ERROR("jlink_usb_message failed with result=%d)", result2);
- return ERROR_JTAG_DEVICE_ERROR;
- }
-
- return result;
+ return ERROR_OK;
}
/* calls the given usb_bulk_* function, allowing for the data to
return result;
}
-/* Read the result from the previous EMU cmd into result_buffer. */
-static int jlink_usb_read_emu_result(struct jlink *jlink)
-{
- int result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep,
- (char *)usb_emu_result_buffer, 1 /* JLINK_EMU_RESULT_BUFFER_SIZE */,
- JLINK_USB_TIMEOUT);
-
- DEBUG_JTAG_IO("jlink_usb_read_result, result = %d", result);
-
- jlink_debug_buffer(usb_emu_result_buffer, result);
- return result;
-}
-
/*
* Send a message and receive the reply - simple messages.
*