+ int retval;
+
+ /* Optional low-level JTAG debug */
+ if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
+ if (vpi->nb_bits > 0) {
+ /* command with a non-empty data payload */
+ char *char_buf = buf_to_hex_str(vpi->buffer_out,
+ (vpi->nb_bits > DEBUG_JTAG_IOZ)
+ ? DEBUG_JTAG_IOZ
+ : vpi->nb_bits);
+ LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
+ "length=%" PRIu32 ", "
+ "nb_bits=%" PRIu32 ", "
+ "buf_out=0x%s%s",
+ jtag_vpi_cmd_to_str(vpi->cmd),
+ vpi->length,
+ vpi->nb_bits,
+ char_buf,
+ (vpi->nb_bits > DEBUG_JTAG_IOZ) ? "(...)" : "");
+ free(char_buf);
+ } else {
+ /* command without data payload */
+ LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
+ "length=%" PRIu32 ", "
+ "nb_bits=%" PRIu32,
+ jtag_vpi_cmd_to_str(vpi->cmd),
+ vpi->length,
+ vpi->nb_bits);
+ }
+ }
+
+ /* Use little endian when transmitting/receiving jtag_vpi cmds.
+ The choice of little endian goes against usual networking conventions
+ but is intentional to remain compatible with most older OpenOCD builds
+ (i.e. builds on little-endian platforms). */
+ h_u32_to_le(vpi->cmd_buf, vpi->cmd);
+ h_u32_to_le(vpi->length_buf, vpi->length);
+ h_u32_to_le(vpi->nb_bits_buf, vpi->nb_bits);
+
+retry_write:
+ retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
+
+ if (retval < 0) {
+ /* Account for the case when socket write is interrupted. */
+#ifdef _WIN32
+ int wsa_err = WSAGetLastError();
+ if (wsa_err == WSAEINTR)
+ goto retry_write;
+#else
+ if (errno == EINTR)
+ goto retry_write;
+#endif
+ /* Otherwise this is an error using the socket, most likely fatal
+ for the connection. B*/
+ log_socket_error("jtag_vpi xmit");
+ /* TODO: Clean way how adapter drivers can report fatal errors
+ to upper layers of OpenOCD and let it perform an orderly shutdown? */
+ exit(-1);
+ } else if (retval < (int)sizeof(struct vpi_cmd)) {
+ /* This means we could not send all data, which is most likely fatal
+ for the jtag_vpi connection (the underlying TCP connection likely not
+ usable anymore) */
+ LOG_ERROR("jtag_vpi: Could not send all data through jtag_vpi connection.");
+ exit(-1);
+ }