+ if (ret < 0) {
+ LOG_ERROR("jaylink_register() failed: %s.",
+ jaylink_strerror_name(ret));
+ return ERROR_FAIL;
+ }
+
+ handle_found = false;
+
+ for (i = 0; i < ret; i++) {
+ if (connlist[i].handle == conn.handle) {
+ handle_found = true;
+ break;
+ }
+ }
+
+ if (!handle_found) {
+ LOG_ERROR("Registration failed: maximum number of connections on the "
+ "device reached.");
+ return ERROR_FAIL;
+ }
+
+ return ERROR_OK;
+}
+
+/*
+ * Adjust the SWD transaction buffer size depending on the free device internal
+ * memory. This ensures that the SWD transactions sent to the device do not
+ * exceed the internal memory of the device.
+ */
+static bool adjust_swd_buffer_size(void)
+{
+ int ret;
+ uint32_t tmp;
+
+ if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_FREE_MEMORY))
+ return true;
+
+ ret = jaylink_get_free_memory(devh, &tmp);
+
+ if (ret != JAYLINK_OK) {
+ LOG_ERROR("jaylink_get_free_memory() failed: %s.",
+ jaylink_strerror_name(ret));
+ return false;
+ }
+
+ if (tmp < 143) {
+ LOG_ERROR("Not enough free device internal memory: %u bytes.", tmp);
+ return false;
+ }
+
+ tmp = MIN(JLINK_TAP_BUFFER_SIZE, (tmp - 16) / 2);
+
+ if (tmp != swd_buffer_size) {
+ swd_buffer_size = tmp;
+ LOG_DEBUG("Adjusted SWD transaction buffer size to %u bytes.",
+ swd_buffer_size);
+ }
+
+ return true;
+}
+
+static int jlink_init(void)
+{
+ int ret;
+ struct jaylink_device **devs;
+ unsigned int i;
+ bool found_device;
+ uint32_t tmp;
+ char *firmware_version;
+ struct jaylink_hardware_version hwver;
+ struct jaylink_hardware_status hwstatus;
+ enum jaylink_usb_address address;
+ size_t length;
+
+ ret = jaylink_init(&jayctx);
+
+ if (ret != JAYLINK_OK) {
+ LOG_ERROR("jaylink_init() failed: %s.",
+ jaylink_strerror_name(ret));
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ ret = jaylink_get_device_list(jayctx, &devs);
+
+ if (ret < 0) {
+ LOG_ERROR("jaylink_get_device_list() failed: %s.",
+ jaylink_strerror_name(ret));
+ jaylink_exit(jayctx);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ found_device = false;
+
+ if (!use_serial_number && !use_usb_address)
+ LOG_INFO("No device selected, using first device.");
+
+ for (i = 0; devs[i]; i++) {
+ if (use_serial_number) {
+ ret = jaylink_device_get_serial_number(devs[i], &tmp);
+
+ if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
+ continue;
+ } else if (ret != JAYLINK_OK) {
+ LOG_WARNING("jaylink_device_get_serial_number() failed: %s.",
+ jaylink_strerror_name(ret));
+ continue;
+ }
+
+ if (serial_number != tmp)
+ continue;
+ }
+
+ if (use_usb_address) {
+ ret = jaylink_device_get_usb_address(devs[i], &address);
+
+ if (ret != JAYLINK_OK) {
+ LOG_WARNING("jaylink_device_get_usb_address() failed: %s.",
+ jaylink_strerror_name(ret));
+ continue;
+ }
+
+ if (usb_address != address)
+ continue;
+ }
+
+ ret = jaylink_open(devs[i], &devh);
+
+ if (ret == JAYLINK_OK) {
+ found_device = true;
+ break;
+ }
+
+ LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret));
+ }
+
+ jaylink_free_device_list(devs, 1);
+
+ if (!found_device) {
+ LOG_ERROR("No J-Link device found.");
+ jaylink_exit(jayctx);