libflashprog: Use newer APIs within flashprog_flash_probe()

We start using the new flashprog_chips_probe() enumeration API.
Handling of multiple chips, i.e. logging their names, is taken
from `cli_classic`.  When a chip name is given, we'll skip the
enumeration and call the new flashprog_flash_probe_chip().

Change-Id: I11dea1e8d6973ce8d9565778c25f2196cb98561c
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/485
diff --git a/cli_config.c b/cli_config.c
index f713712..5275fe2 100644
--- a/cli_config.c
+++ b/cli_config.c
@@ -236,7 +236,11 @@
 
 	if (flashprog_programmer_init(&prog, flash_args.prog_name, flash_args.prog_args))
 		goto free_ret;
-	if (flashprog_flash_probe(&flash, prog, flash_args.chip)) {
+	ret = flashprog_flash_probe(&flash, prog, flash_args.chip);
+	if (ret == 3) {
+		fprintf(stderr, "Please specify which chip definition to use with the -c <chipname> option.\n");
+		goto shutdown_ret;
+	} else if (ret) {
 		fprintf(stderr, "No EEPROM/flash device found.\n");
 		goto shutdown_ret;
 	}
diff --git a/cli_wp.c b/cli_wp.c
index d6c5ed7..c8d7802 100644
--- a/cli_wp.c
+++ b/cli_wp.c
@@ -406,8 +406,7 @@
 		goto free_ret;
 	ret = flashprog_flash_probe(&flash, prog, flash_args.chip);
 	if (ret == 3) {
-		fprintf(stderr, "Multiple flash chip definitions match the detected chip.\n"
-				"Please specify which chip definition to use with the -c <chipname> option.\n");
+		fprintf(stderr, "Please specify which chip definition to use with the -c <chipname> option.\n");
 		goto shutdown_ret;
 	} else if (ret) {
 		fprintf(stderr, "No EEPROM/flash device found.\n");
diff --git a/libflashprog.c b/libflashprog.c
index d32f9bd..411264d 100644
--- a/libflashprog.c
+++ b/libflashprog.c
@@ -192,6 +192,52 @@
  * @{
  */
 
+static int flashprog_flash_probe_any(struct flashprog_flashctx **flashctx,
+				     const struct flashprog_programmer *flashprog)
+{
+	struct flashprog_chips *chip_matches;
+	const struct flashprog_chip *chip;
+	bool first = true;
+	int ret;
+
+	if (flashprog_chips_probe(&chip_matches, flashprog))
+		return 1;
+
+	switch (flashprog_chips_count(chip_matches)) {
+	case 0:
+		ret = 2;
+		goto release_matches;
+	case 1:
+		chip = flashprog_chip_first(chip_matches);
+		break;
+	default:
+		msg_cinfo("Multiple flash chip definitions match the detected chip(s): ");
+		for (chip = flashprog_chip_first(chip_matches); chip;
+		     chip = flashprog_chip_next(chip), first = false)
+			msg_cinfo("%s\"%s\"", first ? "" : ", ", flashprog_chip_name(chip));
+		msg_cinfo("\n");
+		ret = 3;
+		goto release_matches;
+	}
+
+	ret = flashprog_flash_probe_chip(flashctx, flashprog, chip);
+
+release_matches:
+	flashprog_chips_release(chip_matches);
+	return ret;
+}
+
+static const struct flashchip *flashprog_chip_by_name(const char *chip_name)
+{
+	const struct flashchip *chip;
+	for (chip = flashchips; chip->name; ++chip) {
+		if (!strcmp(chip->name, chip_name))
+			return chip;
+	}
+	msg_cerr("Error: Unknown chip '%s' specified.\n", chip_name);
+	return NULL;
+}
+
 /**
  * @brief Probe for a flash chip.
  *
@@ -206,6 +252,8 @@
  * @param[in] chip_name Name of a chip to probe for, or NULL to probe for
  *                      all known chips.
  * @return 0 on success,
+ *         5 if an unknown chip name was provided,
+ *         4 if the chip was detected, but preparation failed,
  *         3 if multiple chips were found,
  *         2 if no chip was found,
  *         or 1 on any other error.
@@ -214,34 +262,14 @@
 			 const struct flashprog_programmer *const flashprog,
 			 const char *const chip_name)
 {
-	int i, ret = 2;
-	struct flashprog_flashctx second_flashctx = { 0, };
+	if (!chip_name)
+		return flashprog_flash_probe_any(flashctx, flashprog);
 
-	chip_to_probe = chip_name; /* chip_to_probe is global in flashprog.c */
+	const struct flashchip *const chip = flashprog_chip_by_name(chip_name);
+	if (!chip)
+		return 5;
 
-	*flashctx = malloc(sizeof(**flashctx));
-	if (!*flashctx)
-		return 1;
-	memset(*flashctx, 0, sizeof(**flashctx));
-
-	for (i = 0; i < registered_master_count; ++i) {
-		int flash_idx = -1;
-		if (!ret || (flash_idx = probe_flash(&registered_masters[i], 0, *flashctx, 0)) != -1) {
-			ret = 0;
-			/* We found one chip, now check that there is no second match. */
-			if (probe_flash(&registered_masters[i], flash_idx + 1, &second_flashctx, 0) != -1) {
-				flashprog_layout_release(second_flashctx.default_layout);
-				free(second_flashctx.chip);
-				ret = 3;
-				break;
-			}
-		}
-	}
-	if (ret) {
-		flashprog_flash_release(*flashctx);
-		*flashctx = NULL;
-	}
-	return ret;
+	return flashprog_flash_probe_chip(flashctx, flashprog, chip);
 }
 
 /** @private */