Add jaylink_device_get_usb_bus_ports()
[libjaylink.git] / libjaylink / swd.c
blob29265b75d65f1642df19487055c19f34f5e8fe12
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2014-2015 Marc Schink <jaylink-dev@marcschink.de>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <stdint.h>
21 #include <stdbool.h>
23 #include "libjaylink.h"
24 #include "libjaylink-internal.h"
26 /**
27 * @file
29 * Serial Wire Debug (SWD) functions.
32 /** @cond PRIVATE */
33 #define CMD_SWD_IO 0xcf
35 /**
36 * Error code indicating that there is not enough free memory on the device to
37 * perform the SWD I/O operation.
39 #define SWD_IO_ERR_NO_MEMORY 0x06
40 /** @endcond */
42 /**
43 * Perform a SWD I/O operation.
45 * @note This function must only be used if the #JAYLINK_TIF_SWD interface is
46 * available and selected.
48 * @param[in,out] devh Device handle.
49 * @param[in] direction Buffer to read the transfer direction from.
50 * @param[in] out Buffer to read host-to-target data from.
51 * @param[out] in Buffer to store target-to-host data on success. Its content
52 * is undefined on failure. The buffer must be large enough to
53 * contain at least the specified number of bits to transfer.
54 * @param[in] length Total number of bits to transfer from host to target and
55 * vice versa.
57 * @retval JAYLINK_OK Success.
58 * @retval JAYLINK_ERR_ARG Invalid arguments.
59 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
60 * @retval JAYLINK_ERR_IO Input/output error.
61 * @retval JAYLINK_ERR_DEV_NO_MEMORY Not enough memory on the device to perform
62 * the operation.
63 * @retval JAYLINK_ERR_DEV Unspecified device error.
64 * @retval JAYLINK_ERR Other error conditions.
66 * @see jaylink_select_interface()
67 * @see jaylink_set_speed()
69 * @since 0.1.0
71 JAYLINK_API int jaylink_swd_io(struct jaylink_device_handle *devh,
72 const uint8_t *direction, const uint8_t *out, uint8_t *in,
73 uint16_t length)
75 int ret;
76 struct jaylink_context *ctx;
77 uint16_t num_bytes;
78 uint8_t buf[4];
79 uint8_t status;
81 if (!devh || !direction || !out || !in || !length)
82 return JAYLINK_ERR_ARG;
84 ctx = devh->dev->ctx;
85 num_bytes = (length + 7) / 8;
87 ret = transport_start_write_read(devh, 4 + 2 * num_bytes,
88 num_bytes + 1, true);
90 if (ret != JAYLINK_OK) {
91 log_err(ctx, "transport_start_write_read() failed: %s.",
92 jaylink_strerror(ret));
93 return ret;
96 buf[0] = CMD_SWD_IO;
97 buf[1] = 0x00;
98 buffer_set_u16(buf, length, 2);
100 ret = transport_write(devh, buf, 4);
102 if (ret != JAYLINK_OK) {
103 log_err(ctx, "transport_write() failed: %s.",
104 jaylink_strerror(ret));
105 return ret;
108 ret = transport_write(devh, direction, num_bytes);
110 if (ret != JAYLINK_OK) {
111 log_err(ctx, "transport_write() failed: %s.",
112 jaylink_strerror(ret));
113 return ret;
116 ret = transport_write(devh, out, num_bytes);
118 if (ret != JAYLINK_OK) {
119 log_err(ctx, "transport_write() failed: %s.",
120 jaylink_strerror(ret));
121 return ret;
124 ret = transport_read(devh, in, num_bytes);
126 if (ret != JAYLINK_OK) {
127 log_err(ctx, "transport_read() failed: %s.",
128 jaylink_strerror(ret));
129 return ret;
132 ret = transport_read(devh, &status, 1);
134 if (ret != JAYLINK_OK) {
135 log_err(ctx, "transport_read() failed: %s.",
136 jaylink_strerror(ret));
137 return ret;
140 if (status == SWD_IO_ERR_NO_MEMORY) {
141 return JAYLINK_ERR_DEV_NO_MEMORY;
142 } else if (status > 0) {
143 log_err(ctx, "SWD I/O operation failed: 0x%x.", status);
144 return JAYLINK_ERR_DEV;
147 return JAYLINK_OK;