Hi guys

I've been struggling with this problem for a very long time now..

Every time I set the communication status for a serial port and then connect to a device, the value for byteSize is chenged to 7 insted of 8..

mov dcbMCS.BaudRate,2400
mov dcbMCS.ByteSize, 8
mov dcbMCS.Parity, NOPARITY
mov dcbMCS.StopBits, ONESTOPBIT


But If I start hyper terminal &  run the same device and then close the terminal, my program runs correctly & ByteSize is set to 8 like it's supposed to..
This happens not only with one device, I tryed three diffrent devices & the same thing happens all the time..

If any one knows what the problem is please help

Best regards..
Posted on 2005-10-17 11:31:54 by mistronr1
mistronr1,

Show the rest of your code where you use SetCommState to 'set' the com port, and then what is the return value from that command?

hth,

farrier
Posted on 2005-10-17 13:48:56 by farrier
OK here is what I do


PortProcMCS PROC comX:DWORD
LOCAL val:DWORD
invoke CreateFile,addr comX,GENERIC_READ,0,0,OPEN_EXISTING,0,0
;----TO DO error handling
mov hComMCS,eax

mov dcbMCS.DCBlength,sizeof DCB
invoke GetCommState,hComMCS, addr dcbMCS
;----TO DO error handling
mov m_dcbMCS.BaudRate,2400
mov m_dcbMCS.ByteSize, 8
mov m_dcbMCS.Parity, NOPARITY
mov m_dcbMCS.StopBits, ONESTOPBIT

invoke SetCommState ,hComMCS, addr dcbMCS
;----TO DO error handling

invoke GetCommTimeouts,hComMCS, addr CommTimeoutsMCS
;----TO DO error handling
mov CommTimeoutsMCS.ReadIntervalTimeout, 10 
mov CommTimeoutsMCS.ReadTotalTimeoutMultiplier, 0 
mov CommTimeoutsMCS.ReadTotalTimeoutConstant, 0 
mov CommTimeoutsMCS.WriteTotalTimeoutMultiplier, 0 
mov CommTimeoutsMCS.WriteTotalTimeoutConstant, 5000
invoke SetCommTimeouts ,hComMCS, addr CommTimeoutsMCS
;----TO DO error handling
invoke SetCommMask,hComMCS,EV_RLSD or EV_ERR
;----TO DO error handling
invoke PurgeComm, hComAP800,9
;----TO DO error handling

ret
PortProcMCS ENDP


When I run Portmon from systeminternals I see wordlength to be 7, if I run hyper terminal it changes to 8, again I run my program I get it to become 8, but I don't want to run hyper terminal every time I want my program to initialize correct...

I don't think the rest of  the program is intressting, this part is the one that that sets the com port settings..
thanks in advance
Posted on 2005-10-17 14:07:52 by mistronr1
mistronr1,

Instead of just:

GENERIC_READ

use:

GENERIC_READ or GENERIC_WRITE

In the CreateFile command.  This should allow you to actually make changes and send data to the Serial Port.

farrier
Posted on 2005-10-18 01:01:36 by farrier
I tryed with GENERIC_READ or GENERIC_WRITE but Still the same problem..

the strange thing is that I've seen commercial programs suffering the same problem..

Posted on 2005-10-18 05:45:49 by mistronr1
mistronr1,

Again,

What is the return value from:

SetCommState

?

"Always" check for errors in your return codes, at least until your code works without problems.

farrier
Posted on 2005-10-18 06:10:15 by farrier
GetLastError gives 0 no error alt all, I even tryed to follow whats.

It seams like the ByteSize have no effect on the serial port what so ever..

If I set it to be 7 in hyper terminal, it will be 7 when I run my program, if I again change it in hyper terminal it gets the new value..

Posted on 2005-10-18 09:42:34 by mistronr1
Two years ago I used the old style setting mode because I found a similar problem in a commercial project. I used something like next sequence to fix the problem:

1-GetCommState
2-BuildCommDCB
3-SetCommState

I have to go now, so I will test it later (if you did not).

Regards.

Kecol.-
Posted on 2005-10-18 10:25:39 by Kecol
That's it  thanx alot.


mov m_dcbMCS.DCBlength,sizeof DCB
invoke GetCommState,hComMCS, addr m_dcbMCS
;----TO DO error handling
; mov m_dcbMCS.BaudRate,2400
; mov m_dcbMCS.ByteSize, 8
; mov m_dcbMCS.Parity, NOPARITY
; mov m_dcbMCS.StopBits, ONESTOPBIT
invoke BuildCommDCB,addr MCSvalue, addr m_dcbMCS
invoke SetCommState ,hComMCS, addr m_dcbMCS


setting the values manualy doesn't work but using BuildCommDCB works like a charm..

Best regards
Posted on 2005-10-18 11:13:17 by mistronr1
mistronr1, nice to help you. Let me ask you something now: try to debug returned values in your m_dcbMCS (DCB struct) and post them here.

1-GetCommState
trace(m_dcbMCS) <- post this data
2-BuildCommState
trace(m_dcbMCS) <- and this data too
3-SetCommState

Of course you can do it if you want to. But I think this will tell us where exactly the problem is.
Posted on 2005-10-18 15:12:43 by Kecol
ok here we go...
I start by running hyper terminal & give the device a wrong value on WordLength,
then I run my program without BuildCommDCB & this is what I get::

portmon

IRP_MJ_CREATE SUCCESS Options: Open
IOCTL_SERIAL_GET_BAUD_RATE SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL SUCCESS
IOCTL_SERIAL_GET_CHARS SUCCESS
IOCTL_SERIAL_GET_HANDFLOW SUCCESS
IOCTL_SERIAL_GET_BAUD_RATE SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL SUCCESS
IOCTL_SERIAL_GET_CHARS SUCCESS
IOCTL_SERIAL_GET_HANDFLOW SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE SUCCESS Rate: 2400
IOCTL_SERIAL_SET_DTR SUCCESS
IOCTL_SERIAL_SET_LINE_CONTROL SUCCESS StopBits: 1 Parity: NONE WordLength: 7
IOCTL_SERIAL_SET_CHAR SUCCESS EOF:0 ERR:0 BRK:0 EVT:0 XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW SUCCESS Shake:80000009 Replace:80000080 XonLimit:2048 XoffLimit:512
IOCTL_SERIAL_GET_TIMEOUTS SUCCESS
IOCTL_SERIAL_SET_TIMEOUTS SUCCESS RI:10 RM:0 RC:0 WM:0 WC:5000
IOCTL_SERIAL_SET_WAIT_MASK SUCCESS Mask: RLSD ERR
IRP_MJ_READ CANCELLED Length 2
IRP_MJ_CLEANUP SUCCESS
IRP_MJ_CLOSE SUCCESS


in this case WordLength:7

Ollydbg

00401815  .  68 D4464000  PUSH FHClien.004046D4                    ; /pDCB = FHClien.004046D4
0040181A  .  FF35 B0474000 PUSH DWORD PTR DS:[4047B0]              ; |hCommDev = 00000088 (window)
00401820  .  E8 49090000  CALL <JMP.&KERNEL32.GetCommState>        ; \GetCommState
00401825  .  C705 D8464000>MOV DWORD PTR DS:[4046D8],960     ;<---- Break point
0040182F  .  C605 1A474000>MOV BYTE PTR DS:[40471A],8
00401836  .  C605 1B474000>MOV BYTE PTR DS:[40471B],0
0040183D  .  C605 1C474000>MOV BYTE PTR DS:[40471C],0
00401844  .  68 D4464000  PUSH FHClien.004046D4                  ; /pDCB = FHClien.004046D4
00401849  .  FF35 B0474000 PUSH DWORD PTR DS:[4047B0]              ; |hCommDev = 00000088 (window)
0040184F  .  E8 4A090000  CALL <JMP.&KERNEL32.SetCommState>        ; \SetCommState
-------------------------------------------------------memory--------------------------------------------------------------------
004046D0  00 00 00 00 50 00 00 00 00 00 00 00 00 00 00 00  ....P...........
004046E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
004046F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00404700  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00404710  11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ...............
00404720  00 00 00 00 1C 00 00 00 00 96 00 00 01 00 00 00  .............
00404730  00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00  ...............
00404740  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

Momory dosen't change before and after SetCommState the only value that changes is the value at 40471A & it gets value of 08 as expected..

And now with BuildCommDCB included:

portmon


IOCTL_SERIAL_GET_BAUD_RATE SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL SUCCESS
IOCTL_SERIAL_GET_CHARS SUCCESS
IOCTL_SERIAL_GET_HANDFLOW SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE SUCCESS Rate: 2400
IOCTL_SERIAL_SET_DTR SUCCESS
IOCTL_SERIAL_SET_LINE_CONTROL SUCCESS StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR Serial1 SUCCESS EOF:0 ERR:0 BRK:0 EVT:0 XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW SUCCESS Shake:80000009 Replace:80000080 XonLimit:2048 XoffLimit:512


wordLength is now 8

ollydbg

00401815  .  68 D4464000  PUSH FHClilen.004046D4                  ; /pDCB = FHClilen.004046D4
0040181A  .  FF35 B0474000 PUSH DWORD PTR DS:[4047B0]              ; |hCommDev = 0000009C (window)
00401820  .  E8 59090000  CALL <JMP.&KERNEL32.GetCommState>        ; \GetCommState
00401825  .  C705 D8464000>MOV DWORD PTR DS:[4046D8],960          ; memory 1
0040182F  .  C605 1A474000>MOV BYTE PTR DS:[40471A],8
00401836  .  C605 1B474000>MOV BYTE PTR DS:[40471B],0
0040183D  .  C605 1C474000>MOV BYTE PTR DS:[40471C],0
00401844  .  68 D4464000  PUSH FHClilen.004046D4                  ; /pDCB = FHClilen.004046D4
00401849  .  68 10414000  PUSH FHClilen.00404110                  ; |String = "baud=2400 parity=N data=8 stop=1"
0040184E  .  E8 07090000  CALL <JMP.&KERNEL32.BuildCommDCBA>      ; \BuildCommDCBA
00401853  .  68 D4464000  PUSH FHClilen.004046D4                  ; /pDCB = FHClilen.004046D4
00401858  .  FF35 B0474000 PUSH DWORD PTR DS:[4047B0]              ; |hCommDev = 0000009C (window)
0040185E  .  E8 4B090000  CALL <JMP.&KERNEL32.SetCommState>        ; \SetCommState memory 2

memory 1

004046D0  00 00 00 00 1C 00 00 00 60 09 00 00 95 60 00 00  .......`...`..
004046E0  00 00 00 08 00 02 07 00 00 11 13 00 00 00 00 00  ...........
004046F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00404700  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00404710  11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ...............
00404720  00 00 00 00 1C 00 00 00 00 96 00 00 01 00 00 00  .............
00404730  00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00  ...............
00404740  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

memory 2

004046D0  00 00 00 00 1C 00 00 00 60 09 00 00 95 60 00 00  .......`...`..
004046E0  00 00 00 08 00 02 08 00 00 11 13 00 00 00 00 00  ...........
004046F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00404700  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00404710  11 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00  ..............
00404720  00 00 00 00 1C 00 00 00 00 96 00 00 01 00 00 00  .............
00404730  00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00  ...............
00404740  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................


That's it can you see why the values in the first data and the scound are not the same...

best regards
Posted on 2005-10-21 13:34:47 by mistronr1
mistronr1, I was trying to find the problem, and I think I did it. Using DOS mode style (BuildCommDCB) or not is not the problem.  I wrote a program to check it. The problem is that you must set another fields of the BCD struct, not just the classic used in DOS days.

This doesn't work:

    dcb.DCBlength = sizeof(DCB)
    dcb.BaudRate =  2400
    dcb.ByteSize =  8
    dcb.Parity = NOPARITY
    dcb.StopBits = ONESTOPBIT
    SetCommState(hCom,&dcb)

And this neither

    dcb.DCBlength = sizeof(DCB)
    mode = "baud=2400 parity=N data=8 stop=1"
    BuilCommDCB(&mode,&dcb)
    SetCommState(hCom,&dcb)

But if you insert the next line of code before either of previous ones, it will work.

    GetCommState(hCom,&dcb)

And that works because GetCommState fill all neccesary data for you.

I post a testing program, so you can see what I am talking about. Use flags to config it. Compile it for 'console mode'.

Hope this help to understanding the problem (and resolve it).

Regards.

Kecol.-
Attachments:
Posted on 2005-10-21 18:14:03 by Kecol
Thanks Kecel

I did some analysis and found out the following

if we don't use USE_OLD_MODE your program indicates no error but the device doesn't run properly, the reason is that windows sets ByteSize to 7 when ever we call GetCommState..
use portmon from systeminternals to see the outcome -- http://www.sysinternals.com/Utilities/Portmon.html --

if we on the other hand set USE_OLD_MODE and FILL_DCB we get good results as long as we don't call GetCommState at the end..

I included a text file with all the results....
Posted on 2005-10-22 17:41:15 by mistronr1
mistronr1, I suppose windows use default values on error (with DCB fields values) when setting port state. So my conclusion on this topic is:

Fill every DCB struct field with correct values before calling SetCommState.

Or stick to an easiest method:
1-GetCommState
2-BuildCommDCB
3-SetCommState


(or you can write your own driver too :))

Regards.

Kecol.-
Posted on 2005-10-24 07:34:19 by Kecol
Hi Kecol

the strange thing is that I had to use the old + the new style to fill DCB structure, if I use only old or only new style it doesn't work..

Posted on 2005-10-24 13:06:42 by mistronr1
I had  extracted this text from the last SDK:

To set only a few members of the DCB structure, you should modify a DCB structure that has been filled in by a call to GetCommState. This ensures that the other members of the DCB structure have appropriate values.

The SetCommState function fails if the XonChar member of the DCB structure is equal to the XoffChar member.


So, I was not wrong with my conclusion. But I was wrong in not checking that on first :sad:.



Posted on 2005-10-24 13:25:14 by Kecol
That's it

thanks alot man, now everything is OK, just by setting XonChar to be 1 solved the problem...

Best Regards
Posted on 2005-10-24 13:37:15 by mistronr1
If you NEVER use GetCommState, will the system ever write to the DCB?

The reason I'm asking this is that I will be driving the DCB etc. from the internals of my compiler. It is much less convenient to drive BuildCommState from the internals of the compiler.

Another way of asking this is: If the compiler fills in the entire DCB correctly and modifies particular cells such as BaudRate as the source code of the user indicates in statements, is there a problem with the system changing values in the DCB?

If the system writes to the DCB (without a  GetCommState), I suppose I could maintain my own private DCB's and transfer their entire contents to the declared ones when I want to set them, but I would like to avoid this if possible.
Posted on 2005-12-17 01:40:58 by mikes