Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 1 | /* |
Uwe Hermann | 50985c2 | 2013-04-23 22:24:30 +0200 | [diff] [blame] | 2 | * This file is part of the libsigrok project. |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 3 | * |
Bert Vermeulen | 13d8e03 | 2013-03-24 11:21:00 +0100 | [diff] [blame] | 4 | * Copyright (C) 2013 Bert Vermeulen <bert@biot.com> |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 5 | * |
| 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 3 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 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. |
| 15 | * |
| 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/>. |
| 18 | */ |
| 19 | |
| 20 | #include <stdio.h> |
| 21 | #include <glib.h> |
Uwe Hermann | 545f978 | 2012-10-24 00:41:21 +0200 | [diff] [blame] | 22 | #include "config.h" /* Needed for HAVE_LIBUSB_1_0 and others. */ |
Bert Vermeulen | 45c59c8 | 2012-07-05 00:55:07 +0200 | [diff] [blame] | 23 | #include "libsigrok.h" |
| 24 | #include "libsigrok-internal.h" |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 25 | |
Uwe Hermann | 2ad1deb | 2014-04-25 18:40:59 +0200 | [diff] [blame] | 26 | /** @cond PRIVATE */ |
Martin Ling | 3544f84 | 2013-12-23 03:38:35 +0000 | [diff] [blame] | 27 | #define LOG_PREFIX "device" |
Uwe Hermann | 2ad1deb | 2014-04-25 18:40:59 +0200 | [diff] [blame] | 28 | /** @endcond */ |
Uwe Hermann | a885ce3 | 2012-11-11 12:44:16 +0100 | [diff] [blame] | 29 | |
Uwe Hermann | 7b870c3 | 2012-10-21 16:13:36 +0200 | [diff] [blame] | 30 | /** |
Uwe Hermann | 393fb9c | 2012-10-22 00:30:12 +0200 | [diff] [blame] | 31 | * @file |
| 32 | * |
| 33 | * Device handling in libsigrok. |
| 34 | */ |
| 35 | |
| 36 | /** |
Uwe Hermann | 7b870c3 | 2012-10-21 16:13:36 +0200 | [diff] [blame] | 37 | * @defgroup grp_devices Devices |
| 38 | * |
| 39 | * Device handling in libsigrok. |
| 40 | * |
| 41 | * @{ |
| 42 | */ |
| 43 | |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 44 | /** @private |
Uwe Hermann | 91aea75 | 2014-03-20 21:58:57 +0100 | [diff] [blame] | 45 | * Allocate and initialize new struct sr_channel |
| 46 | * @param[in] index @copydoc sr_channel::index |
| 47 | * @param[in] type @copydoc sr_channel::type |
| 48 | * @param[in] enabled @copydoc sr_channel::enabled |
| 49 | * @param[in] name @copydoc sr_channel::name |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 50 | * |
Uwe Hermann | 91aea75 | 2014-03-20 21:58:57 +0100 | [diff] [blame] | 51 | * @return NULL (failure) or new struct sr_channel*. |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 52 | */ |
Uwe Hermann | 56d0d24 | 2014-03-24 21:36:04 +0100 | [diff] [blame] | 53 | SR_PRIV struct sr_channel *sr_channel_new(int index, int type, |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 54 | gboolean enabled, const char *name) |
| 55 | { |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 56 | struct sr_channel *ch; |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 57 | |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 58 | if (!(ch = g_try_malloc0(sizeof(struct sr_channel)))) { |
| 59 | sr_err("Channel malloc failed."); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 60 | return NULL; |
| 61 | } |
| 62 | |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 63 | ch->index = index; |
| 64 | ch->type = type; |
| 65 | ch->enabled = enabled; |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 66 | if (name) |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 67 | ch->name = g_strdup(name); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 68 | |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 69 | return ch; |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 70 | } |
| 71 | |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 72 | /** |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 73 | * Set the name of the specified channel in the specified device. |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 74 | * |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 75 | * If the channel already has a different name assigned to it, it will be |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 76 | * removed, and the new name will be saved instead. |
| 77 | * |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 78 | * @param sdi The device instance the channel is connected to. |
| 79 | * @param[in] channelnum The number of the channel whose name to set. |
| 80 | * Note that the channel numbers start at 0. |
| 81 | * @param[in] name The new name that the specified channel should get. A copy |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 82 | * of the string is made. |
Uwe Hermann | 0e3b143 | 2011-12-28 17:16:33 +0100 | [diff] [blame] | 83 | * |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 84 | * @return SR_OK on success, or SR_ERR_ARG on invalid arguments. |
Uwe Hermann | 9fb5f2d | 2013-04-13 18:58:11 +0200 | [diff] [blame] | 85 | * |
Uwe Hermann | 4711724 | 2014-05-04 20:51:05 +0200 | [diff] [blame] | 86 | * @since 0.3.0 |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 87 | */ |
Uwe Hermann | f3ca73e | 2014-03-24 16:05:42 +0100 | [diff] [blame] | 88 | SR_API int sr_dev_channel_name_set(const struct sr_dev_inst *sdi, |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 89 | int channelnum, const char *name) |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 90 | { |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 91 | GSList *l; |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 92 | struct sr_channel *ch; |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 93 | int ret; |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 94 | |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 95 | if (!sdi) { |
| 96 | sr_err("%s: sdi was NULL", __func__); |
Uwe Hermann | 0e3b143 | 2011-12-28 17:16:33 +0100 | [diff] [blame] | 97 | return SR_ERR_ARG; |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 98 | } |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 99 | |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 100 | ret = SR_ERR_ARG; |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 101 | for (l = sdi->channels; l; l = l->next) { |
| 102 | ch = l->data; |
| 103 | if (ch->index == channelnum) { |
| 104 | g_free(ch->name); |
| 105 | ch->name = g_strdup(name); |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 106 | ret = SR_OK; |
| 107 | break; |
| 108 | } |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 109 | } |
| 110 | |
Bert Vermeulen | 37e8b4c | 2012-07-22 20:05:36 +0200 | [diff] [blame] | 111 | return ret; |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 112 | } |
| 113 | |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 114 | /** |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 115 | * Enable or disable a channel on the specified device. |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 116 | * |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 117 | * @param sdi The device instance the channel is connected to. |
| 118 | * @param channelnum The channel number, starting from 0. |
| 119 | * @param state TRUE to enable the channel, FALSE to disable. |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 120 | * |
Daniel Elstner | 2a854d7 | 2014-01-19 20:39:11 +0100 | [diff] [blame] | 121 | * @return SR_OK on success or SR_ERR on failure. In case of invalid |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 122 | * arguments, SR_ERR_ARG is returned and the channel enabled state |
Daniel Elstner | 2a854d7 | 2014-01-19 20:39:11 +0100 | [diff] [blame] | 123 | * remains unchanged. |
Uwe Hermann | 9fb5f2d | 2013-04-13 18:58:11 +0200 | [diff] [blame] | 124 | * |
Uwe Hermann | 4711724 | 2014-05-04 20:51:05 +0200 | [diff] [blame] | 125 | * @since 0.3.0 |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 126 | */ |
Uwe Hermann | f3ca73e | 2014-03-24 16:05:42 +0100 | [diff] [blame] | 127 | SR_API int sr_dev_channel_enable(const struct sr_dev_inst *sdi, int channelnum, |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 128 | gboolean state) |
| 129 | { |
| 130 | GSList *l; |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 131 | struct sr_channel *ch; |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 132 | int ret; |
Daniel Elstner | 2a854d7 | 2014-01-19 20:39:11 +0100 | [diff] [blame] | 133 | gboolean was_enabled; |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 134 | |
| 135 | if (!sdi) |
| 136 | return SR_ERR_ARG; |
| 137 | |
| 138 | ret = SR_ERR_ARG; |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 139 | for (l = sdi->channels; l; l = l->next) { |
| 140 | ch = l->data; |
| 141 | if (ch->index == channelnum) { |
| 142 | was_enabled = ch->enabled; |
| 143 | ch->enabled = state; |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 144 | ret = SR_OK; |
Daniel Elstner | 2a854d7 | 2014-01-19 20:39:11 +0100 | [diff] [blame] | 145 | if (!state != !was_enabled && sdi->driver |
Uwe Hermann | f3ca73e | 2014-03-24 16:05:42 +0100 | [diff] [blame] | 146 | && sdi->driver->config_channel_set) { |
| 147 | ret = sdi->driver->config_channel_set( |
Uwe Hermann | 3f239f0 | 2014-03-24 22:39:42 +0100 | [diff] [blame] | 148 | sdi, ch, SR_CHANNEL_SET_ENABLED); |
Daniel Elstner | 2a854d7 | 2014-01-19 20:39:11 +0100 | [diff] [blame] | 149 | /* Roll back change if it wasn't applicable. */ |
| 150 | if (ret == SR_ERR_ARG) |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 151 | ch->enabled = was_enabled; |
Daniel Elstner | 2a854d7 | 2014-01-19 20:39:11 +0100 | [diff] [blame] | 152 | } |
Bert Vermeulen | be5bf44 | 2012-07-22 12:23:59 +0200 | [diff] [blame] | 153 | break; |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | return ret; |
| 158 | } |
| 159 | |
| 160 | /** |
Uwe Hermann | 9c5332d | 2012-10-21 16:52:56 +0200 | [diff] [blame] | 161 | * Determine whether the specified device instance has the specified |
| 162 | * capability. |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 163 | * |
Uwe Hermann | 9c5332d | 2012-10-21 16:52:56 +0200 | [diff] [blame] | 164 | * @param sdi Pointer to the device instance to be checked. Must not be NULL. |
Uwe Hermann | 8ec95d2 | 2012-03-21 19:28:43 +0100 | [diff] [blame] | 165 | * If the device's 'driver' field is NULL (virtual device), this |
| 166 | * function will always return FALSE (virtual devices don't have |
| 167 | * a hardware capabilities list). |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 168 | * @param[in] key The option that should be checked for is supported by the |
Bert Vermeulen | 4d15e5c | 2013-01-25 16:20:40 +0100 | [diff] [blame] | 169 | * specified device. |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 170 | * |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 171 | * @retval TRUE Device has the specified option |
| 172 | * @retval FALSE Device does not have the specified option, invalid input |
| 173 | * parameters or other error conditions. |
Uwe Hermann | 9fb5f2d | 2013-04-13 18:58:11 +0200 | [diff] [blame] | 174 | * |
Uwe Hermann | 53f05fa | 2013-11-03 16:08:38 +0100 | [diff] [blame] | 175 | * @since 0.2.0 |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 176 | */ |
Bert Vermeulen | 4d15e5c | 2013-01-25 16:20:40 +0100 | [diff] [blame] | 177 | SR_API gboolean sr_dev_has_option(const struct sr_dev_inst *sdi, int key) |
Bert Vermeulen | 7d65887 | 2011-01-31 22:34:14 +0100 | [diff] [blame] | 178 | { |
Bert Vermeulen | 003595a | 2013-03-25 20:21:10 +0100 | [diff] [blame] | 179 | GVariant *gvar; |
Bert Vermeulen | 4d15e5c | 2013-01-25 16:20:40 +0100 | [diff] [blame] | 180 | const int *devopts; |
Bert Vermeulen | 003595a | 2013-03-25 20:21:10 +0100 | [diff] [blame] | 181 | gsize num_opts, i; |
| 182 | int ret; |
Bert Vermeulen | 7d65887 | 2011-01-31 22:34:14 +0100 | [diff] [blame] | 183 | |
Bert Vermeulen | 003595a | 2013-03-25 20:21:10 +0100 | [diff] [blame] | 184 | if (!sdi || !sdi->driver || !sdi->driver->config_list) |
Uwe Hermann | 8ec95d2 | 2012-03-21 19:28:43 +0100 | [diff] [blame] | 185 | return FALSE; |
Uwe Hermann | 218557b | 2011-02-13 11:27:52 +0100 | [diff] [blame] | 186 | |
Martin Ling | 8f996b8 | 2013-04-20 01:00:49 +0100 | [diff] [blame] | 187 | if (sdi->driver->config_list(SR_CONF_DEVICE_OPTIONS, |
poljar (Damir Jelić) | 92b68bb | 2014-01-16 02:53:41 +0100 | [diff] [blame] | 188 | &gvar, sdi, NULL) != SR_OK) |
Uwe Hermann | 8ec95d2 | 2012-03-21 19:28:43 +0100 | [diff] [blame] | 189 | return FALSE; |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 190 | |
Bert Vermeulen | 003595a | 2013-03-25 20:21:10 +0100 | [diff] [blame] | 191 | ret = FALSE; |
| 192 | devopts = g_variant_get_fixed_array(gvar, &num_opts, sizeof(int32_t)); |
| 193 | for (i = 0; i < num_opts; i++) { |
Bert Vermeulen | d099d88 | 2014-10-09 23:42:24 +0200 | [diff] [blame] | 194 | if ((devopts[i] & SR_CONF_MASK) == key) { |
Bert Vermeulen | 003595a | 2013-03-25 20:21:10 +0100 | [diff] [blame] | 195 | ret = TRUE; |
| 196 | break; |
| 197 | } |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 198 | } |
Bert Vermeulen | 003595a | 2013-03-25 20:21:10 +0100 | [diff] [blame] | 199 | g_variant_unref(gvar); |
Uwe Hermann | 94799bc | 2011-12-28 16:19:15 +0100 | [diff] [blame] | 200 | |
Bert Vermeulen | 003595a | 2013-03-25 20:21:10 +0100 | [diff] [blame] | 201 | return ret; |
Uwe Hermann | a1bb33a | 2010-04-02 20:18:27 +0200 | [diff] [blame] | 202 | } |
Anatoly Sokolov | fd9836b | 2012-01-29 16:56:06 +0400 | [diff] [blame] | 203 | |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 204 | /** @private |
| 205 | * Allocate and init new device instance struct. |
Uwe Hermann | 2eb84c9 | 2013-12-16 10:24:32 +0100 | [diff] [blame] | 206 | * @param[in] index @copydoc sr_dev_inst::index |
| 207 | * @param[in] status @copydoc sr_dev_inst::status |
| 208 | * @param[in] vendor @copydoc sr_dev_inst::vendor |
| 209 | * @param[in] model @copydoc sr_dev_inst::model |
| 210 | * @param[in] version @copydoc sr_dev_inst::version |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 211 | * |
Uwe Hermann | 2eb84c9 | 2013-12-16 10:24:32 +0100 | [diff] [blame] | 212 | * @retval NULL Error |
| 213 | * @retval struct sr_dev_inst *. Dynamically allocated, free using |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 214 | * sr_dev_inst_free(). |
| 215 | */ |
Soeren Apel | 1b9e567 | 2014-09-27 22:20:51 +0200 | [diff] [blame] | 216 | SR_PRIV struct sr_dev_inst *sr_dev_inst_new(int status, |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 217 | const char *vendor, const char *model, const char *version) |
| 218 | { |
| 219 | struct sr_dev_inst *sdi; |
| 220 | |
| 221 | if (!(sdi = g_try_malloc(sizeof(struct sr_dev_inst)))) { |
Uwe Hermann | c4227fc | 2013-01-29 12:55:00 +0100 | [diff] [blame] | 222 | sr_err("Device instance malloc failed."); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 223 | return NULL; |
| 224 | } |
| 225 | |
Bert Vermeulen | e8d3d6c | 2012-07-29 03:01:57 +0200 | [diff] [blame] | 226 | sdi->driver = NULL; |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 227 | sdi->status = status; |
| 228 | sdi->inst_type = -1; |
| 229 | sdi->vendor = vendor ? g_strdup(vendor) : NULL; |
| 230 | sdi->model = model ? g_strdup(model) : NULL; |
| 231 | sdi->version = version ? g_strdup(version) : NULL; |
Soeren Apel | 2fe6210 | 2014-09-23 17:43:27 +0200 | [diff] [blame] | 232 | sdi->serial_num = NULL; |
| 233 | sdi->connection_id = NULL; |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 234 | sdi->channels = NULL; |
Uwe Hermann | 660e398 | 2014-03-14 21:09:37 +0100 | [diff] [blame] | 235 | sdi->channel_groups = NULL; |
Martin Ling | 0812c40 | 2014-05-04 23:07:00 +0100 | [diff] [blame] | 236 | sdi->session = NULL; |
Bert Vermeulen | 9e2e986 | 2012-10-01 03:03:24 +0200 | [diff] [blame] | 237 | sdi->conn = NULL; |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 238 | sdi->priv = NULL; |
| 239 | |
| 240 | return sdi; |
| 241 | } |
| 242 | |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 243 | /** @private |
| 244 | * Free device instance struct created by sr_dev_inst(). |
Uwe Hermann | 2eb84c9 | 2013-12-16 10:24:32 +0100 | [diff] [blame] | 245 | * @param sdi struct* to free. |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 246 | */ |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 247 | SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi) |
| 248 | { |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 249 | struct sr_channel *ch; |
Bert Vermeulen | d3cff73 | 2012-08-04 12:03:05 +0200 | [diff] [blame] | 250 | GSList *l; |
| 251 | |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 252 | for (l = sdi->channels; l; l = l->next) { |
| 253 | ch = l->data; |
| 254 | g_free(ch->name); |
Bert Vermeulen | 379d260 | 2014-09-08 03:25:41 +0200 | [diff] [blame] | 255 | g_free(ch->priv); |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 256 | g_free(ch); |
Bert Vermeulen | d3cff73 | 2012-08-04 12:03:05 +0200 | [diff] [blame] | 257 | } |
Uwe Hermann | ba7dd8b | 2014-03-24 21:34:20 +0100 | [diff] [blame] | 258 | g_slist_free(sdi->channels); |
Bert Vermeulen | d3cff73 | 2012-08-04 12:03:05 +0200 | [diff] [blame] | 259 | |
Uwe Hermann | 660e398 | 2014-03-14 21:09:37 +0100 | [diff] [blame] | 260 | if (sdi->channel_groups) |
| 261 | g_slist_free(sdi->channel_groups); |
poljar (Damir Jelić) | 90c7f4e | 2013-11-19 01:08:18 +0100 | [diff] [blame] | 262 | |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 263 | g_free(sdi->vendor); |
| 264 | g_free(sdi->model); |
| 265 | g_free(sdi->version); |
Soeren Apel | 2fe6210 | 2014-09-23 17:43:27 +0200 | [diff] [blame] | 266 | g_free(sdi->serial_num); |
| 267 | g_free(sdi->connection_id); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 268 | g_free(sdi); |
| 269 | } |
| 270 | |
| 271 | #ifdef HAVE_LIBUSB_1_0 |
| 272 | |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 273 | /** @private |
| 274 | * Allocate and init struct for USB device instance. |
Uwe Hermann | 2eb84c9 | 2013-12-16 10:24:32 +0100 | [diff] [blame] | 275 | * @param[in] bus @copydoc sr_usb_dev_inst::bus |
| 276 | * @param[in] address @copydoc sr_usb_dev_inst::address |
| 277 | * @param[in] hdl @copydoc sr_usb_dev_inst::devhdl |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 278 | * |
Uwe Hermann | 2eb84c9 | 2013-12-16 10:24:32 +0100 | [diff] [blame] | 279 | * @retval NULL Error |
| 280 | * @retval other struct sr_usb_dev_inst * for USB device instance. |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 281 | */ |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 282 | SR_PRIV struct sr_usb_dev_inst *sr_usb_dev_inst_new(uint8_t bus, |
| 283 | uint8_t address, struct libusb_device_handle *hdl) |
| 284 | { |
| 285 | struct sr_usb_dev_inst *udi; |
| 286 | |
| 287 | if (!(udi = g_try_malloc(sizeof(struct sr_usb_dev_inst)))) { |
Uwe Hermann | c4227fc | 2013-01-29 12:55:00 +0100 | [diff] [blame] | 288 | sr_err("USB device instance malloc failed."); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 289 | return NULL; |
| 290 | } |
| 291 | |
| 292 | udi->bus = bus; |
| 293 | udi->address = address; |
| 294 | udi->devhdl = hdl; |
| 295 | |
| 296 | return udi; |
| 297 | } |
| 298 | |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 299 | /** @private |
| 300 | * Free struct * allocated by sr_usb_dev_inst(). |
Uwe Hermann | 2eb84c9 | 2013-12-16 10:24:32 +0100 | [diff] [blame] | 301 | * @param usb struct* to free. Must not be NULL. |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 302 | */ |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 303 | SR_PRIV void sr_usb_dev_inst_free(struct sr_usb_dev_inst *usb) |
| 304 | { |
Bert Vermeulen | a006798 | 2013-05-06 00:40:17 +0200 | [diff] [blame] | 305 | g_free(usb); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 306 | } |
| 307 | |
| 308 | #endif |
| 309 | |
Uwe Hermann | c4f2dfd | 2013-11-13 19:56:13 +0100 | [diff] [blame] | 310 | #ifdef HAVE_LIBSERIALPORT |
| 311 | |
Uwe Hermann | 9fb5f2d | 2013-04-13 18:58:11 +0200 | [diff] [blame] | 312 | /** |
| 313 | * @private |
Bert Vermeulen | 299bdb2 | 2012-11-11 20:38:47 +0100 | [diff] [blame] | 314 | * |
| 315 | * Both parameters are copied to newly allocated strings, and freed |
| 316 | * automatically by sr_serial_dev_inst_free(). |
Uwe Hermann | 9fb5f2d | 2013-04-13 18:58:11 +0200 | [diff] [blame] | 317 | * |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 318 | * @param[in] port OS-specific serial port specification. Examples: |
Uwe Hermann | 9fb5f2d | 2013-04-13 18:58:11 +0200 | [diff] [blame] | 319 | * "/dev/ttyUSB0", "/dev/ttyACM1", "/dev/tty.Modem-0", "COM1". |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 320 | * @param[in] serialcomm A serial communication parameters string, in the form |
| 321 | * of \<speed\>/\<data bits\>\<parity\>\<stopbits\>, for example |
| 322 | * "9600/8n1" or "600/7o2". This is an optional parameter; |
| 323 | * it may be filled in later. |
Uwe Hermann | 9fb5f2d | 2013-04-13 18:58:11 +0200 | [diff] [blame] | 324 | * |
| 325 | * @return A pointer to a newly initialized struct sr_serial_dev_inst, |
| 326 | * or NULL on error. |
Bert Vermeulen | 299bdb2 | 2012-11-11 20:38:47 +0100 | [diff] [blame] | 327 | */ |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 328 | SR_PRIV struct sr_serial_dev_inst *sr_serial_dev_inst_new(const char *port, |
Bert Vermeulen | 299bdb2 | 2012-11-11 20:38:47 +0100 | [diff] [blame] | 329 | const char *serialcomm) |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 330 | { |
| 331 | struct sr_serial_dev_inst *serial; |
| 332 | |
Bert Vermeulen | 299bdb2 | 2012-11-11 20:38:47 +0100 | [diff] [blame] | 333 | if (!port) { |
Uwe Hermann | c4227fc | 2013-01-29 12:55:00 +0100 | [diff] [blame] | 334 | sr_err("Serial port required."); |
Bert Vermeulen | 299bdb2 | 2012-11-11 20:38:47 +0100 | [diff] [blame] | 335 | return NULL; |
| 336 | } |
| 337 | |
| 338 | if (!(serial = g_try_malloc0(sizeof(struct sr_serial_dev_inst)))) { |
Uwe Hermann | c4227fc | 2013-01-29 12:55:00 +0100 | [diff] [blame] | 339 | sr_err("Serial device instance malloc failed."); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 340 | return NULL; |
| 341 | } |
| 342 | |
| 343 | serial->port = g_strdup(port); |
Bert Vermeulen | 299bdb2 | 2012-11-11 20:38:47 +0100 | [diff] [blame] | 344 | if (serialcomm) |
| 345 | serial->serialcomm = g_strdup(serialcomm); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 346 | |
| 347 | return serial; |
| 348 | } |
| 349 | |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 350 | /** @private |
| 351 | * Free struct sr_serial_dev_inst * allocated by sr_serial_dev_inst(). |
Uwe Hermann | 2eb84c9 | 2013-12-16 10:24:32 +0100 | [diff] [blame] | 352 | * @param serial struct sr_serial_dev_inst * to free. Must not be NULL. |
Matthias Heidbrink | 04cb915 | 2013-11-22 20:40:52 +0100 | [diff] [blame] | 353 | */ |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 354 | SR_PRIV void sr_serial_dev_inst_free(struct sr_serial_dev_inst *serial) |
| 355 | { |
| 356 | g_free(serial->port); |
Bert Vermeulen | 299bdb2 | 2012-11-11 20:38:47 +0100 | [diff] [blame] | 357 | g_free(serial->serialcomm); |
Alexandru Gagniuc | acac8fc | 2012-12-19 21:39:38 -0600 | [diff] [blame] | 358 | g_free(serial); |
Bert Vermeulen | 48a486c | 2012-07-25 00:20:06 +0200 | [diff] [blame] | 359 | } |
Uwe Hermann | c4f2dfd | 2013-11-13 19:56:13 +0100 | [diff] [blame] | 360 | #endif |
| 361 | |
Uwe Hermann | df823ac | 2013-12-27 16:18:28 +0100 | [diff] [blame] | 362 | /** @private */ |
Martin Ling | ae67644 | 2013-11-29 00:48:42 +0000 | [diff] [blame] | 363 | SR_PRIV struct sr_usbtmc_dev_inst *sr_usbtmc_dev_inst_new(const char *device) |
| 364 | { |
| 365 | struct sr_usbtmc_dev_inst *usbtmc; |
| 366 | |
| 367 | if (!device) { |
| 368 | sr_err("Device name required."); |
| 369 | return NULL; |
| 370 | } |
| 371 | |
| 372 | if (!(usbtmc = g_try_malloc0(sizeof(struct sr_usbtmc_dev_inst)))) { |
| 373 | sr_err("USBTMC device instance malloc failed."); |
| 374 | return NULL; |
| 375 | } |
| 376 | |
| 377 | usbtmc->device = g_strdup(device); |
| 378 | usbtmc->fd = -1; |
| 379 | |
| 380 | return usbtmc; |
| 381 | } |
| 382 | |
Uwe Hermann | df823ac | 2013-12-27 16:18:28 +0100 | [diff] [blame] | 383 | /** @private */ |
Martin Ling | ae67644 | 2013-11-29 00:48:42 +0000 | [diff] [blame] | 384 | SR_PRIV void sr_usbtmc_dev_inst_free(struct sr_usbtmc_dev_inst *usbtmc) |
| 385 | { |
| 386 | g_free(usbtmc->device); |
| 387 | g_free(usbtmc); |
| 388 | } |
| 389 | |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 390 | /** |
| 391 | * Get the list of devices/instances of the specified driver. |
| 392 | * |
| 393 | * @param driver The driver to use. Must not be NULL. |
| 394 | * |
| 395 | * @return The list of devices/instances of this driver, or NULL upon errors |
| 396 | * or if the list is empty. |
| 397 | * |
Uwe Hermann | 53f05fa | 2013-11-03 16:08:38 +0100 | [diff] [blame] | 398 | * @since 0.2.0 |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 399 | */ |
Bert Vermeulen | f99e32a | 2013-04-22 15:55:06 +0200 | [diff] [blame] | 400 | SR_API GSList *sr_dev_list(const struct sr_dev_driver *driver) |
Bert Vermeulen | 811deee | 2012-08-06 00:59:25 +0200 | [diff] [blame] | 401 | { |
Bert Vermeulen | 811deee | 2012-08-06 00:59:25 +0200 | [diff] [blame] | 402 | if (driver && driver->dev_list) |
| 403 | return driver->dev_list(); |
| 404 | else |
| 405 | return NULL; |
| 406 | } |
| 407 | |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 408 | /** |
Bert Vermeulen | 8102cee | 2014-02-26 21:25:07 +0100 | [diff] [blame] | 409 | * Clear the list of device instances a driver knows about. |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 410 | * |
Bert Vermeulen | 8102cee | 2014-02-26 21:25:07 +0100 | [diff] [blame] | 411 | * @param driver The driver to use. This must be a pointer to one of |
| 412 | * the entries returned by sr_driver_list(). Must not be NULL. |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 413 | * |
Bert Vermeulen | 8102cee | 2014-02-26 21:25:07 +0100 | [diff] [blame] | 414 | * @retval SR_OK Success |
| 415 | * @retval SR_ERR_ARG Invalid driver |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 416 | * |
| 417 | * @since 0.2.0 |
| 418 | */ |
Bert Vermeulen | f99e32a | 2013-04-22 15:55:06 +0200 | [diff] [blame] | 419 | SR_API int sr_dev_clear(const struct sr_dev_driver *driver) |
Bert Vermeulen | 811deee | 2012-08-06 00:59:25 +0200 | [diff] [blame] | 420 | { |
Bert Vermeulen | 8102cee | 2014-02-26 21:25:07 +0100 | [diff] [blame] | 421 | int ret; |
| 422 | |
| 423 | if (!driver) { |
| 424 | sr_err("Invalid driver."); |
| 425 | return SR_ERR_ARG; |
| 426 | } |
| 427 | |
| 428 | if (driver->dev_clear) |
| 429 | ret = driver->dev_clear(); |
Bert Vermeulen | 811deee | 2012-08-06 00:59:25 +0200 | [diff] [blame] | 430 | else |
Bert Vermeulen | 8102cee | 2014-02-26 21:25:07 +0100 | [diff] [blame] | 431 | ret = std_dev_clear(driver, NULL); |
| 432 | |
| 433 | return ret; |
Bert Vermeulen | 811deee | 2012-08-06 00:59:25 +0200 | [diff] [blame] | 434 | } |
| 435 | |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 436 | /** |
| 437 | * Open the specified device. |
| 438 | * |
| 439 | * @param sdi Device instance to use. Must not be NULL. |
| 440 | * |
| 441 | * @return SR_OK upon success, a negative error code upon errors. |
| 442 | * |
| 443 | * @since 0.2.0 |
| 444 | */ |
Bert Vermeulen | efdecf4 | 2013-04-23 00:21:57 +0200 | [diff] [blame] | 445 | SR_API int sr_dev_open(struct sr_dev_inst *sdi) |
| 446 | { |
| 447 | int ret; |
| 448 | |
| 449 | if (!sdi || !sdi->driver || !sdi->driver->dev_open) |
| 450 | return SR_ERR; |
| 451 | |
| 452 | ret = sdi->driver->dev_open(sdi); |
| 453 | |
| 454 | return ret; |
| 455 | } |
| 456 | |
Uwe Hermann | 576ff5b | 2013-05-05 17:14:20 +0200 | [diff] [blame] | 457 | /** |
| 458 | * Close the specified device. |
| 459 | * |
| 460 | * @param sdi Device instance to use. Must not be NULL. |
| 461 | * |
| 462 | * @return SR_OK upon success, a negative error code upon errors. |
| 463 | * |
| 464 | * @since 0.2.0 |
| 465 | */ |
Bert Vermeulen | efdecf4 | 2013-04-23 00:21:57 +0200 | [diff] [blame] | 466 | SR_API int sr_dev_close(struct sr_dev_inst *sdi) |
| 467 | { |
| 468 | int ret; |
| 469 | |
| 470 | if (!sdi || !sdi->driver || !sdi->driver->dev_close) |
| 471 | return SR_ERR; |
| 472 | |
| 473 | ret = sdi->driver->dev_close(sdi); |
| 474 | |
| 475 | return ret; |
| 476 | } |
| 477 | |
Soeren Apel | 0157fdc | 2014-10-16 20:17:04 +0200 | [diff] [blame^] | 478 | /** |
| 479 | * Queries a device instances' driver. |
| 480 | * |
| 481 | * @param sdi Device instance to use. Must not be NULL. |
| 482 | * |
| 483 | * @return The driver instance or NULL on error. |
| 484 | */ |
| 485 | SR_API struct sr_dev_driver *sr_dev_inst_driver_get(struct sr_dev_inst *sdi) |
| 486 | { |
| 487 | if (!sdi || !sdi->driver) |
| 488 | return NULL; |
| 489 | |
| 490 | return sdi->driver; |
| 491 | } |
| 492 | |
| 493 | /** |
| 494 | * Queries a device instances' vendor. |
| 495 | * |
| 496 | * @param sdi Device instance to use. Must not be NULL. |
| 497 | * |
| 498 | * @return The vendor string or NULL. |
| 499 | */ |
| 500 | SR_API const char *sr_dev_inst_vendor_get(struct sr_dev_inst *sdi) |
| 501 | { |
| 502 | if (!sdi) |
| 503 | return NULL; |
| 504 | |
| 505 | return sdi->vendor; |
| 506 | } |
| 507 | |
| 508 | /** |
| 509 | * Queries a device instances' model. |
| 510 | * |
| 511 | * @param sdi Device instance to use. Must not be NULL. |
| 512 | * |
| 513 | * @return The model string or NULL. |
| 514 | */ |
| 515 | SR_API const char *sr_dev_inst_model_get(struct sr_dev_inst *sdi) |
| 516 | { |
| 517 | if (!sdi) |
| 518 | return NULL; |
| 519 | |
| 520 | return sdi->model; |
| 521 | } |
| 522 | |
| 523 | /** |
| 524 | * Queries a device instances' version. |
| 525 | * |
| 526 | * @param sdi Device instance to use. Must not be NULL. |
| 527 | * |
| 528 | * @return The version string or NULL. |
| 529 | */ |
| 530 | SR_API const char *sr_dev_inst_version_get(struct sr_dev_inst *sdi) |
| 531 | { |
| 532 | if (!sdi) |
| 533 | return NULL; |
| 534 | |
| 535 | return sdi->version; |
| 536 | } |
| 537 | |
| 538 | /** |
| 539 | * Queries a device instances' serial number. |
| 540 | * |
| 541 | * @param sdi Device instance to use. Must not be NULL. |
| 542 | * |
| 543 | * @return The serial number string or NULL. |
| 544 | */ |
| 545 | SR_API const char *sr_dev_inst_sernum_get(struct sr_dev_inst *sdi) |
| 546 | { |
| 547 | if (!sdi) |
| 548 | return NULL; |
| 549 | |
| 550 | return sdi->serial_num; |
| 551 | } |
| 552 | |
| 553 | /** |
| 554 | * Queries a device instances' connection identifier. |
| 555 | * |
| 556 | * @param sdi Device instance to use. Must not be NULL. |
| 557 | * |
| 558 | * @return A copy of the connection id string or NULL. The caller is responsible |
| 559 | * for g_free()ing the string when it is no longer needed. |
| 560 | */ |
| 561 | SR_API const char *sr_dev_inst_connid_get(struct sr_dev_inst *sdi) |
| 562 | { |
| 563 | struct drv_context *drvc; |
| 564 | struct sr_usb_dev_inst *usb; |
| 565 | struct libusb_device **devlist; |
| 566 | struct libusb_device_descriptor des; |
| 567 | int r, cnt, i, a, b; |
| 568 | char connection_id[64]; |
| 569 | |
| 570 | if (!sdi) |
| 571 | return NULL; |
| 572 | |
| 573 | if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_USB)) { |
| 574 | /* connection_id isn't populated, let's do that here. */ |
| 575 | |
| 576 | drvc = sdi->driver->priv; |
| 577 | usb = sdi->conn; |
| 578 | |
| 579 | if ((cnt = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist)) < 0) { |
| 580 | sr_err("Failed to retrieve device list: %s.", |
| 581 | libusb_error_name(cnt)); |
| 582 | return NULL; |
| 583 | } |
| 584 | |
| 585 | for (i = 0; i < cnt; i++) { |
| 586 | if ((r = libusb_get_device_descriptor(devlist[i], &des)) < 0) { |
| 587 | sr_err("Failed to get device descriptor: %s.", |
| 588 | libusb_error_name(r)); |
| 589 | continue; |
| 590 | } |
| 591 | |
| 592 | /* Find the USB device by the logical address we know. */ |
| 593 | b = libusb_get_bus_number(devlist[i]); |
| 594 | a = libusb_get_device_address(devlist[i]); |
| 595 | if (b != usb->bus || a != usb->address) |
| 596 | continue; |
| 597 | |
| 598 | usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)); |
| 599 | sdi->connection_id = g_strdup(connection_id); |
| 600 | break; |
| 601 | } |
| 602 | |
| 603 | libusb_free_device_list(devlist, 1); |
| 604 | } |
| 605 | |
| 606 | return sdi->connection_id; |
| 607 | } |
| 608 | |
Uwe Hermann | 7b870c3 | 2012-10-21 16:13:36 +0200 | [diff] [blame] | 609 | /** @} */ |