Check what serial port i'm using in linux - c

I have a plugged usb-serial device plugged to my windows and serial mapped it using virtualbox e.g COM1 -> /dev/ttyS0..
Now how will i know which serial port my device is using.. I know right now im using /dev/ttyS0. but what if i don't know?.. Linux Debian is creating this permanent serial port devices on boot time /dev/ttyS0-S3.
How can i make a test that /dev/ttyS0 is the real port im using in c.
Here's my way of testing if it's the right port or not.
devfd=open("/dev/ttyS0",O_WRONLY | O_NOCTTY | O_NDELAY);
if(s_fd<0) exit(1);
printf("open\n"); //It will always return true printing open because this device is created on boot time and is always available. so i made another check and that is to write to the port(Assuming i have set the permission to have full access to the serial port). if i can write to the port then it means it is really the port im using.
test=write(devfd,"ATZ",4);
if(test<0) printf("Can't write to port: Maybe not the serial port ur using\n");
printf("Device is avaialable\n"); // returns true because we can write to the port
Can you show me other samples in c of how can Check serial port if there's a device plugged to that serial port?
Or a test in c to the following serial port /dev/ttyS0 - /dev/ttyS3 if the following have devices plugged on them.
Thanks.

The Standard Serial ports are mapped as /ttyS0,/ttyS1,... as you correctly stated.
Generic USB Serial Ports as well as most G3 modems are accessible as /dev/ttyUSB0 through /dev/ttyUSB255
The better way to distinguish if a serial port 'connected' with a modem is to send ATIx commands to the serial port. These are Identity commands that you may use to detect the model name of the device and many other details.
First you try to send ATIx command not changing the baud rate. If you do not receive any valid response (ASCII multi-line text followed by OK<CR><LF> ERROR...<CR><LF> then you may alter the baud rate and retry. It is better to first set the maximum supported by port speed and then decrease it until you find a modem or you end up with 110 baud or other reasonable limit.
There is a way to detect if most likely there is nothing connected to the serial port. The idea behind is to detect the frame error that persists during some reasonable time (tens times to receive a byte at selected baud rate), say 2-3sec. To see how enable/disable frame errors detection look at man termios. Howeever, I am not absolutely sure that in the setup you described this will be possible (from within VM), so you have to try.
Also look at this post How to connect to a terminal to Serial-USB device on Ubuntu 10.10?

Be aware, that I found by experience that writing to a serial port to test it can have dire consequences; as my script hung (but only when running on ESXi hypervisor) when trying to test write to a disconnected device
In case it helps, here is a safer way to check
cat /proc/tty/driver/serial | \
grep -v unknown | \
sed 's/^/ttyS/g'
and then check output for ttyS0 for example

Related

Replace a printer with a pc using serial port

I have to update my question (May 4th). The male db25 connector misled me to the parallel port so I rephrased it.
I have an old computer system that sends live data (temperature from some external devices) to a parallel dot printer. This computer must not be changed.
Instead of printing I would like to connect the printer cable in an (ubuntu os) pc serial port in order to receive those data and redirecting them in stdout.
Checking the db25 pins I discovered that it is used as RS232 serial cable. There are only three pin connected:
pin 2 (TXD)
pin 3 (RXD)
pin 7 (GND)
So my intentions are firstly to connect those pins to a db9 serial connector in order to plug it in a pc serial port and secondly to open and read the input data using:
chmod o+rw /dev/ttyS0
cat -v < /dev/ttyS0
I believe that it is a simple solution and it is going to work.

Reading from and writing to registers of an IMU via UART

I have an IMU that has a UART interface. The manufacturer has provided a Windows based program that get all the data from the IMU and displays it in real time. (The device is connected to the PC via the USB). I need to write my own software that does this in order to integrate it into my project.
The datasheet/manual for the IMU gives all details about which registers have to be written to and read from (issue commands and read responses) in order to get the IMU data. My question is, how do I implement this in C under Linux?
The closest information I found out was this one but when compiling it it seems I need Linux kernel headers since that program uses #include <linux/module.h> so I'm not sure if I am on the right track.
You need not any kernel headers to talk over a serial port with any device connected to that serial port.
You would get a 'connection' to your device by simply opening a file /dev/ttyUSB0 with open() call (the actual name could be found by looking into dmesg for relevant device messages or by looking what device node appears under /dev when you plug your device into usb port).
Then you would need to set the baud rate and the word format (number of bits, parity and number of stop bits). To achieve that from the user-space process you would use a set of ioctls. For details read man ioctl and man ioctl_list

BLE Bridge Mode in Linux example

I want to use Bluetooth(4.0) on my board to transmit it's Name so any Mobile Application can see it's name and Mobile application initiates the pairing and connection with my Bluetooth.
I have seen some examples of Bluetooth(4.0) scanning nearby devices; For example:- It does scan for Bluetooth Mouser/Keyboard, but in this case Bluetooth(4.0) is in mode where it chooses the device it want to connect while I want it reverse so Any mobile application can see my Bluetooth and gets connect with it and does communication.
How can I put my Bluetooth(4.0) in such mode in Linux? Is there any C library using which I can put Bluetooth(4.0) is the mode where it goes in Bridge mode instead of scanning nearby devices?
You can set the name of your device like this:
hciconfig name "foo"
and check your name with:
hciconfig name
You also have to enable Low Energy advertising for your device to be found by others:
hciconfig leadv
You can configure your device to accept incoming connections like this (lm for link mode):
hciconfig lm MASTER,ACCEPT
This way the kernel will accept a connection, even if there are no listening sockets.
Considering you want to do actual communication, you would need to write a program, accepting the connection and sending/receiving data. Just putting your device in a mode where other devices can connect to it isn't really worth anything (because you can't communicate).
The basic principle is to open up an L2CAP socket, with the Channel ID of 4 (for Low Energy), then do standard bind/listen/accept. I suggest you look at the source code of Bluez and the examples.

Serial Port Connection Between Host and Guest with Virtualbox

I'm trying to learn how to write C code that will read from the serial port in Linux. I've found what seems to be a good tutorial here.
I want to be able to test this code, so I think I need either a serial port, or a way to write to the serial port while the code from above is reading.
I'm running Ubuntu 10.04 as a virtual machine on my Mac using virtualbox. My idea was to set up a virtual serial connection and write from the host to the guest. Hopefully something as simple as cat "Hello World" > /tmp/fake_serial in a host terminal, and for that to be read by the program in the link above.
Is this possible? I've tried adding a serial port using virtual box and when I try to do the above command I get an error saying I can't write to a socket.
The second option I thought of was using something like minicom inside the guest OS, to connect to say /dev/ttyS1 and write messages for my code to read at the same time. Again, assuming that the baud rates and other settings are OK, would this be possible?
I don't have a lot of experience working with serial ports, so I'd appreciate any suggestions about the best way to do this. Thanks in advance.
So to get this working I just added another Ubuntu VM on VirtualBox, and connected the two together via a virtual serial port. My main, original VM, which I use for a lot of developing will be referred to as VM1. The new VM, with a small hardrive that will only be used for sending messages to VM1 will be called VM2. These are both Ubuntu 10.04 VMs.
In VirtualBox go to Settings for VM1, go to ports, and change the settings as follows:
Now go to VM2, and select settings, ports, then change as follows:
Now first you need to start VM1. When that's booted then boot VM2. Now you can open a terminal in VM1, and type screen /dev/ttyS0 38400 (you may need to run sudo apt-get install screen before this works). Then go to VM2, open a terminal, and type echo "Hello" > /dev/ttyS0.
You should see Hello appear in the terminal open in VM1. When you're done running screen press ctrl-a k to kill it, otherwise if you try to do other stuff with the serial port you may get an error message saying that the port is busy.
When I had to do some serial port testing from my real to virtual machine I ended up doing a "loop back" type testing. I took two USB-Serial converters and a RS232 F-F adaptor and connected my machine to itself. Then in VirtualBox under Settings->USB you can route one of the two USB-Serial converters to be "owned" by your VirtualBox.
Once you plug in the converters one will register with the Mac and one with the Ubuntu "computer" then you can do serial communication as normal between the two machines.
You may also be able to emulate a virtual serial port using a pty ("pseudo-teletype" device), but I'm not positive on that one since I believe the ability to do that was locked down in newer kernels.
I ran into a similar situation running a QNX guest using VirtualBox 5.0.10 on an Ubuntu 14.04 host.
My solution seems general enough to apply to the above-mentioned case.
I configured the guest VM in the same way that Kells1986 setup his VM1:
Under the "Serial Ports"/"Port1" tab:
check "Enable Serial Port"
set "Port Number" to "COM1"
set "IRQ" to "4"
set "I/O Port" to "0x3F8"
set "Port Mode" to "Host Pipe"
uncheck "Connect to existing pipe/socket"
set "Path/Address" to an accessible file-system path (e.g. "/home/safayet/vmSerialPipe")
According to the VirtualBox manual:
You can tell VirtualBox to connect the virtual serial port to a
software pipe on the host. ... On a Mac, Linux or Solaris host, a local domain socket is used ... On Linux there are various tools which can connect to a local domain socket or create one in server mode. The most flexible tool is socat and is available as part of many distributions.
A domain socket is an IPC mechanism on UNIX systems similar to a pipe.
I connected to the "pipe" end of the virtual serial port on the Ubuntu host using the socat command:
socat - UNIX-CONNECT:/home/safayet/vmSerialPipe

Detecting a RS-232 com port in Linux

I have an ECR(Electronic Cash Register) device,it has a RS-232 com port cable for the connection to PC but I have not been given any drivers for it. I am trying to connect the device to PC but PC is not able to detect the cable. How to detect this device attached on this RS-232? I am working under Linux. Any help on how to find the device is appreciated?
Following is the code snippet I found in C to connect to device based on Baudrate and Com Port number.
int OpenComport(int comport_number, int baudrate)
int SendByte(int comport_number, unsigned char byte)
int SendBuf(int comport_number, unsigned char *buf, int size)
Please see my answer to a related question which shows how to open and configure the serial port.
On Linux, serial ports are almost always /dev/ttyS[0123] (that is /dev/ttyS0, /dev/ttyS1, etc.) for the hardwired ports, and /dev/ttyUSB* for USB ports. The hardwired "devices" may appear only when the hardware is present on some distributions. On others, they always appear whether there is hardware or not. (Try cat /dev/ttyS2 and see if you get the error "no such device".) This is a kernel configuration option which is frequently set to create the device entries whether the hardware is there or not.
The USB ports are present only when there is hardware plugged in, but if there are multiple USB serial ports, it can be difficult identifying which is which.
There is a mechanism within /etc/udev/rules.d/* which can be configured if some aspects of the devices are consistent. See man 7 udev for details.
For applications I have written, I determine which device is which by writing to the device and identifying its response. For devices which don't respond, this is either a worthy programming challenge or a mundane configuration solution.
I think you need to do a little reading about RS-232, and well, C programming also. There are no drivers for RS-232. It is a very "dumb" protocol - you basically just shove data out the port.
The PC cannot detect the cable? That's because it's not USB. Believe it or not, Plug-and-play didn't always exist; you tell the software what port the device is supposedly connected to, and it tries to talk to it.
Furthermore, those aren't "code snippets", those are just function prototypes. There isn't any actual code there.
1>since there's no operating system on your ECR so I guess u don't need any drivers ,instead a firmware will be there in the ECR , which tries to communicate with your Linux UART driver
2> Rs-232 is basically a serial protocol , I mean it has 9 wires , and hence a connecter with 9 pins are used DB-9 connectors ,all the communications inside a processor is in parallel format so a chip called UART is used to convert all the parallel data into serial data , and since yu want to pass the data in Rs-232 format , it needs to be packaged in that format .
3> Linux kernel already has a uart driver , which is implemented for RS-232 . so need to worry about drivers from Linux side.
4> Open a terminal type " dmesg | grep tty " ( connect only the ECR to the PC for rs-232 ports ). it will return something like ttyS or ttyUSB etc , however u just concentrate on ttyS if u have connected only through rs-232 cable .
5> Once u are sure of the ttyS device from the dmesg use minicom (its easy to use ) to communicate with the device.
regards,
Zubraj

Resources