contrib: Change udev rules mode to 660
[libjaylink.git] / libjaylink / jtag.c
blobd40517c4915b1e9a31b0a439ae3880e75d78e8fd
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
37 #define CMD_JTAG_CLEAR_TMS 0xc9
38 #define CMD_JTAG_SET_TMS 0xca
39 #define CMD_JTAG_CLEAR_TCK 0xda
40 #define CMD_JTAG_SET_TCK 0xdb
42 /**
43 * Error code indicating that there is not enough free memory on the device to
44 * perform the JTAG I/O operation.
46 #define JTAG_IO_ERR_NO_MEMORY 0x06
47 /** @endcond */
49 /**
50 * Perform a JTAG I/O operation.
52 * @note This function must only be used if the #JAYLINK_TIF_JTAG interface is
53 * available and selected. Nevertheless, this function can be used if the
54 * device doesn't have the #JAYLINK_DEV_CAP_SELECT_TIF capability.
56 * @param[in,out] devh Device handle.
57 * @param[in] tms Buffer to read TMS data from.
58 * @param[in] tdi Buffer to read TDI data from.
59 * @param[out] tdo Buffer to store TDO data on success. Its content is
60 * undefined on failure. The buffer must be large enough to
61 * contain at least the specified number of bits to transfer.
62 * @param[in] length Number of bits to transfer.
63 * @param[in] version Version of the JTAG command to use.
65 * @retval JAYLINK_OK Success.
66 * @retval JAYLINK_ERR_ARG Invalid arguments.
67 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
68 * @retval JAYLINK_ERR_IO Input/output error.
69 * @retval JAYLINK_ERR_DEV_NO_MEMORY Not enough memory on the device to perform
70 * the operation.
71 * @retval JAYLINK_ERR_DEV Unspecified device error.
72 * @retval JAYLINK_ERR Other error conditions.
74 * @see jaylink_select_interface()
75 * @see jaylink_set_speed()
77 * @since 0.1.0
79 JAYLINK_API int jaylink_jtag_io(struct jaylink_device_handle *devh,
80 const uint8_t *tms, const uint8_t *tdi, uint8_t *tdo,
81 uint16_t length, enum jaylink_jtag_version version)
83 int ret;
84 struct jaylink_context *ctx;
85 uint8_t buf[4];
86 uint16_t num_bytes;
87 uint16_t read_length;
88 uint8_t status;
89 uint8_t cmd;
91 if (!devh || !tms || !tdi || !tdo || !length)
92 return JAYLINK_ERR_ARG;
94 num_bytes = (length + 7) / 8;
95 read_length = num_bytes;
97 switch (version) {
98 case JAYLINK_JTAG_VERSION_2:
99 cmd = CMD_JTAG_IO_V2;
100 break;
101 case JAYLINK_JTAG_VERSION_3:
102 cmd = CMD_JTAG_IO_V3;
103 /* In this version, the response includes a status byte. */
104 read_length++;
105 break;
106 default:
107 return JAYLINK_ERR_ARG;
110 ctx = devh->dev->ctx;
111 ret = transport_start_write_read(devh, 4 + 2 * num_bytes,
112 read_length, true);
114 if (ret != JAYLINK_OK) {
115 log_err(ctx, "transport_start_write_read() failed: %s",
116 jaylink_strerror(ret));
117 return ret;
120 buf[0] = cmd;
121 buf[1] = 0x00;
122 buffer_set_u16(buf, length, 2);
124 ret = transport_write(devh, buf, 4);
126 if (ret != JAYLINK_OK) {
127 log_err(ctx, "transport_write() failed: %s",
128 jaylink_strerror(ret));
129 return ret;
132 ret = transport_write(devh, tms, num_bytes);
134 if (ret != JAYLINK_OK) {
135 log_err(ctx, "transport_write() failed: %s",
136 jaylink_strerror(ret));
137 return ret;
140 ret = transport_write(devh, tdi, num_bytes);
142 if (ret != JAYLINK_OK) {
143 log_err(ctx, "transport_write() failed: %s",
144 jaylink_strerror(ret));
145 return ret;
148 ret = transport_read(devh, tdo, num_bytes);
150 if (ret != JAYLINK_OK) {
151 log_err(ctx, "transport_read() failed: %s",
152 jaylink_strerror(ret));
153 return ret;
156 if (version == JAYLINK_JTAG_VERSION_2)
157 return JAYLINK_OK;
159 ret = transport_read(devh, &status, 1);
161 if (ret != JAYLINK_OK) {
162 log_err(ctx, "transport_read() failed: %s",
163 jaylink_strerror(ret));
164 return ret;
167 if (status == JTAG_IO_ERR_NO_MEMORY) {
168 return JAYLINK_ERR_DEV_NO_MEMORY;
169 } else if (status > 0) {
170 log_err(ctx, "JTAG I/O operation failed: 0x%x", status);
171 return JAYLINK_ERR_DEV;
174 return JAYLINK_OK;
178 * Clear the JTAG test reset (TRST) signal.
180 * @param[in,out] devh Device handle.
182 * @retval JAYLINK_OK Success.
183 * @retval JAYLINK_ERR_ARG Invalid arguments.
184 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
185 * @retval JAYLINK_ERR_IO Input/output error.
186 * @retval JAYLINK_ERR Other error conditions.
188 * @since 0.1.0
190 JAYLINK_API int jaylink_jtag_clear_trst(struct jaylink_device_handle *devh)
192 int ret;
193 struct jaylink_context *ctx;
194 uint8_t buf[1];
196 if (!devh)
197 return JAYLINK_ERR_ARG;
199 ctx = devh->dev->ctx;
200 ret = transport_start_write(devh, 1, true);
202 if (ret != JAYLINK_OK) {
203 log_err(ctx, "transport_start_write() failed: %s",
204 jaylink_strerror(ret));
205 return ret;
208 buf[0] = CMD_JTAG_CLEAR_TRST;
210 ret = transport_write(devh, buf, 1);
212 if (ret != JAYLINK_OK) {
213 log_err(ctx, "transport_write() failed: %s",
214 jaylink_strerror(ret));
215 return ret;
218 return JAYLINK_OK;
222 * Set the JTAG test reset (TRST) signal.
224 * @param[in,out] devh Device handle.
226 * @retval JAYLINK_OK Success.
227 * @retval JAYLINK_ERR_ARG Invalid arguments.
228 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
229 * @retval JAYLINK_ERR_IO Input/output error.
230 * @retval JAYLINK_ERR Other error conditions.
232 * @since 0.1.0
234 JAYLINK_API int jaylink_jtag_set_trst(struct jaylink_device_handle *devh)
236 int ret;
237 struct jaylink_context *ctx;
238 uint8_t buf[1];
240 if (!devh)
241 return JAYLINK_ERR_ARG;
243 ctx = devh->dev->ctx;
244 ret = transport_start_write(devh, 1, true);
246 if (ret != JAYLINK_OK) {
247 log_err(ctx, "transport_start_write() failed: %s",
248 jaylink_strerror(ret));
249 return ret;
252 buf[0] = CMD_JTAG_SET_TRST;
254 ret = transport_write(devh, buf, 1);
256 if (ret != JAYLINK_OK) {
257 log_err(ctx, "transport_write() failed: %s",
258 jaylink_strerror(ret));
259 return ret;
262 return JAYLINK_OK;
266 * Clear the JTAG test mode select (TMS) signal.
268 * @param[in,out] devh Device handle.
270 * @retval JAYLINK_OK Success.
271 * @retval JAYLINK_ERR_ARG Invalid arguments.
272 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
273 * @retval JAYLINK_ERR_IO Input/output error.
274 * @retval JAYLINK_ERR Other error conditions.
276 * @since 0.3.0
278 JAYLINK_API int jaylink_jtag_clear_tms(struct jaylink_device_handle *devh)
280 int ret;
281 struct jaylink_context *ctx;
282 uint8_t buf[1];
284 if (!devh)
285 return JAYLINK_ERR_ARG;
287 ctx = devh->dev->ctx;
288 ret = transport_start_write(devh, 1, true);
290 if (ret != JAYLINK_OK) {
291 log_err(ctx, "transport_start_write() failed: %s",
292 jaylink_strerror(ret));
293 return ret;
296 buf[0] = CMD_JTAG_CLEAR_TMS;
298 ret = transport_write(devh, buf, 1);
300 if (ret != JAYLINK_OK) {
301 log_err(ctx, "transport_write() failed: %s",
302 jaylink_strerror(ret));
303 return ret;
306 return JAYLINK_OK;
310 * Set the JTAG test mode select (TMS) signal.
312 * @param[in,out] devh Device handle.
314 * @retval JAYLINK_OK Success.
315 * @retval JAYLINK_ERR_ARG Invalid arguments.
316 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
317 * @retval JAYLINK_ERR_IO Input/output error.
318 * @retval JAYLINK_ERR Other error conditions.
320 * @since 0.3.0
322 JAYLINK_API int jaylink_jtag_set_tms(struct jaylink_device_handle *devh)
324 int ret;
325 struct jaylink_context *ctx;
326 uint8_t buf[1];
328 if (!devh)
329 return JAYLINK_ERR_ARG;
331 ctx = devh->dev->ctx;
332 ret = transport_start_write(devh, 1, true);
334 if (ret != JAYLINK_OK) {
335 log_err(ctx, "transport_start_write() failed: %s",
336 jaylink_strerror(ret));
337 return ret;
340 buf[0] = CMD_JTAG_SET_TMS;
342 ret = transport_write(devh, buf, 1);
344 if (ret != JAYLINK_OK) {
345 log_err(ctx, "transport_write() failed: %s",
346 jaylink_strerror(ret));
347 return ret;
350 return JAYLINK_OK;
354 * Clear the JTAG test clock (TCK) signal.
356 * @param[in,out] devh Device handle.
358 * @retval JAYLINK_OK Success.
359 * @retval JAYLINK_ERR_ARG Invalid arguments.
360 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
361 * @retval JAYLINK_ERR_IO Input/output error.
362 * @retval JAYLINK_ERR Other error conditions.
364 * @since 0.3.0
366 JAYLINK_API int jaylink_jtag_clear_tck(struct jaylink_device_handle *devh)
368 int ret;
369 struct jaylink_context *ctx;
370 uint8_t buf[1];
372 if (!devh)
373 return JAYLINK_ERR_ARG;
375 ctx = devh->dev->ctx;
376 ret = transport_start_write(devh, 1, true);
378 if (ret != JAYLINK_OK) {
379 log_err(ctx, "transport_start_write() failed: %s",
380 jaylink_strerror(ret));
381 return ret;
384 buf[0] = CMD_JTAG_CLEAR_TCK;
386 ret = transport_write(devh, buf, 1);
388 if (ret != JAYLINK_OK) {
389 log_err(ctx, "transport_write() failed: %s",
390 jaylink_strerror(ret));
391 return ret;
394 return JAYLINK_OK;
398 * Set the JTAG test clock (TCK) signal.
400 * @param[in,out] devh Device handle.
402 * @retval JAYLINK_OK Success.
403 * @retval JAYLINK_ERR_ARG Invalid arguments.
404 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
405 * @retval JAYLINK_ERR_IO Input/output error.
406 * @retval JAYLINK_ERR Other error conditions.
408 * @since 0.3.0
410 JAYLINK_API int jaylink_jtag_set_tck(struct jaylink_device_handle *devh)
412 int ret;
413 struct jaylink_context *ctx;
414 uint8_t buf[1];
416 if (!devh)
417 return JAYLINK_ERR_ARG;
419 ctx = devh->dev->ctx;
420 ret = transport_start_write(devh, 1, true);
422 if (ret != JAYLINK_OK) {
423 log_err(ctx, "transport_start_write() failed: %s",
424 jaylink_strerror(ret));
425 return ret;
428 buf[0] = CMD_JTAG_SET_TCK;
430 ret = transport_write(devh, buf, 1);
432 if (ret != JAYLINK_OK) {
433 log_err(ctx, "transport_write() failed: %s",
434 jaylink_strerror(ret));
435 return ret;
438 return JAYLINK_OK;