AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

DllCall to GetCommState

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
olfen



Joined: 04 Jun 2005
Posts: 99
Location: Stuttgart, Germany

PostPosted: Thu May 25, 2006 3:16 pm    Post subject: DllCall to GetCommState Reply with quote

Hi,
this function retrieves the configuration settings of a given serial port.
Having hardly any C\C++ experience it took me some time to find out that there is a bitmask in the DCB (Device Configuration Block) structure.

Using BuildCommDCB and SetCommState functions it should also be possible to configure a serial port.
Data can be written to a serial port using one of the binary writing functions on this forum.
I appologize for the script not beeing commented at all, also I am not sure if I did everything right. Comments and suggestions are welcome.

Regards,
olfen

Code:

GetCommState(ComPort)
{
/*
http://msdn.microsoft.com/library/en-us/fileio/fs/createfile.asp?frame=true
http://msdn.microsoft.com/library/en-us/devio/base/getcommstate.asp?frame=true
http://msdn.microsoft.com/library/en-us/devio/base/dcb_str.asp

http://msdn.microsoft.com/library/en-us/devio/base/buildcommdcb.asp?frame=true
http://msdn.microsoft.com/library/en-us/devio/base/setcommstate.asp?frame=true
http://msdn.microsoft.com/library/en-us/devio/base/waitcommevent.asp?frame=true

typedef struct _DCB {
    DWORD DCBlength;      /* sizeof(DCB)                     */
    DWORD BaudRate;       /* Baudrate at which running       */
    DWORD fBinary: 1;     /* Binary Mode (skip EOF check)    */
    DWORD fParity: 1;     /* Enable parity checking          */
    DWORD fOutxCtsFlow:1; /* CTS handshaking on output       */
    DWORD fOutxDsrFlow:1; /* DSR handshaking on output       */
    DWORD fDtrControl:2;  /* DTR Flow control                */
    DWORD fDsrSensitivity:1; /* DSR Sensitivity              */
    DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
    DWORD fOutX: 1;       /* Enable output X-ON/X-OFF        */
    DWORD fInX: 1;        /* Enable input X-ON/X-OFF         */
    DWORD fErrorChar: 1;  /* Enable Err Replacement          */
    DWORD fNull: 1;       /* Enable Null stripping           */
    DWORD fRtsControl:2;  /* Rts Flow control                */
    DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
    DWORD fDummy2:17;     /* Reserved                        */
    WORD wReserved;       /* Not currently used              */
    WORD XonLim;          /* Transmit X-ON threshold         */
    WORD XoffLim;         /* Transmit X-OFF threshold        */
    BYTE ByteSize;        /* Number of bits/byte, 4-8        */
    BYTE Parity;          /* 0-4=None,Odd,Even,Mark,Space    */
    BYTE StopBits;        /* 0,1,2 = 1, 1.5, 2               */
    char XonChar;         /* Tx and Rx X-ON character        */
    char XoffChar;        /* Tx and Rx X-OFF character       */
    char ErrorChar;       /* Error replacement char          */
    char EofChar;         /* End of Input character          */
    char EvtChar;         /* Received Event character        */
    WORD wReserved1;      /* Fill for now.                   */
} DCB, *LPDCB;

Flowcontrol
Xon/Xoff: 21393 -> 0101 0011 1001 0001
Hardware: 24725 -> 0110 0000 1001 0101
Off:      20625 -> 0101 0000 1001 0001
*/

global
local h, cs, ch, port, DCB, Str, Uint

port=com%comport%
h := DllCall("CreateFile","Str", port,"Uint",0x80000000,"Uint",3,"UInt",0,"UInt",3,"Uint",0,"UInt",0)
If (h = -1 or h = 0 or ErrorLevel != 0)
return, -1
VarSetCapacity(DCB, 28, 0)
cs := DllCall("GetCommState", Uint, h, str, DCB)
If (cs = 0 or ErrorLevel != 0)
return, -2

;DCB_DCBlength:=ExtractInteger(DCB, 0, true, 4)
DCB_BaudRate:=ExtractInteger(DCB, 4, true, 4)

DCB_fBitMask:=ExtractInteger(DCB, 8, true, 4)
DCB_fBitMaskDec:=DCB_fBitMask
DCB_fBitMask:=DecToBin(DCB_fBitMask)

StringLeft, DCB_fAbortOnError, DCB_fBitMask, 1
StringMid, DCB_fRtsControl, DCB_fBitMask, 2, 2
StringMid, DCB_fNull, DCB_fBitMask, 4, 1
StringMid, DCB_fErrorChar, DCB_fBitMask, 5, 1
StringMid, DCB_fInX, DCB_fBitMask, 6, 1
StringMid, DCB_fOutX, DCB_fBitMask, 7, 1
StringMid, DCB_fTXContinueOnXoff, DCB_fBitMask, 8, 1
StringMid, DCB_fDsrSensitivity, DCB_fBitMask, 9, 1
StringMid, DCB_fDtrControl, DCB_fBitMask, 10, 2
StringMid, DCB_fOutxDsrFlow, DCB_fBitMask, 12, 1
StringMid, DCB_fOutxCtsFlow, DCB_fBitMask, 13, 1
StringMid, DCB_fParity, DCB_fBitMask, 14, 1
StringRight, DCB_fBinary, DCB_fBitMask, 1

IfEqual, DCB_fDtrControl, 00, SetEnv, DCB_fDtrControl, DTR_CONTROL_DISABLE
IfEqual, DCB_fDtrControl, 01, SetEnv, DCB_fDtrControl, DTR_CONTROL_ENABLE
IfEqual, DCB_fDtrControl, 10, SetEnv, DCB_fDtrControl, DTR_CONTROL_HANDSHAKE

IfEqual, DCB_fRtsControl, 00, SetEnv, DCB_fRtsControl, RTS_CONTROL_DISABLE
IfEqual, DCB_fRtsControl, 01, SetEnv, DCB_fRtsControl, RTS_CONTROL_ENABLE
IfEqual, DCB_fRtsControl, 10, SetEnv, DCB_fRtsControl, RTS_CONTROL_HANDSHAKE
IfEqual, DCB_fRtsControl, 11, SetEnv, DCB_fRtsControl, RTS_CONTROL_TOGGLE

DCB_XonLim:=ExtractInteger(DCB, 14, true, 2)
DCB_XoffLim:=ExtractInteger(DCB, 16, true, 2)
DCB_ByteSize:=ExtractInteger(DCB, 18, true, 1)

DCB_Parity:=ExtractInteger(DCB, 19, true, 1)
IfEqual, DCB_Parity, 2, SetEnv, DCB_Parity, Even
IfEqual, DCB_Parity, 3, SetEnv, DCB_Parity, Mark
IfEqual, DCB_Parity, 0, SetEnv, DCB_Parity, None
IfEqual, DCB_Parity, 1, SetEnv, DCB_Parity, Odd
IfEqual, DCB_Parity, 4, SetEnv, DCB_Parity, Space

DCB_StopBits:=ExtractInteger(DCB, 20, true, 1)
IfEqual, DCB_StopBits, 2, SetEnv, DCB_StopBits, 2
IfEqual, DCB_StopBits, 1, SetEnv, DCB_StopBits, 1,5
IfEqual, DCB_StopBits, 0, SetEnv, DCB_StopBits, 1

DCB_XonChar:=ExtractInteger(DCB, 21, true, 1)
DCB_XoffChar:=ExtractInteger(DCB, 22, true, 1)
DCB_ErrorChar:=ExtractInteger(DCB, 23, true, 1)
DCB_EofChar:=ExtractInteger(DCB, 24, true, 1)
DCB_EvtChar:=ExtractInteger(DCB, 25, true, 1)

ch:=DllCall("CloseHandle", "Uint", h)
If (ch = 0 or ErrorLevel != 0)
return, -3
return, 0
}

ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
   Loop %pSize%  ; Build the integer by adding up its bytes.
      result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
   if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
      return result  ; Signed vs. unsigned doesn't matter in these cases.
   ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
   return -(0xFFFFFFFF - result + 1)
}

DecToBin(In_Val)
{
   local bit, bin, dec
   if In_Val is not integer
   return, "ERROR"
   dec:=In_Val
   Loop
   {
      bit:=mod(dec, 2)
      dec:=dec//2
      bin=%bit%%bin%
      IfEqual, dec, 0, break
  }
   return, %bin%
}

msgbox, % GetCommState(4)
listvars
pause



Edit: Changed naming of variables and return values.


Last edited by olfen on Fri May 26, 2006 11:55 am; edited 2 times in total
Back to top
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10464

PostPosted: Fri May 26, 2006 12:27 am    Post subject: Reply with quote

Nice-looking script. I like how you documented the complete structure and the purpose of each of its members.
Back to top
View user's profile Send private message Send e-mail
olfen



Joined: 04 Jun 2005
Posts: 99
Location: Stuttgart, Germany

PostPosted: Fri May 26, 2006 9:30 am    Post subject: Reply with quote

Quote:

I like how you documented the complete structure and the purpose of each of its members.

I have to disappoint you. It is extracted from Winbase.h Smile .

Meanwhile, I also got BuildCommDCB and SetCommState working and am looking forward to posting it after further testing.

Browsing MSDN I stumbled across WaitCommEvent:
Quote:

The WaitCommEvent function waits for an event to occur for a specified communications device. The set of events that are monitored by this function is contained in the event mask associated with the device handle.

The WaitCommEvent function should be executed as an overlapped operation so the other threads of the process can perform I/O operations during the wait.

Can it be "executed as an overlapped operation" in AutoHotkey?
Would this make it possible to have a rudimentary serial terminal?
Back to top
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10464

PostPosted: Sat May 27, 2006 1:01 am    Post subject: Reply with quote

olfen wrote:
Can [WaitCommEvent] be "executed as an overlapped operation" in AutoHotkey? Would this make it possible to have a rudimentary serial terminal?
I don't know enough about it to give a useful answer. Maybe someone else here knows.
Back to top
View user's profile Send private message Send e-mail
wisely
Guest





PostPosted: Sun Oct 14, 2007 2:27 am    Post subject: Reply with quote

Quote:
I also got BuildCommDCB and SetCommState working and am looking forward to posting it after further testing.
Browsing MSDN I stumbled across WaitCommEvent:

olfen, please i would like to know when you are going to post your working BuildCommDCB and SetCommState functions Question
And thanks for the GetCommState function
Back to top
olfen



Joined: 04 Jun 2005
Posts: 99
Location: Stuttgart, Germany

PostPosted: Sun Oct 14, 2007 9:35 am    Post subject: Reply with quote

Sorry, I had forgotten about it. I cannot remember, if this snippet works ok. Please test.
Code:
#NoEnv

; http://msdn2.microsoft.com/en-us/library/aa363214.aspx
VarSetCapacity(DCB, 28)

; http://msdn.microsoft.com/library/en-us/devio/base/buildcommdcb.asp
; The string must have the same form as the mode command's command-line arguments:
; COMx[:][baud=b][parity=p][data=d][stop=s][to={on|off}][xon={on|off}][odsr={on|off}][octs={on|off}][dtr={on|off|hs}][rts={on|off|hs|tg}][idsr={on|off}]
mode = COM1:baud=9600 parity=N data=8 stop=1
DllCall("BuildCommDCB", "str",mode, "uint",&DCB)

; http://msdn2.microsoft.com/en-us/library/aa363858.aspx
hCOMM := DllCall("CreateFile", "Str","COM1:" ,"Uint",0x80000000, "Uint",3, "UInt",0, "UInt",3, "Uint",0, "UInt",0)

; http://msdn2.microsoft.com/en-us/library/aa363436.aspx
DllCall("SetCommState", "Uint",hCOMM, "uint",&DCB)

DllCall("CloseHandle", "Uint",hCOMM)
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group