I’m working on some basic serial communication stuff and I’ve come across this issue that I can’t seem to work around. I’m trying to set my comm state to a certain baud rate, stop bit, parity bit and data size. As shown in my example code below, I’m getting the current COM state from getComState and modifying some values.
DCB dcb = { 0 };
// for set timeout for readfile function
COMMTIMEOUTS timeouts = { 0, // interval timeout. 0 = not used
0, // read multiplier
500, // read constant (milliseconds)
0, // Write multiplier
500 // Write Constant
};
if (SetCommTimeouts(usb_device, &timeouts) == FALSE) {
"ERROR: SetCommTimeouts failed with error %d.n", GetLastError();
add_log_trace("ERROR: SetCommTimeouts failed with error %d.n", GetLastError());
}
BOOL fSuccess;
// Initialize the DCB structure.
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
// Build on the current configuration by first retrieving all current
// settings.
fSuccess = GetCommState(usb_device, &dcb);
// Fill in some DCB values and set the com state:
// 115,200 bps, 8 data bits, no parity, and 1 stop bit.
dcb.BaudRate = CBR_115200; // baud rate
dcb.ByteSize = 8; // data size, xmit and rcv
dcb.Parity = NOPARITY; // parity bit
dcb.StopBits = ONESTOPBIT; // stop bit
fSuccess = SetCommState(usb_device, &dcb);
However, this function tends to fail me no matter what I do. The error is pretty straight forward(error code 87) which signifies that there is an invalid parameter. After doing some research the solution seems pretty obvious. However, I’ve tried the solutions listed below including some sanity test and nothing seems to work.
- Setting the DCB struct to only initialize with the size
- Disabling handshake in the DCB struct
- Setting the DCB struct to no values
- Using an alternate way to set the DCB struct besides GetCommState
- Setting the CommState to the same state that I get from GetCommState
- Ensuring the COM port name is correct when opening the file
I’ve also taken into account the remarks that were left by MSDN developers in regards to using the SetComState function however, the function call continues to fail nevertheless.
I’ve attempted running similar code on a linux box and setting the com port works fine. I came across some articles where they’re stating that Windows has messed up their usbser.sys file which handled communication between the OS and the device.
- Accessing COM-port with Windows 10
- USB serial interface problems with Windows 10
I’m tempted to try replacing the usbser.sys file with an older one however I’d wanted a second opinion in regards to this issue. Is this a common issue? Is there a more straight forward solution? I’d appreciate if someone could point me in the right direction or correct me in some of my assumptions and methodology. Hopefully this post isn’t too board in terms of scope. I’m just trying to set my baud rate right using SetCommState. Lolz.
Thank you
- Remove From My Forums
-
Question
-
Is anyone familiar with error 87 — invalid parameter from the SetCommState function ?
Here’s what I have :
BOOL gs2 = GetCommState(hCOM2, &dcb2);
dcb2.BaudRate = 312500;
dcb2.ByteSize = BIT;
dcb2.Parity = PARITY;
dcb2.StopBits = STOP;
bStatus2 = SetCommState(hCOM2, &dcb2);
DWORD dw = GetLastError();I open the first serial port (which is a USB) & the handle is valid, GetCommState returns OK, & SetCommState returns OK.
I open the second serial port hCOM2 (which is a RS232) & the handle
is valid, GetCommState returns OK, but SetCommState returns error 87 !I can’t figure out what the problem is ! Any suggestions ?
ak
Answers
-
Hi ak
It seems you might have handshaking enabled on the port and a timeout set to about 90 seconds. If timeout is set the function exits with return value 1 after the timeout period has expired, and the bytestransmitted will contain no. of bytes actually transmitted.
Check if handshaking is enabled and if so make sure the device on the other end is keeping the handshaking high. otherwise disable handshaking in the DCB structure.
Regards Mathew
Operating System and Hardware: Windows 10. Virtual COM Port from http://freevirtualserialports.com/
NodeJS Version: 4.4.4
Serialport version: 3.1.2
Python Version (if you’re having trouble building serialport):
(Run node -v && npm -v && python --version
to get the version numbers.)
Expected behavior
open a serial port and send data.
Actual behavior
Error message SetCommState: Unknown error code 87
is displayed.
Steps and/or code to reproduce the issue
- in the node_modulesserial_portbin folder I executed this command
node serialport-terminal.js -p COM1
I get the error message.
-
I also have my own code to open a serial port. I get the same error displayed on screen when I try and open the serial port.
-
If I open a serial port that is already opened by some Windows software, I get the expected result of Error: Opening COM2: Access denied.
I was trying to use Virtual COM ports so that I can do a loopback test between two Node applications.
Copy link
Contributor
Author
I have debugged the Windows C++ code in the package and found the problem with node-serialport and the Virtual Comm Ports.
This Microsoft MSDN web site has an example of using a Serial Port which works with a Virtual Comm Port.
a) Call CreateFile()
b) Call GetCommsState() to get current ‘DCB’ data structure (node-serial port is missing this step)
c) Change the baud rate in the DCB data structure
d) Call SetCommState to configure the serial port
node-serialport was not calling GetCommState() to get the current state.
I added this to the C++ source and it all worked.
So here is my change to serialport_win.cpp
DCB dcb = { 0 };
dcb.DCBlength = sizeof(DCB);
if (data->hupcl == false) {
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
} else {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
}
To this
DCB dcb = { 0 };
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
if (!GetCommState(file, &dcb)) {
printf("error getting comm state");
return;
}
if (data->hupcl == false) {
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
} else {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
}
I have not had a chance to test this on any physical serial ports (or USB serial ports) but following the MSDN example this is the proper way to do things.
Copy link
Contributor
Author
I have created Pull Request #824 with the bug fix
This is really helpful, I can take a closer look at that code and see about
adding it but what you say makes sense. Even on linux you’re supposed to
get the state, modify it and set it again. If you want to submit a PR in
the meantime people with windows machines can test your branch out. And if
it tests out, I’m happy to merge.
Francis Gulotta
wizard@roborooter.com
On Tue, May 24, 2016 at 2:32 PM, Roger Hardiman notifications@github.com
wrote:
I have debugged the Windows C++ code in the package and found the problem
with node-serialport and the Virtual Comm Ports.This Microsoft MSDN web site
https://msdn.microsoft.com/en-gb/library/windows/desktop/aa363201(v=vs.85).aspx
has an example of using a Serial Port which works with a Virtual Comm Port.a) Call CreateFile()
b) Call GetCommsState() to get current ‘DCB’ data structure (node-serial
port is missing this step)
c) Change the baud rate in the DCB data structure
d) Call SetCommState to configure the serial portnode-serialport was not calling GetCommState() to get the current state.
I added this to the C++ source and it all worked.So here is my change to serialport_win.cpp
DCB dcb = { 0 };
dcb.DCBlength = sizeof(DCB);
if (data->hupcl == false) {
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
} else {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
}To this
DCB dcb = { 0 };
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);if (!GetCommState(file, &dcb)) {
printf(«error getting comm state»);
return;
}if (data->hupcl == false) {
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
} else {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
}I have not had a chance to test this on any physical serial ports (or USB
serial ports) but following the MSDN example this is the proper way to do
things.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
#817 (comment)
You beat me to the punch! I left some comments there. It’s great!
Copy link
Contributor
Author
Hi
Thanks for looking at the Issue.
Thanks for the comments on the PR. The printf in there was my debugging
code and I never meant to leave it in so I’m glad you spotted it. I’ll
update the PR.
I’m out on the road at the moment but when I get back I have a PL2303
based USB serial device and a CH340/HL340 based USB serial port plus a
short serial cable so I can run open COM1 with Node-serialport and open
COM2 with node-Serialport and send some data between the two devices to
test the GetCommState
Roger
On 24/05/2016 19:59, Francis Gulotta wrote:
This is really helpful, I can take a closer look at that code and see
about
adding it but what you say makes sense. Even on linux you’re supposed to
get the state, modify it and set it again. If you want to submit a PR in
the meantime people with windows machines can test your branch out. And if
it tests out, I’m happy to merge.
Francis Gulotta
wizard@roborooter.comOn Tue, May 24, 2016 at 2:32 PM, Roger Hardiman notifications@github.com
wrote:I have debugged the Windows C++ code in the package and found the
problem
with node-serialport and the Virtual Comm Ports.This Microsoft MSDN web site
https://msdn.microsoft.com/en-gb/library/windows/desktop/aa363201(v=vs.85).aspx
has an example of using a Serial Port which works with a Virtual
Comm Port.a) Call CreateFile()
b) Call GetCommsState() to get current ‘DCB’ data structure (node-serial
port is missing this step)
c) Change the baud rate in the DCB data structure
d) Call SetCommState to configure the serial portnode-serialport was not calling GetCommState() to get the current state.
I added this to the C++ source and it all worked.So here is my change to serialport_win.cpp
DCB dcb = { 0 };
dcb.DCBlength = sizeof(DCB);
if (data->hupcl == false) {
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
} else {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
}To this
DCB dcb = { 0 };
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);if (!GetCommState(file, &dcb)) {
printf(«error getting comm state»);
return;
}if (data->hupcl == false) {
dcb.fDtrControl = DTR_CONTROL_DISABLE; // disable DTR to avoid reset
} else {
dcb.fDtrControl = DTR_CONTROL_ENABLE;
}I have not had a chance to test this on any physical serial ports
(or USB
serial ports) but following the MSDN example this is the proper way
to do
things.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub#817 (comment)
—
You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#817 (comment)
Roger Hardiman
RJH Technical Consultancy Ltd
07968 245759
www.rjh.org.uk
roger@rjh.org.uk
I released serialport@4.0.0-beta2
with these changes. Thanks!
Copy link
Contributor
Author
Hi
Thanks for applying the PR so quickly and getting a beta release issued.
Roger
——— Original message ———
From: Francis Gulotta notifications@github.com
Date:25/05/2016 4:27 AM (GMT+00:00)
To: EmergingTechnologyAdvisors/node-serialport node-serialport@noreply.github.com
Cc: Roger Hardiman roger@rjh.org.uk,Author author@noreply.github.com
Subject: Re: [EmergingTechnologyAdvisors/node-serialport] SetCommState:
Unknown error code 87 (#817)
I released serialport@4.0.0-beta2 with these changes. Thanks!
—
You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
lock
bot
locked as resolved and limited conversation to collaborators
May 6, 2018
Вопрос:
Я работаю над некоторыми базовыми средствами последовательной связи, и я столкнулся с этой проблемой, и я не могу работать. Я пытаюсь установить состояние связи в определенную скорость передачи, стоп-бит, бит четности и размер данных. Как показано в моем примере кода ниже, я получаю текущее состояние COM из getComState и изменяю некоторые значения.
DCB dcb = { 0 };
// for set timeout for readfile function
COMMTIMEOUTS timeouts = { 0, // interval timeout. 0 = not used
0, // read multiplier
500, // read constant (milliseconds)
0, // Write multiplier
500 // Write Constant
};
if (SetCommTimeouts(usb_device, &timeouts) == FALSE) {
"ERROR: SetCommTimeouts failed with error %d.n", GetLastError();
add_log_trace("ERROR: SetCommTimeouts failed with error %d.n", GetLastError());
}
BOOL fSuccess;
// Initialize the DCB structure.
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
// Build on the current configuration by first retrieving all current
// settings.
fSuccess = GetCommState(usb_device, &dcb);
// Fill in some DCB values and set the com state:
// 115,200 bps, 8 data bits, no parity, and 1 stop bit.
dcb.BaudRate = CBR_115200; // baud rate
dcb.ByteSize = 8; // data size, xmit and rcv
dcb.Parity = NOPARITY; // parity bit
dcb.StopBits = ONESTOPBIT; // stop bit
fSuccess = SetCommState(usb_device, &dcb);
Однако эта функция, как правило, меня не касается, независимо от того, что я делаю. Ошибка довольно проста (код ошибки 87), что означает, что существует недопустимый параметр. После некоторых исследований решение кажется довольно очевидным. Тем не менее, я пробовал решения, перечисленные ниже, включая некоторые тесты на здравомыслие, и ничего не работает.
- Установка структуры DCB только для инициализации с размером
- Отключение рукопожатия в структуре DCB
- Установка структуры DCB без значений
- Использование альтернативного способа установки структуры DCB помимо GetCommState
- Установка CommState в том же состоянии, которое я получаю из GetCommState
- Обеспечение правильности имени COM-порта при открытии файла
Я также принял во внимание замечания, оставленные разработчиками MSDN в отношении использования функции SetComState, однако вызов функции продолжает терпеть неудачу.
Я попытался запустить аналогичный код в ящике Linux, и настройка COM-порта прекрасна. Я столкнулся с некоторыми статьями, в которых говорится, что Windows испортила файл usbser.sys, который обрабатывал связь между ОС и устройством.
- Доступ к COM-порту с Windows 10
- Проблемы с последовательным интерфейсом USB с Windows 10
У меня возникает соблазн попробовать заменить файл usbser.sys на более старый, но мне хотелось получить второе мнение по этому вопросу. Это распространенная проблема? Есть ли более прямолинейное решение? Я был бы признателен, если бы кто-то мог указать мне в правильном направлении или исправить меня в некоторых моих предположениях и методологии. Надеюсь, этот пост не слишком подходит с точки зрения объема. Я просто пытаюсь установить скорость бод с помощью SetCommState. Lolz.
спасибо
I have some stupid code to access a Windows COM-port (just some pseudo-code of the most relevant functions):
// open device:
COMMTIMEOUTS timeouts;
DCB ComSettings;
memset(&ComSettings,0,sizeof(ComSettings));
ComSettings.DCBlength=sizeof(DCB);
*fd=CreateFile(serialParams>port,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
GetCommState(*fd,&ComSettings);
ComSettings.BaudRate=9600;
ComSettings.ByteSize=8;
ComSettings.Parity=NOPARITY;
ComSettings.fParity=0;
ComSettings.StopBits=ONESTOPBIT;
ComSettings.fOutX=FALSE;
ComSettings.fInX=FALSE;
ComSettings.fBinary=TRUE;
ComSettings.fDtrControl=DTR_CONTROL_DISABLE;
ComSettings.fRtsControl=RTS_CONTROL_DISABLE;
ComSettings.fAbortOnError=FALSE;
SetCommState(*fd,&ComSettings);
timeouts.ReadIntervalTimeout =MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier =0;
timeouts.ReadTotalTimeoutConstant =0;
timeouts.WriteTotalTimeoutMultiplier=0;
timeouts.WriteTotalTimeoutConstant =250;
SetCommTimeouts(*fd, &timeouts);
Reading of data from serial port is done with
ReadFile()
and writing with
WriteFile()
In my particular case the device is a USB gadget which connects as serial interface and where speed-settings and other things do not really matter.
This code is working fine with all Windows variants including 8.1 but for Windows 10 some users report there is no communication possible with the device. Unfortunately I do not have the related Win10 version for testing.
So my question: are there some issues/important changes in Windows 10 which could cause such a behaviour or require some changes in serial port communications?
Thanks!
****** Update ******************************************************************
Just as update to this: function SetCommState() fails with an error 87 (ERROR_INVALID_PARAMETER). Here it does not matter if I set own parameters, if I use the data received from GetCommState() or if I completely initialise and configure the DCB-structure. So…is this a known bug in SetCommState() of Win 10?
Just to note: it fails only in 4 of 5 cases, so it is not a systematic error, but a random one!