@@ -41,10 +41,12 @@ struct UART_Handle {
4141 UART_Bus bus_id ;
4242 CircularBuffer * rx_buffer ;
4343 CircularBuffer * tx_buffer ;
44+ CircularBuffer * original_tx_buffer ; /* Stored during passthrough */
4445 uint32_t volatile rx_dma_head ;
4546 UART_RxCallback rx_callback ;
4647 uint32_t rx_threshold ;
4748 bool initialized ;
49+ UART_Handle * passthrough_target ;
4850};
4951
5052/* Global array to keep track of active UART handles */
@@ -260,10 +262,12 @@ UART_Handle *UART_init(
260262 handle -> bus_id = bus_id ;
261263 handle -> rx_buffer = rx_buffer ;
262264 handle -> tx_buffer = tx_buffer ;
265+ handle -> original_tx_buffer = nullptr ;
263266 handle -> rx_dma_head = 0 ;
264267 handle -> rx_callback = nullptr ;
265268 handle -> rx_threshold = 0 ;
266269 handle -> initialized = false;
270+ handle -> passthrough_target = nullptr ;
267271
268272 /* Initialize hardware layer */
269273 UART_LL_init (bus_id , rx_buffer -> buffer , rx_buffer -> size );
@@ -289,6 +293,11 @@ void UART_deinit(UART_Handle *handle)
289293 return ;
290294 }
291295
296+ /* Cannot deinit while passthrough is active */
297+ if (handle -> passthrough_target ) {
298+ THROW (ERROR_RESOURCE_BUSY );
299+ }
300+
292301 /* Deinitialize hardware layer */
293302 UART_LL_deinit (handle -> bus_id );
294303
@@ -470,3 +479,80 @@ void UART_set_rx_callback(
470479 handle -> rx_callback (handle , rx_buffer_available (handle ));
471480 }
472481}
482+
483+ /**
484+ * @brief Passthrough callback function.
485+ *
486+ * This callback is triggered when data is received on a UART bus in passthrough
487+ * mode. It starts transmission on the target bus to forward the received data.
488+ *
489+ * @param handle UART handle of the receiving bus
490+ * @param bytes_available Number of bytes available (unused)
491+ */
492+ static void passthrough_callback (UART_Handle * handle , uint32_t bytes_available )
493+ {
494+ (void )bytes_available ; /* Unused parameter */
495+
496+ if (!handle || !handle -> passthrough_target ) {
497+ return ;
498+ }
499+
500+ /* Start transmission on the target bus */
501+ start_transmission (handle -> passthrough_target );
502+ }
503+
504+ void UART_enable_passthrough (UART_Handle * handle1 , UART_Handle * handle2 )
505+ {
506+ if (!handle1 || !handle1 -> initialized || !handle2 ||
507+ !handle2 -> initialized ) {
508+ THROW (ERROR_DEVICE_NOT_READY );
509+ }
510+
511+ // Check that handles are different
512+ if (handle1 == handle2 ) {
513+ THROW (ERROR_INVALID_ARGUMENT );
514+ }
515+
516+ // Check if either handle is already in passthrough mode
517+ if (handle1 -> passthrough_target || handle2 -> passthrough_target ) {
518+ THROW (ERROR_RESOURCE_BUSY );
519+ }
520+
521+ // Set up shared buffers:
522+ // - Store normal tx_buffers in each handle
523+ // - Redirect each handle's rx_buffer to the other handle's tx_buffer
524+ handle1 -> original_tx_buffer = handle1 -> tx_buffer ;
525+ handle2 -> original_tx_buffer = handle2 -> tx_buffer ;
526+ handle1 -> tx_buffer = handle2 -> rx_buffer ;
527+ handle2 -> tx_buffer = handle1 -> rx_buffer ;
528+
529+ // Set up passthrough targets
530+ handle1 -> passthrough_target = handle2 ;
531+ handle2 -> passthrough_target = handle1 ;
532+
533+ // Set up RX callbacks to trigger transmission on the other bus
534+ UART_set_rx_callback (handle1 , passthrough_callback , 1 );
535+ UART_set_rx_callback (handle2 , passthrough_callback , 1 );
536+ }
537+
538+ void UART_disable_passthrough (UART_Handle * handle1 , UART_Handle * handle2 )
539+ {
540+ if (handle1 -> passthrough_target != handle2 ||
541+ handle2 -> passthrough_target != handle1 ) {
542+ THROW (ERROR_INVALID_ARGUMENT );
543+ }
544+
545+ /* Disable passthrough callbacks */
546+ UART_set_rx_callback (handle1 , nullptr , 0 );
547+ UART_set_rx_callback (handle2 , nullptr , 0 );
548+
549+ /* Restore original TX buffers */
550+ handle1 -> tx_buffer = handle1 -> original_tx_buffer ;
551+ handle2 -> tx_buffer = handle2 -> original_tx_buffer ;
552+ handle1 -> original_tx_buffer = nullptr ;
553+ handle2 -> original_tx_buffer = nullptr ;
554+
555+ /* Clear passthrough targets */
556+ handle1 -> passthrough_target = nullptr ;
557+ handle2 -> passthrough_target = nullptr ;
558+ }
0 commit comments