diff --git a/application.c b/application.c index 5638ab1..16cc470 100644 --- a/application.c +++ b/application.c @@ -138,9 +138,11 @@ struct cable_t { bool cables[LENGTH(usb_cables)]; // cable definitions the connectors set match to uint16_t unconnected_nb[LENGTH(usb_cables)]; // number of unconnected pairs which should be connected according to cable specification uint16_t unspecified_nb[LENGTH(usb_cables)]; // number of connected pairs which are not specified by cable + uint16_t optional_nb[LENGTH(usb_cables)]; // number of connected pairs which are optional for this cable uint8_t cable_best; // best matching cable index (e.g. with lowest score) uint8_t (*unconnected)[2]; // unconnected pairs which should be connected according to best cable specification uint8_t (*unspecified)[2]; // connected pairs which are not specified by best cable + uint8_t (*optional)[2]; // connected pairs which are optional for best cable }; /** clear the cable information @@ -174,6 +176,9 @@ static void cable_clear(struct cable_t* cable) for (uint8_t i = 0; i < LENGTH(cable->unspecified_nb); i++) { cable->unspecified_nb[i] = 0; } + for (uint8_t i = 0; i < LENGTH(cable->optional_nb); i++) { + cable->optional_nb[i] = 0; + } cable->cable_best = 0xff; if (cable->unconnected) { free(cable->unconnected); @@ -183,6 +188,10 @@ static void cable_clear(struct cable_t* cable) free(cable->unspecified); cable->unspecified = NULL; } + if (cable->optional) { + free(cable->optional); + cable->optional = NULL; + } } /** detect cable presence by testing inter-connector ground connections @@ -348,7 +357,7 @@ static void cable_cables(struct cable_t* cable) /** calculate number of issues for matching cables * @param[in,out] cable cable for which to find the number of issues - * @note resets connections and connections_nb, sets unconnected_nb, unspecified_nb, and cable_best based on cables + * @note resets connections and connections_nb, sets unconnected_nb, unspecified_nb, optional_nb, and cable_best based on cables */ static void cable_issues_nb(struct cable_t* cable) { @@ -364,6 +373,9 @@ static void cable_issues_nb(struct cable_t* cable) for (uint8_t i = 0; i < LENGTH(cable->unspecified_nb); i++) { cable->unspecified_nb[i] = 0; } + for (uint8_t i = 0; i < LENGTH(cable->optional_nb); i++) { + cable->optional_nb[i] = 0; + } cable->cable_best = 0xff; // ensure connections are available @@ -392,7 +404,7 @@ static void cable_issues_nb(struct cable_t* cable) // calculate score for cables uint16_t best_score = UINT16_MAX; // best cable score - for (uint8_t cable_i = 0; cable_i < LENGTH(usb_cables) && cable_i < LENGTH(cable->cables) && cable_i < LENGTH(cable->unconnected_nb) && cable_i < LENGTH(cable->unspecified_nb); cable_i++) { + for (uint8_t cable_i = 0; cable_i < LENGTH(usb_cables) && cable_i < LENGTH(cable->cables) && cable_i < LENGTH(cable->unconnected_nb) && cable_i < LENGTH(cable->unspecified_nb) && cable_i < LENGTH(cable->optional_nb); cable_i++) { if (!cable->cables[cable_i]) { // skip if the cable connectors do not match continue; } @@ -400,16 +412,28 @@ static void cable_issues_nb(struct cable_t* cable) cable->unconnected_nb[cable_i] = usb_cable->mandatory_pairs_nb; cable->unspecified_nb[cable_i] = 0; for (uint16_t i = 0; i < cable->connections_nb; i++) { - bool match = false; + bool mandatory = false; for (uint8_t j = 0; j < usb_cable->mandatory_pairs_nb; j++) { if (cable->connections[i][0] == usb_cable->mandatory_pairs[j][0] && cable->connections[i][1] == usb_cable->mandatory_pairs[j][1]) { - match = true; + mandatory = true; } else if (cable->connections[i][0] == usb_cable->mandatory_pairs[j][1] && cable->connections[i][1] == usb_cable->mandatory_pairs[j][0]) { - match = true; + mandatory = true; } } - if (match) { + bool optional = false; + if (!mandatory) { + for (uint8_t j = 0; j < usb_cable->optional_pairs_nb; j++) { + if (cable->connections[i][0] == usb_cable->optional_pairs[j][0] && cable->connections[i][1] == usb_cable->optional_pairs[j][1]) { + optional = true; + } else if (cable->connections[i][0] == usb_cable->optional_pairs[j][1] && cable->connections[i][1] == usb_cable->optional_pairs[j][0]) { + optional = true; + } + } + } + if (mandatory) { cable->unconnected_nb[cable_i]--; + } else if (optional) { + cable->optional_nb[cable_i]++; } else { cable->unspecified_nb[cable_i]++; } @@ -424,7 +448,7 @@ static void cable_issues_nb(struct cable_t* cable) /** list issues for best matching cable * @param[in,out] cable cable for which to calculate the score - * @note set unconnected and unspecified based on cable_best + * @note set unconnected, unspecified, and optional based on cable_best */ static void cable_issues(struct cable_t* cable) { @@ -447,6 +471,11 @@ static void cable_issues(struct cable_t* cable) cable->unspecified = NULL; } cable->unspecified_nb[cable->cable_best] = 0; + if (cable->optional) { + free(cable->optional); + cable->optional = NULL; + } + cable->optional_nb[cable->cable_best] = 0; // find if cable pairs are actual connection const struct usb_cable_t* usb_cable = &usb_cables[cable->cable_best]; @@ -478,15 +507,40 @@ static void cable_issues(struct cable_t* cable) // find if connection is defined in cable for (uint16_t i = 0; i < cable->connections_nb; i++) { - bool match = false; + bool mandatory = false; for (uint8_t j = 0; j < usb_cable->mandatory_pairs_nb; j++) { if (cable->connections[i][0] == usb_cable->mandatory_pairs[j][0] && cable->connections[i][1] == usb_cable->mandatory_pairs[j][1]) { - match = true; + mandatory = true; } else if (cable->connections[i][0] == usb_cable->mandatory_pairs[j][1] && cable->connections[i][1] == usb_cable->mandatory_pairs[j][0]) { - match = true; + mandatory = true; } } - if (!match) { + bool optional = false; + if (!mandatory) { + for (uint8_t j = 0; j < usb_cable->optional_pairs_nb; j++) { + if (cable->connections[i][0] == usb_cable->optional_pairs[j][0] && cable->connections[i][1] == usb_cable->optional_pairs[j][1]) { + optional = true; + } else if (cable->connections[i][0] == usb_cable->optional_pairs[j][1] && cable->connections[i][1] == usb_cable->optional_pairs[j][0]) { + optional = true; + } + } + } + + if (optional) { + cable->optional_nb[cable->cable_best]++; + uint8_t (*new_connections)[2] = realloc(cable->optional, cable->optional_nb[cable->cable_best] * sizeof(uint8_t[2])); // no integer overflow is possible because of the max number of connections + if (NULL == new_connections) { // allocation failed + if (cable->optional) { + free(cable->optional); + } + cable->optional = NULL; + cable->optional_nb[cable->cable_best] = 0; + return; // fail-safe return (without indicating error) + } + cable->optional = new_connections; + cable->optional[cable->optional_nb[cable->cable_best] - 1][0] = cable->connections[i][0]; + cable->optional[cable->optional_nb[cable->cable_best] - 1][1] = cable->connections[i][1]; + } else if (!mandatory) { cable->unspecified_nb[cable->cable_best]++; uint8_t (*new_connections)[2] = realloc(cable->unspecified, cable->unspecified_nb[cable->cable_best] * sizeof(uint8_t[2])); // no integer overflow is possible because of the max number of connections if (NULL == new_connections) { // allocation failed @@ -565,10 +619,11 @@ static void command_cables(void* argument) // step 2: check for known cable configuration printf("= cable check =\n"); for (uint8_t cable = 0; cable < LENGTH(usb_cables); cable++) { // test every cable - if (0xff == cable_i || cable == cable_i) { - uint8_t pair_defined, pair_undefined; - bool result = usb_cables_test_cable(&usb_cables[cable], &pair_defined, &pair_undefined, false); - printf("%02u %s: %s (defined=%u/%u, undefined=%u)\n", cable, result ? "OK" : "KO", usb_cables[cable].name, pair_defined, usb_cables[cable].mandatory_pairs_nb, pair_undefined); + iwdg_reset(); // kick the dog + if (0xff == cable_i || cable == cable_i) { // only test specified cable (or all if unspecified) + uint8_t pair_defined, pair_optional, pair_undefined; + bool result = usb_cables_test_cable(&usb_cables[cable], &pair_defined, &pair_optional, &pair_undefined, false); + printf("%02u %s: %s (defined=%u/%u, optional=%u/%u, undefined=%u)\n", cable, result ? "OK" : "KO", usb_cables[cable].name, pair_defined, usb_cables[cable].mandatory_pairs_nb, pair_optional, usb_cables[cable].optional_pairs_nb, pair_undefined); } } @@ -656,7 +711,7 @@ static void command_find(void* argument) continue; } uint16_t issues = cable->unconnected_nb[cable_i] + cable->unspecified_nb[cable_i]; - printf("- %02u %s: %u (unconnected=%u/%u, undefined=%u)\n", cable_i, usb_cables[cable_i].name, issues, cable->unconnected_nb[cable_i], usb_cables[cable_i].mandatory_pairs_nb, cable->unspecified_nb[cable_i]); + printf("- %02u %s: %u (unconnected=%u/%u, optional=%u/%u, undefined=%u)\n", cable_i, usb_cables[cable_i].name, issues, cable->unconnected_nb[cable_i], usb_cables[cable_i].mandatory_pairs_nb, cable->optional_nb[cable_i], usb_cables[cable_i].optional_pairs_nb, cable->unspecified_nb[cable_i]); } // print connection details @@ -671,10 +726,10 @@ static void command_find(void* argument) const uint16_t issues = cable->unconnected_nb[cable->cable_best] + cable->unspecified_nb[cable->cable_best]; if (0 == issues) { printf("perfect matching cable: %s\n", usb_cable->name); - goto end; + } else { + printf("closest matching cable: %s\n", usb_cable->name); + printf("connection issue(s): %u (%u unconnected, %u unspecified)\n", issues, cable->unconnected_nb[cable->cable_best], cable->unspecified_nb[cable->cable_best]); } - printf("closest matching cable: %s\n", usb_cable->name); - printf("connection issue(s): %u (%u unconnected, %u unspecified)\n", issues, cable->unconnected_nb[cable->cable_best], cable->unspecified_nb[cable->cable_best]); if (cable->unconnected_nb[cable->cable_best] > 0) { printf("unconnected pins:\n"); for (uint16_t i = 0; i < cable->unconnected_nb[cable->cable_best]; i++) { @@ -695,7 +750,7 @@ static void command_find(void* argument) } } if (cable->unspecified_nb[cable->cable_best] > 0) { - printf("unspecified pins connections:\n"); + printf("unspecified connections:\n"); for (uint16_t i = 0; i < cable->unspecified_nb[cable->cable_best]; i++) { const struct usb_connector_t* connector_from = usb_cables_get_connector(cable->unspecified[i][0]); const struct usb_connector_t* connector_to = usb_cables_get_connector(cable->unspecified[i][1]); @@ -713,6 +768,25 @@ static void command_find(void* argument) printf("%s\n", usb_pins[cable->unspecified[i][1]].name); } } + if (cable->optional_nb[cable->cable_best] > 0) { + printf("optional connections:\n"); + for (uint16_t i = 0; i < cable->optional_nb[cable->cable_best]; i++) { + const struct usb_connector_t* connector_from = usb_cables_get_connector(cable->optional[i][0]); + const struct usb_connector_t* connector_to = usb_cables_get_connector(cable->optional[i][1]); + if (NULL == connector_from || NULL == connector_to) { + continue; + } + printf("- %s ", connector_from->name); + if (connector_from->variant) { + printf("(%s) ", connector_from->variant); + } + printf("%s to %s ", usb_pins[cable->optional[i][0]].name, connector_to->name); + if (connector_to->variant) { + printf("(%s) ", connector_to->variant); + } + printf("%s\n", usb_pins[cable->optional[i][1]].name); + } + } printf("there is %s load in the cable\n", cable->load ? "a" : "no"); end: @@ -895,10 +969,10 @@ static void command_test(void* argument) } bool cable_ok = false; // if the cable is connected while (!cable_ok) { // wait until all pin pairs of cable are connected - uint8_t defined, undefined; // pair counting variables - cable_ok = usb_cables_test_cable(&test_cables[cable], &defined, &undefined, true); // test cable + uint8_t defined, optional, undefined; // pair counting variables + cable_ok = usb_cables_test_cable(&test_cables[cable], &defined, &optional, &undefined, true); // test cable if (!cable_ok && defined > 0) { // not all pairs are connected - printf("connection issues: defined=%u/%u, undefined=%u\n", defined, test_cables[cable].mandatory_pairs_nb, undefined); // show issue summary + printf("connection issues: defined=%u/%u, optional=%u/%u, undefined=%u\n", defined, test_cables[cable].mandatory_pairs_nb, optional, test_cables[cable].optional_pairs_nb, undefined); // show issue summary } if (!cable_ok) { if (user_input_available) { // user interruption @@ -1516,6 +1590,15 @@ void main(void) if (NULL != connector_from && NULL != connector_to) { snprintf(line, LENGTH(line), "%s_%s %s_%s", connector_from->shortname, usb_pins[cable_current->unspecified[i][0]].name, connector_to->shortname, usb_pins[cable_current->unspecified[i][1]].name); } + } else if (cable_message_i == 5U + cable_next->unconnected_nb[cable_next->cable_best] + cable_next->unspecified_nb[cable_next->cable_best]) { + snprintf(line, LENGTH(line), "optional: %u", cable_next->optional_nb[cable_next->cable_best]); + } else if (cable_message_i < 6U + cable_next->unconnected_nb[cable_next->cable_best] + cable_next->unspecified_nb[cable_next->cable_best] + cable_next->optional_nb[cable_next->cable_best]) { + uint16_t i = cable_message_i - 6U - cable_next->unconnected_nb[cable_next->cable_best] - cable_next->unspecified_nb[cable_next->cable_best]; + const struct usb_connector_t* connector_from = usb_cables_get_connector(cable_current->optional[i][0]); + const struct usb_connector_t* connector_to = usb_cables_get_connector(cable_current->optional[i][1]); + if (NULL != connector_from && NULL != connector_to) { + snprintf(line, LENGTH(line), "%s_%s %s_%s", connector_from->shortname, usb_pins[cable_current->optional[i][0]].name, connector_to->shortname, usb_pins[cable_current->optional[i][1]].name); + } } else { // end reached snprintf(line, LENGTH(line), "closest match"); cable_message_i = 0; // restart diff --git a/usb_cables.c b/usb_cables.c index 6eacb22..05b4fe2 100644 --- a/usb_cables.c +++ b/usb_cables.c @@ -4946,12 +4946,12 @@ bool usb_cables_test_load(const struct usb_connector_t* connector) return loaded; } -bool usb_cables_test_cable(const struct usb_cable_t* cable, uint8_t* defined, uint8_t* undefined, bool print) +bool usb_cables_test_cable(const struct usb_cable_t* cable, uint8_t* defined, uint8_t* optional, uint8_t* undefined, bool print) { if (NULL == cable) { return false; } - uint8_t _defined = 0, _undefined = 0; // internal pair counting variables + uint8_t _defined = 0, _optional = 0, _undefined = 0; // internal pair counting variables usb_cables_connectors_float(cable->connectors, cable->connectors_nb); // ensure we start in a safe state for (uint8_t connector_from = 0; connector_from < cable->connectors_nb; connector_from++) { // test from every connector @@ -4973,7 +4973,7 @@ bool usb_cables_test_cable(const struct usb_cable_t* cable, uint8_t* defined, ui continue; } - // figure out if this connection pair is defined + // figure out if this connection pair is defined as mandatory bool pair_defined = false; for (uint8_t pair = 0; pair < cable->mandatory_pairs_nb; pair++) { if (cable->mandatory_pairs[pair][0] == cable->connectors[connector_from]->pins[pin_from] && cable->mandatory_pairs[pair][1] == cable->connectors[connector_to]->pins[pin_to]) { @@ -4984,10 +4984,25 @@ bool usb_cables_test_cable(const struct usb_cable_t* cable, uint8_t* defined, ui } } + // figure out if this connection pair is defined as optional + bool pair_optional = false; + if (!pair_defined) { + for (uint8_t pair = 0; pair < cable->optional_pairs_nb; pair++) { + if (cable->optional_pairs[pair][0] == cable->connectors[connector_from]->pins[pin_from] && cable->optional_pairs[pair][1] == cable->connectors[connector_to]->pins[pin_to]) { + pair_optional = true; + } + if (cable->optional_pairs[pair][1] == cable->connectors[connector_from]->pins[pin_from] && cable->optional_pairs[pair][0] == cable->connectors[connector_to]->pins[pin_to]) { + pair_optional = true; + } + } + } + uint8_t connection = usb_cables_test_pins(usb_pin_from, usb_pin_to); if (connection >= 0x22) { if (pair_defined) { _defined++; + } else if (pair_optional) { + _optional++; } else { _undefined++; if (print) { @@ -5013,6 +5028,9 @@ bool usb_cables_test_cable(const struct usb_cable_t* cable, uint8_t* defined, ui if (defined) { *defined = _defined; } + if (optional) { + *optional = _optional; + } if (undefined) { *undefined = _undefined; } diff --git a/usb_cables.h b/usb_cables.h index f5fad32..2edeff3 100644 --- a/usb_cables.h +++ b/usb_cables.h @@ -114,13 +114,14 @@ bool usb_cables_test_ground(const struct usb_connector_t** connectors, uint8_t c bool usb_cables_test_load(const struct usb_connector_t* connector); /** test USB cable connections * @param[in] usb_cable USB cable to test - * @param[out] defined number of pin pairs that are connected according to definition + * @param[out] defined number of pin pairs that are connected according to mandatory definition + * @param[out] optional number of pin pairs that are connected according to optional definition * @param[out] undefined number of pin pairs that are connected but not according to definition * @param[in] print print connection errors * @return if the connections of the cable correspond to the definition * @note each pair is tested in both directions */ -bool usb_cables_test_cable(const struct usb_cable_t* cable, uint8_t* defined, uint8_t* undefined, bool print); +bool usb_cables_test_cable(const struct usb_cable_t* cable, uint8_t* defined, uint8_t* optional, uint8_t* undefined, bool print); /** test connections between connectors * @param[in] connectors connectors to check * @param[in] connectors_nb numbers of connectors