/* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /** USB cable definitions and utilities * @file * @author King Kévin * @date 2019-2020 */ /** the USB pin type */ enum usb_pin_type_e { USB_PIN_TYPE_UNDEFINED, /*< the default type, undefined */ USB_PIN_TYPE_GROUND, /*< ground (including ground drain) */ USB_PIN_TYPE_POWER, /*< power (VBUS, VCONN) */ USB_PIN_TYPE_SHIELD, /*< shield */ USB_PIN_TYPE_DIFFERENTIAL, /*< differential data pairs (D+/-, SSTX+/-, SSRX+/-) */ USB_PIN_TYPE_IDENTIFICATION, /*< pin to identify type (often connected to power or ground through resistor) */ USB_PIN_TYPE_OTHER, /*< any other type */ }; /** the type of connection between two pins */ struct usb_connection_t { /** pin1 is driven using pull up/down, pin2 is floating, set if a pattern set on pin1 is received on pin2 * @note this method is similar to tx_drive_float, but meant for ground pins, which should not be driven. * @note prone to false negative when there is an inline resistor (which forms a voltage divider) * @note this might not be set (e.g. tested) if tx_drive_float or tx_drive_pull are set */ bool tx_pull_float; /** pin1 is driven using push/pull, pin2 is floating, set if a pattern set on pin1 is received on pin2 * @note this can also detect connections with inline resistors, since no pull-up/down will form a voltage divider * @note prone to false positive since pin2 is floating * @note this might not be set (e.g. tested) tx_drive_pull is set */ bool tx_drive_float; /** pin1 is driven using push/pull, pin2 is pulled up/down, set if a pattern set on pin1 is received on pin1 * @note this will detect direct connections, when nothing is could be powered * @note prone to false negative when there is an inline resistor (which forms a voltage divider) */ bool tx_drive_pull; /** pin2 is driven using pull up/down, pin1 is floating, set if a pattern set on pin2 is received on pin1 * @note this method is similar to tx_drive_float, but meant for ground pins, which should not be driven. * @note prone to false negative when there is an inline resistor (which forms a voltage divider) * @note this might not be set (e.g. tested) if tx_drive_float or tx_drive_pull are set */ bool rx_pull_float; /** pin2 is driven using push/pull, pin1 is floating, set if a pattern set on pin2 is received on pin1 * @note this can also detect connections with inline resistors, since no pull-up/down will form a voltage divider * @note prone to false positive since pin1 is floating * @note this might not be set (e.g. tested) tx_drive_pull is set */ bool rx_drive_float; /** pin2 is driven using push/pull, pin1 is pulled up/down, set if a pattern set on pin2 is received on pin1 * @note this will detect direct connections, when nothing is could be powered * @note prone to false negative when there is an inline resistor (which forms a voltage divider) */ bool rx_drive_pull; }; /** USB pin definition */ struct usb_pin_t { const char* name; /*< pin name */ uint32_t port; /*< on which MCU port is this pin connected */ uint16_t pin; /*< on which MCU pin is this pin connected */ enum usb_pin_type_e type; /*< pin type */ }; /** USB connector definition */ struct usb_connector_t { const char* name; /*< connector name (A, B, mini-B, micro-B, C, ...) */ const char* shortname; /*< short connector name (A, B, mB, uB, C, ...) */ const char* variant; /*< variant if there are more than one of the same connector */ uint8_t pins_nb; /*< number of pins */ const uint8_t* pins; /*< all connector pins indexes */ }; /** USB connector identifiers */ enum usb_connectors_e { USB_CONNECTOR_A_HOST, USB_CONNECTOR_C_HOST, USB_CONNECTOR_A_DEVICE, USB_CONNECTOR_B_DEVICE, USB_CONNECTOR_MINIB_DEVICE, USB_CONNECTOR_MICROB_DEVICE, USB_CONNECTOR_C_DEVICE, USB_CONNECTOR_LIGHTNING_DEVICE, USB_CONNECTOR_COUNT, }; /** USB cable definition */ struct usb_cable_t { const char* name; /*< cable name */ const char* shortname; /*< short cable name (to fit LCD screen) */ const char* variant; /*< description of the variant of this cable (in case they have the same cable name) */ uint8_t connectors_nb; /*< number of connectors */ const struct usb_connector_t** connectors; /*< list of connectors this cables uses */ uint8_t mandatory_pairs_nb; /* number of connected pin pairs */ const uint8_t (*mandatory_pairs)[2]; /*< list of connected pin index pairs (order does not matter) */ uint8_t optional_pairs_nb; /* number of connected pin pairs */ const uint8_t (*optional_pairs)[2]; /*< list of connected pin index pairs (order does not matter) */ }; /** USB cable identifiers */ enum usb_cable_e { USB_CABLE_AA0, USB_CABLE_AA2, USB_CABLE_AA3, USB_CABLE_AB0_HOST, USB_CABLE_ABBC_HOST, USB_CABLE_AB2_HOST, USB_CABLE_AB3_HOST, USB_CABLE_AB0_DEVICE, USB_CABLE_ABBC_DEVICE, USB_CABLE_AB2_DEVICE, USB_CABLE_AB3_DEVICE, USB_CABLE_AAB2_HOST, USB_CABLE_AAB2_DEVICE, USB_CABLE_AMB0_HOST, USB_CABLE_AMBBC_HOST, USB_CABLE_AMB2_HOST, USB_CABLE_AMB0_DEVICE, USB_CABLE_AMBBC_DEVICE, USB_CABLE_AMB2_DEVICE, USB_CABLE_AAMB2_HOST, USB_CABLE_AAMB2_DEVICE, USB_CABLE_AUB0_HOST, USB_CABLE_AUBBC_HOST, USB_CABLE_AUB2_HOST, USB_CABLE_AUB3_HOST, USB_CABLE_AUB0_DEVICE, USB_CABLE_AUBBC_DEVICE, USB_CABLE_AUB2_DEVICE, USB_CABLE_AUB3_DEVICE, USB_CABLE_CSHUNT_HOST, USB_CABLE_CSHUNT_DEVICE, USB_CABLE_AC0_A_HOST_CA_HOST, USB_CABLE_AC0_A_HOST_CB_HOST, USB_CABLE_AC0_A_HOST_CA_DEVICE, USB_CABLE_AC0_A_HOST_CB_DEVICE, USB_CABLE_AC0_A_DEVICE_CA_HOST, USB_CABLE_AC0_A_DEVICE_CB_HOST, USB_CABLE_AC0_A_DEVICE_CA_DEVICE, USB_CABLE_AC0_A_DEVICE_CB_DEVICE, USB_CABLE_AC2_A_HOST_CA_HOST, USB_CABLE_AC2_A_HOST_CB_HOST, USB_CABLE_AC2_A_HOST_CA_DEVICE, USB_CABLE_AC2_A_HOST_CB_DEVICE, USB_CABLE_AC2_A_DEVICE_CA_HOST, USB_CABLE_AC2_A_DEVICE_CB_HOST, USB_CABLE_AC2_A_DEVICE_CA_DEVICE, USB_CABLE_AC2_A_DEVICE_CB_DEVICE, USB_CABLE_AC3_A_HOST_CA_HOST, USB_CABLE_AC3_A_HOST_CB_HOST, USB_CABLE_AC3_A_HOST_CA_DEVICE, USB_CABLE_AC3_A_HOST_CB_DEVICE, USB_CABLE_AC3_A_DEVICE_CA_HOST, USB_CABLE_AC3_A_DEVICE_CB_HOST, USB_CABLE_AC3_A_DEVICE_CA_DEVICE, USB_CABLE_AC3_A_DEVICE_CB_DEVICE, USB_CABLE_CB2_CA_HOST, USB_CABLE_CB2_CB_HOST, USB_CABLE_CB2_CA_DEVICE, USB_CABLE_CB2_CB_DEVICE, USB_CABLE_CB3_CA_HOST, USB_CABLE_CB3_CB_HOST, USB_CABLE_CB3_CA_DEVICE, USB_CABLE_CB3_CB_DEVICE, USB_CABLE_CMB2_CA_HOST, USB_CABLE_CMB2_CB_HOST, USB_CABLE_CMB2_CA_DEVICE, USB_CABLE_CMB2_CB_DEVICE, USB_CABLE_CUB2_CA_HOST, USB_CABLE_CUB2_CB_HOST, USB_CABLE_CUB2_CA_DEVICE, USB_CABLE_CUB2_CB_DEVICE, USB_CABLE_CUB3_CA_HOST, USB_CABLE_CUB3_CB_HOST, USB_CABLE_CUB3_CA_DEVICE, USB_CABLE_CUB3_CB_DEVICE, USB_CABLE_CC2_CA_HOST_CA_DEVICE, USB_CABLE_CC2_CA_HOST_CB_DEVICE, USB_CABLE_CC2_CB_HOST_CA_DEVICE, USB_CABLE_CC2_CB_HOST_CB_DEVICE, USB_CABLE_CCFF_CA_HOST_CA_DEVICE, USB_CABLE_CCFF_CA_HOST_CB_DEVICE, USB_CABLE_CCFF_CB_HOST_CA_DEVICE, USB_CABLE_CCFF_CB_HOST_CB_DEVICE, USB_CABLE_COUNT, }; /** USB pin definitions */ extern const struct usb_pin_t usb_pins[105]; /** USB connectors definitions */ extern const struct usb_connector_t* usb_connectors[USB_CONNECTOR_COUNT]; /** USB cables definitions */ extern const struct usb_cable_t usb_cables[USB_CABLE_COUNT]; /** set every USB pin from every USB connector to input floating */ void usb_cables_pins_float(void); /** set every pin of connector to input floating * @param[in] connector connector on which to set the pins floating */ void usb_cables_connector_float(const struct usb_connector_t* connector); /** set every pin to the connectors to input floating * @param[in] connectors list on connectors on which to set the pins floating * @param[in] connectors_nb numbers of connectors */ void usb_cables_connectors_float(const struct usb_connector_t** connectors, uint8_t connectors_nb); /** get connector from pin * @param[in] pin pin index in usb_pins * @return corresponding connector (NULL if none found) */ const struct usb_connector_t* usb_cables_get_connector(uint8_t pin); /** test if two pins are connected * @param[in] pin1 first pin * @param[in] pin2 second pin * @param[out] connection pins interconnection details (optional) * @return if the two pins are connected */ bool usb_cables_test_pins(const struct usb_pin_t* pin1, const struct usb_pin_t* pin2, struct usb_connection_t* connection); /** test connectors for connections between ground pins of the connectors * @param[in] connectors connectors to test * @param[in] connectors_nb numbers of connectors * @param[out] connected which of the connectors are connected (optional) * @return if at least on ground connection has been found * @note connection between pin on the same connector are not tested * @note it assumes all grounds are connected (e.g. only one cable is connected) * @note this check is very fast */ bool usb_cables_test_ground(const struct usb_connector_t** connectors, uint8_t connectors_nb, bool* connected); /** test if there is a load on the connector * @param[in] connector connector to test * @return if there is a load on the connector */ 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 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* optional, uint8_t* undefined, bool print); /** test connections between connectors * @param[in] connectors connectors to check * @param[in] connectors_nb numbers of connectors * @param[in] include_intra if connections between pins within a connector should be tested * @param[in] ground_only only test connections between ground pins * @param[out] connections_nb number of connections found * @return list of pin pairs connections (NULL if 0 connections have been found or no connections have been found but no memory is available) * @the list of pin pairs connections is allocated memory which should be freed by the caller */ uint8_t** usb_cables_test_connections(const struct usb_connector_t** connectors, uint8_t connectors_nb, bool include_intra, bool ground_only, uint16_t* connections_nb);