Add jaylink_device_get_usb_bus_ports()
[libjaylink.git] / libjaylink / jtag.c
blobc0c65de0e312a65f1baa46e683c47c0432ec5fde
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 * JTAG functions.
32 /** @cond PRIVATE */
33 #define CMD_JTAG_IO_V2 0xce
34 #define CMD_JTAG_IO_V3 0xcf
35 #define CMD_JTAG_CLEAR_TRST 0xde
36 #define CMD_JTAG_SET_TRST 0xdf
38 /**
39 * Error code indicating that there is not enough free memory on the device to
40 * perform the JTAG I/O operation.
42 #define JTAG_IO_ERR_NO_MEMORY 0x06
43 /** @endcond */
45 /**
46 * Perform a JTAG I/O operation.
48 * @note This function must only be used if the #JAYLINK_TIF_JTAG interface is
49 * available and selected. Nevertheless, this function can be used if the
50 * device doesn't have the #JAYLINK_DEV_CAP_SELECT_TIF capability.
52 * @param[in,out] devh Device handle.
53 * @param[in] tms Buffer to read TMS data from.
54 * @param[in] tdi Buffer to read TDI data from.
55 * @param[out] tdo Buffer to store TDO data on success. Its content is
56 * undefined on failure. The buffer must be large enough to
57 * contain at least the specified number of bits to transfer.
58 * @param[in] length Number of bits to transfer.
59 * @param[in] version Version of the JTAG command to use.
61 * @retval JAYLINK_OK Success.
62 * @retval JAYLINK_ERR_ARG Invalid arguments.
63 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
64 * @retval JAYLINK_ERR_IO Input/output error.
65 * @retval JAYLINK_ERR_DEV_NO_MEMORY Not enough memory on the device to perform
66 * the operation.
67 * @retval JAYLINK_ERR_DEV Unspecified device error.
68 * @retval JAYLINK_ERR Other error conditions.
70 * @see jaylink_select_interface()
71 * @see jaylink_set_speed()
73 * @since 0.1.0
75 JAYLINK_API int jaylink_jtag_io(struct jaylink_device_handle *devh,
76 const uint8_t *tms, const uint8_t *tdi, uint8_t *tdo,
77 uint16_t length, enum jaylink_jtag_version version)
79 int ret;
80 struct jaylink_context *ctx;
81 uint8_t buf[4];
82 uint16_t num_bytes;
83 uint16_t read_length;
84 uint8_t status;
85 uint8_t cmd;
87 if (!devh || !tms || !tdi || !tdo || !length)
88 return JAYLINK_ERR_ARG;
90 num_bytes = (length + 7) / 8;
91 read_length = num_bytes;
93 switch (version) {
94 case JAYLINK_JTAG_VERSION_2:
95 cmd = CMD_JTAG_IO_V2;
96 break;
97 case JAYLINK_JTAG_VERSION_3:
98 cmd = CMD_JTAG_IO_V3;
99 /* In this version, the response includes a status byte. */
100 read_length++;
101 break;
102 default:
103 return JAYLINK_ERR_ARG;
106 ctx = devh->dev->ctx;
107 ret = transport_start_write_read(devh, 4 + 2 * num_bytes,
108 read_length, true);
110 if (ret != JAYLINK_OK) {
111 log_err(ctx, "transport_start_write_read() failed: %s.",
112 jaylink_strerror(ret));
113 return ret;
116 buf[0] = cmd;
117 buf[1] = 0x00;
118 buffer_set_u16(buf, length, 2);
120 ret = transport_write(devh, buf, 4);
122 if (ret != JAYLINK_OK) {
123 log_err(ctx, "transport_write() failed: %s.",
124 jaylink_strerror(ret));
125 return ret;
128 ret = transport_write(devh, tms, num_bytes);
130 if (ret != JAYLINK_OK) {
131 log_err(ctx, "transport_write() failed: %s.",
132 jaylink_strerror(ret));
133 return ret;
136 ret = transport_write(devh, tdi, num_bytes);
138 if (ret != JAYLINK_OK) {
139 log_err(ctx, "transport_write() failed: %s.",
140 jaylink_strerror(ret));
141 return ret;
144 ret = transport_read(devh, tdo, num_bytes);
146 if (ret != JAYLINK_OK) {
147 log_err(ctx, "transport_read() failed: %s.",
148 jaylink_strerror(ret));
149 return ret;
152 if (version == JAYLINK_JTAG_VERSION_2)
153 return JAYLINK_OK;
155 ret = transport_read(devh, &status, 1);
157 if (ret != JAYLINK_OK) {
158 log_err(ctx, "transport_read() failed: %s.",
159 jaylink_strerror(ret));
160 return ret;
163 if (status == JTAG_IO_ERR_NO_MEMORY) {
164 return JAYLINK_ERR_DEV_NO_MEMORY;
165 } else if (status > 0) {
166 log_err(ctx, "JTAG I/O operation failed: 0x%x.", status);
167 return JAYLINK_ERR_DEV;
170 return JAYLINK_OK;
174 * Clear the JTAG test reset (TRST) signal.
176 * @param[in,out] devh Device handle.
178 * @retval JAYLINK_OK Success.
179 * @retval JAYLINK_ERR_ARG Invalid arguments.
180 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
181 * @retval JAYLINK_ERR_IO Input/output error.
182 * @retval JAYLINK_ERR Other error conditions.
184 * @since 0.1.0
186 JAYLINK_API int jaylink_jtag_clear_trst(struct jaylink_device_handle *devh)
188 int ret;
189 struct jaylink_context *ctx;
190 uint8_t buf[1];
192 if (!devh)
193 return JAYLINK_ERR_ARG;
195 ctx = devh->dev->ctx;
196 ret = transport_start_write(devh, 1, true);
198 if (ret != JAYLINK_OK) {
199 log_err(ctx, "transport_start_write() failed: %s.",
200 jaylink_strerror(ret));
201 return ret;
204 buf[0] = CMD_JTAG_CLEAR_TRST;
206 ret = transport_write(devh, buf, 1);
208 if (ret != JAYLINK_OK) {
209 log_err(ctx, "transport_write() failed: %s.",
210 jaylink_strerror(ret));
211 return ret;
214 return JAYLINK_OK;
218 * Set the JTAG test reset (TRST) signal.
220 * @param[in,out] devh Device handle.
222 * @retval JAYLINK_OK Success.
223 * @retval JAYLINK_ERR_ARG Invalid arguments.
224 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
225 * @retval JAYLINK_ERR_IO Input/output error.
226 * @retval JAYLINK_ERR Other error conditions.
228 * @since 0.1.0
230 JAYLINK_API int jaylink_jtag_set_trst(struct jaylink_device_handle *devh)
232 int ret;
233 struct jaylink_context *ctx;
234 uint8_t buf[1];
236 if (!devh)
237 return JAYLINK_ERR_ARG;
239 ctx = devh->dev->ctx;
240 ret = transport_start_write(devh, 1, true);
242 if (ret != JAYLINK_OK) {
243 log_err(ctx, "transport_start_write() failed: %s.",
244 jaylink_strerror(ret));
245 return ret;
248 buf[0] = CMD_JTAG_SET_TRST;
250 ret = transport_write(devh, buf, 1);
252 if (ret != JAYLINK_OK) {
253 log_err(ctx, "transport_write() failed: %s.",
254 jaylink_strerror(ret));
255 return ret;
258 return JAYLINK_OK;