diff --git a/firmware/application/usb_serial_cdc.c b/firmware/application/usb_serial_cdc.c index 9e0468bd0..705299f08 100644 --- a/firmware/application/usb_serial_cdc.c +++ b/firmware/application/usb_serial_cdc.c @@ -20,9 +20,31 @@ */ #include "usb_serial_cdc.h" +#include "usb_serial_descriptor.h" #include "usb_serial_endpoints.h" #include "usb_serial_event.hpp" +#include + +/* Defined in hackrf/firmware/hackrf_usb/usb_device.c. After upstream commit + * 85dfacf6 ("Universalize: firmware/hackrf_usb"), the global `usb_device` is + * left zero-initialized and is populated at runtime from per-board + * `usb_device_*` constants inside hackrf_usb.c. Mayhem does not link + * hackrf_usb.c, so we must populate `usb_device` ourselves before usb_run(). + * The descriptor fields are const-qualified, so we follow the upstream + * pattern of memcpy from a const template. */ +extern usb_configuration_t* usb_configurations[]; + +static const usb_device_t usb_device_mayhem = { + .descriptor = usb_descriptor_device, + .descriptor_strings = usb_descriptor_strings, + .qualifier_descriptor = usb_descriptor_device_qualifier, + .configurations = &usb_configurations, + .configuration = 0, + .wcid_string_descriptor = wcid_string_descriptor, + .wcid_feature_descriptor = wcid_feature_descriptor, +}; + uint32_t EVT_MASK_USB = EVENT_MASK(8); extern void usb0_isr(void); @@ -85,6 +107,8 @@ void usb_configuration_changed(usb_device_t* const device) { } void setup_usb_serial_controller(void) { + memcpy(&usb_device, &usb_device_mayhem, sizeof(usb_device_mayhem)); + usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); @@ -97,7 +121,10 @@ void setup_usb_serial_controller(void) { usb_queue_init(&usb_endpoint_bulk_in_queue); usb_endpoint_init(&usb_endpoint_control_out, false); - usb_endpoint_init(&usb_endpoint_control_in, false); + /* Control IN needs ZLP for descriptor reads whose length is a multiple of + * the max packet size (otherwise the host hangs waiting for the transfer + * to terminate). Matches upstream hackrf_usb.c after commit db73ecbf. */ + usb_endpoint_init(&usb_endpoint_control_in, true); usb_run(&usb_device); } diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index b0b836203..163e00052 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -217,7 +217,25 @@ set(CPPWARN "-Wall -Wextra") if(NOT DEFINED BOARD) set(BOARD "HACKRF_ONE") endif() -set(DDEFS "-DLPC43XX -DLPC43XX_M4 -D__NEWLIB__ -D${BOARD} -DTOOLCHAIN_GCC -DTOOLCHAIN_GCC_ARM -D_RANDOM_TCC=0 -D'VERSION_STRING=\"${VERSION}\"'") + +# Upstream hackrf headers now gate on IS_* macros normally populated by +# hackrf/firmware/platform-detect.cmake. We don't include that here, so derive +# the IS_* set from BOARD ourselves. IS_H1_R9 is forced to 0 (compile-time +# constant) so `if (IS_H1_R9)` branches resolve without needing the runtime +# detected_platform() symbol, which mayhem doesn't link in. +if(BOARD STREQUAL "HACKRF_ONE") + set(BOARD_IS_DEFS "-DIS_HACKRF_ONE=1 -DIS_NOT_PRALINE=1 -DIS_H1_R9=0 -DIS_NOT_H1_R9=1 -DIS_NOT_RAD1O=1 -DIS_NOT_JAWBREAKER=1 -DIS_H1_OR_PRALINE=1 -DIS_H1_OR_RAD1O=1 -DIS_H1_OR_JAWBREAKER=1 -DIS_EXPANSION_COMPATIBLE=1") +elseif(BOARD STREQUAL "PRALINE") + set(BOARD_IS_DEFS "-DIS_PRALINE=1 -DIS_NOT_HACKRF_ONE=1 -DIS_NOT_H1_R9=1 -DIS_NOT_RAD1O=1 -DIS_NOT_JAWBREAKER=1 -DIS_H1_OR_PRALINE=1 -DIS_FOUR_LEDS=1 -DIS_EXPANSION_COMPATIBLE=1") +elseif(BOARD STREQUAL "RAD1O") + set(BOARD_IS_DEFS "-DIS_RAD1O=1 -DIS_NOT_PRALINE=1 -DIS_NOT_HACKRF_ONE=1 -DIS_NOT_H1_R9=1 -DIS_NOT_JAWBREAKER=1 -DIS_H1_OR_RAD1O=1 -DIS_FOUR_LEDS=1") +elseif(BOARD STREQUAL "JAWBREAKER") + set(BOARD_IS_DEFS "-DIS_JAWBREAKER=1 -DIS_NOT_PRALINE=1 -DIS_NOT_HACKRF_ONE=1 -DIS_NOT_H1_R9=1 -DIS_NOT_RAD1O=1 -DIS_H1_OR_JAWBREAKER=1") +else() + set(BOARD_IS_DEFS "") +endif() + +set(DDEFS "-DLPC43XX -DLPC43XX_M4 -D__NEWLIB__ -D${BOARD} ${BOARD_IS_DEFS} -DTOOLCHAIN_GCC -DTOOLCHAIN_GCC_ARM -D_RANDOM_TCC=0 -D'VERSION_STRING=\"${VERSION}\"'") # List all default ASM defines here, like -D_DEBUG=1 set(DADEFS) @@ -765,7 +783,6 @@ set(MODE_CPPSRC ${HACKRF_PATH}/firmware/common/si5351c.c ${HACKRF_PATH}/firmware/common/i2c_bus.c ${HACKRF_PATH}/firmware/common/mixer.c - ${HACKRF_PATH}/firmware/common/clkin.c ${HACKRF_PATH}/firmware/common/spi_bus.c ${HACKRF_PATH}/firmware/common/sgpio.c ${HACKRF_PATH}/firmware/common/rf_path.c @@ -773,7 +790,6 @@ set(MODE_CPPSRC ${HACKRF_PATH}/firmware/common/spi_ssp.c ${HACKRF_PATH}/firmware/common/rffc5071_spi.c ${HACKRF_PATH}/firmware/common/rffc5071.c - ${HACKRF_PATH}/firmware/common/clkin.c ${HACKRF_PATH}/firmware/common/gpdma.c ${HACKRF_PATH}/firmware/libopencm3/lib/cm3/nvic.c diff --git a/firmware/baseband/sd_over_usb/hackrf_core.c b/firmware/baseband/sd_over_usb/hackrf_core.c index f0d7427d3..a34898ad1 100644 --- a/firmware/baseband/sd_over_usb/hackrf_core.c +++ b/firmware/baseband/sd_over_usb/hackrf_core.c @@ -39,6 +39,7 @@ #include "platform_scu.h" #include "fixed_point.h" #include "clkin.h" +#include "usb_type.h" #include #include #include @@ -147,34 +148,16 @@ static struct gpio gpio_h1r9_hw_sync_enable = GPIO(5, 5); #endif // clang-format on -i2c_bus_t i2c0 = { - .obj = (void*)I2C0_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - -i2c_bus_t i2c1 = { - .obj = (void*)I2C1_BASE, - .start = i2c_lpc_start, - .stop = i2c_lpc_stop, - .transfer = i2c_lpc_transfer, -}; - -// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { -// .duty_cycle_count = 15, -// }; - -const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { - .duty_cycle_count = 255, -}; +/* i2c0, i2c1, and i2c_config_si5351c_fast_clock are defined in + * hackrf/firmware/common/i2c_bus.c and si5351c.c; use those instead of + * redefining them here to avoid multiple-definition link errors. */ si5351c_driver_t clock_gen = { .bus = &i2c0, .i2c_address = 0x60, }; -const ssp_config_t ssp_config_max283x = { +ssp_config_t ssp_config_max283x = { /* FIXME speed up once everything is working reliably */ /* // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz @@ -188,7 +171,7 @@ const ssp_config_t ssp_config_max283x = { .gpio_select = &gpio_max283x_select, }; -const ssp_config_t ssp_config_max5864 = { +ssp_config_t ssp_config_max5864 = { /* FIXME speed up once everything is working reliably */ /* // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz @@ -202,14 +185,8 @@ const ssp_config_t ssp_config_max5864 = { .gpio_select = &gpio_max5864_select, }; -spi_bus_t spi_bus_ssp1 = { - .obj = (void*)SSP1_BASE, - .config = &ssp_config_max5864, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; +/* spi_bus_ssp1 is defined in hackrf/firmware/common/spi_bus.c. We update + * its .config at runtime in clock_init() to point at ssp_config_max5864. */ max283x_driver_t max283x = {}; @@ -224,14 +201,8 @@ ssp_config_t ssp_config_w25q80bv = { .clock_prescale_rate = 2, }; -spi_bus_t spi_bus_ssp0 = { - .obj = (void*)SSP0_BASE, - .config = &ssp_config_w25q80bv, - .start = spi_ssp_start, - .stop = spi_ssp_stop, - .transfer = spi_ssp_transfer, - .transfer_gather = spi_ssp_transfer_gather, -}; +/* spi_bus_ssp0 is defined in hackrf/firmware/common/spi_bus.c. We update + * its .config at runtime in clock_init() to point at ssp_config_w25q80bv. */ w25q80bv_driver_t spi_flash = { .bus = &spi_bus_ssp0, @@ -240,43 +211,8 @@ w25q80bv_driver_t spi_flash = { .target_init = w25q80bv_target_init, }; -sgpio_config_t sgpio_config = { - .gpio_q_invert = &gpio_q_invert, - .gpio_trigger_enable = &gpio_hw_sync_enable, - .slice_mode_multislice = true, -}; - -rf_path_t rf_path = { - .switchctrl = 0, -#ifdef HACKRF_ONE - .gpio_hp = &gpio_hp, - .gpio_lp = &gpio_lp, - .gpio_tx_mix_bp = &gpio_tx_mix_bp, - .gpio_no_mix_bypass = &gpio_no_mix_bypass, - .gpio_rx_mix_bp = &gpio_rx_mix_bp, - .gpio_tx_amp = &gpio_tx_amp, - .gpio_tx = &gpio_tx, - .gpio_mix_bypass = &gpio_mix_bypass, - .gpio_rx = &gpio_rx, - .gpio_no_tx_amp_pwr = &gpio_no_tx_amp_pwr, - .gpio_amp_bypass = &gpio_amp_bypass, - .gpio_rx_amp = &gpio_rx_amp, - .gpio_no_rx_amp_pwr = &gpio_no_rx_amp_pwr, -#endif -#ifdef RAD1O - .gpio_tx_rx_n = &gpio_tx_rx_n, - .gpio_tx_rx = &gpio_tx_rx, - .gpio_by_mix = &gpio_by_mix, - .gpio_by_mix_n = &gpio_by_mix_n, - .gpio_by_amp = &gpio_by_amp, - .gpio_by_amp_n = &gpio_by_amp_n, - .gpio_mixer_en = &gpio_mixer_en, - .gpio_low_high_filt = &gpio_low_high_filt, - .gpio_low_high_filt_n = &gpio_low_high_filt_n, - .gpio_tx_amp = &gpio_tx_amp, - .gpio_rx_lna = &gpio_rx_lna, -#endif -}; +/* sgpio_config and rf_path are defined in hackrf/firmware/common/sgpio.c and + * rf_path.c. Their gpio_* fields are populated at runtime in pin_setup(). */ jtag_gpio_t jtag_gpio_cpld = { .gpio_tms = &gpio_cpld_tms, @@ -681,7 +617,7 @@ void cpu_clock_init(void) { si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); // soft reset - si5351c_reset_pll(&clock_gen); + si5351c_reset_pll(&clock_gen, SI5351C_PLL_BOTH); si5351c_enable_clock_outputs(&clock_gen); // FIXME disable I2C @@ -866,6 +802,55 @@ void ssp1_set_mode_max5864(void) { void pin_setup(void) { const platform_scu_t* scu = platform_scu(); + /* spi_bus_ssp0/1 are defined in hackrf/firmware/common/spi_bus.c with no + * .config. Patch in our SSP configs and SPI driver entry points here. */ + spi_bus_ssp0.config = &ssp_config_w25q80bv; + spi_bus_ssp0.start = spi_ssp_start; + spi_bus_ssp0.stop = spi_ssp_stop; + spi_bus_ssp0.transfer = spi_ssp_transfer; + spi_bus_ssp0.transfer_gather = spi_ssp_transfer_gather; + + spi_bus_ssp1.config = &ssp_config_max5864; + spi_bus_ssp1.start = spi_ssp_start; + spi_bus_ssp1.stop = spi_ssp_stop; + spi_bus_ssp1.transfer = spi_ssp_transfer; + spi_bus_ssp1.transfer_gather = spi_ssp_transfer_gather; + + /* sgpio_config / rf_path are defined in common/sgpio.c and rf_path.c + * with minimal initializers. Populate the gpio_* fields here. */ + sgpio_config.gpio_q_invert = &gpio_q_invert; + sgpio_config.gpio_trigger_enable = &gpio_hw_sync_enable; + sgpio_config.slice_mode_multislice = true; + +#ifdef HACKRF_ONE + rf_path.gpio_hp = &gpio_hp; + rf_path.gpio_lp = &gpio_lp; + rf_path.gpio_tx_mix_bp = &gpio_tx_mix_bp; + rf_path.gpio_no_mix_bypass = &gpio_no_mix_bypass; + rf_path.gpio_rx_mix_bp = &gpio_rx_mix_bp; + rf_path.gpio_tx_amp = &gpio_tx_amp; + rf_path.gpio_tx = &gpio_tx; + rf_path.gpio_mix_bypass = &gpio_mix_bypass; + rf_path.gpio_rx = &gpio_rx; + rf_path.gpio_no_tx_amp_pwr = &gpio_no_tx_amp_pwr; + rf_path.gpio_amp_bypass = &gpio_amp_bypass; + rf_path.gpio_rx_amp = &gpio_rx_amp; + rf_path.gpio_no_rx_amp_pwr = &gpio_no_rx_amp_pwr; +#endif +#ifdef RAD1O + rf_path.gpio_tx_rx_n = &gpio_tx_rx_n; + rf_path.gpio_tx_rx = &gpio_tx_rx; + rf_path.gpio_by_mix = &gpio_by_mix; + rf_path.gpio_by_mix_n = &gpio_by_mix_n; + rf_path.gpio_by_amp = &gpio_by_amp; + rf_path.gpio_by_amp_n = &gpio_by_amp_n; + rf_path.gpio_mixer_en = &gpio_mixer_en; + rf_path.gpio_low_high_filt = &gpio_low_high_filt; + rf_path.gpio_low_high_filt_n = &gpio_low_high_filt_n; + rf_path.gpio_tx_amp = &gpio_tx_amp; + rf_path.gpio_rx_lna = &gpio_rx_lna; +#endif + /* Configure all GPIO as Input (safe state) */ // gpio_init(); @@ -1070,3 +1055,17 @@ void halt_and_flash(const uint32_t duration) { delay(duration); } } + +/* Upstream commit 85dfacf6 ("Universalize: firmware/hackrf_usb") wired + * usb_endpoint_control_out.setup_complete to transceiver_usb_setup_complete + * (defined in hackrf_usb/usb_api_transceiver.c). That function dispatches + * transceiver-specific SETUP packets and falls through to usb_setup_complete + * for everything else. sd_over_usb doesn't link the transceiver API, so + * provide a shim that always delegates to the standard handler. Without + * this, EP0 SETUP packets get a no-op completion and enumeration times out + * (host reports "device descriptor read/64, error -110"). */ +void usb_setup_complete(usb_endpoint_t* const endpoint); +void transceiver_usb_setup_complete(usb_endpoint_t* const endpoint); +void transceiver_usb_setup_complete(usb_endpoint_t* const endpoint) { + usb_setup_complete(endpoint); +} diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.c b/firmware/baseband/sd_over_usb/sd_over_usb.c index ac0e24ba3..244869fb1 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.c +++ b/firmware/baseband/sd_over_usb/sd_over_usb.c @@ -22,6 +22,28 @@ #include "sd_over_usb.h" #include "scsi.h" +#include "usb_descriptor.h" + +#include + +/* Defined in hackrf/firmware/hackrf_usb/usb_device.c. After upstream commit + * 85dfacf6 ("Universalize: firmware/hackrf_usb"), the global `usb_device` is + * left zero-initialized and is populated at runtime from per-board + * `usb_device_*` constants inside hackrf_usb.c. The sd_over_usb baseband + * does not link hackrf_usb.c, so populate `usb_device` ourselves before + * usb_run(). The descriptor fields are const-qualified, so use the upstream + * memcpy-from-template pattern. */ +extern usb_configuration_t* usb_configurations[]; + +static const usb_device_t usb_device_sd_over_usb = { + .descriptor = usb_descriptor_device, + .descriptor_strings = usb_descriptor_strings, + .qualifier_descriptor = usb_descriptor_device_qualifier, + .configurations = &usb_configurations, + .configuration = 0, + .wcid_string_descriptor = wcid_string_descriptor, + .wcid_feature_descriptor = wcid_feature_descriptor, +}; volatile bool scsi_running = false; @@ -74,6 +96,8 @@ void start_usb(void) { pin_setup(); cpu_clock_init(); + memcpy(&usb_device, &usb_device_sd_over_usb, sizeof(usb_device_sd_over_usb)); + usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); @@ -85,7 +109,10 @@ void start_usb(void) { usb_queue_init(&usb_endpoint_bulk_in_queue); usb_endpoint_init(&usb_endpoint_control_out, false); - usb_endpoint_init(&usb_endpoint_control_in, false); + /* Match the new usb_endpoint_init() contract introduced upstream by + * db73ecbf, control IN needs ZLP for transfers whose length is a + * multiple of the EP0 max packet size, otherwise the host hangs. */ + usb_endpoint_init(&usb_endpoint_control_in, true); nvic_set_priority(NVIC_USB0_IRQ, 255); diff --git a/hackrf b/hackrf index 442d95e23..0bf478ed2 160000 --- a/hackrf +++ b/hackrf @@ -1 +1 @@ -Subproject commit 442d95e23dcfcbd22ec18d51a2ad7ddcca680ed2 +Subproject commit 0bf478ed259410a5cef085b6a50c795a80c096ad