Do not catch values not covered by an enum
[libjaylink.git] / libjaylink / target.c
blobf212f0bb292cddcbde8c357213f0db524a0b8e98
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 * Target related functions.
32 /** @cond PRIVATE */
33 #define CMD_SET_SPEED 0x05
34 #define CMD_SET_TARGET_POWER 0x08
35 #define CMD_GET_SPEEDS 0xc0
36 #define CMD_SELECT_TIF 0xc7
37 #define CMD_CLEAR_RESET 0xdc
38 #define CMD_SET_RESET 0xdd
40 #define TIF_GET_SELECTED 0xfe
41 #define TIF_GET_AVAILABLE 0xff
42 /** @endcond */
44 /**
45 * Set the target interface speed.
47 * @param[in,out] devh Device handle.
48 * @param[in] speed Speed in kHz or #JAYLINK_SPEED_ADAPTIVE_CLOCKING for
49 * adaptive clocking. Speed of 0 kHz is not allowed and
50 * adaptive clocking must only be used if the device has the
51 * #JAYLINK_DEV_CAP_ADAPTIVE_CLOCKING capability.
53 * @retval JAYLINK_OK Success.
54 * @retval JAYLINK_ERR_ARG Invalid arguments.
55 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
56 * @retval JAYLINK_ERR Other error conditions.
58 * @see jaylink_get_speeds()
60 * @since 0.1.0
62 JAYLINK_API int jaylink_set_speed(struct jaylink_device_handle *devh,
63 uint16_t speed)
65 int ret;
66 struct jaylink_context *ctx;
67 uint8_t buf[3];
69 if (!devh || !speed)
70 return JAYLINK_ERR_ARG;
72 ctx = devh->dev->ctx;
73 ret = transport_start_write(devh, 3, true);
75 if (ret != JAYLINK_OK) {
76 log_err(ctx, "transport_start_write() failed: %i.", ret);
77 return ret;
80 buf[0] = CMD_SET_SPEED;
81 buffer_set_u16(buf, speed, 1);
83 ret = transport_write(devh, buf, 3);
85 if (ret != JAYLINK_OK) {
86 log_err(ctx, "transport_write() failed: %i.", ret);
87 return ret;
90 return JAYLINK_OK;
93 /**
94 * Retrieve target interface speeds.
96 * The speeds are applicable for the currently selected target interface only
97 * and calculated as follows:
99 * @par
100 * <tt>speeds = @a freq / n</tt> with <tt>n >= @a div</tt>, where @p n is an
101 * integer
103 * Assuming, for example, a base frequency @a freq of 4 MHz and a minimum
104 * divider @a div of 4 then the highest possible target interface speed is
105 * 4 MHz / 4 = 1 MHz. The next highest speed is 800 kHz for a divider of 5, and
106 * so on.
108 * @note This function must only be used if the device has the
109 * #JAYLINK_DEV_CAP_GET_SPEEDS capability.
111 * @param[in,out] devh Device handle.
112 * @param[out] speed Speed information on success, and undefined on failure.
114 * @retval JAYLINK_OK Success.
115 * @retval JAYLINK_ERR_ARG Invalid arguments.
116 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
117 * @retval JAYLINK_ERR_PROTO Protocol violation.
118 * @retval JAYLINK_ERR Other error conditions.
120 * @see jaylink_select_interface()
122 * @since 0.1.0
124 JAYLINK_API int jaylink_get_speeds(struct jaylink_device_handle *devh,
125 struct jaylink_speed *speed)
127 int ret;
128 struct jaylink_context *ctx;
129 uint8_t buf[6];
130 uint16_t div;
132 if (!devh || !speed)
133 return JAYLINK_ERR_ARG;
135 ctx = devh->dev->ctx;
136 ret = transport_start_write_read(devh, 1, 6, true);
138 if (ret != JAYLINK_OK) {
139 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
140 return ret;
143 buf[0] = CMD_GET_SPEEDS;
145 ret = transport_write(devh, buf, 1);
147 if (ret != JAYLINK_OK) {
148 log_err(ctx, "transport_write() failed: %i.", ret);
149 return ret;
152 ret = transport_read(devh, buf, 6);
154 if (ret != JAYLINK_OK) {
155 log_err(ctx, "transport_read() failed: %i.", ret);
156 return ret;
159 div = buffer_get_u16(buf, 4);
161 if (!div) {
162 log_err(ctx, "Minimum frequency divider is zero.");
163 return JAYLINK_ERR_PROTO;
166 speed->freq = buffer_get_u32(buf, 0);
167 speed->div = div;
169 return JAYLINK_OK;
173 * Select the target interface.
175 * @note This function must only be used if the device has the
176 * #JAYLINK_DEV_CAP_SELECT_TIF capability.
178 * @warning This function may return a value for @p prev_iface which is not
179 * covered by #jaylink_target_interface.
181 * @param[in,out] devh Device handle.
182 * @param[in] iface Target interface to select.
183 * @param[out] prev_iface Previously selected target interface on success, and
184 * undefined on failure. Can be NULL.
186 * @retval JAYLINK_OK Success.
187 * @retval JAYLINK_ERR_ARG Invalid arguments.
188 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
189 * @retval JAYLINK_ERR Other error conditions.
191 * @see jaylink_get_available_interfaces()
193 * @since 0.1.0
195 JAYLINK_API int jaylink_select_interface(struct jaylink_device_handle *devh,
196 enum jaylink_target_interface iface,
197 enum jaylink_target_interface *prev_iface)
199 int ret;
200 struct jaylink_context *ctx;
201 uint8_t buf[4];
203 if (!devh)
204 return JAYLINK_ERR_ARG;
206 if (iface > JAYLINK_TIF_MAX)
207 return JAYLINK_ERR_ARG;
209 ctx = devh->dev->ctx;
210 ret = transport_start_write_read(devh, 2, 4, true);
212 if (ret != JAYLINK_OK) {
213 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
214 return ret;
217 buf[0] = CMD_SELECT_TIF;
218 buf[1] = iface;
220 ret = transport_write(devh, buf, 2);
222 if (ret != JAYLINK_OK) {
223 log_err(ctx, "transport_write() failed: %i.", ret);
224 return ret;
227 ret = transport_read(devh, buf, 4);
229 if (ret != JAYLINK_OK) {
230 log_err(ctx, "transport_read() failed: %i.", ret);
231 return ret;
234 if (prev_iface)
235 *prev_iface = buffer_get_u32(buf, 0);
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_select_interface()
262 * @since 0.1.0
264 JAYLINK_API int jaylink_get_available_interfaces(
265 struct jaylink_device_handle *devh, uint32_t *interfaces)
267 int ret;
268 struct jaylink_context *ctx;
269 uint8_t buf[4];
271 if (!devh || !interfaces)
272 return JAYLINK_ERR_ARG;
274 ctx = devh->dev->ctx;
275 ret = transport_start_write_read(devh, 2, 4, true);
277 if (ret != JAYLINK_OK) {
278 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
279 return ret;
282 buf[0] = CMD_SELECT_TIF;
283 buf[1] = TIF_GET_AVAILABLE;
285 ret = transport_write(devh, buf, 2);
287 if (ret != JAYLINK_OK) {
288 log_err(ctx, "transport_write() failed: %i.", ret);
289 return ret;
292 ret = transport_read(devh, buf, 4);
294 if (ret != JAYLINK_OK) {
295 log_err(ctx, "transport_read() failed: %i.", ret);
296 return ret;
299 *interfaces = buffer_get_u32(buf, 0);
301 return JAYLINK_OK;
305 * Retrieve the selected target interface.
307 * @note This function must only be used if the device has the
308 * #JAYLINK_DEV_CAP_SELECT_TIF capability.
310 * @warning This function may return a value for @p iface which is not covered
311 * by #jaylink_target_interface.
313 * @param[in,out] devh Device handle.
314 * @param[out] iface Selected target interface on success, and undefined on
315 * failure.
317 * @retval JAYLINK_OK Success.
318 * @retval JAYLINK_ERR_ARG Invalid arguments.
319 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
320 * @retval JAYLINK_ERR Other error conditions.
322 * @see jaylink_select_interface()
324 * @since 0.1.0
326 JAYLINK_API int jaylink_get_selected_interface(
327 struct jaylink_device_handle *devh,
328 enum jaylink_target_interface *iface)
330 int ret;
331 struct jaylink_context *ctx;
332 uint8_t buf[4];
334 if (!devh || !iface)
335 return JAYLINK_ERR_ARG;
337 ctx = devh->dev->ctx;
338 ret = transport_start_write_read(devh, 2, 4, true);
340 if (ret != JAYLINK_OK) {
341 log_err(ctx, "transport_start_write_read() failed: %i.", ret);
342 return ret;
345 buf[0] = CMD_SELECT_TIF;
346 buf[1] = TIF_GET_SELECTED;
348 ret = transport_write(devh, buf, 2);
350 if (ret != JAYLINK_OK) {
351 log_err(ctx, "transport_write() failed: %i.", ret);
352 return ret;
355 ret = transport_read(devh, buf, 4);
357 if (ret != JAYLINK_OK) {
358 log_err(ctx, "transport_read() failed: %i.", ret);
359 return ret;
362 *iface = buffer_get_u32(buf, 0);
364 return JAYLINK_OK;
368 * Clear the target reset signal.
370 * @param[in,out] devh Device handle.
372 * @retval JAYLINK_OK Success.
373 * @retval JAYLINK_ERR_ARG Invalid arguments.
374 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
375 * @retval JAYLINK_ERR Other error conditions.
377 * @since 0.1.0
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, true);
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 * @since 0.1.0
420 JAYLINK_API int jaylink_set_reset(struct jaylink_device_handle *devh)
422 int ret;
423 struct jaylink_context *ctx;
424 uint8_t buf[1];
426 if (!devh)
427 return JAYLINK_ERR_ARG;
429 ctx = devh->dev->ctx;
430 ret = transport_start_write(devh, 1, true);
432 if (ret != JAYLINK_OK) {
433 log_err(ctx, "transport_start_write() failed: %i.", ret);
434 return ret;
437 buf[0] = CMD_SET_RESET;
439 ret = transport_write(devh, buf, 1);
441 if (ret != JAYLINK_OK) {
442 log_err(ctx, "transport_write() failed: %i.", ret);
443 return ret;
446 return JAYLINK_OK;
450 * Set the target power supply.
452 * If enabled, the target is supplied with 5 V from pin 19 of the 20-pin
453 * JTAG / SWD connector.
455 * @note This function must only be used if the device has the
456 * #JAYLINK_DEV_CAP_SET_TARGET_POWER capability.
458 * @param[in,out] devh Device handle.
459 * @param[in] enable Determines whether to enable or disable the target power
460 * supply.
462 * @retval JAYLINK_OK Success.
463 * @retval JAYLINK_ERR_ARG Invalid arguments.
464 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
465 * @retval JAYLINK_ERR Other error conditions.
467 * @since 0.1.0
469 JAYLINK_API int jaylink_set_target_power(struct jaylink_device_handle *devh,
470 bool enable)
472 int ret;
473 struct jaylink_context *ctx;
474 uint8_t buf[2];
476 if (!devh)
477 return JAYLINK_ERR_ARG;
479 ctx = devh->dev->ctx;
480 ret = transport_start_write(devh, 2, true);
482 if (ret != JAYLINK_OK) {
483 log_err(ctx, "transport_start_wrte() failed: %i.", ret);
484 return ret;
487 buf[0] = CMD_SET_TARGET_POWER;
488 buf[1] = enable;
490 ret = transport_write(devh, buf, 2);
492 if (ret != JAYLINK_OK) {
493 log_err(ctx, "transport_write() failed: %i.", ret);
494 return ret;
497 return JAYLINK_OK;