unable to read Through linux Serial port - c

Hi I have written a program in c to communicate with /dev/ttyS0 to a device . when i do write i am able to do that but i get ERROR: Resource temporarily unavailable, -1 as return from read(). can you please check what i am doing wrong . the port is supposed to be a half duplex ,9600bps,8N1 , and a inter byte delay of 4ms . also can anyone tell me how to set inter byte delay in milliseconds. Below is my code.
#include<stdio.h>
#include<termios.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#define BAUDRATE B9600
#define PORT "/dev/ttyS0"
int main()
{
struct termios new_tio,old_new_tio;
int fd;
unsigned char msgS[5]="",msgR[10]="";
fd = open(PORT,O_RDWR|O_NOCTTY|O_NDELAY);
if(fd == -1)
printf("Failed to open PORT: %s \n\n",PORT);
perror("Error:");
tcgetattr(fd,&old_new_tio);
memset(&new_tio,0,sizeof(new_tio));
new_tio.c_cflag = BAUDRATE|CS8|CLOCAL|CREAD|CSIZE|PARENB;
new_tio.c_oflag = 0;
new_tio.c_iflag = 0;
new_tio.c_cc[VMIN] = 10;
new_tio.c_cc[VTIME] = 0.004;
cfsetispeed(&new_tio,BAUDRATE);
cfsetospeed(&new_tio,BAUDRATE);
new_tio.c_cc[VINTR] = 0;
new_tio.c_cc[VQUIT] = 0;
new_tio.c_cc[VERASE] = 0;
new_tio.c_cc[VKILL] = 0;
new_tio.c_cc[VEOF] = 4;
new_tio.c_cc[VSWTC] = 0; /* '\0' */
new_tio.c_cc[VSTART] = 0; /* Ctrl-q */
new_tio.c_cc[VSTOP] = 0; /* Ctrl-s */
new_tio.c_cc[VSUSP] = 0; /* Ctrl-z */
new_tio.c_cc[VEOL] = 0; /* '\0' */
new_tio.c_cc[VREPRINT] = 0; /* Ctrl-r */
new_tio.c_cc[VDISCARD] = 0; /* Ctrl-u */
new_tio.c_cc[VWERASE] = 0; /* Ctrl-w */
new_tio.c_cc[VLNEXT] = 0; /* Ctrl-v */
new_tio.c_cc[VEOL2] = 0;
tcflush(fd,TCIFLUSH);
tcsetattr(fd,TCSANOW,&new_tio);
msgS[0] = '*';
msgS[1] = 'G';
msgS[2] = 'U';
msgS[3] = 'S';
msgS[4] = '\r';
printf("Message to be sent : %s \n\n",msgS);
int i = write(fd,&msgS,5);
if(i != 5)
printf("error while writing to the port\n\n");
int j = read(fd,&msgR,10);
if(j != 10)
printf("error while reading from port\n\n");
printf("Message Recieved : %s\n\n",msgR);
return 0;
}

You open the port in non-blocking mode (using O_NDELAY). Therefore your read would never block and only read what's already arrived. You should either use select to wait for the data first, or use a blocking mode.
I doubt you can fine-tune inter-byte delay. To increase it, you can enable using two stop bits instead of one (CSTOPB).

Related

Libusb error for Input and Output under Ubuntu Linux - C programming for USB

I have made a C-program that should talk USB. But I have got an error -1 that says I have som Input/Output errors.
My C code is here below. I going to explain how it works. The function getDevices() print out the vendor ID and the product ID and also the device name. Remember those when you running the function getDevices().
Then you have to choose what device you want to connect. When you have choose the device, then you write in the vendor ID and product ID here.
#define USB_VENDOR_ID 1155
#define USB_PRODUCT_ID 14415 /* USB product ID used by the device */
After that, you need to run the function connectUSB(). It simply connect to your USB depening on which USB_VENDOR_ID and USB_PRODUCT_ID you have been written.
I have issues to read the incomming message. I got the error LIBUSB_ERROR_IO = -1 when I try to read.
So why does I get -1 error when I try to read? I have tried with:
Run the C-code as full administration rights, e.g root
Unmout the USB device inside the computer, not plug it out
Tested to have a USB reader software ON meanwhile I use this C-program
If you want to try my code, you have to install LibUSB. From debbased systems such as Debian, Ubuntu, Raspberry etc. it can be done by writing this command in the terminal.
sudo apt-get install libusb-1.0.0-dev libusb-1.0-0
My C-code below.
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#include <string.h>
libusb_context *CONTEXT; //a libusb session
libusb_device_handle *DEVICEHANDLE; //a device handle
libusb_device * DEVICE_POINTER; // a pointer to a device
libusb_device **ARRAY_OF_POINTERS_TO_DEVICE; // an array of pointers to devices
ssize_t NUMBER_OF_USB_DEVICES; // Initial zero devices
static uint8_t receiveBuf[64];
uint8_t transferBuf[64];
uint16_t counter = 0;
#define USB_ENDPOINT_IN 0x80 /* endpoint address */
#define USB_ENDPOINT_OUT 0x01 /* endpoint address */
#define USB_TIMEOUT 3000 /* Connection timeout (in ms) */
#define USB_VENDOR_ID 1155
#define USB_PRODUCT_ID 14415 /* USB product ID used by the device */
/*
* Here we are going to read the USB
*/
int readUSB() {
int nread, r, counter = 0;
nread = 4;
int transfered;
unsigned char data[4];
r = libusb_bulk_transfer(DEVICEHANDLE, USB_ENDPOINT_IN, data, nread, &transfered, USB_TIMEOUT);
if (LIBUSB_ERROR_TIMEOUT == r) {
printf("LIBUSB_ERROR_TIMEOUT = %d\n", r);
return -1;
}else if(LIBUSB_ERROR_PIPE == r){
printf("LIBUSB_ERROR_PIPE = %d\n", r);
return -1;
}else if(LIBUSB_ERROR_OVERFLOW == r){
printf("LIBUSB_ERROR_OVERFLOW = %d\n", r);
return -1;
}else if(LIBUSB_ERROR_NO_DEVICE == r){
printf("LIBUSB_ERROR_NO_DEVICE = %d\n", r);
return -1;
}else if(LIBUSB_ERROR_IO == r){
printf("LIBUSB_ERROR_IO = %d\n", r);
return -1;
} else {
printf("r = %d, %d receive %d bytes from device: %s\n", r, ++counter, nread, data);
return 0;
}
return 0;
}
/*
* Here are we going to write to the USB
*/
int writeUSB() {
int n, ret;
uint16_t count = 0;
//count up
n = sprintf(transferBuf, "%d\0", count++);
//write transfer
//probably unsafe to use n twice...
ret = libusb_bulk_transfer(DEVICEHANDLE, USB_ENDPOINT_OUT, transferBuf, n,
&n, USB_TIMEOUT);
//Error handling
switch (ret) {
case 0:
printf("send %d bytes to device\n", n);
return 0;
case LIBUSB_ERROR_TIMEOUT:
printf("ERROR in bulk write: %d Timeout\n", ret);
break;
case LIBUSB_ERROR_PIPE:
printf("ERROR in bulk write: %d Pipe\n", ret);
break;
case LIBUSB_ERROR_OVERFLOW:
printf("ERROR in bulk write: %d Overflow\n", ret);
break;
case LIBUSB_ERROR_NO_DEVICE:
printf("ERROR in bulk write: %d No Device\n", ret);
break;
default:
printf("ERROR in bulk write: %d\n", ret);
break;
}
return -1;
return 0;
}
/*
* This will connect to our USB device
*/
int connectUSB() {
int r;
r = libusb_init(&CONTEXT);
if(r > 0){
printf("Libusb_init error %d\n", r);
return -1;
}
//libusb_set_debug(CONTEXT, 0);
//Open Device with VendorID and ProductID
DEVICEHANDLE = libusb_open_device_with_vid_pid(CONTEXT, USB_VENDOR_ID, USB_PRODUCT_ID);
if (DEVICEHANDLE == NULL) {
perror("DEVICEHANDLE == NULL");
return -1;
}
//Claim Interface 0 from the device
r = libusb_claim_interface(DEVICEHANDLE, 0);
if (r == LIBUSB_ERROR_NOT_FOUND) {
fprintf(stderr, "LIBUSB_ERROR_NOT_FOUND = %d\n", r);
return -1;
}else if(r == LIBUSB_ERROR_BUSY){
fprintf(stderr, "LIBUSB_ERROR_BUSY = %d\n", r);
return -1;
}else if(r == LIBUSB_ERROR_NO_DEVICE){
fprintf(stderr, "LIBUSB_ERROR_NO_DEVICE = %d\n", r);
return -1;
}
printf("Interface claimed\n");
return 0;
}
/*
* This will show all the devices for USB and send it thru sockets
*/
int getDevices() {
/*
* Special local device handle for only get the name of the USB device
*/
libusb_device_handle *DEVICEHANDLE_NULL; //a device handle
/*
* Compute the number of USB
*/
int returnValue = libusb_init(NULL);
NUMBER_OF_USB_DEVICES = libusb_get_device_list(NULL,
&ARRAY_OF_POINTERS_TO_DEVICE);
/*
* Create our list of Vendor, Product and device
* Vendor and product are important for connect the USB and device is important for the user to see which USB to connect
*/
uint16_t vendor[NUMBER_OF_USB_DEVICES];
uint16_t product[NUMBER_OF_USB_DEVICES];
char device[NUMBER_OF_USB_DEVICES][256 * 2];
/*
* Loop thru all USB devices
*/
ssize_t deviceIndex = 0;
while (deviceIndex < NUMBER_OF_USB_DEVICES) {
/*
* Get the description of the USB device
*/
DEVICE_POINTER = ARRAY_OF_POINTERS_TO_DEVICE[deviceIndex];
struct libusb_device_descriptor deviceDescriptor;
returnValue = libusb_get_device_descriptor(DEVICE_POINTER,
&deviceDescriptor);
if (returnValue != LIBUSB_SUCCESS)
break;
/*
* Open the USB device with NULL. It's only because we want the name of the USB device
*/
DEVICEHANDLE_NULL = NULL;
returnValue = libusb_open(DEVICE_POINTER, &DEVICEHANDLE_NULL);
if (returnValue != LIBUSB_SUCCESS) {
/*
* There was an error. Not success.
*/
if (DEVICEHANDLE_NULL != NULL) {
libusb_close(DEVICEHANDLE_NULL);
DEVICEHANDLE_NULL = NULL;
}
/*
* Write as there was no info at all to display
*/
product[deviceIndex] = 0;
vendor[deviceIndex] = 0;
memcpy(device[deviceIndex], "-", 256 * 2 * sizeof(char));
deviceIndex++;
continue;
}
/*
* Get the string associated with iManufacturer index.
*/
const int STRING_LENGTH = 256;
unsigned char stringManufacturer[STRING_LENGTH];
unsigned char stringProduct[STRING_LENGTH];
char stringDeviceName[STRING_LENGTH * 2];
if (DEVICEHANDLE_NULL != NULL && deviceDescriptor.iManufacturer > 0) {
returnValue = libusb_get_string_descriptor_ascii(DEVICEHANDLE_NULL,
deviceDescriptor.iManufacturer, stringManufacturer,
STRING_LENGTH);
if (returnValue < 0)
break;
}
/*
* Get string associated with iProduct index.
*/
if (DEVICEHANDLE_NULL != NULL && deviceDescriptor.iProduct > 0) {
returnValue = libusb_get_string_descriptor_ascii(DEVICEHANDLE_NULL,
deviceDescriptor.iProduct, stringProduct, STRING_LENGTH);
if (returnValue < 0)
break;
}
/*
* Combine manufacturer and product
*/
strcpy(stringDeviceName, (char*) stringManufacturer);
strcat(stringDeviceName, " "); // a space only
strcat(stringDeviceName, (char*) stringProduct);
//printf("%s\n", stringDeviceName);
/*
* Save them all into arrays
*/
product[deviceIndex] = deviceDescriptor.idProduct;
vendor[deviceIndex] = deviceDescriptor.idVendor;
memcpy(device[deviceIndex], stringDeviceName, 256 * 2 * sizeof(char));
/*
* Close and try next one.
*/
if (DEVICEHANDLE_NULL != NULL) {
libusb_close(DEVICEHANDLE_NULL);
DEVICEHANDLE_NULL = NULL;
}
/*
* Next USB device
*/
deviceIndex++;
}
/*
* Print our result what we found and send them to socket
*/
for (int i = 0; i < 11; i++) {
printf("Name: %s\n", device[i]);
printf("Vendor: %u\n", vendor[i]);
printf("Product: %u\n\n", product[i]);
}
libusb_exit(NULL);
return 0;
}

Serial communication between GSM module and computer

I am working on a project having GSM module and it is also communicating serially with computer.
I have written a code in C on Visual Studio 2010 to transmit and receive data serially.
Code is given below:-
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <commdlg.h>
int nread,nwrite;
int main()
{
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char *words, *buffRead, *buffWrite;
DWORD dwBytesWritten,dwBytesRead;
HANDLE hSerial= CreateFile(L"COM1", GENERIC_READ | GENERIC_WRITE,
0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if ( hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf(" serial port does not exist \n");
}
printf(" some other error occured. Inform user.\n");
}
//DCB dcbSerialParams ;
//GetCommState( hSerial, &dcbSerialParams.dcb);
if (!GetCommState(hSerial, &dcbSerialParams.dcb))
{
printf("error getting state \n");
}
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
dcbSerialParams.dcb.BaudRate = CBR_9600;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
dcbSerialParams.dcb.fBinary = TRUE;
dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.dcb.fOutxCtsFlow = FALSE;
dcbSerialParams.dcb.fOutxDsrFlow = FALSE;
dcbSerialParams.dcb.fDsrSensitivity= FALSE;
dcbSerialParams.dcb.fAbortOnError = TRUE;
if (!SetCommState(hSerial, &dcbSerialParams.dcb))
{
printf(" error setting serial port state \n");
}
GetCommTimeouts(hSerial,&timeouts);
//COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 1000;
timeouts.WriteTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier= 1000;
if(!SetCommTimeouts(hSerial, &timeouts))
{
printf("error setting port state \n");
}
while(1)
{
//****************Write Operation*********************//
char data_tx[]="at\r";
words=&data_tx[0];
nwrite = strlen(words);
buffWrite = words;
dwBytesWritten = 0;
if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL))
{
printf("error writing to output buffer \n");
}
printf("Data written to write buffer is\n %s \n",buffWrite);
//***************Read Operation******************//
dwBytesRead = 0;
nread = strlen(words);
buffRead = new char[nread +1];
memset(buffRead, 0, nread+1); // ensure that string will be null-terminated
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
printf("Data read from read buffer is \n %s \n ",buffRead);
Sleep(10000);
}
CloseHandle(hSerial);
}
When command "at\r" is transmitted from computer to GSM module it receive it should respond to it by sending OK.
Now I am getting only O. If I send "at\r" again I am getting K.
I have verified it on hyper terminal GSM module is working properly.If I send "at" and enter it responds with OK.
Also I have verified my C code on other program it is working properly.
I want to know why it is not working properly with GSM module.
You need to call sleep before reading the result. 250 ms is more than enough

Interacting with a serial port using the C functions fopen, fread, and fwrite?

I have been attempting to communicate with a device of mine via an RS232 serial port(in my case it is COM6). My code is supposed to write a string of ascii values to the device and then read the response, however I cannot seem to get any response. The program seems to work relatively fine when I have it write and read to a file in my computer, but not for when I designate COM6. Here is the latest edition of my code:
using namespace std;
const char ASCII[ ]= "0123456789ABCDEF";
char *Checksum (char *buffer)
{
static char Hex[10];
static int a1, a2;
register unsigned int i;
int sum;
printf("%s \n", buffer);
sum = 256;
for ( i=0 ; i<strlen(buffer) ; i++ )
{
sum-=buffer[i];
if ( sum<0 )
sum+= 256;
}
a1 = (sum & 0xF0) >> 4;
a2 = sum & 0x0F;
Hex[0] = ASCII[a1];
Hex[1] = ASCII[a2];
Hex[2] = 0;
printf("the checksum is %s \n",Hex);
return(Hex);
}
int main()
{
char data[80], input[80], *data2;
char *response;
DCB dcb;
bool retVal;
DWORD dwBytesTransferred;
DWORD byteswritten;
printf("the variable response is initially: %d\n", response);
dcb.BaudRate = CBR_19200; //19200 Baud
dcb.ByteSize = 8; //8 data bits
dcb.Parity = NOPARITY; //no parity
dcb.StopBits = ONESTOPBIT; //1 stop
//New open port area
HANDLE hPort;
if ((hPort = CreateFile ( "\\\\.\\COM6",
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) != INVALID_HANDLE_VALUE)
{
printf("SUCCESS opening the port\n");// success
}
//GetCommState
DCB Dcb;
GetCommState (hPort, &Dcb);
Dcb.BaudRate = CBR_19200;
Dcb.StopBits = ONESTOPBIT;
Dcb.ByteSize = 8;
Dcb.Parity = NOPARITY;
Dcb.fParity = 0;
Dcb.fOutxCtsFlow = 0;
Dcb.fOutxDsrFlow = 0;
Dcb.fDsrSensitivity = 0;
Dcb.fTXContinueOnXoff = TRUE;
Dcb.fOutX = 0;
Dcb.fInX = 0;
Dcb.fNull = 0;
Dcb.fErrorChar = 0;
Dcb.fAbortOnError = 0;
Dcb.fRtsControl = RTS_CONTROL_DISABLE;
Dcb.fDtrControl = DTR_CONTROL_DISABLE;
//Flushing
FlushFileBuffers( hPort );
PurgeComm (hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
COMSTAT comStat;
DWORD dwErrorFlags;
ClearCommError ( hPort, &dwErrorFlags, &comStat );
//NEW commtimeouts area
COMMTIMEOUTS CommTimeOuts;
DWORD dwTimeout = 3000; // <- set timeout in milliseconds
if(!dwTimeout)
{ // Don't use timeout -> Read the bytes already in input buffer and return immediately
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
} else
{ // Use given timeout, wait until the requested number of bytes are read - or timeout
CommTimeOuts.ReadIntervalTimeout = 0;
CommTimeOuts.ReadTotalTimeoutConstant = dwTimeout;
}
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts (hPort, &CommTimeOuts);
printf("insert ASCII code string you wish to send:");
scanf("%s", input);
strcpy(data, "{0x02}");
strcat(data, input);
printf("%s \n", data);
data2=Checksum(data);
strcat(data, data2);
strcat(data, "{0x03}");
printf("the final sent message will be: %s \n",data);
retVal = WriteFile(hPort,data, strlen(data), &byteswritten, NULL);
printf("Number of bytes written: %d\n", byteswritten);
printf("Write Success? %d\n", retVal);
retVal=ReadFile (hPort, &response, 20, &dwBytesTransferred, NULL);
printf("Read Success? %d\n", retVal);
printf("Port Response: %d\n", response);
free(response);
return 0;
}
Summary of latest discoveries: Using the Free Serial Port Monitor that Habi suggested I now know for sure that WriteFile is functioning correctly and COM6 is in receiving the message. I'm still looking for a crossover cable to double check that the message is being transferred across the line. I figure while I try to figure that out if someone could look at this new edition and tell me if there is anything wrong, particularly in relation to the ReadFile function, it would be much appreciated. It bothers me that the Free Serial Port software is only showing the data passed from my computer and not a response from the device at all. =\
Instead of
"COM6"
try
"\\\\.\\COM6"
And I would recommend to use CreateFile(), ReadFile(), WriteFile().
To open the COM port try this:
HANDLE hComDev;
if ((hComDev = CreateFile ( "\\\\.\\COM6",
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) != INVALID_HANDLE_VALUE)
{
// success
}
It seems that calling GetCommState() is missing in your code. Try this to configure the COM port:
DCB Dcb;
GetCommState (hComDev, &Dcb);
Dcb.BaudRate = CBR_19200;
Dcb.StopBits = ONESTOPBIT;
Dcb.ByteSize = 8;
Dcb.Parity = NOPARITY;
Dcb.fParity = 0;
Dcb.fOutxCtsFlow = 0;
Dcb.fOutxDsrFlow = 0;
Dcb.fDsrSensitivity = 0;
Dcb.fTXContinueOnXoff = TRUE;
Dcb.fOutX = 0;
Dcb.fInX = 0;
Dcb.fNull = 0;
Dcb.fErrorChar = 0;
Dcb.fAbortOnError = 0;
Dcb.fRtsControl = RTS_CONTROL_DISABLE;
Dcb.fDtrControl = DTR_CONTROL_DISABLE;
And to initially clear the COM port, I would do a reset like this before starting to send and receive bytes:
FlushFileBuffers( hComDev );
PurgeComm (hComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
COMSTAT comStat;
DWORD dwErrorFlags;
ClearCommError ( hComDev, &dwErrorFlags, &comStat );
You ask for timeouts? To configure time outs try this:
COMMTIMEOUTS CommTimeOuts;
DWORD dwTimeout = .... // <- set timeout in milliseconds
if(!dwTimeout)
{ // Don't use timeout -> Read the bytes already in input buffer and return immediately
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
}
else
{ // Use given timeout, wait until the requested number of bytes are read - or timeout
CommTimeOuts.ReadIntervalTimeout = 0;
CommTimeOuts.ReadTotalTimeoutConstant = dwTimeout;
}
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts (hComDev, &CommTimeOuts);
My code is supposed to write a string of ascii values to the device
and then read the response, however I cannot seem to get any response.
Are you sure that the bytes are really sent to the device? If you have the option, take a oscilloscope and monitor the PC's Tx line. Send some bytes and check baudrate and start/stop bits. If you have no hardware to monitor this signal, take a software based serial monitor, e.g. Free Serial Port Monitor. I have no experience with that kind of software tools but they should show you at least that the Windows drivers try to send something via the COM port of your choice.
Greetings
Habi
If you have been trying for a month then I would recommend you look at the windows function CreateFile. I have used this for serial port comms and it works fine. You might also want to look at the DCB struct and GetCommState and SetCommState functions to configure the serial port. WriteFile can be used to write data to the serial port. I cannot post all of my code as it owned by my company, but this should help you get started.
Also ClearCommError may be of help to you to query if any data is on the serial port buffer when you are waiting to read from it.
I encountered a similar problem and found the other answers helpful, but I was not receiving characters.
Ultimately I found the problem was with RTS_CONTROL_DISABLE or DTR_CONTROL_DISABLE.
By having RTS and DTR held low, the program was indicating to the modem/device that the program was not ready to receive data, and the modem was respecting this signal and dutifully not sending.
By changing these to RTS_CONTROL_ENABLE and DTR_CONTROL_ENABLE, the program indicates to the modem that data may be sent, and I began receiving characters. Not all devices respect these signals so it may work in some configurations with DTR and RTS disabled -- the modem may send data anyway.
It's possible, but you need to config com port via cmd mode command,
and there is no way to config timeout value via cmd command.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
// use mode command to config port
// mode com2 dtr=off rts=off baud=9600 parity=N data=8 stop=1 to=on
FILE *f = fopen("\\\\.\\COM2", "wb+");
setvbuf(f, NULL, _IONBF, 0);
if(f == NULL) return -1;
while(1)
{
static char p[5];
int cnt = fread(&p, 1, sizeof(p), f);
printf("read[%d]:%s\n", cnt, p);
if(p[0] == '0') break;
memset(p, 0, sizeof(p));
}
fclose(f);
return 0;
}

Serial communication not working. Readfile goes wrong

After hours of browsing and reading, I still can't figure out why my code isn't working. I saw similar code snippets on different websites, but I can't seem to get it to work. The writing part is working, but the reading goes wrong. Every 'real character' is followed by three null terminators. Writing a string of 19 characters works and the FPGA I am using gives the correct data on the display. The FPGA should reverse the input and send this pack to the serial port. In the Hyperterminal this is working without any problem.
Can someone maybe point me on my mistake and tell me what I am doing wrong?
Thanks in advance =)
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <commdlg.h>
//#include <windef.h>
#define BUFFERLENGTH 19
void writeToSerial(char *line, HANDLE hSerial, DWORD dwBytesWritten);
void printBuffer(char * buffRead, DWORD dwBytesRead);
int main(){
HANDLE hSerial;
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char *line, *buffWrite, *buffRead;
DWORD dwBytesWritten, dwBytesRead;
/* Create a handle to the serial port */
hSerial = CreateFile("COM3",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
/* Check if the handle is valid */
if(hSerial == INVALID_HANDLE_VALUE){
if(GetLastError() == ERROR_FILE_NOT_FOUND){
printf("Serial port does not exist \n");
}else{
printf("Port occupied. Please close terminals!\n");
}
}else{
printf("Handle created\n");
/* Check the state of the comm port */
if(!GetCommState(hSerial, &dcbSerialParams.dcb)){
printf("Error getting state \n");
}else{
printf("Port available\n");
/* Configure the settings of the port */
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
/* Basic settings */
dcbSerialParams.dcb.BaudRate = CBR_57600;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
/* Misc settings */
dcbSerialParams.dcb.fBinary = TRUE;
dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.dcb.fOutxCtsFlow = FALSE;
dcbSerialParams.dcb.fOutxDsrFlow = FALSE;
dcbSerialParams.dcb.fDsrSensitivity= FALSE;
dcbSerialParams.dcb.fAbortOnError = TRUE;
/* Apply the settings */
if(!SetCommState(hSerial, &dcbSerialParams.dcb)){
printf("Error setting serial port state \n");
}else{
printf("Settings applied\n");
GetCommTimeouts(hSerial,&timeouts);
//COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier= 10;
if(!SetCommTimeouts(hSerial, &timeouts)){
printf("Error setting port state \n");
}else{
/* Ready for communication */
line = "Something else\r";
//****************Write Operation*********************//
writeToSerial(line, hSerial, dwBytesWritten);
//***************Read Operation******************//
if(ReadFile(hSerial, buffRead, BUFFERLENGTH, &dwBytesRead, NULL)){
printBuffer(buffRead, dwBytesRead);
}
}
}
}
}
CloseHandle(hSerial);
system("PAUSE");
return 0;
}
void printBuffer(char * buffRead, DWORD dwBytesRead){
int j;
for(j = 0; j < dwBytesRead; j++){
if(buffRead[j] != '\0'){
printf("%d: %c\n", j, buffRead[j]);
}
}
}
void writeToSerial(char *line, HANDLE hSerial, DWORD dwBytesWritten){
WriteFile(hSerial, line, 19, &dwBytesWritten,NULL);
if(dwBytesWritten){
printf("Writing success, you wrote '%s'\n", line);
}else{
printf("Writing went wrong =[\n");
}
}
In this line:
if(ReadFile(hSerial, buffRead, BUFFERLENGTH, &dwBytesRead, NULL))
the buffRead parameter is an uninitialised pointer. Change the declaration to:
char *line, *buffWrite, buffRead [BUFFERLENGTH+1];
Hyper terminal probably doesn't display null characters so it's possible that your fpga is actually sending them.
You could try testing it with Br#y Terminal in hex mode, or looking at the line with an oscilloscope.

SIGPIPE With Running Program

I have two daemons, and A is speaking to B. B is listening on a port, and A opens a tcp connection to that port. A is able to open a socket to B, but when it attempts to actually write said socket, I get a SIGPIPE, so I'm trying to figure out where B could be closing the open socket.
However, if I attach to both daemons in gdb, the SIGPIPE happens before any of the code for handling data is called. This kind of makes sense, because the initial write is never successful, and the listeners are triggered from receiving data. My question is - what could cause daemon B to close the socket before any data is sent? The socket is closed less than a microsecond after opening it, so I'm thinking it can't be a timeout or anything of the sort. I would love a laundry list of possibilities to track down, as I've been chewing on this one for a few days and I'm pretty much out of ideas.
As requested, here is the code that accepts and handles communication:
{
extern char *PAddrToString(pbs_net_t *);
int i;
int n;
time_t now;
fd_set *SelectSet = NULL;
int SelectSetSize = 0;
int MaxNumDescriptors = 0;
char id[] = "wait_request";
char tmpLine[1024];
struct timeval timeout;
long OrigState = 0;
if (SState != NULL)
OrigState = *SState;
timeout.tv_usec = 0;
timeout.tv_sec = waittime;
SelectSetSize = sizeof(char) * get_fdset_size();
SelectSet = (fd_set *)calloc(1,SelectSetSize);
pthread_mutex_lock(global_sock_read_mutex);
memcpy(SelectSet,GlobalSocketReadSet,SelectSetSize);
/* selset = readset;*/ /* readset is global */
MaxNumDescriptors = get_max_num_descriptors();
pthread_mutex_unlock(global_sock_read_mutex);
n = select(MaxNumDescriptors, SelectSet, (fd_set *)0, (fd_set *)0, &timeout);
if (n == -1)
{
if (errno == EINTR)
{
n = 0; /* interrupted, cycle around */
}
else
{
int i;
struct stat fbuf;
/* check all file descriptors to verify they are valid */
/* NOTE: selset may be modified by failed select() */
for (i = 0; i < MaxNumDescriptors; i++)
{
if (FD_ISSET(i, GlobalSocketReadSet) == 0)
continue;
if (fstat(i, &fbuf) == 0)
continue;
/* clean up SdList and bad sd... */
pthread_mutex_lock(global_sock_read_mutex);
FD_CLR(i, GlobalSocketReadSet);
pthread_mutex_unlock(global_sock_read_mutex);
} /* END for each socket in global read set */
free(SelectSet);
log_err(errno, id, "Unable to select sockets to read requests");
return(-1);
} /* END else (errno == EINTR) */
} /* END if (n == -1) */
for (i = 0; (i < max_connection) && (n != 0); i++)
{
pthread_mutex_lock(svr_conn[i].cn_mutex);
if (FD_ISSET(i, SelectSet))
{
/* this socket has data */
n--;
svr_conn[i].cn_lasttime = time(NULL);
if (svr_conn[i].cn_active != Idle)
{
void *(*func)(void *) = svr_conn[i].cn_func;
netcounter_incr();
pthread_mutex_unlock(svr_conn[i].cn_mutex);
func((void *)&i);
/* NOTE: breakout if state changed (probably received shutdown request) */
if ((SState != NULL) &&
(OrigState != *SState))
break;
}
else
{
pthread_mutex_lock(global_sock_read_mutex);
FD_CLR(i, GlobalSocketReadSet);
pthread_mutex_unlock(global_sock_read_mutex);
close_conn(i, TRUE);
pthread_mutex_unlock(svr_conn[i].cn_mutex);
pthread_mutex_lock(num_connections_mutex);
sprintf(tmpLine, "closed connections to fd %d - num_connections=%d (select bad socket)",
i,
num_connections);
pthread_mutex_unlock(num_connections_mutex);
log_err(-1, id, tmpLine);
}
}
else
pthread_mutex_unlock(svr_conn[i].cn_mutex);
} /* END for i */
/* NOTE: break out if shutdown request received */
if ((SState != NULL) && (OrigState != *SState))
return(0);
/* have any connections timed out ?? */
now = time((time_t *)0);
for (i = 0;i < max_connection;i++)
{
struct connection *cp;
pthread_mutex_lock(svr_conn[i].cn_mutex);
cp = &svr_conn[i];
if (cp->cn_active != FromClientDIS)
{
pthread_mutex_unlock(svr_conn[i].cn_mutex);
continue;
}
if ((now - cp->cn_lasttime) <= PBS_NET_MAXCONNECTIDLE)
{
pthread_mutex_unlock(svr_conn[i].cn_mutex);
continue;
}
if (cp->cn_authen & PBS_NET_CONN_NOTIMEOUT)
{
pthread_mutex_unlock(svr_conn[i].cn_mutex);
continue; /* do not time-out this connection */
}
/* NOTE: add info about node associated with connection - NYI */
snprintf(tmpLine, sizeof(tmpLine), "connection %d to host %s has timed out after %d seconds - closing stale connection\n",
i,
PAddrToString(&cp->cn_addr),
PBS_NET_MAXCONNECTIDLE);
log_err(-1, "wait_request", tmpLine);
/* locate node associated with interface, mark node as down until node responds */
/* NYI */
close_conn(i, TRUE);
pthread_mutex_unlock(svr_conn[i].cn_mutex);
} /* END for (i) */
return(0);
}
NOTE: I didn't write this code.
Is it possible you messed up and somewhere else in the program you try to close the same handle twice?
That could do this to you very easily.
HINT: systrace can determine if this is happening.

Resources