libflashprog: Add new API to probe all buses for chips
The new flashprog_chips_probe() will supersede our existing logic to
probe for an unspecified chip. It returns an enumeration of detected
chips. It's up to the caller to handle multiple chip matches.
Change-Id: I21ec201b92289995430130d72823fe4ca8b03bb6
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/483
diff --git a/include/libflashprog.h b/include/libflashprog.h
index eec69ee..8afd8d5 100644
--- a/include/libflashprog.h
+++ b/include/libflashprog.h
@@ -49,6 +49,8 @@
__attribute__((nonnull))
int flashprog_chips_all(struct flashprog_chips **);
__attribute__((nonnull))
+int flashprog_chips_probe(struct flashprog_chips **, const struct flashprog_programmer *);
+__attribute__((nonnull))
unsigned int flashprog_chips_count(const struct flashprog_chips *);
void flashprog_chips_release(struct flashprog_chips *);
diff --git a/libflashprog.map b/libflashprog.map
index 709db87..033d5f8 100644
--- a/libflashprog.map
+++ b/libflashprog.map
@@ -11,6 +11,7 @@
flashprog_chip_voltage_range;
flashprog_chips_all;
flashprog_chips_count;
+ flashprog_chips_probe;
flashprog_chips_release;
flashprog_flag_get;
flashprog_flag_set;
diff --git a/libflashprog/chips.c b/libflashprog/chips.c
index 0b43e6f..919d0eb 100644
--- a/libflashprog/chips.c
+++ b/libflashprog/chips.c
@@ -21,6 +21,7 @@
#include "flash.h"
#include "flashchips.h"
+#include "programmer.h"
/**
* @defgroup flashprog-chips Chip Enumeration
@@ -30,6 +31,16 @@
/* Magic pointer that represents our built in database. */
#define FLASHCHIPS_DB (struct flashprog_chips *)(uintptr_t)-1
+/** @private */
+struct flashprog_chips {
+ /** @private */
+ struct chip_entry {
+ struct flashprog_chip chip;
+ const struct master_common *bus;
+ struct chip_entry *next;
+ } *entries;
+};
+
static bool chip_from_db(const struct flashprog_chip *chip) {
return flashchips <= chip && chip < flashchips + flashchips_size;
}
@@ -47,6 +58,72 @@
return 0;
}
+static int flashprog_chips_probe_bus(struct flashprog_chips *chips,
+ struct registered_master *bus)
+{
+ flashprog_bus_probe(bus, NULL);
+
+ int chip;
+ for (chip = 0; flashchips[chip].name; ++chip) {
+ /* Ignore generic entries if we already have a match. */
+ if (chips->entries &&
+ ((flashchips[chip].id.model == SFDP_DEVICE_ID) ||
+ (flashchips[chip].id.model == GENERIC_DEVICE_ID)))
+ continue;
+
+ if (!flashprog_chip_match(bus, &flashchips[chip]))
+ continue;
+
+ struct chip_entry *const entry = malloc(sizeof(*entry));
+ if (!entry) {
+ msg_cerr("Out of memory!\n");
+ return 1;
+ }
+
+ entry->chip = flashchips[chip];
+ entry->bus = &bus->common;
+ entry->next = chips->entries;
+
+ chips->entries = entry;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Probe for flash chips.
+ *
+ * Probes for flash chips on a given programmer. Can return multiple
+ * matches in case of ambiguous IDs or when the programmer features
+ * multiple buses.
+ *
+ * @param[out] chips Points to a struct flashprog_chips pointer that gets
+ * set if probing is successful. *chips has to be freed
+ * by the caller with @ref flashprog_chips_release after
+ * successful calls.
+ * @param[in] flashprog The flash programmer used to access the chip.
+ * @return 0 on success
+ */
+int flashprog_chips_probe(struct flashprog_chips **chips, const struct flashprog_programmer *flashprog)
+{
+ struct flashprog_chips *const matched_chips = calloc(1, sizeof(*matched_chips));
+ if (!matched_chips) {
+ msg_gerr("Out of memory!\n");
+ return 1;
+ }
+
+ int bus_index;
+ for (bus_index = 0; bus_index < registered_master_count; bus_index++) {
+ if (flashprog_chips_probe_bus(matched_chips, ®istered_masters[bus_index])) {
+ flashprog_chips_release(matched_chips);
+ return 1;
+ }
+ }
+
+ *chips = matched_chips;
+ return 0;
+}
+
/**
* @brief Count the chips in an enumeration.
*
@@ -72,9 +149,14 @@
*/
void flashprog_chips_release(struct flashprog_chips *chips)
{
- if (chips == FLASHCHIPS_DB)
+ if (!chips || chips == FLASHCHIPS_DB)
return;
+ struct chip_entry *next;
+ for (; chips->entries; chips->entries = next) {
+ next = chips->entries->next;
+ free(chips->entries);
+ }
free(chips);
}
@@ -95,7 +177,7 @@
if (chips == FLASHCHIPS_DB)
return flashchips;
- return NULL;
+ return &chips->entries->chip;
}
/**
@@ -124,7 +206,8 @@
return NULL;
}
- return NULL;
+ /* If not in the DB, it must be a probed `chip_entry`. */
+ return &((const struct chip_entry *)chip)->next->chip;
}
/** @} */ /* end flashprog-chips */