I have a C program that trying to read data from COM Port in windows.
I am able to write the data on com port but not able to read it.
This is my read function? if anyone could take a look and point me to correct direction.
I am starting a seperate thread in main method
------ Code of main method function ------
if(!SetCommMask(hSerial,eventFlags)){
printf("Error in setting the event maskwith error: %d \n",GetLastError());}
_beginthread(*readDataFromPort,0,NULL);
----- Code of read data function ------
void readDataFromPort(void*)
{
DWORD dwReadResult;
bool waitOnRead = FALSE;
bool abContinue = TRUE;
memset(&ovRead,0,sizeof(ovRead));
ovRead.hEvent = CreateEvent(0,TRUE,0,0);
if(ovRead.hEvent == NULL){
fprintf(stderr,"Error creating overlapped event for reading");
}
//Reading data from port
while (true){
//Changed the overlap to NULL
if(WaitCommEvent(hSerial,&eventFlags,NULL)){
if(GetCommMask(hSerial,&dwMask)){
ResetEvent(ovRead.hEvent);
if(dwMask == EV_RXCHAR){
printf("character arrived");
}
}
memset(tmp,0,sizeof(tmp));
if(!ReadFile(hSerial, tmp, sizeof(tmp), NULL, &ovRead)){
if(GetLastError()!=ERROR_IO_PENDING){
printf("error io pending: Error is %d\n",GetLastError());
break;
}else{
waitOnRead=TRUE;
}
}
if(waitOnRead){
dwReadResult = WaitForSingleObject(ovRead.hEvent,10000);
switch(dwReadResult){
case WAIT_OBJECT_0:
if(!GetOverlappedResult(hSerial,&ovRead,&dwBytesRead,TRUE)){
printf("Damn error again :-(");
}else{
if(dwBytesRead>0){
++Rx;
printf("Tx - %d: Rx - %d\n",Tx,Rx);
printf("%s",tmp);
}
}
}
}
waitOnRead=FALSE;
}
if(strlen(tmp)>0 && inLoop){
writeDataToPort(*tmp);
}
}
CloseHandle(ovRead.hEvent);
_endthread();
}
> Blockquote
_beginthread(*readDataFromPort,0,NULL);
This snippet starts the thread regardless of SetComMask outcome, but if you are reading OK must have worked.
Check out MSDN threaded port read/write which works (VC5 compile worked straight off out of the box) above code looks really similar though, is it same?.
Related
Implementing a data link protocol. I managed to send the whole file through the virtual serial port - which should be the hard part. The weird thing is I'm getting a segfault on fclose() when trying to save it. The file is being created, which means the open is successful, but nothing it being stored in it. Even changed the implementation to buffer all the file into memory before saving it.
int app_rx(const char* outputFile){
file_data_t fileData;
if(!receive_ctrl_pckt(&fileData)){
printf("Could not receive control packet\n");
return FAILURE;
}
printf("Receiving file [%s]\nFile size: %d\n", fileData.fileName, fileData.fileSize);
unsigned char fileBuffer[fileData.fileSize];
int fileIndex = 0;
int totalBytes = 0;
int stop = 0;
size_t sqNo = 0;
int bytes;
FILE* out = fopen(outputFile, "w");
do{
activeBuffer = (activeBuffer + 1) % 2;
printf("Receiving packet %lu\n", sqNo);
bytes = llread(BUFFERS[TMP_BUFFER]);
if(bytes == DUP_ERR){
printf("Duplicate data. Discarding packet\n");
}
else if (bytes == WH_ERR){
printf("Invalid header. Discarding packet\n");
}
else if (bytes == WD_ERR){
printf("Corrupted data. Awaiting retransmission\n");
}
else{
printf("Packet %lu successfully received\n", sqNo);
int retrieveRes = retrieve_payload(sqNo);
switch(retrieveRes){
case CTRL_END: {
stop = 1;
break;
}
case FAILURE: {
printf("Unknown error\nExiting...");
exit(1);
}
case SQ_ERR:{
printf("Unsynchronized packets\nExiting");
exit(1);
}
default:{
for(int i = 0; i < retrieveRes; i++){
fileBuffer[fileIndex] = BUFFERS[activeBuffer][i];
fileIndex++;
}
sqNo = (sqNo + 1) % 255;
totalBytes += bytes;
break;
}
}
}
}while(!stop);
printf("file index: %d\n", fileIndex);
fwrite(fileBuffer, sizeof(unsigned char), fileIndex, out);
printf("here\n");
fclose(out);
if(totalBytes == fileData.fileSize){
return SUCCESS;
}
else{
return FAILURE;
}
}
Stdout:
Packet 9 successfully received
Receiving packet 10
Asserting data integrity
Packet 10 successfully received
Receiving packet 11
Asserting data integrity
Packet 11 successfully received
file index: 10968
here
make: *** [Makefile:35: run_rx] Segmentation fault (core dumped)
Giant method, I know. Just trying to get it under before refactoring properly. Can't for the sake of nothing figure out what's going on. I know this works because I've copied the exact same file using this method with a simple copyfile.c test driver which mimics the cp command.
Any ideas? I find it particularly odd that it creates the output file, but doesn't write anything on it.
EDIT: managed to get it going by opening the file right before writting to it. Still don't quite understand what happened
There is a potential buffer overflow risk for array fileBuffer, except that retrieveRes is guaranteed smaller or equal than fileData.fileSize, if there is a buffer overflow, pointer out may be overwritten and caused a segment fault when call fclose. The buffer overflow can be verified by print the value of out before do/while loop and call to fclose.
I am trying to write a simple device driver for sending and receiving a structure between user application and the driver using ioctl.
Here is my unlocked ioctl function -
long ioctl_func(struct file *filep,unsigned int cmd,unsigned long arg)
{
int ret = 0;
struct ioctl_struct *my_struct = kmalloc(sizeof(struct ioctl_struct),GFP_KERNEL);
struct ioctl_struct *my_struct1 = kmalloc(sizeof(struct ioctl_struct),GFP_KERNEL);
switch(cmd)
{
case CMD_WRITE_STRUCT:
printk("Inside CMD_WRITE_STRUCT\n");
ret = copy_from_user(my_struct,(struct ioctl_struct *)arg,sizeof(struct ioctl_struct));
if(ret > 0)
{
printk("Error copy_from_user\n");
return -1;
}
printk("Structure received from user app:\nid = %d\nname = %s\ndata = %ld\n",my_struct->id,my_struct->name,my_struct->data);
return 0;
case CMD_READ_STRUCT:
printk("Inside CMD_READ_STRUCT\n");
my_struct1->id = 99;
strcpy(my_struct1->name,"Hello User!");
my_struct1->data = 65535;
ret = copy_to_user((char *)arg,my_struct1,sizeof(struct ioctl_struct));
if(ret)
{
printk("Error copy_to_user\n");
} return -1;
printk("Sent structure to user\n");
return 0;
default: printk("Invalid ioctl cmd\n");
break;
}
return 0;
}
I am being able to pass a structure from user application to driver successfully using consecutive CMD_WRITE_STRUCT commands.
However,once i do a CMD_READ_STRUCT, ioctl call on the user application returns -1 ,with error "operation not permitted",but structure is successfully copied to user.
After an CMD_READ,CMD_WRITE doesnt work anymore as ioctl shows error "invalid file descriptor".
What am i doing wrong?
Seems like your code has a simple issue here which explains this: "However,once i do a CMD_READ_STRUCT, ioctl call on the user application returns -1 ,with error "operation not permitted",but structure is successfully copied to user. "
if(ret)
{
printk("Error copy_to_user\n");
} return -1;
it should be like
if(ret)
{
printk("Error copy_to_user\n");
return -1;
}
For the other issue I think maybe you have put some error checking in your application which would close the file in case of -1 return. Just a wild guess.
I have tried to read data from sensors. The sensors controller is using db9 header (com1), because I will use com1, I use db9 to usb converter and get com 11.
I have program to read and write to the serial port, it work when I use com1, but when I change to com 11, the program fail to open the com because it reach ERROR_FILE_NOT_FOUND
here is my program for the serial port programming:
Serial::Serial(char *portName)
{
this->connected = false;
wchar_t wcPort[64];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wcPort, strlen(portName), portName, _TRUNCATE);
this->hSerial = CreateFile(wcPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
//Check if the connection was successfull
if(this->hSerial==INVALID_HANDLE_VALUE)
{
//If not success full display an Error
if(GetLastError()==ERROR_FILE_NOT_FOUND){
//Print Error if neccessary
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else
{
DCB dcbSerialParams = {0};
if (!GetCommState(this->hSerial, &dcbSerialParams))
{
printf("failed to get current serial parameters!");
}
else
{
dcbSerialParams.BaudRate=CBR_38400;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
dcbSerialParams.fOutX=TRUE;
dcbSerialParams.fInX=TRUE;
if(!SetCommState(hSerial, &dcbSerialParams))
{
printf("ALERT: Could not set Serial Port parameters");
}
else
{
this->connected = true;
}
}
}
}
Is it because the software/program or the hardware problem?
when I try with hyperterminal, it can read and write the com 11.
To open COM ports numbered 10 and higher, you need to prefix the name with \\.\.
Now, in C, you must escape all those backslashes. So the port you need to open is "\\\\.\\COM11".
I'm writing a code and im using libudev.h so far i can i can detect devices and open them and put the fd's of the opened devices in devlist for reading and writing of data. My problem is that when i unplugged the device i get a segmentation error.
if (FD_ISSET(fd, &fds))
{
dev = udev_monitor_receive_device(mon);
if (dev)
{
if(strcmp(udev_device_get_action(dev),"add")==0)
{
if(strcmp(udev_device_get_devnode(dev), "/dev/ttyUSB0")==0)
{
fd1 = open(udev_device_get_devnode(dev), O_RDWR | O_NONBLOCK);
if(fd1<0)
{
printf("Can't open Device\n");
exit(0);
}
}
printf("Device plugged\n");
printf(" Node: %s\n", udev_device_get_devnode(dev));
printf(" Action: %s\n", udev_device_get_action(dev));
printf("device opened\n");
int opt =1;
ioctl(fd1, FIONBIO,(char *) &opt);
for(loop=0; loop<MAXDEV; loop++)
if(devlist[loop] == 0)
{
devlist[loop] = fd1;
fd1 = -1;
}
}
else {
printf("Device unplugged\n");
printf(" Node: %s\n", udev_device_get_devnode(dev));
printf(" Action: %s\n", udev_device_get_action(dev));
FD_CLR(devlist[loop],&fds);
close(devlist[loop]);
devlist[loop] = -1;
}
udev_device_unref(dev);
}
Once i get deviced open i can read to its fd and there's no problem with it but when i unplugged the device i get error.
this is the part where i'm having trouble.
printf("Device unplugged\n");
printf(" Node: %s\n", udev_device_get_devnode(dev));
printf(" Action: %s\n", udev_device_get_action(dev));
FD_CLR(devlist[loop],&fds);
close(devlist[loop]);
devlist[loop] = -1;
Thanks..
Accessing a USB serial adapter after it's been unplugged doesn't cause a segfault for me--I tested this pretty heavily for my work a while back.
I notice for one thing that you don't seem to have initialized "loop" to the element of "devlist" that corresponds to unplugged device. That might happen to work if you haven't returned from the function between the plug and unplug events and you unplug the same device as you last plugged in. But that's my bet for where you're segfaulting.
The other candidate I'd suspect is your code for reading or writing the device. The read and write syscalls will return -1 after the device is unplugged, and if you aren't checking for that error or your error handling code has a bug, that could be your problem too.
In general, I'd recommend running your program under gdb and getting a stack trace when it crashes. That will tell you which line number the error occurred on.
I am studing serial communication with win32 using C now. reading from serial port is given as below.
DWORD dwEventMask;
DWORD dwSize;
if(!SetCommMask(hSerial, EV_RXCHAR)){
//Error handling
printf("Error Setting Comm Mask \n");
}
if(WaitCommEvent(hSerial, &dwEventMask, NULL))
{
unsigned char szBuf[1024];
DWORD dwIncommingReadSize;
do
{
if(ReadFile(hSerial, &szBuf, 1, &dwIncommingReadSize, NULL) != 0) {
//Handle Error Condition
}
if(dwIncommingReadSize > 0)
{
dwSize += dwIncommingReadSize;
sb.sputn(&szBuf, dwIncommingReadSize);
printf("Reading from port \n");
}
else{
//Handle Error Condition
}
printf("Reading data from port \n");
} while(dwIncommingReadSize > 0);
}
else
{
//Handle Error Condition
}
They have used DWORD dwIncommingReadSize for while condition (while(dwIncommingReadSize > 0);.
Please explain how this condition is satifisfied. No modification can be seen for that.
Again please explain following part.
if(dwIncommingReadSize > 0)
{
dwSize += dwIncommingReadSize;
sb.sputn(&szBuf, dwIncommingReadSize);
printf("Reading from port \n");
}
This line:
if(ReadFile(hSerial, &szBuf, 1, &dwIncommingReadSize, NULL)
passes the address of dwIncommingReadSize (however badly spelt it may be) to the function so it can change it to whatever it wants.
It's similar to:
void fn (int *x) { *x = 42; }
:
int xyzzy = 1;
fn (&xyzzy);
// Here, xyzzy is now 42.
In terms of your second question, it's a little hard to tell without seeing more of the code, but it looks like it's simply increasing a "total size" variable for each block of data read in (plus whatever sb.sputn is supposed to do).
This is typical where a single read may not get all the data you want - you simply store what you got and then go back for more.