How to get the status of a serial COM port - windows

What I mean is that, when I code a project, I need to communicate with the serial port like COM1, COM2... but sometimes there is no device connected and I also can use the function CreateFile to get the COM port handle.
When I use the WriteFile function to send a string to the COM port the software blocks.
After I dig into the problem I find another function GetCommModemStatus which can get status of the COM port but when I use the usb-rs232 transition line, the second parameter always returns 0.
How can I get the COM port status so that I can check if is there some devices connected to the computer?

If I understand correctly, you want to detect if a device is connected to your COM port and ready to accept packets. If that's the case, you need to check control signals (DTR/DSR and CTS/RTS) before sending data, assuming your device is aware of them and sets the appropriate PIN on your DB-9 or DB-25 connector. Some devices rely on software handshaking instead (XON/XOFF) and do not set control signals. Your best bet would be to consult documentation of your device.
I have been using ComPort Library version 4.10 by Dejan Crnila. It does support both hardware and software handshakings, so you can focus on your own code instead of reinventing the wheel.

As several people have already pointed out, it is not a good idea to try to "re-invent the wheel." Except for "quick and dirty" testing, your code will have to handle the com port in a separate thread and the available solutions all make this much easier.
BUT, if you Really want to do it, I'll give you some pointers.
If you are using "WriteFile" then you have probably already figured out the "CreateFile" part of the procedure and how complicated things can get depends upon what kind of IO you specified in that procedure, Overlapped or not. Overlapped IO is more complicated but does let the OS handle some of the burden.
You mentioned that your call to "WriteFile" hangs. You should look up the "SetCommTimeOuts" function. Setting both the WriteTotalTimeoutMultiplier and WriteTotalTimeoutConstant members of TCommTimeouts to zero will tell the OS to return immediately. You may also need to "SetCommMask" if your target uses handshaking.
What happens next really depends on what your target is supposed to do. The GetCommMask function can be used to check the status of the handshake lines.

Related

Is ACK mandatory in CAN bus communication

I am making a CAN simulator for GPS trackers, they only record CAN data and doesn't send ACK. Is it possible to send CAN data with raspberry, using mcp2515/tja1050, without any device on bus that would trigger ACK?
This will usually generate a continuous retransmit.
Some devices have a "one-shot" transmit mode when just sends the CAN frame and does not attempt a retransmission. If you transmitter has this mode you can do what you describe, otherwise you will get a lot of retransmissions.
No it isn't possible, you need at least 2 nodes that are actively participating in the communication. This can however be fixed by just providing another CAN controller on the bus, which doesn't have to do anything intelligent except the ACK part.
For development/debug/test purposes you can however put your own node in "loopback mode", meaning it will speak to itself. Can be handy if you have to proper hardware available yet.
You can try to set the controlmode presume-ack to on.
Assuming you are using the ip command for creating your can sockets that would be something like
ip link set <DEVICE> type can presume-ack on
This will ignore missing ACKs. However I am not sure whether this works with all controllers.

how custom route for a process?

In my computer, there are two network adapters, connecting to different subnet. As below:
adapter A: 10.20.30.201
adapter B: 10.20.31.201
I want to make all outgoing data of a special process (for example Process A) through adapter A. That is I want to make adapter A as the process's default route.
I know, I can modify route table for some special destination, But what I want to do here is very different. Process A may communicate with many different IP and I don't know in advance.
Winsock2 provides LSP as a way to lay a dll in TCP/IP stack. I'm not familiar with LSP and don't know whether LSP can do what I want to do.
Can anybody give me some suggestion, Thanks.
A quick background on LSP:
An application, which uses Winsock2 API, calls a combination of WSA-prefix functions, eg WSAConnect, WSASocket, WSASend, WSARecv, etc.
If an application still use old winsock functions, these functions are mapped to Winsock2 behind the scene anyway. For instances: send() is mapped to WSASend(), recv() to WSARecv(), etc
WSA-prefix functions will internally call their corresponding WSP-prefix functions provided by LSP. For instances WSASend() calls WSPSend(), WSASocket() call WSPSocket(), etc. In short, WSAWhateverFunction() will calls WSPWhateverFunction(). Their parameters/returns are also the same (Not quite, but kind of).
LSP is a dll with these WSP-prefix functions implemented, eg. modify outbound/inbound traffic, filtering, etc. However an LSP is still a userspace dll. It's as limited as other userspace programs, and has no higher privilege than its host application, eg internet browsers. It has access to same set of system functions that is available to other programs, eg. winsock etc.
Conclusion is if your program can direct out-coming traffic to specific NIC, LSP can do it too. If it can't, neither can LSP. LSP therefore is irrelevant to your problem.

Serial Ports, CreateFile and SetCommState

I'm using Windows API's CreateFile and SetCommState functions to open a number of serial ports to read and write from, selecting ports using this notation:
\\?\COM1
I've been logging performance closely, and for some odd reason the CreateFile call takes about as much time as the SetCommState calls do (about 4.1 seconds).
I find this very odd and makes me suspect that both CreateFile and SetCommState perform a set of similar tasks with the windows subsystem that handles serial port communication.
Could there be a way to speed up one of both calls, or eliminate one, for example calling CreateFile in such a way it already uses the DCB I've got prepared to call SetCommState with?
The documentation you posted suggests calling GetCommState to initialize the DCB structure. I wonder if the delay is because you're setting something you don't care about? For what it's worth, I've noticed much bigger delays opening Bluetooth virtual COM ports than regular or USB ports.

How do I check the destination that a socket is connected to?

If,for example,The socket in my compiled application is designed to connect to 123.456.789.0.
How do I check if its connected to 123.456.789.0? Is there a way to do this?
The idea is this:I want to prevent other people editing my program and changing the address to,for example, 127.0.0.1 and make it connect through a proxy.
Is there any function/way/trick to check the address after the socket is connected?
Use the getpeername function to retrieve the address of the remote host.
If someone edits your program like you mention, they'll probably alter such a check as well though.
nos's comment about the insecurity of this approach is correct, but incomplete. You wouldn't even need to change the program's code to circumvent your proposed mechanism.
The easiest way around it would be to add an IP alias to one of the machine's network interfaces. Then a program can bind to that interface on the port your program connects to, and the OS's network stack will happily send connections to the attacker's local program, not your remote one.
So, now you say you want to know how to list the computer's interfaces so you can detect this sort of subversion. Your opponent counterattacks, launching your program as a sub-process of theirs after installing a Winsock hook that routes Winsock calls back through the parent process.
We then expect to find you asking how to read the executable code section of a particular DLL loaded into your process space, so you can check that the code is what you expect. Now your opponent drops the Winsock shim, switching to an NDIS layer filter, rewriting packets from your program right before they hit the NIC.
Next we find you looking for someone to tell how to list the drivers installed on a Windows system, so you can check that one of these filters isn't present. Your opponent thinks for about 6 seconds and decides to start screwing with packet routing, selecting one of at least three different attacks I can think of off the top of my head. (No, wait, four.)
I'm not a security expert. Yet, I've spent five minutes on this and already have your security beat seven different ways.
Are you doomed? Maybe, maybe not.
Instead of you coming up with fixes to the risks you can see, better to post a new question saying what it is you're trying to protect, and have the experts comment on risks and possible fixes. (Don't add it here. Your question is already answered, correctly, by nos. This is a different question.)
Security is hard. Expertise counts for far more in that discipline than in most other areas of computer science.

How can I send null characters to the serial port using the Windows API?

I am working on a Windows utility program which communicates with some custom hardware using a standard COM port. The communication protocol (which is out of my control) requires me to transmit and receive raw 8-bit data bytes.
I am currently using the following Windows API function to send data to the COM port:
WriteFile(hFile, lpBuffer, numberOfBytesToWrite, ...)
where hFile is a reference to the properly opened COM port, and lpBuffer is an array of bytes that I have stored in memory. The code works perfectly until a null character (ASCII zero) needs to be sent to the device. WriteFile stops sending as soon as it detects the null character because it assumes that it has reached the end of the string. This happens even though I set numberOfBytesToWrite properly.
How can I send raw data to the COM port using the Windows API? I would prefer to use a standard API call similar to WriteFile, but I am open to suggestions.
I am currently using RapidQ to build the utility, but all it does is call the Windows API function directly.
Edit: My setup consists of a Windows PC connected via serial port to the custom hardware module. The module has a small screen on which I am able to view the transmitted characters. I have tested this setup with another third-party utility program. I am able to communicate with the module using this third party program, and null characters show up properly. In my own program, when I use WriteFile, a null character anywhere in the transmit stream stops the rests of the stream from being sent.
I've done Windows serial port programming before, and am sure that I have been able to send null characters through the serial ports (various file transfer protocols wouldn't have worked otherwise). I can think of two possible explanations:
The receiving device is printing the data it received using a method that stops at the first null character. How are you determining that the transmitting device is terminating at the first null? Could the problem be somewhere further down the line?
The serial driver is broken. This is rather unlikely, but is a possible explanation. If you are using some dodgy proprietary third party serial port and its drivers, then they might be suspect. If you are using a standard built-in serial port with the normal Windows drivers, then this is probably not a problem.
I just had a quick look at RapidQ and there's a third possible explanation:
The marshaling that RapidQ may do in the process of calling Win32 API functions may have trouble with embedded null characters in the data to send. I don't know anything about RapidQ, but this is yet another link in the chain that must be considered.
Serial Communications in Win32
Greg is probably correct, but I would also check on your com port settings. Make sure your DCB settings are set properly. Look up SetCommState, and GetCommState for information.
Normally, Serial is 8N1, but your device might be using some other parity, or stop bit configuration, etc.
Like Greg, I've done a lot of work over serial myself, and this can often be the source of problems... Try talking with RS485 and an incorrect DCB structure... heh..
Larry
PS: If you don't already have one, I'd recommend getting yourself a good serial break-out box. I have one somewhere around the house, and it will show you what all the signals are, on all the lines during all of your communications, and is a very powerful debugging tool.
I have used WriteFile in the past and it worked fine with null bytes. I would dig into RapidQ, it could be the problem.
If none of this helps, you can always do what I do. Use Greg's COMM code to test the device with. Remember Qmodem? :) Very nice tool for testing/debugging serial routines. You ccould even use Qmodem and a simple Qmodem script to read the COM port on another box (or another port in the same box), and print out the hex value of every char sent. Oh wait. Qmodem has that built in. :) Use the Debug ASCII emulation and it will show the hex values of every char that comes across the serial port. Then, you could at least verify if your code is working correctly or not.
Now, Question. Does WriteFile return when it hits the NULL, or does it just sit and wait, and never return?
If it never returns, then it may not be your code. WriteFile only returns when it has sent all dwBytesToWrite, or if there is an error. Anything else, and it's TRYING to write, but there is a failure on the other end.
To send a NULL character through serial you can use the setEndOfFile() function, giving the port handler as file.
If you have too many NULL data to send it's probably not ideal, but it's a workaround.
Function details

Resources