@@ -49,11 +49,15 @@ struct UART_Handle {
4949 UART_RxCallback rx_callback ;
5050 uint32_t rx_threshold ;
5151 bool initialized ;
52+ UART_Handle * passthrough_target ;
5253};
5354
5455/* Global array to keep track of active UART handles */
5556static UART_Handle * g_active_handles [UART_BUS_COUNT ] = { nullptr };
5657
58+ /* Store disabled TX buffers during passthrough */
59+ static CircularBuffer * g_disabled_tx_buffers [2 ] = { nullptr };
60+
5761/**
5862 * @brief Get the number of available UART bus instances.
5963 *
@@ -276,6 +280,7 @@ UART_Handle *UART_init(
276280 handle -> rx_callback = nullptr ;
277281 handle -> rx_threshold = 0 ;
278282 handle -> initialized = false;
283+ handle -> passthrough_target = nullptr ;
279284
280285 /* Initialize hardware layer */
281286 UART_LL_init (bus_id , rx_buffer -> buffer , rx_buffer -> size );
@@ -301,6 +306,11 @@ void UART_deinit(UART_Handle *handle)
301306 return ;
302307 }
303308
309+ /* Cannot deinit while passthrough is active */
310+ if (handle -> passthrough_target ) {
311+ THROW (ERROR_RESOURCE_BUSY );
312+ }
313+
304314 /* Deinitialize hardware layer */
305315 UART_LL_deinit (handle -> bus_id );
306316
@@ -482,3 +492,76 @@ void UART_set_rx_callback(
482492 handle -> rx_callback (handle , rx_buffer_available (handle ));
483493 }
484494}
495+
496+ /**
497+ * @brief Passthrough callback function.
498+ *
499+ * This callback is triggered when data is received on a UART bus in passthrough
500+ * mode. It starts transmission on the target bus to forward the received data.
501+ *
502+ * @param handle UART handle of the receiving bus
503+ * @param bytes_available Number of bytes available (unused)
504+ */
505+ static void passthrough_callback (UART_Handle * handle , uint32_t bytes_available )
506+ {
507+ (void )bytes_available ; /* Unused parameter */
508+
509+ if (!handle || !handle -> passthrough_target ) {
510+ return ;
511+ }
512+
513+ /* Start transmission on the target bus */
514+ start_transmission (handle -> passthrough_target );
515+ }
516+
517+ void UART_enable_passthrough (UART_Handle * handle1 , UART_Handle * handle2 )
518+ {
519+ // Only one passthrough pair is allowed at a time
520+ if ((g_disabled_tx_buffers [0 ] != nullptr ) ||
521+ (g_disabled_tx_buffers [1 ] != nullptr )) {
522+ THROW (ERROR_RESOURCE_BUSY );
523+ }
524+
525+ if (!handle1 || !handle1 -> initialized || !handle2 ||
526+ !handle2 -> initialized ) {
527+ THROW (ERROR_DEVICE_NOT_READY );
528+ }
529+
530+ // Set up shared buffers:
531+ // - Normal tx_buffers are temporarily disabled
532+ // - Redirect each handle's rx_buffer to the other handle's tx_buffer
533+ g_disabled_tx_buffers [0 ] = handle1 -> tx_buffer ;
534+ g_disabled_tx_buffers [1 ] = handle2 -> tx_buffer ;
535+ handle1 -> tx_buffer = handle2 -> rx_buffer ;
536+ handle2 -> tx_buffer = handle1 -> rx_buffer ;
537+
538+ // Set up passthrough targets
539+ handle1 -> passthrough_target = handle2 ;
540+ handle2 -> passthrough_target = handle1 ;
541+
542+ // Set up RX callbacks to trigger transmission on the other bus
543+ UART_set_rx_callback (handle1 , passthrough_callback , 1 );
544+ UART_set_rx_callback (handle2 , passthrough_callback , 1 );
545+ }
546+
547+ void UART_disable_passthrough (UART_Handle * handle1 , UART_Handle * handle2 )
548+ {
549+ if (handle1 -> passthrough_target != handle2 ||
550+ handle2 -> passthrough_target != handle1 ) {
551+ THROW (ERROR_INVALID_ARGUMENT );
552+ }
553+
554+ /* Restore original TX buffers */
555+ handle1 -> tx_buffer = g_disabled_tx_buffers [0 ];
556+ handle2 -> tx_buffer = g_disabled_tx_buffers [1 ];
557+ g_disabled_tx_buffers [0 ] = nullptr ;
558+ g_disabled_tx_buffers [1 ] = nullptr ;
559+
560+ /* Clear passthrough targets */
561+ handle1 -> passthrough_target = nullptr ;
562+ handle2 -> passthrough_target = nullptr ;
563+
564+ /* Disable RX callbacks */
565+ UART_set_rx_callback (handle1 , nullptr , 0 );
566+ UART_set_rx_callback (handle2 , nullptr , 0 );
567+ }
0 commit comments