Change API of jaylink_select_interface()
[libjaylink.git] / libjaylink / target.c
blob8bf38e15bf8ffcc045dc00c2645fbb156eff3d98
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>
22 #include "libjaylink.h"
23 #include "libjaylink-internal.h"
25 /**
26 * @file
28 * Target related functions.
31 /** @cond PRIVATE */
32 #define CMD_SET_SPEED 0x05
33 #define CMD_SET_TARGET_POWER 0x08
34 #define CMD_GET_SPEEDS 0xc0
35 #define CMD_SELECT_TIF 0xc7
36 #define CMD_CLEAR_RESET 0xdc
37 #define CMD_SET_RESET 0xdd
39 #define TIF_GET_SELECTED 0xfe
40 #define TIF_GET_AVAILABLE 0xff
41 /** @endcond */
43 /**
44 * Set the target interface speed.
46 * @param[in,out] devh Device handle.
47 * @param[in] speed Speed in kHz or #JAYLINK_SPEED_ADAPTIVE_CLOCKING for
48 * adaptive clocking. Speed of 0 kHz is not allowed and
49 * adaptive clocking must only be used if the device has the
50 * #JAYLINK_DEV_CAP_ADAPTIVE_CLOCKING capability.
52 * @retval JAYLINK_OK Success.
53 * @retval JAYLINK_ERR_ARG Invalid arguments.
54 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
55 * @retval JAYLINK_ERR Other error conditions.
57 JAYLINK_API int jaylink_set_speed(struct jaylink_device_handle *devh,
58 uint16_t speed)
60 int ret;
61 struct jaylink_context *ctx;
62 uint8_t buf[3];
64 if (!devh || !speed)
65 return JAYLINK_ERR_ARG;
67 ctx = devh->dev->ctx;
68 ret = transport_start_write(devh, 3, 1);
70 if (ret != JAYLINK_OK) {
71 log_err(ctx, "transport_start_write() failed: %i.", ret);
72 return ret;
75 buf[0] = CMD_SET_SPEED;
76 buffer_set_u16(buf, speed, 1);
78 ret = transport_write(devh, buf, 3);
80 if (ret != JAYLINK_OK) {
81 log_err(ctx, "transport_write() failed: %i.", ret);
82 return ret;
85 return JAYLINK_OK;
88 /**
89 * Retrieve target interface speeds.
91 * The speeds are applicable for the currently selected target interface only
92 * and calulcated as follows:
94 * @par
95 * <tt>speeds = @a freq / n</tt> with <tt>n >= @a div</tt>, where @p n is an
96 * integer
98 * Assuming, for example, a base frequency @a freq of 4 MHz and a minimum
99 * divider @a div of 4 then the highest possible target interface speed is
100 * 4 MHz / 4 = 1 MHz. The next highest speed is 800 kHz for a divider of 5, and
101 * so on.
103 * @note This function must only be used if the device has the
104 * #JAYLINK_DEV_CAP_GET_SPEEDS capability.
106 * @param[in,out] devh Device handle.
107 * @param[out] freq Base frequency in Hz on success, and undefined on failure.
108 * @param[out] div Minimum divider on success, and undefined on failure.
110 * @retval JAYLINK_OK Success.
111 * @retval JAYLINK_ERR_ARG Invalid arguments.
112 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
113 * @retval JAYLINK_ERR_PROTO Protocol violation.
114 * @retval JAYLINK_ERR Other error conditions.
116 * @see jaylink_select_interface() to select the target interface.
117 * @see jaylink_get_selected_interface() to retrieve the currently selected
118 * interface.
119 * @see jaylink_set_speed() to set the target interface speed.
121 JAYLINK_API int jaylink_get_speeds(struct jaylink_device_handle *devh,
122 uint32_t *freq, uint16_t *div)
124 int ret;
125 struct jaylink_context *ctx;
126 uint8_t buf[6];
127 uint16_t dummy;
129 if (!devh || !freq || !div)
130 return JAYLINK_ERR_ARG;
132 ctx = devh->dev->ctx;
133 ret = transport_start_write_read(devh, 1, 6, 1);
135 if (ret != JAYLINK_OK) {
136 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
137 return ret;
140 buf[0] = CMD_GET_SPEEDS;
142 ret = transport_write(devh, buf, 1);
144 if (ret != JAYLINK_OK) {
145 log_err(ctx, "transport_write() failed: %i.", ret);
146 return ret;
149 ret = transport_read(devh, buf, 6);
151 if (ret != JAYLINK_OK) {
152 log_err(ctx, "transport_read() failed: %i.", ret);
153 return ret;
156 dummy = buffer_get_u16(buf, 4);
158 if (!dummy) {
159 log_err(ctx, "Minimum frequency divider is zero.");
160 return JAYLINK_ERR_PROTO;
163 *freq = buffer_get_u32(buf, 0);
164 *div = dummy;
166 return JAYLINK_OK;
170 * Select the target interface.
172 * @note This function must only be used if the device has the
173 * #JAYLINK_DEV_CAP_SELECT_TIF capability.
175 * @param[in,out] devh Device handle.
176 * @param[in] interface Target interface to select.
177 * @param[out] prev_interface Previously selected target interface on success,
178 * and undefined on failure. Can be NULL.
180 * @retval JAYLINK_OK Success.
181 * @retval JAYLINK_ERR_ARG Invalid arguments.
182 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
183 * @retval JAYLINK_ERR Other error conditions.
185 * @see jaylink_get_caps() to retrieve device capabilities.
187 JAYLINK_API int jaylink_select_interface(struct jaylink_device_handle *devh,
188 enum jaylink_target_interface interface,
189 enum jaylink_target_interface *prev_interface)
191 int ret;
192 struct jaylink_context *ctx;
193 uint8_t buf[4];
194 uint32_t tmp;
196 if (!devh)
197 return JAYLINK_ERR_ARG;
199 if (interface > JAYLINK_TIF_MAX)
200 return JAYLINK_ERR_ARG;
202 ctx = devh->dev->ctx;
203 ret = transport_start_write_read(devh, 2, 4, 1);
205 if (ret != JAYLINK_OK) {
206 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
207 return ret;
210 buf[0] = CMD_SELECT_TIF;
211 buf[1] = interface;
213 ret = transport_write(devh, buf, 2);
215 if (ret != JAYLINK_OK) {
216 log_err(ctx, "transport_write() failed: %i.", ret);
217 return ret;
220 ret = transport_read(devh, buf, 4);
222 if (ret != JAYLINK_OK) {
223 log_err(ctx, "transport_read() failed: %i.", ret);
224 return ret;
227 tmp = buffer_get_u32(buf, 0);
229 if (tmp > JAYLINK_TIF_MAX) {
230 log_err(ctx, "Invalid target interface: %u.", tmp);
231 return JAYLINK_ERR;
234 if (prev_interface)
235 *prev_interface = tmp;
237 return JAYLINK_OK;
241 * Retrieve the available target interfaces.
243 * The target interfaces are stored in a 32-bit bit field where each individual
244 * bit represents a target interface. A set bit indicates an available target
245 * interface. See #jaylink_target_interface for a description of the target
246 * interfaces and their bit positions.
248 * @note This function must only be used if the device has the
249 * #JAYLINK_DEV_CAP_SELECT_TIF capability.
251 * @param[in,out] devh Device handle.
252 * @param[out] interfaces Target interfaces on success, and undefined on
253 * failure.
255 * @retval JAYLINK_OK Success.
256 * @retval JAYLINK_ERR_ARG Invalid arguments.
257 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
258 * @retval JAYLINK_ERR Other error conditions.
260 * @see jaylink_get_caps() to retrieve device capabilities.
261 * @see jaylink_select_interface() to select a target interface.
263 JAYLINK_API int jaylink_get_available_interfaces(
264 struct jaylink_device_handle *devh, uint32_t *interfaces)
266 int ret;
267 struct jaylink_context *ctx;
268 uint8_t buf[4];
270 if (!devh || !interfaces)
271 return JAYLINK_ERR_ARG;
273 ctx = devh->dev->ctx;
274 ret = transport_start_write_read(devh, 2, 4, 1);
276 if (ret != JAYLINK_OK) {
277 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
278 return ret;
281 buf[0] = CMD_SELECT_TIF;
282 buf[1] = TIF_GET_AVAILABLE;
284 ret = transport_write(devh, buf, 2);
286 if (ret != JAYLINK_OK) {
287 log_err(ctx, "transport_write() failed: %i.", ret);
288 return ret;
291 ret = transport_read(devh, buf, 4);
293 if (ret != JAYLINK_OK) {
294 log_err(ctx, "transport_read() failed: %i.", ret);
295 return ret;
298 *interfaces = buffer_get_u32(buf, 0);
300 return JAYLINK_OK;
304 * Retrieve the selected target interface.
306 * @note This function must only be used if the device has the
307 * #JAYLINK_DEV_CAP_SELECT_TIF capability.
309 * @param[in,out] devh Device handle.
310 * @param[out] interface Selected target interface on success, and undefined on
311 * failure.
313 * @retval JAYLINK_OK Success.
314 * @retval JAYLINK_ERR_ARG Invalid arguments.
315 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
316 * @retval JAYLINK_ERR Other error conditions.
318 * @see jaylink_get_caps() to retrieve device capabilities.
320 JAYLINK_API int jaylink_get_selected_interface(
321 struct jaylink_device_handle *devh,
322 enum jaylink_target_interface *interface)
324 int ret;
325 struct jaylink_context *ctx;
326 uint8_t buf[4];
327 uint32_t tmp;
329 if (!devh || !interface)
330 return JAYLINK_ERR_ARG;
332 ctx = devh->dev->ctx;
333 ret = transport_start_write_read(devh, 2, 4, 1);
335 if (ret != JAYLINK_OK) {
336 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
337 return ret;
340 buf[0] = CMD_SELECT_TIF;
341 buf[1] = TIF_GET_SELECTED;
343 ret = transport_write(devh, buf, 2);
345 if (ret != JAYLINK_OK) {
346 log_err(ctx, "transport_write() failed: %i.", ret);
347 return ret;
350 ret = transport_read(devh, buf, 4);
352 if (ret != JAYLINK_OK) {
353 log_err(ctx, "transport_read() failed: %i.", ret);
354 return ret;
357 tmp = buffer_get_u32(buf, 0);
359 if (tmp > JAYLINK_TIF_MAX) {
360 log_err(ctx, "Invalid target interface: %u.", tmp);
361 return JAYLINK_ERR;
364 *interface = tmp;
366 return JAYLINK_OK;
370 * Clear the target reset signal.
372 * @param[in,out] devh Device handle.
374 * @retval JAYLINK_OK Success.
375 * @retval JAYLINK_ERR_ARG Invalid arguments.
376 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
377 * @retval JAYLINK_ERR Other error conditions.
379 JAYLINK_API int jaylink_clear_reset(struct jaylink_device_handle *devh)
381 int ret;
382 struct jaylink_context *ctx;
383 uint8_t buf[1];
385 if (!devh)
386 return JAYLINK_ERR_ARG;
388 ctx = devh->dev->ctx;
389 ret = transport_start_write(devh, 1, 1);
391 if (ret != JAYLINK_OK) {
392 log_err(ctx, "transport_start_write() failed: %i.", ret);
393 return ret;
396 buf[0] = CMD_CLEAR_RESET;
398 ret = transport_write(devh, buf, 1);
400 if (ret != JAYLINK_OK) {
401 log_err(ctx, "transport_write() failed: %i.", ret);
402 return ret;
405 return JAYLINK_OK;
409 * Set the target reset signal.
411 * @param[in,out] devh Device handle.
413 * @retval JAYLINK_OK Success.
414 * @retval JAYLINK_ERR_ARG Invalid arguments.
415 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
416 * @retval JAYLINK_ERR Other error conditions.
418 JAYLINK_API int jaylink_set_reset(struct jaylink_device_handle *devh)
420 int ret;
421 struct jaylink_context *ctx;
422 uint8_t buf[1];
424 if (!devh)
425 return JAYLINK_ERR_ARG;
427 ctx = devh->dev->ctx;
428 ret = transport_start_write(devh, 1, 1);
430 if (ret != JAYLINK_OK) {
431 log_err(ctx, "transport_start_write() failed: %i.", ret);
432 return ret;
435 buf[0] = CMD_SET_RESET;
437 ret = transport_write(devh, buf, 1);
439 if (ret != JAYLINK_OK) {
440 log_err(ctx, "transport_write() failed: %i.", ret);
441 return ret;
444 return JAYLINK_OK;
448 * Enable or disable the target power supply.
450 * If enabled, the target is supplied with 5 V from pin 19 of the 20-pin
451 * JTAG / SWD connector.
453 * @note This function must only be used if the device has the
454 * #JAYLINK_DEV_CAP_SET_TARGET_POWER capability.
456 * @param devh Device handle.
457 * @param enable Determines whether to enable or disable the target power
458 * supply.
460 * @retval JAYLINK_OK Success.
461 * @retval JAYLINK_ERR_ARG Invalid arguments.
462 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
463 * @retval JAYLINK_ERR Other error conditions.
465 * @see jaylink_get_caps() to retrieve device capabilities.
467 JAYLINK_API int jaylink_set_target_power(struct jaylink_device_handle *devh,
468 int enable)
470 int ret;
471 struct jaylink_context *ctx;
472 uint8_t buf[2];
474 if (!devh)
475 return JAYLINK_ERR_ARG;
477 ctx = devh->dev->ctx;
478 ret = transport_start_write(devh, 2, 1);
480 if (ret != JAYLINK_OK) {
481 log_err(ctx, "transport_start_wrte() failed: %i.", ret);
482 return ret;
485 if (enable)
486 enable = 1;
488 buf[0] = CMD_SET_TARGET_POWER;
489 buf[1] = enable;
491 ret = transport_write(devh, buf, 2);
493 if (ret != JAYLINK_OK) {
494 log_err(ctx, "transport_write() failed: %i.", ret);
495 return ret;
498 return JAYLINK_OK;