]> sigrok.org Git - libsigrok.git/commitdiff
fx2lafw: add support for "probe names" scan option
authorGerhard Sittig <redacted>
Sun, 14 Aug 2022 18:27:25 +0000 (20:27 +0200)
committerGerhard Sittig <redacted>
Wed, 24 Aug 2022 18:05:25 +0000 (20:05 +0200)
Add support for the SR_CONF_PROBE_NAMES scan option. Optionally assign
user specified channel names instead of the driver's builtin names.

It's essential to create sdi and devc before scanning the probe names
spec. The previous logic which printed channel names to a local buffer
got replaced by a const table of channel names. This commit is a little
longer because checks are added, to make sure that future models with
more channels won't exceed the static const tables.

This implementation exclusively allows to specify logic channel names.
Analog channels keep the open coded naming pattern. Because the driver
supports different models with differing numbers of channels of several
types, covering analog channels in the "probe names" feature requires
more runtime effort to create the table of default channel names for the
specific device that was found. This remains as an option for a later
commit.

src/hardware/fx2lafw/api.c
src/hardware/fx2lafw/protocol.c
src/hardware/fx2lafw/protocol.h

index 4665bca2419deae0f0347e6e2aa5039462ef04d0..255788bfdd0731233ca75e0a9454bb7021ce5de2 100644 (file)
@@ -117,6 +117,7 @@ static const struct fx2lafw_profile supported_fx2[] = {
 
 static const uint32_t scanopts[] = {
        SR_CONF_CONN,
+       SR_CONF_PROBE_NAMES,
 };
 
 static const uint32_t drvopts[] = {
@@ -161,6 +162,15 @@ static const uint64_t samplerates[] = {
        SR_MHZ(48),
 };
 
+static const char *channel_names_logic[] = {
+       "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+       "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
+};
+
+static const char *channel_names_analog[] = {
+       "A0", "A1", "A2", "A3",
+};
+
 static gboolean is_plausible(const struct libusb_device_descriptor *des)
 {
        int i;
@@ -190,21 +200,27 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
        struct libusb_device_descriptor des;
        libusb_device **devlist;
        struct libusb_device_handle *hdl;
-       int ret, i, j;
-       int num_logic_channels = 0, num_analog_channels = 0;
+       int ret, i;
+       size_t j, num_logic_channels, num_analog_channels;
        const char *conn;
+       const char *probe_names;
        char manufacturer[64], product[64], serial_num[64], connection_id[64];
-       char channel_name[16];
+       size_t ch_max, ch_idx;
+       const char *channel_name;
 
        drvc = di->context;
 
        conn = NULL;
+       probe_names = NULL;
        for (l = options; l; l = l->next) {
                src = l->data;
                switch (src->key) {
                case SR_CONF_CONN:
                        conn = g_variant_get_string(src->data, NULL);
                        break;
+               case SR_CONF_PROBE_NAMES:
+                       probe_names = g_variant_get_string(src->data, NULL);
+                       break;
                }
        }
        if (conn)
@@ -301,34 +317,56 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
                sdi->serial_num = g_strdup(serial_num);
                sdi->connection_id = g_strdup(connection_id);
 
+               devc = fx2lafw_dev_new();
+               devc->profile = prof;
+               sdi->priv = devc;
+               devices = g_slist_append(devices, sdi);
+
                /* Fill in channellist according to this device's profile. */
                num_logic_channels = prof->dev_caps & DEV_CAPS_16BIT ? 16 : 8;
+               if (num_logic_channels > ARRAY_SIZE(channel_names_logic))
+                       num_logic_channels = ARRAY_SIZE(channel_names_logic);
                num_analog_channels = prof->dev_caps & DEV_CAPS_AX_ANALOG ? 1 : 0;
+               if (num_analog_channels > ARRAY_SIZE(channel_names_analog))
+                       num_analog_channels = ARRAY_SIZE(channel_names_analog);
+
+               /*
+                * Allow user specs to override the builtin probe names.
+                *
+                * Implementor's note: Because the device's number of
+                * logic channels is not known at compile time, and thus
+                * the location of the analog channel names is not known
+                * at compile time, and the construction of a list with
+                * default names at runtime is not done here, and we
+                * don't want to keep several default lists around, this
+                * implementation only supports to override the names of
+                * logic probes. The use case which motivated the config
+                * key is protocol decoders, which are logic only.
+                */
+               ch_max = num_logic_channels;
+               devc->channel_names = sr_parse_probe_names(probe_names,
+                       channel_names_logic, ch_max, ch_max, &ch_max);
+               ch_idx = 0;
 
                /* Logic channels, all in one channel group. */
                cg = sr_channel_group_new(sdi, "Logic", NULL);
                for (j = 0; j < num_logic_channels; j++) {
-                       sprintf(channel_name, "D%d", j);
-                       ch = sr_channel_new(sdi, j, SR_CHANNEL_LOGIC,
-                                               TRUE, channel_name);
+                       channel_name = devc->channel_names[j];
+                       ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_LOGIC,
+                               TRUE, channel_name);
                        cg->channels = g_slist_append(cg->channels, ch);
                }
 
                for (j = 0; j < num_analog_channels; j++) {
-                       snprintf(channel_name, 16, "A%d", j);
-                       ch = sr_channel_new(sdi, j + num_logic_channels,
-                                       SR_CHANNEL_ANALOG, TRUE, channel_name);
+                       channel_name = channel_names_analog[j];
+                       ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG,
+                               TRUE, channel_name);
 
                        /* Every analog channel gets its own channel group. */
                        cg = sr_channel_group_new(sdi, channel_name, NULL);
                        cg->channels = g_slist_append(NULL, ch);
                }
 
-               devc = fx2lafw_dev_new();
-               devc->profile = prof;
-               sdi->priv = devc;
-               devices = g_slist_append(devices, sdi);
-
                devc->samplerates = samplerates;
                devc->num_samplerates = ARRAY_SIZE(samplerates);
                has_firmware = usb_match_manuf_prod(devlist[i],
index 963d0336e59c4000e24a0f51542776cbda9678b4..8854f5a69afd7221931b606b6d0c24a6001426c9 100644 (file)
@@ -255,6 +255,7 @@ SR_PRIV struct dev_context *fx2lafw_dev_new(void)
 
        devc = g_malloc0(sizeof(struct dev_context));
        devc->profile = NULL;
+       devc->channel_names = NULL;
        devc->fw_updated = 0;
        devc->cur_samplerate = 0;
        devc->limit_frames = 1;
index 2c56b02ca6962cae97d55d03f190182aa4b1438f..91f0e9fb64745154b4b0fddbbcab5c0157a213b5 100644 (file)
@@ -89,6 +89,7 @@ struct fx2lafw_profile {
 
 struct dev_context {
        const struct fx2lafw_profile *profile;
+       char **channel_names;
        GSList *enabled_analog_channels;
        /*
         * Since we can't keep track of an fx2lafw device after upgrading