From 5b81efe2932eb28c77d4817bca75c0006be99b68 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald <matthias@ringwald.ch> Date: Thu, 4 Jan 2018 17:21:25 +0100 Subject: [PATCH] windows: repeat UART read/write operation if not all bytes have been read or written --- platform/windows/btstack_uart_block_windows.c | 179 ++++++++++-------- 1 file changed, 99 insertions(+), 80 deletions(-) diff --git a/platform/windows/btstack_uart_block_windows.c b/platform/windows/btstack_uart_block_windows.c index 17e6d664d..2909dabad 100644 --- a/platform/windows/btstack_uart_block_windows.c +++ b/platform/windows/btstack_uart_block_windows.c @@ -79,76 +79,9 @@ static HANDLE serial_port_handle; static OVERLAPPED overlapped_read; static OVERLAPPED overlapped_write; +// -- engine that retries send/receive if not all bytes have been transferred -static int btstack_uart_windows_init(const btstack_uart_config_t * config){ - uart_config = config; - return 0; -} - -static void btstack_uart_windows_process_write(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { - - btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); - - DWORD bytes_written; - BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_write, &bytes_written, FALSE); - if(!ok){ - DWORD err = GetLastError(); - if (err == ERROR_IO_INCOMPLETE){ - // IO_INCOMPLETE -> wait for completed - btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); - } else { - log_error("btstack_uart_windows_process_write: error writing"); - } - return; - } - - // assert all bytes written - if (bytes_written != write_bytes_len){ - log_error("btstack_uart_windows_process_write: requested write %u but %u were written", (int) write_bytes_len, (int) bytes_written); - return; - } - - // notify done - if (block_sent){ - block_sent(); - } -} - -static void btstack_uart_windows_process_read(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { - - btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); - - DWORD bytes_read; - BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_read, &bytes_read, FALSE); - if(!ok){ - DWORD err = GetLastError(); - if (err == ERROR_IO_INCOMPLETE){ - // IO_INCOMPLETE -> wait for completed - btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); - } else { - log_error("btstack_uart_windows_process_write: error writing"); - } - return; - } - - // assert all bytes read - if (bytes_read != read_bytes_len){ - log_error("btstack_uart_windows_process_read: requested read %u but %u were read", (int) read_bytes_len, (int) bytes_read); - return; - } - - // notify done - if (block_received){ - block_received(); - } -} - -static void btstack_uart_windows_send_block(const uint8_t *data, uint16_t size){ - - // setup async write - write_bytes_data = data; - write_bytes_len = size; - +static void btstack_uart_windows_send_engine(void){ // start write DWORD bytes_written; BOOL ok = WriteFile(serial_port_handle, // handle @@ -158,7 +91,6 @@ static void btstack_uart_windows_send_block(const uint8_t *data, uint16_t size){ &overlapped_write); // overlapped structure if (ok){ - // assert all bytes written if (bytes_written != write_bytes_len){ log_error("btstack_uart_windows_send_block: requested write %u but %u were written", (int) write_bytes_len, (int) bytes_written); @@ -186,13 +118,7 @@ static void btstack_uart_windows_send_block(const uint8_t *data, uint16_t size){ btstack_run_loop_enable_data_source_callbacks(&transport_data_source_write, DATA_SOURCE_CALLBACK_WRITE); } -static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){ - - // setup async read - read_bytes_data = buffer; - read_bytes_len = len; - - // go +static void btstack_uart_windows_receive_engine(void){ DWORD bytes_read; BOOL ok = ReadFile(serial_port_handle, // handle read_bytes_data, // (LPCSTR) 8-bit data @@ -201,7 +127,6 @@ static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){ &overlapped_read); // overlapped structure if (ok){ - // assert all bytes read if (bytes_read != read_bytes_len){ log_error("btstack_uart_windows_receive_block: requested read %u but %u were read", (int) read_bytes_len, (int) bytes_read); @@ -221,7 +146,7 @@ static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){ DWORD err = GetLastError(); if (err != ERROR_IO_PENDING){ - log_error("btstack_uart_windows_receive_block: error reading"); + log_error("error reading"); return; } @@ -229,6 +154,100 @@ static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){ btstack_run_loop_enable_data_source_callbacks(&transport_data_source_read, DATA_SOURCE_CALLBACK_READ); } + +// -- overlapped IO handlers for read & write + +static void btstack_uart_windows_process_write(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { + + btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); + + DWORD bytes_written; + BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_write, &bytes_written, FALSE); + if(!ok){ + DWORD err = GetLastError(); + if (err == ERROR_IO_INCOMPLETE){ + // IO_INCOMPLETE -> wait for completed + btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); + } else { + log_error("write: error writing"); + } + return; + } + + // assert all bytes written + if (bytes_written != write_bytes_len){ + log_debug("write: requested to write %u but %u were written, try again", (int) write_bytes_len, (int) bytes_written); + btstack_uart_windows_send_engine(); + write_bytes_data += bytes_written; + write_bytes_len -= bytes_written; + return; + } + + // notify done + if (block_sent){ + block_sent(); + } +} + + +static void btstack_uart_windows_process_read(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { + + btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); + + DWORD bytes_read; + BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_read, &bytes_read, FALSE); + if(!ok){ + DWORD err = GetLastError(); + if (err == ERROR_IO_INCOMPLETE){ + // IO_INCOMPLETE -> wait for completed + btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); + } else { + log_error("error reading"); + } + return; + } + + + // assert all bytes read + if (bytes_read != read_bytes_len){ + log_debug("read: requested read %u but %u were read, try again", (int) read_bytes_len, (int) bytes_read); + read_bytes_data += bytes_read; + read_bytes_len -= bytes_read; + btstack_uart_windows_receive_engine(); + return; + } + + // notify done + if (block_received){ + block_received(); + } +} + +// -- API implementation + +static int btstack_uart_windows_init(const btstack_uart_config_t * config){ + uart_config = config; + return 0; +} + +static void btstack_uart_windows_send_block(const uint8_t *data, uint16_t size){ + // setup async write + write_bytes_data = data; + write_bytes_len = size; + + // go + btstack_uart_windows_send_engine(); +} + +static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){ + // setup async read + read_bytes_data = buffer; + read_bytes_len = len; + + // go + btstack_uart_windows_receive_engine(); +} + static void btstack_uart_windows_set_baudrate_option(DCB * serial_params, uint32_t baudrate){ serial_params->BaudRate = baudrate; } @@ -444,4 +463,4 @@ static const btstack_uart_block_t btstack_uart_windows = { const btstack_uart_block_t * btstack_uart_block_windows_instance(void){ return &btstack_uart_windows; -} \ No newline at end of file +}