Reputation: 1038
I'm trying to read in data from a serial port in Windows 7 using the Windows API. When I try to read in data, the WaitCommEvent()
fires just fine and the ReadFile()
call returns 1 as the status, but no data is read in. In the the ReadFile documentation it says that:
When a synchronous read operation reaches the end of a file,
ReadFile
returnsTRUE
and sets*lpNumberOfBytesRead
to zero.
However, I'm sure there are no EOT
characters in the data being sent over the serial port.
I currently have two USB cables plugged into my computer and connected to each other. I know that they can send and receive data as I have tested them with Putty.
Why won't ReadFile()
read in any data?
My code is below.
Header:
typedef struct uart_handle
{
uint8_t port_num;
char port_name[10];
uint32_t baud_rate;
uint8_t byte_size;
uint8_t stop;
uint8_t parity;
int32_t error;
HANDLE handle;
} uart_handle;
Main file:
uart_handle* serial_comm_init(uint8_t port_num, uint32_t baud_rate, uint8_t byte_size, uint8_t stop, uint8_t parity)
{
uart_handle* uart;
DCB uart_params = { 0 };
COMMTIMEOUTS timeouts = { 0 };
int status;
uart = (uart_handle*) malloc(1 * sizeof(uart_handle));
status = 0;
// Set port name
if (port_num > 9)
{
sprintf(uart->port_name, "\\\\.\\COM%d", port_num);
}
else
{
sprintf(uart->port_name, "COM%d", port_num);
}
// Set baud rate
uart->baud_rate = baud_rate;
// Set byte size
uart->byte_size = byte_size;
// Set stop bit
uart->stop = stop;
// Set parity
uart->parity = parity;
// Set up comm state
uart_params.DCBlength = sizeof(uart_params);
status = GetCommState(uart->handle, &uart_params);
uart_params.BaudRate = uart->baud_rate;
uart_params.ByteSize = uart->byte_size;
uart_params.StopBits = uart->stop;
uart_params.Parity = uart->parity;
SetCommState(uart->handle, &uart_params);
// Setup actual file handle
uart->handle = CreateFile(uart->port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (uart->handle == INVALID_HANDLE_VALUE) {
printf("Error opening serial port %s.\n", uart->port_name);
free(uart);
return NULL;
}
else {
printf("Serial port %s opened successfully.\n", uart->port_name);
}
// Set timeouts
status = GetCommTimeouts(uart->handle, &timeouts);
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
status = SetCommTimeouts(uart->handle, &timeouts);
if (status == 0) {
printf("Error setting comm timeouts: %d", GetLastError());
}
return uart;
}
int32_t serial_comm_read(void* handle, uint8_t* msg, uint32_t msg_size, uint32_t timeout_ms, uint32_t flag)
{
uart_handle* uart;
uint32_t num_bytes_read;
uint32_t event_mask;
int32_t status;
uart = (uart_handle*) handle;
num_bytes_read = 0;
event_mask = 0;
status = 0;
memset(msg, 0, msg_size);
// Register Event
status = SetCommMask(uart->handle, EV_RXCHAR);
// Wait for event
status = WaitCommEvent(uart->handle, &event_mask, NULL);
printf("Recieved characters.\n");
do {
status = ReadFile(uart->handle, msg, msg_size, &num_bytes_read, NULL);
printf("Status: %d\n", status);
printf("Num bytes read: %d\n", num_bytes_read);
printf("Message: %s\n", msg);
} while (num_bytes_read > 0);
printf("Read finished.\n");
return 0;
}
Output:
Serial port COM9 opened successfully.
Recieved characters.
Status: 1
Num bytes read: 0
Message:
Read finished.
Upvotes: 3
Views: 2676
Reputation: 70931
The code shown calls GetCommState()
on an uninitialised handle:
status = GetCommState(uart->handle, &uart_params);
provoking UB doing so. Its returned status is not tested.
Due to this uart_params
probably contains BS no useful data.
Do yourself a favour: Always and ever check the return value on all relevant function calls (and let the code act accordingly)! Consider as "relevant" all those functions returning or changing data used afterwards.
Upvotes: 3