+#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);
+
+ usb_out_buffer[0] = EMU_CMD_READ_CONFIG;
+ result = jlink_usb_io(jlink_handle, 1, size);
+
+ if (result != ERROR_OK) {
+ LOG_ERROR("jlink_usb_read failed (requested=%d, result=%d)", size, result);
+ return ERROR_FAIL;
+ }
+
+ memcpy(cfg, usb_in_buffer, size);
+ 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;
+}
+
+/*
+ * List of unsupported version string markers.
+ *
+ * The firmware versions does not correspond directly with
+ * "Software and documentation pack for Windows", it may be
+ * distinguished by the "compile" date in the information string.
+ *
+ * For example, version string is:
+ * "J-Link ARM V8 compiled May 3 2012 18:36:22"
+ * Marker sould be:
+ * "May 3 2012"
+ *
+ * The list must be terminated by NULL string.
+ */
+static const char * const unsupported_versions[] = {
+ "Jan 31 2011",
+ "JAN 31 2011",
+ NULL /* End of list */
+};
+
+static void jlink_check_supported(const char *str)
+{
+ const char * const *p = unsupported_versions;
+ while (*p) {
+ if (NULL != strstr(str, *p)) {
+ LOG_WARNING(
+ "Unsupported J-Link firmware version.\n"
+ " Please check http://www.segger.com/j-link-older-versions.html for updates");
+ return;
+ }
+ p++;
+ }
+}
+