diff options
author | Marc Zyngier <maz@kernel.org> | 2023-10-22 14:02:06 +0100 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2023-10-22 14:13:00 +0100 |
commit | c8a9d9619c510490a4d9470491af5ab2a0e9e99a (patch) | |
tree | 597dcc002c8d3ba6954044afcd5a082cfb738081 | |
parent | 9a1c099ce9d7eb62c3c7259c5cca09ede84a0d44 (diff) | |
download | cs-sw-c8a9d9619c510490a4d9470491af5ab2a0e9e99a.tar.gz |
Only advertise a single CDC for single board configurations
Advertising two CDC endpoints when a single CS board is present is
a bit silly, specially considering that connecting to the absent
port leads to undesirable effects...
Instead, account for the present ports early by immediately probing
for the I2C PUPs, and keep track of which ports are alive. Then
make sure that we only advertise a single CDC configuration when
only a single CS board is present.
Finally, map all single-board configurations to the first CDC port,
irrespective of the board being P0 or P1. This allows single boards
configured with the alternate configuration (for random reasons) to
be able to use ttyACM0.
Also update the README file.
Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r-- | README | 17 | ||||
-rw-r--r-- | m1-pd-bmc.h | 2 | ||||
-rw-r--r-- | start.c | 55 | ||||
-rw-r--r-- | usb_descriptors.c | 29 | ||||
-rw-r--r-- | vdmtool.c | 10 |
5 files changed, 81 insertions, 32 deletions
@@ -143,8 +143,8 @@ contraption. It should be obvious, but maybe it is better stating it. ** Use it If you have correctly built and flashed the firmware, you will have -the Pico led blinking at the rate of twice a second, and a couple of -/dev/ttyACM* being advertised by your host: +the Pico led blinking at the rate of twice a second, and one or two +/dev/ttyACM* devices being advertised by your host: [708023.097129] usb 1-4: new full-speed USB device number 72 using xhci_hcd [708023.265195] usb 1-4: New USB device found, idVendor=2e8a, idProduct=000a, bcdDevice= 1.00 @@ -169,25 +169,22 @@ and you should see something like: This is the Central Scrutinizer Control character is ^_ Press ^_ + ? for help + P0: Probing port 0 P0: VBUS OFF - P0: Device ID: 0x91 + P0: Device ID: B_revB (0x91) P0: Init P0: STATUS0: 0x80 P0: VBUS OFF P0: Disconnected P0: S: DISCONNECTED - P0: Empty debug message - P0: IRQ=0 10 0 - P0: Connected: cc1=2 cc2=0 + P0: Connected: cc1=2 cc2=1 P0: Polarity: CC1 (normal) + P0: VCONN on CC2 P0: VBUS ON P0: S: DFP_VBUS_ON - P0: Empty debug message - P0: IRQ=71 4 0 P0: S: DFP_CONNECTED P0: >VDM serial -> SBU1/2 - P0: IRQ=71 4 1 - P0: <VDM RX SOP"DEBUG (5) [504f] 5ac8052 91340000 306 0 0 + P0: <VDM RX SOP"DEBUG (5) [508f] 5ac8052 44740000 306 0 0 If you see the ">VDM serial -> SBU1/2" line, the serial line should now be connected and you can interact with the M1. Note that you can diff --git a/m1-pd-bmc.h b/m1-pd-bmc.h index 83abc9c..9e62316 100644 --- a/m1-pd-bmc.h +++ b/m1-pd-bmc.h @@ -59,6 +59,8 @@ extern const struct upstream_ops *upstream_ops; void set_upstream_ops(bool serial); bool upstream_is_serial(void); +int get_valid_ports(void); + void upstream_tx_str(int32_t port, const char *ptr); #define PRINTF_SIZE 512 @@ -7,6 +7,13 @@ #include "m1-pd-bmc.h" #include "FUSB302.h" +static uint8_t valid_ports = 0; + +static inline int __get_valid_ports(void) +{ + return (valid_ports == 3) + 1; +} + static const struct gpio_pin_config m1_pd_bmc_pin_config0[] = { [M1_BMC_PIN_START ... M1_BMC_PIN_END] = { .skip = true, @@ -229,12 +236,18 @@ static void m1_pd_bmc_gpio_setup_one(const struct gpio_pin_config *pin) gpio_pull_up(pin->pin); } -static void m1_pd_bmc_system_init(const struct hw_context *hw) +static bool m1_pd_bmc_system_init(const struct hw_context *hw) { init_system(hw); for (unsigned int i = 0; i < hw->nr_pins; i++) m1_pd_bmc_gpio_setup_one(&hw->pins[i]); + + /* + * If we can't infer pull-ups on the I2C, it is likely that + * nothing is connected and we'd better skip this port. + */ + return gpio_get(hw->pins[I2C_SCL].pin) && gpio_get(hw->pins[I2C_SDA].pin); } static bool apply_waveshare_2ch_rs232_overrides(void) @@ -259,6 +272,9 @@ static bool apply_waveshare_2ch_rs232_overrides(void) static void usb_tx_bytes(int32_t port, const char *ptr, int len) { + if (__get_valid_ports() != 2) + port = 0; + if (!tud_cdc_n_connected(port)) return; @@ -283,6 +299,9 @@ static int32_t usb_rx_byte(int32_t port) { uint8_t c; + if (__get_valid_ports() != 2) + port = 0; + if (!tud_cdc_n_connected(port) || !tud_cdc_n_available(port)) return -1; @@ -372,6 +391,11 @@ bool upstream_is_serial(void) static int wait_for_usb_connection(void) { + bool connected; + int ports; + + ports = __get_valid_ports(); + do { static bool state = false; static int cnt = 0; @@ -383,9 +407,18 @@ static int wait_for_usb_connection(void) cnt %= 256; if (!cnt) state = !state; - } while (!tud_cdc_n_connected(0) && !tud_cdc_n_connected(1)); - return !tud_cdc_n_connected(0); + connected = false; + connected |= tud_cdc_n_connected(0); + connected |= ports == 2 && tud_cdc_n_connected(1); + } while (!connected); + + return ports == 2 && tud_cdc_n_connected(1); +} + +int get_valid_ports(void) +{ + return __get_valid_ports(); } int main(void) @@ -398,10 +431,15 @@ int main(void) success = set_sys_clock_khz(133000, false); board_init(); + + if (m1_pd_bmc_system_init(&hw0)) + valid_ports |= 1; + if (m1_pd_bmc_system_init(&hw1)) + valid_ports |= 2; + tusb_init(); - m1_pd_bmc_system_init(&hw0); - m1_pd_bmc_system_init(&hw1); + sleep_ms(200); if (apply_waveshare_2ch_rs232_overrides()) { set_upstream_ops(true); @@ -411,6 +449,8 @@ int main(void) port = wait_for_usb_connection(); } + upstream_ops->flush(); + __printf(port, "This is the Central Scrutinizer\n"); __printf(port, "Control character is ^_\n"); __printf(port, "Press ^_ + ? for help\n"); @@ -418,8 +458,9 @@ int main(void) if (!success) __printf(port, "WARNING: Nominal frequency NOT reached\n"); - m1_pd_bmc_fusb_setup(0, &hw0); - if (!upstream_is_serial()) + if (valid_ports & 1) + m1_pd_bmc_fusb_setup(0, &hw0); + if ((valid_ports & 2) && !upstream_is_serial()) m1_pd_bmc_fusb_setup(1, &hw1); m1_pd_bmc_run(); diff --git a/usb_descriptors.c b/usb_descriptors.c index a084ae6..e63ffa6 100644 --- a/usb_descriptors.c +++ b/usb_descriptors.c @@ -44,8 +44,7 @@ static const tusb_desc_device_t usbd_desc_device = { #define USBD_MAX_POWER_MA (250) -#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + \ - TUD_CDC_DESC_LEN * CFG_TUD_CDC) +#define USBD_DESC_LEN(n) (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN * (n)) enum { ITF_NUM_CDC_0, @@ -55,11 +54,10 @@ enum { ITF_NUM_TOTAL, }; -static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { - +static const uint8_t usbd_desc_cfg_dual[USBD_DESC_LEN(2)] = { TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, USBD_STR_LANGUAGE, - USBD_DESC_LEN, + USBD_DESC_LEN(2), TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), @@ -80,6 +78,22 @@ static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { USBD_CDC_DATA_SIZE), }; +static const uint8_t usbd_desc_cfg_single[USBD_DESC_LEN(1)] = { + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL - 2, + USBD_STR_LANGUAGE, + USBD_DESC_LEN(1), + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, + USBD_MAX_POWER_MA), + + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, + USBD_STR_CDC_0_NAME, + EPNUM_CDC_0_CMD, + USBD_CDC_CMD_SIZE, + EPNUM_CDC_0_DATA & 0x7F, + EPNUM_CDC_0_DATA, + USBD_CDC_DATA_SIZE), +}; + const uint8_t *tud_descriptor_device_cb(void) { return (const uint8_t *)&usbd_desc_device; @@ -88,7 +102,10 @@ const uint8_t *tud_descriptor_device_cb(void) const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { (void)index; - return usbd_desc_cfg; + if (get_valid_ports() == 2) + return usbd_desc_cfg_dual; + + return usbd_desc_cfg_single; } #define DESC_STR_MAX_LENGTH 20 @@ -666,15 +666,7 @@ void m1_pd_bmc_fusb_setup(unsigned int port, .serial_pin_set = 2, /* SBU1/2 */ }; - /* - * If we can't infer pull-ups on the I2C, it is likely that - * nothing is connected and we'd better skip this port. - */ - if (!gpio_get(PIN(cxt, I2C_SCL)) || !gpio_get(PIN(cxt, I2C_SDA))) { - cprintf(cxt, "I2C pins low while idling, skipping port\n"); - cxt->hw = NULL; - return; - } + cprintf(cxt, "Probing port %d\n", port); gpio_put(PIN(cxt, LED_G), HIGH); /* No swapping */ |