Currently, I have a desktop app that I used to read and write data to a proprietary hardware device via a serial port interface. The app starts by listing the serial COM devices connected to the computer, and once a device is selected, one can interact with the app to communicate with the corresponding device. I no longer have such a device at hand, but I would still like to use the app nonetheless.
I have already developed a command-line utility that, given a binary message in stdin, emits the corresponding binary reply (the same reply that the proprietary hardware device would send via serial port) to stdout. Let's call this utility a simulator.
How do I set up a virtual serial port such that the app can detect it, and that whenever the app sends a message using the serial port protocol, such message is forwarded to the simulator, and the simulator's reply is returned back to the desktop app?
I'm on Mac OS 12 with an M1 CPU. I'm also open to solutions on Windows 10 (with less priority).
I have looked at previous questions on StackOverflow that might be similar to this one, but they were either incomplete or slightly different, with no obvious way to infer the solution for my actual problem.
Serial ports are unlike other channels. That's why separate system calls exist for them.
Normally, serial ports are created by physical devices (an old-fashioned serial port or a newer USB-based one) and the associated driver. Since writing a driver is quite difficult, a pragmatic and possibly unexpected approach would be to use hardware, specifically two USB-to-serial adapters. That way, a serial port is created by the drivers of the USB-to-serial adapter.
The two USB-to-serial adapters are wired to each other (RX to TX and vice versa). The will appear as two serial ports on macOS (/dev/cu.usb...).
The legacy application then connects to one of the serial ports. And your command line utility (acting as a device emulation) connects to the other serial port. All data send by the command line utility will go to the legacy application, and vice versa.
The remaining issue is how to connect your command line utility to the serial port. If you are lucky, you can use the screen command. But more likely, you will need to modify it to read and write from the serial port (instead of stdin and stdout).
Related
What I want to achieve is that I plug in a device, for example a mouse, but in general any device that outputs serial data via USB, and then either screen it in terminal, or store it in a file and, if possible, use python to do things with it.
As a concrete example, let's say I want access to the data from a trackpad plugged into a USB port on a macbook. When I run /dev/{tty,cu}.* in terminal, I get a bunch of devices, but none of them is the one I want. When I run ioreg -p IOUSB -l -b | grep -E "#|PortNum|USB Serial Number", I see that the device is plugged in, at a specific address (i.e. #14200000), as well as <class AppleUSBDevice, id 0x100002c38, registered, matched, active, busy 0 (10 ms), retain 14> and "PortNum" = 2.
Yes, the device is plugged in, no it does not show up in /dev/{tty,cu}.*. I don't want to have to write a device driver, I have heard that it is not the easiest thing to do. Are there any solutions for accessing low-level data from devices that don't show up in the /dev/ directory?
Devices showing up as /dev/tty... and /dev/cu... are devices implementing the asynchronous serial data communication protocol derived from RS-232. There used to be dedicated serial ports on computers. Today on a Mac, they are usually connected via USB.
Few USB devices implement the serial protocol. Instead they implement the HID protocol (keyboard, mouse etc.), USB mass storage protocol (external drives of all kind), USB ECM (for network adapters) or a custom protocol. Except for the ones with a custom protocol, macOS provides device drivers for all of them.
USB isn't a simple serial communication. Instead, devices configure several endpoints. Each endpoint uses a separate communication channel. Even USB CDC ACM for RS-232 like communication uses three endpoints. In addition, USB devices can pretend to be several devices at once. This is call composite device.
My understanding is that you want to observe and record USB communication. The main approaches are:
Use Wireshark. It is well known for observing and recording network traffic but it can do the same for USB. Unfortunately, with the ever tighter security on macOS, it isn't so easy to set up and probably doesn't work on Apple Silicon Macs anymore.
Use a dedicated USB protocol analyzer. They are very powerful and start at about USD 300.
I have an usb device (pole display), which i don't have driver for.
I installed generic usb driver and opened the port for sending(I use bulk transfer) data to device.
With usb monitoring software i see my data gets to device, but nothing much happens on device side.
The device commands(ESC/POS) work when transfered over (virtual) com port, but not over usb port.
Shouldn't device process commands the same way regardless connection type (com vs usb)?
How can i figure out what commands work with the device (for example, if i send some text, i want it to show on display)?
Any help is appreciated!
Look at the USB descriptors the device reports in order to determine its class. If it is a custom device and not a standard class then you'll likely not be able to work with it. There is a big difference between old RS-232 COM protocol and USB. USB devices can have multiple configurations and endpoints, each responding to data in different ways. Many classes exist and are pretty standard (CDC-ACM is typically used for virtual serial ports.) However, it's not uncommon for device manufacturers to include OEM specific configurations and endpoints which can be used for their own custom interfaces, firmware loading, etc.
Is there any initialization data transmitted through the COM port when connecting the device? The device surely can treat COM and USB different, but another possible thing that goes wrong is that the device needs to hear some sort of "I'm going to start sending commands"-signal from you first, and that signal may be different between COM and USB.
So what I would recommend is first (if you have not done that yet) see what data is sent to initialize the COM connection, and if that doesn't have an obvious USB counterpart, connect it to a PC where you do have drivers (assuming that is available somewhere and somehow, which is possible if e.g. you ask this due to OS incompatibility) and see how the connection is initialized there.
If the first doesn't work and the second is unavailable to you, then I'm afraid there's little I can do to help you, since it's usually not visible for you what commands the device wants to hear other than by guesswork, documentation, or comparing to similar devices where you do have that data available.
I am writing a controlling software for a generic USB HID device within a team, working on Windows 7. Due to my status as an intern, my possibilities are limited:
the software must work on Windows
the software must use the default HID driver Windows supplies
My problem is that however I try to access the device while using the HidUSB driver (according to Zadig) my interrupt transfer read attempts always result with a timeout while the device actually does send data. Writing to the device works all the time, whether I use HIDAPI, whether I use libusb, only reading fails. (this is a primitive device atm and even the final packet data specification isn't done, currently it just sends an ON or an OFF string towards the host, and writing to the device changes the state of a LED between 7 colors and off state, so that one's certainly working)
I can't think of the device being faulty, because if I replace the driver on Windows to the WinUSB driver with Zadig, it works with libusb (and hidapi can't open the device thereafter) and on Linux, just by reading /dev/hidraw also returns the data fine. I have also read the HID and the USB specifications and I know that the device descriptors state that the USB packetsizes are 8, while the HID input report's size is capped at 20, tho I don't know what report ID the device uses.
Checking the Windows communications with USBPcap and Wireshark, the sole difference I can notice among the handling of the device is the host packets asking for data is filled with 00s against the HidUSB driver compared to the CCs when used with the WinUSB driver.
For the record, I have already tried libusb, hidapi, HidLibrary and noone within the team has an idea what to do now.
I have also read that Windows disables access to HID keyboards and mice but I found no actual example of a device config ending up as an USB mice. The Device Manager lists my device twice under HID tho, once as HID-compliant device or how it calls (localized Win7 here) and once as USB Input Device, but doesn't list it among the Mouse or Keyboard option.
Sorted it out a while ago, but I think I'll write it down here if someone ends up with a similar issue in the future.
The Windows HID driver invalidates any incoming packet if the report's data size does not match the length of the sent data iow the size within the report descriptor. Linux and the device itself didn't cared that's why I also ruled that out as source during the time I brought the question here. In the above example the on/off message being 4-5 byte vs the reported 20 byte length was the problem, now that the device sends 20B messages, all the solutions which could write via HidUSB can read as well.
I have an Arduino application talking over USB to an application on Windows 8 using the MAVLINK protocol. The connection appears as COM3.
Is there a Windows application that can spy on this connection and display the traffic going in both directions? Raw bytes are fine, I don't need the protocol decoded.
You could log serial port activity using Portmon. (Edit: You need to first connect to the local computer via the Computer menu, and you must start capture on the port before a program opens it.)
You may not want to log USB traffic. Such a log would include a lot of extra information relating to the USB to serial adapter which is providing COM3. Portmon would only give you the bytes transferred over COM3, and the Mavlink protocol is entirely contained within that data stream. If you're sure you want to log all USB traffic to and from that device, then I recommend SnoopyPro. In Windows 7, you need to run it as administrator.
If you can use Windows XP in your environment, USB sniff should work for you. If you need something more powerful (and are willing to pay a fee for it) then USBLyzer might be a viable option.
The answer is SnoopyPro, and you can download it at:
SnoopyPro Sourceforge
This tool allows you to get USB information and also USB communication data. I used it in the past to know how a USB device worked in order to do its driver on Linux. I used this tool as a sniffer.
Basically, SnoopyPro allows you to intercept, display, record and analyze the USB protocol and all transferred data between any USB device connected to your PC and applications. It can be successfully used in application development, USB device driver or hardware development and offers the powerful platform for effective coding, testing and optimization.
I have a Arduino app that needs to talk to my PC across the USB (Serial) connection. I have this bit of code that I lifted from the Arduino Playground at
http://arduino.cc/playground/Interfacing/CPPWindows#VisualStudio2008
this->serialPort1->PortName = "COM5"; // Replace with your COM port!
this->serialPort1->Open();
this->serialPort1->Write( "7" ); // In the future, you'll expand on this
// to write your custom data to the board
this->serialPort1->Close();
My question is how does one determine what COM port the Arduino USB cable is attached to?
There are several ways you can approach this.
The most obvious is that you simply make your application configurable and tell it which serial port to use. The port name should never change, unless you have other processes on your machine allocating virtual COM ports such as Bluetooth drivers.
A second option is that you can do what the Arduino app does and scan the serial ports on the system looking for the hardware. Since you are using the CLR, System.IO.Ports.SerialPort.GetPortNames() will give you a list of all the serial ports on the system. (You can also get this from the registry.) Then you can enumerate through them and check the status of the pins to see which serial ports have devices attached. You should probably include in your sketch a way to query the Arduino so that you can send it a command and have it give a fixed response. This would allow you to discern your application from other serial devices such as modems.
There is a third option which would involve figuring out where the FTDI driver stores its configuration information in the system/registry and going from there. This is a bit more involved, so I can't give any information on if this approach is even viable.