AutoHotkey Community

It is currently May 25th, 2012, 7:34 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: DllCall to GetCommState
PostPosted: May 25th, 2006, 3:16 pm 
Offline

Joined: June 4th, 2005, 1:30 am
Posts: 113
Location: Stuttgart, Germany
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 May 26th, 2006, 11:55 am, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2006, 12:27 am 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
Nice-looking script. I like how you documented the complete structure and the purpose of each of its members.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 26th, 2006, 9:30 am 
Offline

Joined: June 4th, 2005, 1:30 am
Posts: 113
Location: Stuttgart, Germany
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 :) .

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?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 27th, 2006, 1:01 am 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2007, 2:27 am 
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 :?:
And thanks for the GetCommState function


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2007, 9:35 am 
Offline

Joined: June 4th, 2005, 1:30 am
Posts: 113
Location: Stuttgart, Germany
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)


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: nimda and 6 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group