application: get and print optional connections

This commit is contained in:
King Kévin 2019-12-31 16:03:04 +01:00
parent 3ce2418f18
commit 35c708dbd1
3 changed files with 130 additions and 28 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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