windows: repeat UART read/write operation if not all bytes have been read or written

This commit is contained in:
Matthias Ringwald 2018-01-04 17:21:25 +01:00
parent a1a856590c
commit 5b81efe293

View File

@ -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;
}
}