SerialPort port.open "The port 'COM2' does not exist." - c#

I'm having a big problem with the SerialPort.Open();
I am communicating with an usb virtual com port (cdc), and it is listed as COM2.
It works fine in TeraTerm/hyperTerminal ect. but when I try to open the port in C#, it gives me the Exception The port 'COM2' does not exist.
I get the port name using the SerialPort.GetPortNames() function, and it looks fine when I debug.
I have tried to set the name hardcoded, but with no luck.
Now the really strange thing, it works fine on some PC's, and fails on other PC's. On some PC's it fail all the time, and on others it fails 10% of the time.
Even more strange it depends on the usb port used, some ports works fine, others fail (on the same PC!).
Could anybody help me please?

I've worked with virtual serial ports before. Oftentimes they aren't accessible as "COMX:" to some windows API calls, and you have to fully specify them. That might be the case here. Try using the Windows device namespace path for the serial device. For example: "\\.\COM2"
Another thing I've found useful for debugging is opening up a Hyperterm on the given serial port.
One final thing: For debugging your logic on systems that don't have all the hardware, I found this wonderful program called com0com. It is a GPL Sourceforge project that creates tied pairs of virtual com ports on your system. Whatever is written to one can be read from the other, and visa versa. You can either write an emulator and give it one of the ports, or just open up Hyperterm on it. Then give the other to your program. Testing with no cables or other hardware required.

This error can be caused if the driver returns an unexpected "file type" for "COM2".
Try p/Invoking GetFileType and I believe you'll see the pattern. It has to be FILE_TYPE_CHAR or FILE_TYPE_UNKNOWN or else SerialPort will throw that exception.
class Program
{
static void Main(string[] args)
{
string portName = #"COM2";
IntPtr handle = CreateFile(portName, 0, 0, IntPtr.Zero, 3, 0x80, IntPtr.Zero);
if (handle == (IntPtr)(-1))
{
Console.WriteLine("Could not open " + portName + ": " + new Win32Exception().Message);
Console.ReadKey();
return;
}
FileType type = GetFileType(handle);
Console.WriteLine("File " + portName + " reports its type as: " + type);
Console.ReadKey();
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr SecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll")]
static extern FileType GetFileType(IntPtr hFile);
enum FileType : uint
{
UNKNOWN = 0x0000,
DISK = 0x0001,
CHAR = 0x0002,
PIPE = 0x0003,
REMOTE = 0x8000,
}
}
Also see this thread on MSDN forums.

Related

C# output string to aircrack-ng

I'm doing some tests related to information security, and I came across the following situation, I apologize if I'm posting this in the wrong place, any problems let me know and I'll fix it!
Researching about cracking WIFI passwords, I found the aircrack-ng suite of applications, and, after some time of study, I managed to complete the mission of finding the wifi password of my house xD
without further ado, below I detail my problem:
aircrack-ng manages to receive the password to be tested by parameter, my question is:
How to pass this parameter from a C# console application
I tried several ways but without success.
In my last attempt, out of desperation I used the sendmessage function, available in the user32.dll library of windows.
Obs: I'm using the compiled aircrack binaries for windows, available at the link:
aircrack-ng for windows
class Program
{
public const Int32 WM_COPYDATA = 0x4A;
[DllImport("user32.dll")]
static extern long SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr FindWindow(string classname, string windowname);
public static IntPtr IntPtrAlloc<T>(T param)
{
IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, retval, false);
return (retval);
}
public static void IntPtrFree(IntPtr preAllocated)
{
if (IntPtr.Zero == preAllocated) throw (new Exception("Go Home"));
Marshal.FreeHGlobal(preAllocated); preAllocated = IntPtr.Zero;
}
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
static void Main()
{
string msg = "123456";
var cds = new COPYDATASTRUCT
{
dwData = new IntPtr(3),
cbData = msg.Length + 1,
lpData = msg
};
IntPtr hWnd = FindWindow("ConsoleWindowClass", #"C:\WINDOWS\system32\cmd.exe aircrack-ng");
IntPtr cdsBuffer = IntPtrAlloc(cds);
SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, cdsBuffer);
}
}
There is an application that currently does this, it's called crunch, it's basically a word generator. And can send this parameter to aircrack using the following command from the console:
crunch 8 8 0123456789 | aircrack-ng -a 2 my-handshake-capture.cap -b my-router-mac-addres -w -
where the last - is replaced in aircrack, by the parameter coming from crunch.
I searched about it in Crunch project available on github, but it's written on c language, and is more complexity for me. Can anyone help me? Thank you very much in advance!
I followed advice at this link: How to write to the stdin of another app?
and I got the horizon I needed!
Well, in the end, the code to work was basically like this:
public static void WriteWord(string word)
{
using (System.Diagnostics.Process airNgProcess = new System.Diagnostics.Process())
{
airNgProcess.StartInfo.FileName = #"D:\aircrack-ng-1.6-win\bin\aircrack-ng.exe";
airNgProcess.StartInfo.Arguments = "francos.cap -b 38:BC:01:D1:A2:64 -w -";
airNgProcess.StartInfo.UseShellExecute = false;
airNgProcess.StartInfo.RedirectStandardInput = true;
airNgProcess.StartInfo.RedirectStandardOutput = true;
airNgProcess.StartInfo.WorkingDirectory = #"D:\aircrack-ng-1.6-win\bin";
airNgProcess.Start();
StreamWriter airNgWriter = airNgProcess.StandardInput;
StreamReader airNgReader = airNgProcess.StandardOutput;
airNgWriter.WriteLine(word);
airNgWriter.Close();
airNgProcess.WaitForExit();
String airNgOutput = airNgReader.ReadToEnd();
Console.WriteLine($"Testing Key: {word}");
if (airNgOutput.IndexOf("KEY FOUND!") > -1)
{
Console.WriteLine($"Wifi password is: {word}");
}
}
}
In the real world, it has no applicability, because, with the junction of the C# application with aircrack-ng, the number of attempts per second has been greatly reduced, it is around 8 thousand attempts per second. This I my computer with a core i9, and 32Gb of memory.
However, by way of study and learning, for me it was very good

Process not suspending (NtSuspendProcess) -> What is going on?

I have adapted a 32-bit memory scanner in C# to 64-bit. Before scanning a program (read: live program), it is supposed to suspend the process. I am using NtSuspendProcess at this point to attempt to achieve this end. The funny thing is, I have this program (do not have access to the source) which, once a file is opened, refuses to suspend. Figuring it was a bug in my scanner, I tried suspending the program, once again when a file is opened, using Process Explorer; it flashes "Suspended" very briefly; I looked under Suspend Count for the threads associated with the process, and it increments just fine when I tell Process Explorer to suspend it...but when I tell Process Explorer to resume the process, it increments the Suspend Count (you read that right, it INCREMENTS it).
So yes, with my memory scanner and Process Explorer, when this program has no files open, it suspends and resumes normally. When the program has a file open, it fails to suspend, and increments the Suspend Count on attempts to resume.
I suspect a number of things here. Somehow, the message to suspend is being duplicated, and being released when resume is called. This explains the Suspend Count incrementing when it should be decrementing. Which might mean the original Suspend message isn't being consumed properly.
How do I even go about debugging this problem from this point? Where do I start?
Below are some code snippets from my memory scanner:
const uint PROCESS_SUSPEND_RESUME = 0x0800;
const uint PROCESS_QUERY_INFORMATION = 0x0400;
const uint MEM_COMMIT = 0x00001000;
const uint PAGE_READWRITE = 0x04;
const uint PROCESS_WM_READ = 0x0010;
[DllImport("ntdll.dll", EntryPoint = "NtSuspendProcess", SetLastError = true, ExactSpelling = false)]
private static extern UIntPtr NtSuspendProcess(UIntPtr processHandle);
[DllImport("ntdll.dll", EntryPoint = "NtResumeProcess", SetLastError = true, ExactSpelling = false)]
private static extern UIntPtr NtResumeProcess(UIntPtr processHandle);
[DllImport("kernel32.dll")]
public static extern UIntPtr OpenProcess(UIntPtr dwDesiredAccess, bool bInheritHandle, UIntPtr dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(UIntPtr hProcess, UIntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr dwSize, out UIntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
[DllImport("kernel32.dll", SetLastError = true)]
static extern UIntPtr VirtualQueryEx(UIntPtr hProcess, UIntPtr lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, UIntPtr dwLength);
[DllImport("kernel32.dll")]
static extern bool CloseHandle(UIntPtr hObject);
private void Button_Extract_Click(object sender, EventArgs e)
{
Process process = Process.GetProcessById(int.Parse(DataGridView_Processes.SelectedRows[0].Cells["Process ID"].Value.ToString()));
UIntPtr processSuspendResumeHandle = OpenProcess(new UIntPtr(PROCESS_SUSPEND_RESUME), false, new UIntPtr((uint)process.Id));
//process.Suspend();
UIntPtr suspendreturnvalue = NtSuspendProcess(processSuspendResumeHandle);
System.Diagnostics.Debug.WriteLine("Return Value: " + suspendreturnvalue.ToString());
UIntPtr processHandle = OpenProcess(new UIntPtr(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ), false, new UIntPtr((uint)process.Id));
//int error = Marshal.GetLastWin32Error();
//System.Diagnostics.Debug.WriteLine("Last Win32 Error: " + error);
SYSTEM_INFO sys_info = new SYSTEM_INFO();
GetSystemInfo(out sys_info);
UIntPtr proc_min_address = sys_info.minimumApplicationAddress;
UIntPtr proc_max_address = sys_info.maximumApplicationAddress;
ulong proc_min_address_l = (ulong)proc_min_address;
ulong proc_max_address_l = (ulong)proc_max_address;
//Skip to end
CloseHandle(processHandle);
NtResumeProcess(processSuspendResumeHandle);
CloseHandle(processSuspendResumeHandle);
MessageBox.Show("Extraction Complete.");
}
Do the following:
Make sure you are running as an admin
Check the return code of OpenProcess it should return a nonzero, if not continue to step 3.
Check the return code of GetLastError, search its value here https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- (this only contains error 0-400 so check the sidebar, there's a link to the other pages that contain other error codes)
Check the returned value of NtSuspendProcess and search it on the link above.
Since it looks like you're accessing the memory, you're probably using this app for game cheats.... so check OpenProcess, NtOpenProcess, NtSuspendProcess, and NtResumeProcess using an assembler such as Cheat Engine or x64dbg.
Go to the address of the functions I highlighted. Check if the first 5 bytes have a JMP instruction. If it has then that means the function has been patched by either an antivirus or an anticheat.
If it's patched, you might wanna disable the antivirus and if its still patched then you're against an anticheat. Switch to C++, use direct syscalls using syswhispers2, use Qt for C++ its a much better alternative to C# Winforms, it has a drag-and-drop form builder too.
If there is nothing suspicious, the functions didn't look patched. The GetLastError calls return normal status. Then you might be against a rootkit anticheat. In that case, you'll have to write your own driver to handle the open process, read memory, and write memory using C++ and WDK. You'll also need to find a mapper for your unsigned driver (KDMapper, LPMapper, etc) since it's not possible to load unsigned driver in the OS without disabling Driver Signature Enforcement feature of Windows, which when disabled, can be detected by an anti cheat.
EDIT:
I found this article about NtSuspendProcess failing when opening a process with PROCESS_SUSPEND_RESUME access mask. Try using PROCESS_ALL_ACCESS access mask instead.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/e119f8e8-98bc-466e-a9bb-88bcbde6524c/why-does-ntsuspendprocess-fail-with-processsuspendresume-but-succeeds-with-processallaccess?forum=windowssdk

Windows API USB IO (winusb.dll)

Edit: This question evolved over time. The basic question was about how to connect to a and read/write to/from a USB device in Windows. Eventually I answered the question with the help of #benvoigt.
I have written a Hid library which writes and reads to/from Hid USB devices. It works well. However, the device I am connecting to has switched from Hid access to vanilla USB. The Hid code does not work when connecting to the different type of device. My aim now is to connect to the USB interface (as opposed to the Hid interface) and read/write to/from it.
On all platforms that access USB, we have to query the interfaces that exist for the USB device, and then "claim" an interface for reading and writing. Here is some code from a LibUsbDotNet sample (LibUsb is a working C USB library and LibUsbDotNet wraps it) https://github.com/LibUsbDotNet/LibUsbDotNet/blob/master/src/Examples/Read.Write/ReadWrite.cs.
using (var context = new UsbContext())
{
context.SetDebugLevel(LogLevel.Info);
//Get a list of all connected devices
var usbDeviceCollection = context.List();
//Narrow down the device by vendor and pid
var selectedDevice = usbDeviceCollection.FirstOrDefault(d => d.ProductId == ProductId && d.VendorId == VendorId);
//Open the device
selectedDevice.Open();
//Get the first config number of the interface
selectedDevice.ClaimInterface(selectedDevice.Configs[0].Interfaces[0].Number);
//Open up the endpoints
var writeEndpoint = selectedDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
var readEnpoint = selectedDevice.OpenEndpointReader(ReadEndpointID.Ep01);
//Create a buffer with some data in it
var buffer = new byte[64];
buffer[0] = 0x3f;
buffer[1] = 0x23;
buffer[2] = 0x23;
//Write three bytes
writeEndpoint.Write(buffer, 3000, out var bytesWritten);
var readBuffer = new byte[64];
//Read some data
readEnpoint.Read(readBuffer, 3000, out var readBytes);
}
}
I have a feeling that LibUsb is achieving the opening of interfaces/endpoints in C like this (https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2199) . This is where it calls Initialize: https://github.com/libusb/libusb/blob/c6f3866414e8deeee19e8a9f10f20bde9cb408d3/libusb/os/windows_winusb.c#L2225 which is where my code is failing.
A little snippet of information is that this is definitely a WinUSB device. I can see that here:
Based on other people's comments and sample code, I can see that I need to use winusb.dll. I am able to call CreateFile to get a handle from the device. According to other sample code I have seen, the next step is to call WinUsb_Initialize. However, when I call this, I get an error code of 8 (ERROR_NOT_ENOUGH_MEMORY). There is some information here https://learn.microsoft.com/en-us/windows/desktop/api/winusb/nf-winusb-winusb_initialize . But, I don't quite understand what it is asking me to do. This is my code so far:
public override async Task InitializeAsync()
{
Dispose();
if (string.IsNullOrEmpty(DeviceId))
{
throw new WindowsException($"{nameof(DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
}
_DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.GenericRead), APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);
var errorCode = Marshal.GetLastWin32Error();
if (errorCode > 0) throw new Exception($"Write handle no good. Error code: {errorCode}");
if (_DeviceHandle.IsInvalid) throw new Exception("Device handle no good");
var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var interfaceHandle);
errorCode = Marshal.GetLastWin32Error();
if (!isSuccess) throw new Exception($"Initialization failed. Error code: {errorCode}");
IsInitialized = true;
RaiseConnected();
}
You can clone the branch of this repo here: https://github.com/MelbourneDeveloper/Device.Net/tree/WindowsUsbDevice. Just run the Usb.Net.WindowsSample project.
I also tried this and got exactly the same result:
public override async Task InitializeAsync()
{
Dispose();
if (string.IsNullOrEmpty(DeviceId))
{
throw new WindowsException($"{nameof(DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
}
_DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.GenericRead), APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);
var errorCode = Marshal.GetLastWin32Error();
if (errorCode > 0) throw new Exception($"Write handle no good. Error code: {errorCode}");
var interfaceHandle = new IntPtr();
var pDll = NativeMethods.LoadLibrary(#"C:\GitRepos\Device.Net\src\Usb.Net.WindowsSample\bin\Debug\net452\winusb.dll");
var pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "WinUsb_Initialize");
var initialize = (WinUsb_Initialize)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(WinUsb_Initialize));
var isSuccess = initialize(_DeviceHandle, ref interfaceHandle);
errorCode = Marshal.GetLastWin32Error();
if (!isSuccess) throw new Exception($"Initialization failed. Error code: {errorCode}");
IsInitialized = true;
RaiseConnected();
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool WinUsb_Initialize(SafeFileHandle DeviceHandle, ref IntPtr InterfaceHandle);
I strongly believe that there is something wrong with the device's WinUSB implementation itself. It works with other libraries like LibUsb, UWP, and Android, but WinUsb doesn't seem to like it. I tried this library: https://github.com/madwizard-thomas/winusbnet and it also fails on the same call with the same error code. The line it fails on and gets error code 8 is here: https://github.com/madwizard-thomas/winusbnet/blob/8f62d751a99be1e31d34b91115715d60aeff2dfc/WinUSBNet/API/WinUSBDevice.cs#L225
What is wrong with my code here? Is there something I need to do to allocate memory for the WinUsb_Initialize call?
How should I use the winusb.dll Windows API? What API calls do I need to make to claim and interface or endpoint for reading and writing?
It would really help me if someone could point me to a simple C or C# sample that reads and writes to a USB device and actually works.
WinDBG output:
************* Path validation summary ************** Response Time (ms) Location Deferred
srv* Symbol search path is: srv* Executable search path is: ModLoad:
00000236157c0000 00000236157c8000 Usb.Net.WindowsSample.exe
ModLoad: 00007ffb62880000 00007ffb62a61000 ntdll.dll ModLoad:
00007ffb60f40000 00007ffb610d0000 C:\WINDOWS\System32\user32.dll
ModLoad: 00007ffb5ed00000 00007ffb5ed20000
C:\WINDOWS\System32\win32u.dll ModLoad: 00007ffb4e1b0000
00007ffb4e214000 C:\WINDOWS\SYSTEM32\MSCOREE.DLL ModLoad:
00007ffb612a0000 00007ffb612c8000 C:\WINDOWS\System32\GDI32.dll
onecore\windows\core\console\open\src\renderer\gdi\invalidate.cpp(121)\conhost.exe!00007FF7169FE2AF:
(caller: 00007FF7169FF414) ReturnHr(1) tid(4230) 80070578 Invalid
window handle. ModLoad: 00007ffb60990000 00007ffb60a42000
C:\WINDOWS\System32\KERNEL32.dll ModLoad: 00007ffb5f000000
00007ffb5f192000 C:\WINDOWS\System32\gdi32full.dll ModLoad:
00007ffb60d90000 00007ffb60f03000 C:\WINDOWS\System32\MSCTF.dll
ModLoad: 00007ffb5ed80000 00007ffb5eff3000
C:\WINDOWS\System32\KERNELBASE.dll ModLoad: 00007ffb60610000
00007ffb606d2000 C:\WINDOWS\System32\OLEAUT32.dll ModLoad:
00007ffb60f10000 00007ffb60f3d000 C:\WINDOWS\System32\IMM32.DLL
************* Path validation summary ************** Response Time (ms) Location Deferred
srv* Symbol search path is: srv* Executable search path is: ModLoad:
00007ff7169f0000 00007ff716a8f000 conhost.exe ModLoad:
00007ffb61340000 00007ffb62780000 C:\WINDOWS\System32\shell32.dll
ModLoad: 00007ffb5cd80000 00007ffb5cda9000
C:\WINDOWS\system32\dwmapi.dll ModLoad: 00007ffb62880000
00007ffb62a61000 ntdll.dll ModLoad: 00007ffb5fcc0000
00007ffb5fd09000 C:\WINDOWS\System32\cfgmgr32.dll ModLoad:
00007ffb5f530000 00007ffb5fc3d000
C:\WINDOWS\System32\windows.storage.dll
onecore\windows\core\console\open\src\renderer\gdi\invalidate.cpp(121)\conhost.exe!00007FF7169FE2AF:
(caller: 00007FF7169FF414) ReturnHr(2) tid(4230) 80070578 Invalid
window handle. ModLoad: 00007ffb61140000 00007ffb61191000
C:\WINDOWS\System32\shlwapi.dll ModLoad: 00007ffb60990000
00007ffb60a42000 C:\WINDOWS\System32\KERNEL32.DLL ModLoad:
00007ffb5ec30000 00007ffb5ec41000
C:\WINDOWS\System32\kernel.appcore.dll ModLoad: 00007ffb5ed80000
00007ffb5eff3000 C:\WINDOWS\System32\KERNELBASE.dll ModLoad:
00007ffb5ec10000 00007ffb5ec2f000 C:\WINDOWS\System32\profapi.dll
ModLoad: 00007ffb5ebc0000 00007ffb5ec0c000
C:\WINDOWS\System32\powrprof.dll ModLoad: 00007ffb5ebb0000
00007ffb5ebba000 C:\WINDOWS\System32\FLTLIB.DLL ModLoad:
00007ffb5f490000 00007ffb5f52f000
C:\WINDOWS\System32\msvcp_win.dll ModLoad: 00007ffb5f1a0000
00007ffb5f29a000 C:\WINDOWS\System32\ucrtbase.dll ModLoad:
00007ffb606e0000 00007ffb60789000 C:\WINDOWS\System32\shcore.dll
ModLoad: 00007ffb4e290000 00007ffb4e4f9000
C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.17134.472_none_fb3f9af53068156d\comctl32.DLL
ModLoad: 00007ffb5ca60000 00007ffb5caf8000
C:\WINDOWS\system32\uxtheme.dll ModLoad: 00007ffb608f0000
00007ffb6098e000 C:\WINDOWS\System32\msvcrt.dll ModLoad:
00007ffb601e0000 00007ffb60304000 C:\WINDOWS\System32\RPCRT4.dll
ModLoad: 00007ffb60a60000 00007ffb60d82000
C:\WINDOWS\System32\combase.dll ModLoad: 00007ffb5fc40000
00007ffb5fcba000 C:\WINDOWS\System32\bcryptPrimitives.dll ModLoad:
00007ffb627a0000 00007ffb62841000 C:\WINDOWS\System32\advapi32.dll
ModLoad: 00007ffb610d0000 00007ffb6112b000
C:\WINDOWS\System32\sechost.dll ModLoad: 00007ffb57b30000
00007ffb57bc6000 C:\WINDOWS\System32\TextInputFramework.dll
(3d80.256c): Break instruction exception - code 80000003 (first
chance) ntdll!LdrpDoDebuggerBreak+0x30: 00007ffb`6294c93c cc
int 3
Well, the weirdness you are seeing around 64 byte transfers is well known:
Delimiting write transfers with short packets
The USB driver stack
driver does not impose the same restrictions on packet size, when
writing to the device, that it imposes when reading from the device.
Some client drivers must make frequent transmissions of small
quantities of control data to manage their devices. It is impractical
to restrict data transmissions to packets of uniform size in such
cases. Therefore, the driver stack does not assign any special
significance to packets of size less than the endpoint's maximum size
during data writes. This allows a client driver to break a large
transfer to the device into multiple URBs of any size less than or
equal to the maximum.
The driver must either end the transmission by means of a packet of
less than maximum size, or delimit the end of the transmission by
means of a zero-length packet. The transmission is not complete until
the driver sends a packet smaller than wMaxPacketSize. If the transfer
size is an exact multiple of the maximum, the driver must send a
zero-length delimiting packet to explicitly terminate the transfer
Delimiting the data transmission with zero-length packets, as required
by the USB specification, is the responsibility of the client driver.
The USB driver stack does not generate these packets automatically.
From USB Transfer and Packet Sizes on MSDN
As for the rest... depending on whether the device declares itself to be a composite device or not, Windows's driver loader will pick either one or multiple device drivers to connect to the device. Those drivers handle choosing which endpoint on the device to talk to. So from userspace, it is normally enough to open the driver interface and begin doing I/O. The HID class driver, for example, knows how to identify and enable the HID endpoint.
Since you have things working with UWP, it seems likely that you have the WinUSB driver loaded (since that's Step #1). Therefore you'll use the WinUSB API to talk to it.
Here's the documentation for the C and C++ API for WinUSB. It has examples of endpoint setup, and looks quite a bit less messy than the libusb code you quoted (although that may have to do with code formatting and style as well).
Here's how to connect to and read/write to/from a USB device via the WinUSB library
All this code is contained in the Device.Net repo: https://github.com/MelbourneDeveloper/Device.Net . There is a sample here. It automatically switched between Hid, and UWP depending on which device is plugged in. https://github.com/MelbourneDeveloper/Device.Net/blob/master/src/Usb.Net.WindowsSample/Program.cs
Connect and get Information
Call SetupDiGetClassDevs to enumerate devices with the WinUSB Guid (dee824ef-729b-4a0e-9c14-b7117d33a817). Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Device.Net/Windows/WindowsDeviceFactoryBase.cs#L35
Call SetupDiGetDeviceInterfaceDetail to get details about the interface and filter by Vid/Pid. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Device.Net/Windows/WindowsDeviceFactoryBase.cs#L64
Call CreateFile with the returned Device Path. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L44
Call WinUsb_Initialize with the handle you got from the previous call. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L53
Call WinUsb_GetDescriptor to get information about the device. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L57
Call WinUsb_QueryInterfaceSettings to get information about the interfaces belonging to the USB device. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L141
Call WinUsb_QueryPipe for each pipe that belongs to the interface. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L148
Call WinUsb_GetAssociatedInterface to get other interfaces other than the default. This will probably not be necessary because you will already have the default interface handle from WinUsb_Initialize. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L69
Write and Read
Call WinUsb_WritePipe to write an array of data. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L115
Call WinUsb_ReadPipe to read an array of data. Code: https://github.com/MelbourneDeveloper/Device.Net/blob/58aca0de118576ba89ec7437b29176d9bdd90aea/src/Usb.Net/Windows/WindowsUsbDevice.cs#L98
API Calls
public static class Kernel32APICalls
{
//Abridged
#region Kernel32
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
#endregion
}
public static partial class WinUsbApiCalls
{
public const uint DEVICE_SPEED = 1;
public const byte USB_ENDPOINT_DIRECTION_MASK = 0X80;
public const int WritePipeId = 0x80;
/// <summary>
/// Not sure where this constant is defined...
/// </summary>
public const int DEFAULT_DESCRIPTOR_TYPE = 0x01;
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_ControlTransfer(IntPtr InterfaceHandle, WINUSB_SETUP_PACKET SetupPacket, byte[] Buffer, uint BufferLength, ref uint LengthTransferred, IntPtr Overlapped);
[DllImport("winusb.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool WinUsb_GetAssociatedInterface(SafeFileHandle InterfaceHandle, byte AssociatedInterfaceIndex, out SafeFileHandle AssociatedInterfaceHandle);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_GetDescriptor(SafeFileHandle InterfaceHandle, byte DescriptorType, byte Index, ushort LanguageID, out USB_DEVICE_DESCRIPTOR deviceDesc, uint BufferLength, out uint LengthTransfered);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_Free(SafeFileHandle InterfaceHandle);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_Initialize(SafeFileHandle DeviceHandle, out SafeFileHandle InterfaceHandle);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_QueryDeviceInformation(IntPtr InterfaceHandle, uint InformationType, ref uint BufferLength, ref byte Buffer);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_QueryInterfaceSettings(SafeFileHandle InterfaceHandle, byte AlternateInterfaceNumber, out USB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_QueryPipe(SafeFileHandle InterfaceHandle, byte AlternateInterfaceNumber, byte PipeIndex, out WINUSB_PIPE_INFORMATION PipeInformation);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_ReadPipe(SafeFileHandle InterfaceHandle, byte PipeID, byte[] Buffer, uint BufferLength, out uint LengthTransferred, IntPtr Overlapped);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_SetPipePolicy(IntPtr InterfaceHandle, byte PipeID, uint PolicyType, uint ValueLength, ref uint Value);
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_WritePipe(SafeFileHandle InterfaceHandle, byte PipeID, byte[] Buffer, uint BufferLength, out uint LengthTransferred, IntPtr Overlapped);
}
Special thanks to #benvoigt for keeping me moving on this problem.

Get the PID of a Windows service

Could anyone help me to know how to get the PID of a Windows service?
I need to get the PID in order to run the following command:
Process.Start(new ProcessStartInfo
{
Filename = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
Arguments = string.Format("/c taskkill /pid {0} /f", pidnumber)
});
What the other answers neglect is the fact that a single process can also host multiple, autonomous services. The multiple instances of the svchost.exe process, each hosting a couple of services, is the best example.
So in general, it is absolutely unsafe to try to kill an arbitrary service by killing it's hosting process (I assume that is what you attempt to do, since you refer to taskkill.exe). You might take down several unrelated services in the process.
If you do know that the service's process only hosts the service you care about, than you can choose the strategy as suggested by #M C in his/her answer.
Alternatively, you can also use the ServiceController class to open a handle to your service and then use it (via the ServiceHandle property) to P/Invoke the QueryServiceStatusEx function to find out the Process ID you want to know.
If you need more details, you should clarify what it is that you're actually trying to achieve. It is not clear from your question.
Update Here is some code I ripped out of an existing project that should do what you want, given you have a ServiceController instance. _As said above, use with care!__
[StructLayout(LayoutKind.Sequential)]
internal sealed class SERVICE_STATUS_PROCESS
{
[MarshalAs(UnmanagedType.U4)]
public uint dwServiceType;
[MarshalAs(UnmanagedType.U4)]
public uint dwCurrentState;
[MarshalAs(UnmanagedType.U4)]
public uint dwControlsAccepted;
[MarshalAs(UnmanagedType.U4)]
public uint dwWin32ExitCode;
[MarshalAs(UnmanagedType.U4)]
public uint dwServiceSpecificExitCode;
[MarshalAs(UnmanagedType.U4)]
public uint dwCheckPoint;
[MarshalAs(UnmanagedType.U4)]
public uint dwWaitHint;
[MarshalAs(UnmanagedType.U4)]
public uint dwProcessId;
[MarshalAs(UnmanagedType.U4)]
public uint dwServiceFlags;
}
internal const int ERROR_INSUFFICIENT_BUFFER = 0x7a;
internal const int SC_STATUS_PROCESS_INFO = 0;
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool QueryServiceStatusEx(SafeHandle hService, int infoLevel, IntPtr lpBuffer, uint cbBufSize, out uint pcbBytesNeeded);
public static int GetServiceProcessId(this ServiceController sc)
{
if (sc == null)
throw new ArgumentNullException("sc");
IntPtr zero = IntPtr.Zero;
try
{
UInt32 dwBytesNeeded;
// Call once to figure the size of the output buffer.
QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, 0, out dwBytesNeeded);
if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
{
// Allocate required buffer and call again.
zero = Marshal.AllocHGlobal((int)dwBytesNeeded);
if (QueryServiceStatusEx(sc.ServiceHandle, SC_STATUS_PROCESS_INFO, zero, dwBytesNeeded, out dwBytesNeeded))
{
var ssp = new SERVICE_STATUS_PROCESS();
Marshal.PtrToStructure(zero, ssp);
return (int)ssp.dwProcessId;
}
}
}
finally
{
if (zero != IntPtr.Zero)
{
Marshal.FreeHGlobal(zero);
}
}
return -1;
}
Assuming you know the name of the EXE the service uses and there is exactly one of them:
int procID = Process.GetProcessesByName("yourservice")[0].Id;
The method Process.GetProcessesByName("yourservice") returns an Array of Processes with your specified name, so in case you don't know how much of "yourservice.exe" runs simultaneously you might need a foreach loop.
See this answer on a similar question:
Finding out Windows service's running process name
Using a WMI query you can -
Find all services related to a single exe (a single exe can host multiple services):
select Name from Win32_Service where ProcessId = 588
Or, to answer this question, you can get the PID of the process that a service is running in:
select ProcessId from Win32_Service where Name = 'wuauserv'

I/O exception error when using serialport.open()

FINAL UPDATE
It was our firmware the whole time. Embarrassing to a degree, but I'm happy we can move forward and I can put learning Java off for another day. My answer is below.
UPDATE
So I have more or less given up on this. I think it is a bug that goes down to the API, but I have neither the time, resources nor skill-set to get to the bottom of it. I think there exists some hardware to whom Windows just gives the middle finger. I have downloaded Eclipse, switched to Java and will try to see if that works. If not, you'll see me back here. However, I would absolutely love to solve this and so if anyone has the time or inclination to dig deep into this one, I'd love to see what you come up with. Obviously I will be checking back here from time to time. Please make sure you '#' me in your comments so I am alerted.
ORIGINAL POST
I know there are a few other people dealing with this issue, but I was hoping someone could help me. I am trying to connect to a COM port, but I am getting an I/O exception when I try to use the serialport.Open() command:
System.IO.IOException: The parameter is incorrect.
at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
at System.IO.Ports.InternalResources.WinIOError()
at System.IO.Ports.SerialStream.InitializeDCB(Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Boolean discardNull)
at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
at System.IO.Ports.SerialPort.Open()
at *programtitlehere.cs*:line 90
I am using a Stellaris LM4F232 to emulate a COM port. I can open, access and I get good results using Termite (a terminal program), but whenever I try with Visual Studio it won't even connect, and I get this error. Now I don't even really know what this error means and despite trying to read elsewhere, I still feel lost.
Can anyone explain to me what is happening here and maybe I can begin to try to figure this out? I can include more code, but to be honest there isn't much there; all the properties of the serial port device are as normal, and it is only happening with this device (I can use an MSP430 no problem with the same details).
My code is shown below for people who would like to see it (note this is just a 'sandbox', not the actual program, but the symptoms are identical):
try
{
serialPort1.PortName = "COM5";
serialPort1.Open();
if (serialPort1.IsOpen == true)
{
textBox1.Text = "CONNECTED";
}
else
{
textBox1.Text = "NOT CONNECTED";
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.ToString(), "ERROR");
}
and the other settings are done with the property manager (the only difference is baud is set to 230400; all others are on their default).
I can open up COM4 with this (an MSP430) which for all intents and purposes is an identical device. I can open COM5 with Termite, so I know the connection is good). And no, I am not trying to open them at the same time. If you need more information let me know and I can post more.
EDIT: I'm on day three of trying to figure this out and still no luck. I don't really understand why I can access this COM port through a terminal program and not my own when, as near as I can see, there is absolutely no difference. Is there a program that can 'examine' a COM port to see the properties of it (besides Windows manager I mean)? I'm getting pretty frustrated and am sort of at a stand still in my project until I figure this out...
EDIT2: I've found an apparent workaround, but I've yet to get it to work here. Now I get a few different I/O errors, but at least it is motion (not sure if it is progress). I've also learned that this is a .NET bug, which has existed since 2.0. I'd still love any help, but if I figure it out I will report back. Zach's code (the workaround linked above) is shown below:
using System;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace SerialPortTester
{
public class SerialPortFixer : IDisposable
{
public static void Execute(string portName)
{
using (new SerialPortFixer(portName))
{
}
}
#region IDisposable Members
public void Dispose()
{
if (m_Handle != null)
{
m_Handle.Close();
m_Handle = null;
}
}
#endregion
#region Implementation
private const int DcbFlagAbortOnError = 14;
private const int CommStateRetries = 10;
private SafeFileHandle m_Handle;
private SerialPortFixer(string portName)
{
const int dwFlagsAndAttributes = 0x40000000;
const int dwAccess = unchecked((int) 0xC0000000);
if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
SafeFileHandle hFile = CreateFile(#"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
IntPtr.Zero);
if (hFile.IsInvalid)
{
WinIoError();
}
try
{
int fileType = GetFileType(hFile);
if ((fileType != 2) && (fileType != 0))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
m_Handle = hFile;
InitializeDcb();
}
catch
{
hFile.Close();
m_Handle = null;
throw;
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
StringBuilder lpBuffer, int nSize, IntPtr arguments);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
IntPtr securityAttrs, int dwCreationDisposition,
int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetFileType(SafeFileHandle hFile);
private void InitializeDcb()
{
Dcb dcb = new Dcb();
GetCommStateNative(ref dcb);
dcb.Flags &= ~(1u << DcbFlagAbortOnError);
SetCommStateNative(ref dcb);
}
private static string GetMessage(int errorCode)
{
StringBuilder lpBuffer = new StringBuilder(0x200);
if (
FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
IntPtr.Zero) != 0)
{
return lpBuffer.ToString();
}
return "Unknown Error";
}
private static int MakeHrFromErrorCode(int errorCode)
{
return (int) (0x80070000 | (uint) errorCode);
}
private static void WinIoError()
{
int errorCode = Marshal.GetLastWin32Error();
throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
}
private void GetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (GetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
private void SetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (SetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
#region Nested type: COMSTAT
[StructLayout(LayoutKind.Sequential)]
private struct Comstat
{
public readonly uint Flags;
public readonly uint cbInQue;
public readonly uint cbOutQue;
}
#endregion
#region Nested type: DCB
[StructLayout(LayoutKind.Sequential)]
private struct Dcb
{
public readonly uint DCBlength;
public readonly uint BaudRate;
public uint Flags;
public readonly ushort wReserved;
public readonly ushort XonLim;
public readonly ushort XoffLim;
public readonly byte ByteSize;
public readonly byte Parity;
public readonly byte StopBits;
public readonly byte XonChar;
public readonly byte XoffChar;
public readonly byte ErrorChar;
public readonly byte EofChar;
public readonly byte EvtChar;
public readonly ushort wReserved1;
}
#endregion
#endregion
}
internal class Program
{
private static void Main(string[] args)
{
SerialPortFixer.Execute("COM1");
using (SerialPort port = new SerialPort("COM1"))
{
port.Write("test");
}
}
}
}
EDIT3: Day 6: I'm still plugging away at this. My water rations are low, but still I struggle on. I feel help must surely be on the horizon. Whoever finds this journal bring my remains back to Canada and find Nicole. Tell her I love her.
But seriously, I have no idea what is causing this problem. I'm wondering if it is purely on the embedded side; maybe because it is USB On-The-Go (OTG), or because the device is capable of being a host also. Has anyone run into that problem? It doesn't explain why I can use Termite (a terminal program, for those viewers just joining us) though. I have been trying to find an open source terminal program that a) works and b) see a). As per usual, I will report back if I discover the issue here as I have now found countless forums where it sounds people have had this issue dating back to 2006.
EDIT4: So as per the advice given, I downloaded a port monitoring software application (I got Eltima Serial Port Monitor), and it does look like a baud issue:
But strangely no matter what baud I set, it still fails. And also can someone explain what the up/down thing means? I tried googling it, but the keywords are too general. As usual, I will keep reporting back any changes.
Also, for the record, I can connect using Eltima at a baud of 115200 (same as Termite). Unfortunately this does not work in Visual Studio.
EDIT5: Our plot takes a surprise twist. I was monitoring what happens when Termite connects to the COM port in question and BLAM! Termite throws the exact same error as my program, but it ignores it. Genius, right? Sloppy, but it works. Now I need to learn how to ignore IOExceptions. I'll report back when I get it figured out.
EDIT6: So as it turns out it is a baud rate issue, but it goes deeper. I have been using Eltima Serial Port Monitoring software, and it is very intuitive and easy to use. I would recommend it. After some research I have learned that you cannot ignore this exception and still connect to the serial port using .NET's library.
So I have to go deeper into the Win32 API and write my own. I have found a few pages that touch on this, but to be honest I have never done anything like this before, so it may be a while before I report back, but I will definitely figure this out and get back to everyone. There are way too many who suffer from this problem.
I have found quite a few forums and websites where I can see the exact same symptoms, but nobody has really done much besides say 'Yeah, .NET sucks'. I plan on writing a full static library class and then publish either on my website, here and wherever else I can. Hopefully .NET will take notice (this bug has existed since 2.0).
This comes from the serial port driver; it is unhappy about one of the settings. With baudrate being a good candidate, drivers tend to allow only up to 115200. Albeit that this should not be a restriction when this is a dedicated CAN bus product.
The best way to tackle this is by using Sysinternals' Portmon utility; you can see what is being sent to the driver. Observe it for Terminate first; that's your known-to-work baseline. Then tinker with SerialPort properties until the initialization commands, as you see them in PortMon, sent by your program matches Termite's. Just the values, not the order. If that doesn't pan out either then take it to the parking lot and back over it with your car several times and buy another brand.
Update: it certainly looks like a baudrate problem. That's an issue in .NET; it is not going to ignore the driver's error return code like your terminal emulator programs do. The actual value should not matter since you are talking to an emulated serial port. There is however a possible issue with the CAN bus speed; rates are variable and it isn't clear to me how they are negotiated. This tended to be done with DIP switches in the olden days, and it may well be that the driver wants you to specify the speed through the baudrate setting. There ought to be something about it on the box or in the manual. Typical speeds are 40, 250 or 500 kbit/s. The manufacturer certainly would know; give them a call.
I faced a similar problem as reported in this thread, but I managed to solve the problem!
I am using STM32F2xx for the VCP!
And indeed it was my firmware problem. I forgot to include serial port settings in my USB callback!
The process of connecting a serial port from PC and firmware:
When a PC opens a serial port communication, the PC will send some command into the "configuration endpoint"
In the firmware, it would have a callback and the firmware will provide all the USB information (they call it a USB descriptor)
USB information is the configuration of each endpoint, (for example, latency, data size transmission, and type of USB - high speed or low speed)
Once the firmware has completed sending all the information, the PC will acknowledge and USB communication is successfully opened
Then, the PC will send a command to get the serial port settings from the firmware
Serial port settings are baudrate, data parity, and bit length.
In firmware, it should reply the serial port settings back to PC (my mistake occurs here; I didn’t not send any serial port settings back to the PC)
If successful, PC will start the serial port communication!
If failed, PC will give an open serial port error (but, do note that this error sometimes is bypassed)
In STM32 firmware code:
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
switch (cmd) {
case CDC_GET_LINE_CODING:
{
// I was missing this part
uint32_t baudrate = 9600;
pbuf[0] = (uint8_t)(baudrate);
pbuf[1] = (uint8_t)(baudrate >> 8);
pbuf[2] = (uint8_t)(baudrate >> 16);
pbuf[3] = (uint8_t)(baudrate >> 24);
pbuf[4] = 0;
pbuf[5] = 0;
pbuf[6] = 8;
break;
}:
....
I ran into the same situation. I am trying to connect serial communication to my 3G USB Dongle (Huawei E303F) at /dev/ttyUSB0. I use Mono in Raspbian (Raspberry Pi 2). On my development PC and macOS, my program runs fine. But when I deploy it into Raspbian, I got the IOException Broken Pipe error on Serial.Open().
It took me three days of debugging, and I tried all possible solutions. Finally I found that I have to set...
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
Before calling .Open().
And so our thrilling tale comes to a close. It was firmware the whole time (i.e. the code on the embedded device). We changed up a few functions and essentially poked around, chopped, added and altogether cleaned up the code and voila, the code is working. This pic sums it up pretty well. Curse you firmware!!
However, the bug described in my (lengthy) question still persists for many people and I know there are lots of people out there who still have it. All I can say is good luck and quadruple check your firmware (apparently triple checking it isn't enough these days).
I had the same problem and setting the baud rate to 1 fixed it!

Categories