266 lines
11 KiB
C
266 lines
11 KiB
C
/* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
/** USB cable definitions and utilities
|
|
* @file
|
|
* @author King Kévin <kingkevin@cuvoodoo.info>
|
|
* @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);
|