]> git.sur5r.net Git - openocd/blobdiff - src/jtag/drivers/jlink.c
jlink: jlink_debug_buffer use inline function when _DEBUG_USB_COMMS_ not define
[openocd] / src / jtag / drivers / jlink.c
index 4a8896baefd13d5896d6b53eccea300d2cfc2bb6..6eb707a1a2282cf307387bc9cee190736a058f75 100644 (file)
@@ -5,6 +5,9 @@
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
+ *   Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD                *
+ *   plagnioj@jcrosoft.com                                                 *
+ *                                                                         *
  *   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 2 of the License, or     *
 http://www.segger.com/cms/admin/uploads/productDocs/RM08001_JLinkUSBProtocol.pdf
  */
 
-#define VID 0x1366
-#define PID 0x0101
+/*
+ * The default pid of the segger is 0x0101
+ * But when you change the USB Address it will also
+ *
+ * pid = ( usb_address > 0x4) ? 0x0101 : (0x101 + usb_address)
+ */
+#define VID 0x1366, 0x1366, 0x1366, 0x1366
+#define PID 0x0101, 0x0102, 0x0103, 0x0104
 
 #define JLINK_WRITE_ENDPOINT   0x02
 #define JLINK_READ_ENDPOINT            0x81
@@ -49,10 +58,10 @@ static unsigned int jlink_hw_jtag_version = 2;
 
 #define JLINK_USB_TIMEOUT              1000
 
-// See Section 1.3.2 of the Segger JLink USB protocol manual
+// See Section 3.3.2 of the Segger JLink USB protocol manual
 /* 2048 is the max value we can use here */
-//#define JLINK_TAP_BUFFER_SIZE 2048
-#define JLINK_TAP_BUFFER_SIZE 256
+#define JLINK_TAP_BUFFER_SIZE 2048
+//#define JLINK_TAP_BUFFER_SIZE 256
 //#define JLINK_TAP_BUFFER_SIZE 384
 
 #define JLINK_IN_BUFFER_SIZE                   2048
@@ -80,14 +89,95 @@ static uint8_t usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE];
 #define EMU_CMD_HW_TRST1               0xdf
 #define EMU_CMD_GET_CAPS               0xe8
 #define EMU_CMD_GET_HW_VERSION 0xf0
+#define EMU_CMD_READ_CONFIG            0xf2
+#define EMU_CMD_WRITE_CONFIG           0xf3
 
 /* bits return from EMU_CMD_GET_CAPS */
+#define EMU_CAP_RESERVED_1             0
 #define EMU_CAP_GET_HW_VERSION         1
+#define EMU_CAP_WRITE_DCC              2
+#define EMU_CAP_ADAPTIVE_CLOCKING      3
+#define EMU_CAP_READ_CONFIG            4
+#define EMU_CAP_WRITE_CONFIG           5
+#define EMU_CAP_TRACE                  6
+#define EMU_CAP_WRITE_MEM              7
+#define EMU_CAP_READ_MEM               8
+#define EMU_CAP_SPEED_INFO             9
+#define EMU_CAP_EXEC_CODE              10
 #define EMU_CAP_GET_MAX_BLOCK_SIZE     11
+#define EMU_CAP_GET_HW_INFO            12
+#define EMU_CAP_SET_KS_POWER           13
+#define EMU_CAP_RESET_STOP_TIMED       14
+#define EMU_CAP_RESERVED_2             15
+#define EMU_CAP_MEASURE_RTCK_REACT     16
+#define EMU_CAP_SELECT_IF              17
+#define EMU_CAP_RW_MEM_ARM79           18
+#define EMU_CAP_GET_COUNTERS           19
+#define EMU_CAP_READ_DCC               20
+#define EMU_CAP_GET_CPU_CAPS           21
+#define EMU_CAP_EXEC_CPU_CMD           22
+#define EMU_CAP_SWO                    23
+#define EMU_CAP_WRITE_DCC_EX           24
+#define EMU_CAP_UPDATE_FIRMWARE_EX     25
+#define EMU_CAP_FILE_IO                        26
+#define EMU_CAP_REGISTER               27
+#define EMU_CAP_INDICATORS             28
+#define EMU_CAP_TEST_NET_SPEED         29
+#define EMU_CAP_RAWTRACE               30
+#define EMU_CAP_RESERVED_3             31
+
+static char *jlink_cap_str[] = {
+       "Always 1.",
+       "Supports command EMU_CMD_GET_HARDWARE_VERSION",
+       "Supports command EMU_CMD_WRITE_DCC",
+       "Supports adaptive clocking",
+       "Supports command EMU_CMD_READ_CONFIG",
+       "Supports command EMU_CMD_WRITE_CONFIG",
+       "Supports trace commands",
+       "Supports command EMU_CMD_WRITE_MEM",
+       "Supports command EMU_CMD_READ_MEM",
+       "Supports command EMU_CMD_GET_SPEED",
+       "Supports command EMU_CMD_CODE_...",
+       "Supports command EMU_CMD_GET_MAX_BLOCK_SIZE",
+       "Supports command EMU_CMD_GET_HW_INFO",
+       "Supports command EMU_CMD_SET_KS_POWER",
+       "Supports command EMU_CMD_HW_RELEASE_RESET_STOP_TIMED",
+       "Reserved",
+       "Supports command EMU_CMD_MEASURE_RTCK_REACT",
+       "Supports command EMU_CMD_HW_SELECT_IF",
+       "Supports command EMU_CMD_READ/WRITE_MEM_ARM79",
+       "Supports command EMU_CMD_GET_COUNTERS",
+       "Supports command EMU_CMD_READ_DCC",
+       "Supports command EMU_CMD_GET_CPU_CAPS",
+       "Supports command EMU_CMD_EXEC_CPU_CMD",
+       "Supports command EMU_CMD_SWO",
+       "Supports command EMU_CMD_WRITE_DCC_EX",
+       "Supports command EMU_CMD_UPDATE_FIRMWARE_EX",
+       "Supports command EMU_CMD_FILE_IO",
+       "Supports command EMU_CMD_REGISTER",
+       "Supports command EMU_CMD_INDICATORS",
+       "Supports command EMU_CMD_TEST_NET_SPEED",
+       "Supports command EMU_CMD_RAWTRACE",
+       "Reserved",
+};
 
 /* max speed 12MHz v5.0 jlink */
 #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",
+};
+
 /* Queue command functions */
 static void jlink_end_state(tap_state_t state);
 static void jlink_state_move(void);
@@ -124,12 +214,42 @@ static int jlink_get_version_info(void);
 
 #ifdef _DEBUG_USB_COMMS_
 static void jlink_debug_buffer(uint8_t *buffer, int length);
+#else
+static inline void jlink_debug_buffer(uint8_t *buffer, int length)
+{
+}
 #endif
 
 static enum tap_state jlink_last_state = TAP_RESET;
 
 static struct jlink* jlink_handle;
 
+/* pid could be specified at runtime */
+static uint16_t vids[] = { VID, 0 };
+static uint16_t pids[] = { PID, 0 };
+
+static uint32_t jlink_caps;
+static uint32_t jlink_hw_type;
+
+/* 256 byte non-volatile memory */
+struct jlink_config {
+       uint8_t usb_address;
+       /* 0ffset 0x01 to 0x03 */
+       uint8_t reserved_1[3];
+       uint32_t kickstart_power_on_jtag_pin_19;
+       /* 0ffset 0x08 to 0x1f */
+       uint8_t reserved_2[24];
+       /* IP only for J-Link Pro */
+       uint8_t ip_address[4];
+       uint8_t subnet_mask[4];
+       /* 0ffset 0x28 to 0x2f */
+       uint8_t reserved_3[8];
+       uint8_t mac_address[6];
+       /* 0ffset 0x36 to 0xff */
+       uint8_t reserved_4[202];
+} __attribute__ ((packed));
+struct jlink_config jlink_cfg;
+
 /***************************************************************************/
 /* External interface implementation */
 
@@ -175,9 +295,7 @@ static void jlink_execute_scan(struct jtag_command *cmd)
        scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
        DEBUG_JTAG_IO("scan input, length = %d", scan_size);
 
-#ifdef _DEBUG_USB_COMMS_
        jlink_debug_buffer(buffer, (scan_size + 7) / 8);
-#endif
        type = jtag_scan_type(cmd->cmd.scan);
        jlink_scan(cmd->cmd.scan->ir_scan,
                        type, buffer, scan_size, cmd->cmd.scan);
@@ -236,9 +354,9 @@ static int jlink_speed(int speed)
 
        if (speed > JLINK_MAX_SPEED)
        {
-               LOG_INFO("Ignoring speed request: %dkHz exceeds %dkHz maximum",
+               LOG_INFO("reduce speed request: %dkHz to %dkHz maximum",
                                speed, JLINK_MAX_SPEED);
-               return ERROR_OK;
+               speed = JLINK_MAX_SPEED;
        }
 
        /* check for RTCK setting */
@@ -530,11 +648,132 @@ static int jlink_get_status(void)
        return ERROR_OK;
 }
 
+#define jlink_dump_printf(context, expr ...)   \
+       do {                                    \
+       if (context)                            \
+               command_print(context, expr);   \
+       else                                    \
+               LOG_INFO(expr);                 \
+       } while(0);
+
+
+static void jlink_caps_dump(struct command_context *ctx)
+{
+       int i;
+
+       jlink_dump_printf(ctx, "J-Link Capabilities");
+
+       for (i = 1; i < 31; i++)
+               if (jlink_caps & (1 << i))
+                       jlink_dump_printf(ctx, "%s", jlink_cap_str[i]);
+}
+
+static void jlink_config_usb_address_dump(struct command_context *ctx, struct jlink_config *cfg)
+{
+       if (!cfg)
+               return;
+
+       jlink_dump_printf(ctx, "USB-Address: 0x%x", cfg->usb_address);
+}
+
+static void jlink_config_kickstart_dump(struct command_context *ctx, struct jlink_config *cfg)
+{
+       if (!cfg)
+               return;
+
+       jlink_dump_printf(ctx, "Kickstart power on JTAG-pin 19: 0x%x",
+               cfg->kickstart_power_on_jtag_pin_19);
+}
+
+static void jlink_config_mac_address_dump(struct command_context *ctx, struct jlink_config *cfg)
+{
+       if (!cfg)
+               return;
+
+       jlink_dump_printf(ctx, "MAC Address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x",
+               cfg->mac_address[5], cfg->mac_address[4],
+               cfg->mac_address[3], cfg->mac_address[2],
+               cfg->mac_address[1], cfg->mac_address[0]);
+}
+
+static void jlink_config_ip_dump(struct command_context *ctx, struct jlink_config *cfg)
+{
+       if (!cfg)
+               return;
+
+       jlink_dump_printf(ctx, "IP Address: %d.%d.%d.%d",
+               cfg->ip_address[3], cfg->ip_address[2],
+               cfg->ip_address[1], cfg->ip_address[0]);
+       jlink_dump_printf(ctx, "Subnet Mask: %d.%d.%d.%d",
+               cfg->subnet_mask[3], cfg->subnet_mask[2],
+               cfg->subnet_mask[1], cfg->subnet_mask[0]);
+}
+
+static void jlink_config_dump(struct command_context *ctx, struct jlink_config *cfg)
+{
+       if (!cfg)
+               return;
+
+       jlink_dump_printf(ctx, "J-Link configuration");
+       jlink_config_usb_address_dump(ctx, cfg);
+       jlink_config_kickstart_dump(ctx, cfg);
+
+       if (jlink_hw_type == JLINK_HW_TYPE_JLINK_PRO)
+       {
+               jlink_config_ip_dump(ctx, cfg);
+               jlink_config_mac_address_dump(ctx, cfg);
+       }
+}
+
+static int jlink_get_config(struct jlink_config *cfg)
+{
+       int result;
+       int size = sizeof(struct jlink_config);
+
+       jlink_simple_command(EMU_CMD_READ_CONFIG);
+
+       result = jlink_usb_read(jlink_handle, size);
+       if (size != result)
+       {
+               LOG_ERROR("jlink_usb_read failed (requested=%d, result=%d)", size, result);
+               return ERROR_FAIL;
+       }
+
+       memcpy(cfg, usb_in_buffer, size);
+
+       /*
+        * Section 4.2.4 IN-transaction
+        * read dummy 0-byte packet
+        */
+       jlink_usb_read(jlink_handle, 1);
+
+       return ERROR_OK;
+}
+
+static int jlink_set_config(struct jlink_config *cfg)
+{
+       int result;
+       int size = sizeof(struct jlink_config);
+
+       jlink_simple_command(EMU_CMD_WRITE_CONFIG);
+
+       memcpy(usb_out_buffer, cfg, size);
+
+       result = jlink_usb_write(jlink_handle, size);
+       if (result != size)
+       {
+               LOG_ERROR("jlink_usb_write failed (requested=%d, result=%d)", 256, result);
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
 static int jlink_get_version_info(void)
 {
        int result;
        int len;
-       uint32_t jlink_caps, jlink_max_size;
+       uint32_t jlink_max_size;
 
        /* query hardware version */
        jlink_simple_command(EMU_CMD_VERSION);
@@ -574,7 +813,7 @@ static int jlink_get_version_info(void)
        }
 
        jlink_caps = buf_get_u32(usb_in_buffer, 0, 32);
-       LOG_INFO("JLink caps 0x%x", (unsigned)jlink_caps);
+       LOG_INFO("J-Link caps 0x%x", (unsigned)jlink_caps);
 
        if (jlink_caps & (1 << EMU_CAP_GET_HW_VERSION))
        {
@@ -590,10 +829,16 @@ static int jlink_get_version_info(void)
 
                uint32_t jlink_hw_version = buf_get_u32(usb_in_buffer, 0, 32);
                uint32_t major_revision = (jlink_hw_version / 10000) % 100;
+               jlink_hw_type = (jlink_hw_version / 1000000) % 100;
                if (major_revision >= 5)
                        jlink_hw_jtag_version = 3;
 
-               LOG_INFO("JLink hw version %i", (int)jlink_hw_version);
+               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]);
        }
 
        if (jlink_caps & (1 << EMU_CAP_GET_MAX_BLOCK_SIZE))
@@ -609,12 +854,35 @@ static int jlink_get_version_info(void)
                }
 
                jlink_max_size = buf_get_u32(usb_in_buffer, 0, 32);
-               LOG_INFO("JLink max mem block %i", (int)jlink_max_size);
+               LOG_INFO("J-Link max mem block %i", (int)jlink_max_size);
+       }
+
+       if (jlink_caps & (1 << EMU_CAP_READ_CONFIG))
+       {
+               if (jlink_get_config(&jlink_cfg) != ERROR_OK)
+                       return ERROR_JTAG_DEVICE_ERROR;
+
+               jlink_config_dump(NULL, &jlink_cfg);
        }
 
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(jlink_pid_command)
+{
+       if (CMD_ARGC != 1)
+       {
+               LOG_ERROR("Need exactly one argument to jlink_pid");
+               return ERROR_FAIL;
+       }
+
+       pids[0] = strtoul(CMD_ARGV[0], NULL, 16);
+       pids[1] = 0;
+       vids[1] = 0;
+
+       return ERROR_OK;
+}
+
 COMMAND_HANDLER(jlink_handle_jlink_info_command)
 {
        if (jlink_get_version_info() == ERROR_OK)
@@ -626,11 +894,18 @@ COMMAND_HANDLER(jlink_handle_jlink_info_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(jlink_handle_jlink_caps_command)
+{
+       jlink_caps_dump(CMD_CTX);
+
+       return ERROR_OK;
+}
+
 COMMAND_HANDLER(jlink_handle_jlink_hw_jtag_command)
 {
        switch (CMD_ARGC) {
        case 0:
-               command_print(CMD_CTX, "jlink hw jtag  %i", jlink_hw_jtag_version);
+               command_print(CMD_CTX, "J-Link hw jtag  %i", jlink_hw_jtag_version);
                break;
        case 1: {
                int request_version = atoi(CMD_ARGV[0]);
@@ -650,20 +925,306 @@ COMMAND_HANDLER(jlink_handle_jlink_hw_jtag_command)
        return ERROR_OK;
 }
 
-static const struct command_registration jlink_command_handlers[] = {
+COMMAND_HANDLER(jlink_handle_jlink_kickstart_command)
+{
+       uint32_t kickstart;
+
+       if (CMD_ARGC < 1)
+       {
+               jlink_config_kickstart_dump(CMD_CTX, &jlink_cfg);
+               return ERROR_OK;
+       }
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], kickstart);
+
+       jlink_cfg.kickstart_power_on_jtag_pin_19 = kickstart;
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(jlink_handle_jlink_mac_address_command)
+{
+       uint8_t addr[6];
+       int i;
+       char *e;
+       const char *str;
+
+       if (CMD_ARGC < 1)
+       {
+               jlink_config_mac_address_dump(CMD_CTX, &jlink_cfg);
+               return ERROR_OK;
+       }
+
+       str = CMD_ARGV[0];
+
+       if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
+               str[11] != ':' || str[14] != ':'))
+       {
+               command_print(CMD_CTX, "ethaddr miss format ff:ff:ff:ff:ff:ff");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       for (i = 5; i >= 0; i--)
+       {
+               addr[i] = strtoul(str, &e, 16);
+               str = e + 1;
+       }
+
+       if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]))
+       {
+               command_print(CMD_CTX, "invalid it's zero mac_address");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       if (!(0x01 & addr[0]))
+       {
+               command_print(CMD_CTX, "invalid it's a multicat mac_address");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       memcpy(jlink_cfg.mac_address, addr, sizeof(addr));
+
+       return ERROR_OK;
+}
+
+static int string_to_ip(const char *s, uint8_t *ip, int *pos)
+{
+       uint8_t lip[4];
+       char *e;
+       const char *s_save = s;
+       int i;
+
+       if (!s)
+               return -EINVAL;
+
+       for (i = 0; i < 4; i++) {
+               lip[i] = strtoul(s, &e, 10);
+
+               if (*e != '.' && i != 3)
+                       return -EINVAL;
+
+               s = e + 1;
+       }
+
+       *pos = e - s_save;
+
+       memcpy(ip, lip, sizeof(lip));
+       return ERROR_OK;
+}
+
+static void cpy_ip(uint8_t *dst, uint8_t *src)
+{
+       int i, j;
+
+       for (i = 0, j = 3; i < 4; i++, j--)
+               dst[i] = src[j];
+}
+
+COMMAND_HANDLER(jlink_handle_jlink_ip_command)
+{
+       uint32_t ip_address;
+       uint32_t subnet_mask = 0;
+       int i, len;
+       int ret;
+       uint8_t subnet_bits = 24;
+
+       if (CMD_ARGC < 1)
+       {
+               jlink_config_ip_dump(CMD_CTX, &jlink_cfg);
+               return ERROR_OK;
+       }
+
+       ret = string_to_ip(CMD_ARGV[0], (uint8_t*)&ip_address, &i);
+       if (ret != ERROR_OK)
+               return ret;
+
+       len = strlen(CMD_ARGV[0]);
+
+       /* check for this format A.B.C.D/E */
+
+       if (i < len)
+       {
+               if (CMD_ARGV[0][i] != '/')
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+
+               COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0] + i + 1, subnet_bits);
+       }
+       else
+       {
+               if (CMD_ARGC > 1)
+               {
+                       ret = string_to_ip(CMD_ARGV[1], (uint8_t*)&subnet_mask, &i);
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+       }
+
+       if (!subnet_mask)
+               subnet_mask = (uint32_t)(subnet_bits < 32 ?
+                               ((1ULL << subnet_bits) -1) : 0xffffffff);
+
+       cpy_ip(jlink_cfg.ip_address, (uint8_t*)&ip_address);
+       cpy_ip(jlink_cfg.subnet_mask, (uint8_t*)&subnet_mask);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(jlink_handle_jlink_reset_command)
+{
+       memset(&jlink_cfg, 0xff, sizeof(jlink_cfg));
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(jlink_handle_jlink_save_command)
+{
+       if (!(jlink_caps & (1 << EMU_CAP_WRITE_CONFIG)))
+       {
+               command_print(CMD_CTX, "J-Link write emulator configuration not supported");
+               return ERROR_OK;
+       }
+
+       command_print(CMD_CTX, "The J-Link need to be unpluged and repluged ta have the config effective");
+       return jlink_set_config(&jlink_cfg);
+}
+
+COMMAND_HANDLER(jlink_handle_jlink_usb_address_command)
+{
+       uint32_t address;
+
+       if (CMD_ARGC < 1)
+       {
+               jlink_config_usb_address_dump(CMD_CTX, &jlink_cfg);
+               return ERROR_OK;
+       }
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+
+       if (address > 0x3 && address != 0xff)
+       {
+               command_print(CMD_CTX, "USB Address must be between 0x00 and 0x03 or 0xff");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       jlink_cfg.usb_address = address;
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(jlink_handle_jlink_config_command)
+{
+       struct jlink_config cfg;
+       int ret = ERROR_OK;
+
+       if (CMD_ARGC == 0)
        {
-               .name = "jlink_info",
+               if (!(jlink_caps & (1 << EMU_CAP_READ_CONFIG)))
+               {
+                       command_print(CMD_CTX, "J-Link read emulator configuration not supported");
+                       goto exit;
+               }
+
+               ret = jlink_get_config(&cfg);
+
+               if ( ret != ERROR_OK)
+                       command_print(CMD_CTX, "J-Link read emulator configuration failled");
+               else
+                       jlink_config_dump(CMD_CTX, &jlink_cfg);
+       }
+
+exit:
+       return ret;
+}
+
+static const struct command_registration jlink_config_subcommand_handlers[] = {
+       {
+               .name = "kickstart",
+               .handler = &jlink_handle_jlink_kickstart_command,
+               .mode = COMMAND_EXEC,
+               .help = "set Kickstart power on JTAG-pin 19.",
+               .usage = "[val]",
+       },
+       {
+               .name = "mac_address",
+               .handler = &jlink_handle_jlink_mac_address_command,
+               .mode = COMMAND_EXEC,
+               .help = "set the MAC Address",
+               .usage = "[ff:ff:ff:ff:ff:ff]",
+       },
+       {
+               .name = "ip",
+               .handler = &jlink_handle_jlink_ip_command,
+               .mode = COMMAND_EXEC,
+               .help = "set the ip address of the J-Link Pro, "
+                       "where A.B.C.D is the ip, "
+                       "E the bit of the subnet mask, "
+                       "F.G.H.I the subnet mask",
+               .usage = "[A.B.C.D[/E] [F.G.H.I]]",
+       },
+       {
+               .name = "reset",
+               .handler = &jlink_handle_jlink_reset_command,
+               .mode = COMMAND_EXEC,
+               .help = "reset the current config",
+       },
+       {
+               .name = "save",
+               .handler = &jlink_handle_jlink_save_command,
+               .mode = COMMAND_EXEC,
+               .help = "save the current config",
+       },
+       {
+               .name = "usb_address",
+               .handler = &jlink_handle_jlink_usb_address_command,
+               .mode = COMMAND_EXEC,
+               .help = "set the USB-Address, "
+                       "This will change the product id",
+               .usage = "[0x00 to 0x03 or 0xff]",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration jlink_subcommand_handlers[] = {
+       {
+               .name = "caps",
+               .handler = &jlink_handle_jlink_caps_command,
+               .mode = COMMAND_EXEC,
+               .help = "show jlink capabilities",
+       },
+       {
+               .name = "info",
                .handler = &jlink_handle_jlink_info_command,
                .mode = COMMAND_EXEC,
                .help = "show jlink info",
        },
        {
-               .name = "jlink_hw_jtag",
+               .name = "hw_jtag",
                .handler = &jlink_handle_jlink_hw_jtag_command,
                .mode = COMMAND_EXEC,
                .help = "access J-Link HW JTAG command version",
                .usage = "[2|3]",
        },
+       {
+               .name = "config",
+               .handler = &jlink_handle_jlink_config_command,
+               .mode = COMMAND_EXEC,
+               .help = "access J-Link configuration, "
+                       "if no argument this will dump the config",
+               .chain = jlink_config_subcommand_handlers,
+       },
+       {
+               .name = "pid",
+               .handler = &jlink_pid_command,
+               .mode = COMMAND_CONFIG,
+               .help = "set the pid of the interface we want to use",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration jlink_command_handlers[] = {
+       {
+               .name = "jlink",
+               .mode = COMMAND_ANY,
+               .help = "perform jlink management",
+               .chain = jlink_subcommand_handlers,
+       },
        COMMAND_REGISTRATION_DONE
 };
 
@@ -828,9 +1389,7 @@ static int jlink_tap_execute(void)
 
                DEBUG_JTAG_IO("pending scan result, length = %d", length);
 
-#ifdef _DEBUG_USB_COMMS_
                jlink_debug_buffer(buffer, DIV_ROUND_UP(length, 8));
-#endif
 
                if (jtag_read_buffer(buffer, command) != ERROR_OK)
                {
@@ -855,8 +1414,6 @@ static struct jlink* jlink_usb_open()
 {
        usb_init();
 
-       const uint16_t vids[] = { VID, 0 };
-       const uint16_t pids[] = { PID, 0 };
        struct usb_dev_handle *dev;
        if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
                return NULL;
@@ -1052,9 +1609,7 @@ static int jlink_usb_write(struct jlink *jlink, int out_length)
        DEBUG_JTAG_IO("jlink_usb_write, out_length = %d, result = %d",
                        out_length, result);
 
-#ifdef _DEBUG_USB_COMMS_
        jlink_debug_buffer(usb_out_buffer, out_length);
-#endif
        return result;
 }
 
@@ -1066,9 +1621,7 @@ static int jlink_usb_read(struct jlink *jlink, int expected_size)
 
        DEBUG_JTAG_IO("jlink_usb_read, result = %d", result);
 
-#ifdef _DEBUG_USB_COMMS_
        jlink_debug_buffer(usb_in_buffer, result);
-#endif
        return result;
 }
 
@@ -1081,9 +1634,7 @@ static int jlink_usb_read_emu_result(struct jlink *jlink)
 
        DEBUG_JTAG_IO("jlink_usb_read_result, result = %d", result);
 
-#ifdef _DEBUG_USB_COMMS_
        jlink_debug_buffer(usb_emu_result_buffer, result);
-#endif
        return result;
 }