Initializing the USB Modem COM Port

I use GsmComm to connect to a usb modem. The COM ports for the modem that I use do not appear in the device manager when I initially connected the modem to the computer. The computer shows it as a removable disk. However, when I launch the application that comes with the modem, the com ports are displayed in the device manager.

Therefore, every time I want to use the device with my application, I must first connect it to the computer, run its software to initialize the COM ports, and then launch my application.

But is there a way to initialize COM ports from my application using C# ?

I read something about creating virtual COM ports for connecting to USB devices, but I have no idea how to do this. Any help or pointers would be greatly appreciated.

February 14, 2016 Patch

I followed the response of antiduh and found that the device is recognized as cdrom on the first connection.

enter image description here

After starting the application, the link changes to harddiskvolume -

enter image description here

and three new com links are created.

enter image description here

+7
c # serial-port usb modem
source share
3 answers

Virtual serial ports are emulated by the device driver that comes with the device. If they do not appear in the device manager until you start their software, then it either dynamically installs the device driver or sends a secret handshake to the driver to tell him to start emulating the port.

The first requires an increase in UAC and the .sys file, if you do not see a prompt when you start your software and you do not see an installed service that can do this, or this .sys file, then you can scratch this feature. The latter is usually done through a call to DeviceIoControl ( ), which you can track using the filter driver. Like IoSpy , a utility that is included in the WDK. Using Dumpbin.exe / import in the utility can provide useful implementation information as well as the SysInternals process monitor.

It is hardly a guarantee of success, it is better to ask the manufacturer about the details. However, they do not often return a phone call and do not include such details in the manual. They, of course, prefer that someone use their shovel. Keep in mind that you see a pig’s curly tail in a bag, it’s best to reduce your losses by returning the device and buying another one from another manufacturer.

+6
source share

I have a hypothesis.

Have you ever seen Windows Object Manager ? This is a neat little Windows namespace that is used to post and showcase all types of crazy little objects, including devices as files. Think of it as a scary version of the `/ dev 'window.

Interestingly, user-space programs can access it by calling CreateFile using a special prefix.

For example, one way to open serial ports in windows is to call CreateFile(@"\\.\COM3") . This is the path that maps to the Object Manager path \GLOBAL??\COM3 .

Here's what the path looks like with WinObj: Screenshot of Windows Object Manager showing OM paths

In my case, you can see that \GLOBAL??\COM3 really connected to \Device\QTUSBSerial0 .

If you watch WinObj before and after this special software, you can find out which target device is symbolically connected to COMX, and then you can find out if this real device is always there.

Naively, I would have thought that one could trace the paths of any Object Manager paths to CreateFile to access objects without having to rely on the \\.\ -To- \GLOBAL??\ mapping. However, it seems that there is a hang - according to this answer , CreateFile will only accept arguments that target the \GLOBAL??\ section of the object manager - it will only accept \\.\ As a path prefix and will not accept , for example, \\.\Device\QTUSBSerial0 or some similar line.

There is one more possibility: create a really small driver / module module to create your own symbolic link using IoCreateSymbolicLink . Write a driver that creates a symbolic link for the object manager \GLOBAL??\CrazyDevice β†’ \Device\CrazyDevice , and then use the hacked SerialPortNet code to call CreateFile(@"\\.\CrazyDevice") .

This is a bit stretched, but maybe this will solve your problem.

Disclaimer: I have never written a Windows device driver or managed an object manager. I barely know what I'm doing here.

+3
source share

See how much time has passed since I used windows, however this concept still applies. First of all, it seems that this usb modem has a switching mode, that is, it first identifies it as a CD so that you can purchase drivers, then it switches after installation is complete on a mass storage device that contains a script that created symbolic links 3 COM port. To use this in an application, you need a few things, first the PID and VID usb, in order to be able to list the device on the hub of your computer. Secondly, you need a copy of this script that starts creating a symbolic link, and you need to call this script from your application after detecting the device (by listing for VID and PID) after executing the script, three COM ports will appear automatically, and you should have access to them as usual. You can also check if the CD-ROM application was at the beginning of the installed DLL (it almost certainly happened, and almost certainly the second script checks the DLL before creating links to the COM port, so make sure the dll stays where it is supposed to be). you will need to associate them with your application in order to get any additional functionality that they provide (but this opens the pandoras window for its own interface, if you do not like to do this, I cannot do this ... I can do this / show an example in Java, but not C #), otherwise, just using the com port is what you want and you really know how to talk to the device (AT commands), then forget about it and open the COM ports and run. at the last point you will need to find your own interface (not a very native interface, just a system call to execute the bash command to run script / exe, all) for C #, so look for a system call function built into the .NET framework.

Let me know if you need any further explanation of the steps.

UPDATE:

to list usb, you can use a library like javas usb4java and implement a function similar to the following

 public Device findDevice(short vendorId, short productId) { // Read the USB device list DeviceList list = new DeviceList();// ---> Here is empty device list int result = LibUsb.getDeviceList(null, list);// ---> Now list is populated if (result < 0) throw new LibUsbException("Unable to get device list", result); try { // Iterate over all devices and scan for the right one for (Device device: list) { DeviceDescriptor descriptor = new DeviceDescriptor(); result = LibUsb.getDeviceDescriptor(device, descriptor); if (result != LibUsb.SUCCESS) throw new LibUsbException("Unable to read device descriptor", result); //Match the VID and PID (function inputs)---> if you find a match, then return success/or the device // you can find the VID and PID from the device manager if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId) return device; } } finally { // Ensure the allocated device list is freed LibUsb.freeDeviceList(list, true); } // Device not found return null; } 

This feature allows you to access your USB device directly from the application. you can start the initialization sequence and mass transfers (most likely, this will work on a virtual COM port device, which is typical for the ftdi chip, for example, since this is an unknown Chines chip, as far as we can go low, we should rely on that that provided, and let windows do the dirty work of the driver) ...

At this point, your program knows that the USB device is connected, if the fucntion function returns null, then sleeps for a second and continue polling until the device is connected.

from now on you need to run a script that will create symbolic links, I will read its .exe file. Here is a copy and past for C # code sent by another member.

 using System.Diagnostics; // Prepare the process to run ProcessStartInfo start = new ProcessStartInfo(); // Enter in the command line arguments, everything you would enter after the executable name itself start.Arguments = arguments; // Enter the executable to run, including the complete path start.FileName = "C:/path/to/your/.exe"; // Do you want to show a console window? start.WindowStyle = ProcessWindowStyle.Hidden; start.CreateNoWindow = true; int exitCode; // Run the external process & wait for it to finish using (Process proc = Process.Start(start)) { proc.WaitForExit(); // Retrieve the app exit code exitCode = proc.ExitCode; } 

having an exit code is very useful to indicate whether the script successfully created symbolic links or not (I hope that the Chines guy who did this follows the correct encoding methods).


EDIT:

Error script. The reason is simple: he does not know that ProductID and VendorID are listing and initializing. (99.99999% they did not recompile the simple script initialization for each individual block, just to copy pid and vid), so it probably gets pid and vid as arguments (at best) or reads from usb hidden mass storage sectors (on which that you may have problems with paths when running the script from a non-root location) ... you may need gdb to find out if some arguments are missing, especially if the .exe file does not output anything to stderr


Finally, at this point you can start searching for a list of COM ports using the standard C # libraries, using something like:

Source code

 var portNames = SerialPort.GetPortNames(); foreach(var port in portNames) { //Try for every portName and break on the first working } 

and when you find the port you are looking for, you can open it using

Source code

 public static void Main() { string name; string message; StringComparer stringComparer = StringComparer.OrdinalIgnoreCase; Thread readThread = new Thread(Read); // Create a new SerialPort object with default settings. _serialPort = new SerialPort(); // Allow the user to set the appropriate properties. _serialPort.PortName = SetPortName(_serialPort.PortName); _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate); _serialPort.Parity = SetPortParity(_serialPort.Parity); _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits); _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits); _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake); // Set the read/write timeouts _serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500; _serialPort.Open(); _continue = true; readThread.Start(); Console.Write("Name: "); name = Console.ReadLine(); Console.WriteLine("Type QUIT to exit"); while (_continue) { message = Console.ReadLine(); if (stringComparer.Equals("quit", message)) { _continue = false; } else { _serialPort.WriteLine( String.Format("<{0}>: {1}", name, message)); } } readThread.Join(); _serialPort.Close(); } public static void Read() { while (_continue) { try { string message = _serialPort.ReadLine(); Console.WriteLine(message); } catch (TimeoutException) { } } } 

Hope this helps you get started!

+2
source share

All Articles