;~ https://www.autoitscript.com/forum/topic/189190-serial-port-udf-com-port-udf/ #TODO CME ERROR (GSM Equipment Related errors) ;~ https://www.micromedia-int.com/en/gsm-2/73-gsm/669-cme-error-gsm-equipment-related-errors ;~ https://m2msupport.net/m2msupport/download-at-command-tester/ #AutoIt3Wrapper_Run_AU3Check=Y #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #cs UDF cfx.au3 serial functions using kernel32.dll V1.0 Uwe Lahni 2008 V2.0 Andrew Calcutt 05/16/2009 Started converting to UDF V2.1 Mikko Keski-Heroja 02/23/2011 UDF is now compatible with Opt("MustDeclareVars",1) and Date.au3. V2.2 Veronesi 04/26/2011 Changed some cosmetics and documentation Add Function to set RTS and to get DCD Status V2.90 Maze 07/01/2017 Renamed to: ComUDF.au3 Deleted functions to set RTS and to get DCD Status Only one global variable: $__g_hCOMUDF_Kernel32 (kernel32.dll) Changed COM port format ("COM" plus number, e.g. "COM1") Changed all function names to start with '_COM_' Changed function _COM_OpenPort to accept only one argument $sDefinitions It gives full flexibility while keeping the amount of parameters small Modified and corrected the parameters for DLLCall Each structure and pointer to that structure is manually defined, according to the names provided in the MSDN reference. Each DllCall uses these names. (While this looks much longer and more complex, it is easier to write new functions in this format and it is also easier to read and check existing functions. It avoids shortcuts therefore can access all data directly from the provided struct. Using shortcuts doesn't allow this and requires access to the correct index of the returned array. (Look for example at the _WinAPI_WriteFile which has a statement that says "$iWritten = $aResult[4]". It takes a while to verify the "4" is indeed the correct index.) There is only one exception regarding the naming, namely the handle to the serial port named "hComPort" and used instead of "hFile".) Added a bunch of new functions, removed obsolete functions Added/modified comments and made a few cosmetic changes V2.91 21/09/2020 * refactoring + AU3Check compiliance - mLipok V2.92 23/09/2020 * small changes - mLipok * better error/extended reporting - mLipok * better example - mLipok V2.93 23/09/2020 * Change variables naming to fit AutoIt convention - Danyfirex * Fixed DllCall return check - Danyfirex * changed function name __PurgeComm >> __COM_Purge - Danyfirex * fixed many function to start it works - Danyfirex V2.94 Danyfirex 25/09/2020 * small fixes - Danyfirex V2.95 28/09/2020 * modified function _COM_SendString - now it use _COM_SendBinary instead _COM_SendCharArray - Danyfirex V2.96 28/09/2020 * small refactoring/cleaning - mLipok V2.97 29/09/2020 * fixed function _COM_OpenPort() - open port above 9 (the same problem which @Chuckero posted to the forum in 30/09/2020 as V2.93) - Danyfirex #ce ; #INDEX# ======================================================================================================================= ; Title .........: Serial communication UDF ; AutoIt Version : 3.3.14.2 ; Description ...: Serial communication using kernel32.dll (no custom dll needed) ; Authors........: Uwe Lahni, Andrew Calcutt, Mikko Keski-Heroja, Veronesi, Maze ; Dll ...........: kernel32.dll ; =============================================================================================================================== ; #VARIABLES# =================================================================================================================== Global $__g_hCOMUDF_Kernel32 ; =============================================================================================================================== ; #CURRENT# ===================================================================================================================== ; _COM_ListPorts ; _COM_OpenPort ; _COM_SetTimeouts ; _COM_ClosePort ; ; _COM_SetBreak ; _COM_ClearBreak ; _COM_GetInputcount ; _COM_GetOutputcount ; _COM_ClearOutputBuffer ; _COM_ClearInputBuffer ; ; _COM_SendByte ; _COM_ReadByte ; _COM_SendBinary ; _COM_ReadBinary ; ; _COM_SendChar ; _COM_ReadChar ; _COM_SendCharArray ; _COM_ReadCharArray ; _COM_SendString ; _COM_ReadString ; ; __COM_ClearCommError ; __COM_Purge ; =============================================================================================================================== ; =============================================================================================================================== ; Function Name: _COM_ListPorts() ; Description: Creates a list of the existing COM ports ; Parameters: (none) ; Returns: on success returns an array of strings ; on error (no com ports existing) returns -1 ; Note: The array contains e.g. "COM1", "COM2", up to "COM256" ; =============================================================================================================================== Func _COM_ListPorts() Local Const $sRegKey = 'HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM' Local $sValue = '' Local $sData = '' Local $aCOMPorts[0] For $i = 1 To 256 $sValue = RegEnumVal($sRegKey, $i) If @error Then ExitLoop $sData = RegRead($sRegKey, $sValue) If @error Then ExitLoop ReDim $aCOMPorts[$i] $aCOMPorts[$i - 1] = $sData Next If UBound($aCOMPorts) = 0 Then Return SetError(0, 1, -1) Return SetError(0, 2, $aCOMPorts) EndFunc ;==>_COM_ListPorts ; =============================================================================================================================== ; Function Name: _COM_OpenPort($sDefinitions) ; Description: Opens a serial port ; Parameters: $sDefinitions - (string) See the notes for the format and default settings ; Returns: on success returns a serial port handle ; on error returns -1 and sets @error to 1 ; Note: ; Defs is a string containing com port and many parameters. Default setting: ; COM1 baud=9600 parity=n data=8 stop=1 to=off xon=off odsr=off octs=off dtr=off rts=off idsr=off ; Usually the user would provide at least the COM port and baud settings, e.g. "COM1 baud=9600". ; All possible values are explained at https://technet.microsoft.com/en-us/library/cc732236.aspx ; ; To test the $sDefinitions sting you can simply open a command prompt and use it with the "mode" command. ; To try e.g. "COM1 baud=9600 parity=N data=8 stop=1" just type "mode COM1 baud=9600 parity=N data=8 stop=1". ; ; The following settings aren't supported by many chipsets. If you intend to use them it is strongly ; recommended to test them with the mode command: ; data=5, data=6, parity=m, parity=s and stop=1.5 ; ; References: ; Open the com port: ; CreateFile https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx ; Prepare the parameters: ; BuildCommDCB https://msdn.microsoft.com/en-us/library/windows/desktop/aa363143(v=vs.85).aspx ; Mode https://technet.microsoft.com/en-us/library/cc732236.aspx ; DCB https://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx ; COMMTIMEOUTS https://msdn.microsoft.com/en-us/library/windows/desktop/aa363190(v=vs.85).aspx ; Set the parameters: ; SetCommState https://msdn.microsoft.com/en-us/library/windows/desktop/aa363436(v=vs.85).aspx ; SetCommTimeouts https://msdn.microsoft.com/en-us/library/windows/desktop/aa363437(v=vs.85).aspx ; =============================================================================================================================== Func _COM_OpenPort($sDefinition) ; The format of $sDefinition is defined here: ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa363145(v=vs.85).aspx ; https://technet.microsoft.com/en-us/library/cc732236.aspx ; To test the $sDefinition open a command prompt windows and use it with the "mode" command Local Const $GENERIC_READ_WRITE = 0xC0000000 Local Const $OPEN_EXISTING = 3 Local Const $FILE_ATTRIBUTE_NORMAL = 0x80 ; open dll $__g_hCOMUDF_Kernel32 = DllOpen('kernel32.dll') If @error Then Return SetError(1, 1, -1) ; parse $sDefinition and set default values $sDefinition = StringStripWS($sDefinition, 3) ; remove leading and trailing whitespaces #Tidy_ILC_Pos=70 ; default value, options If StringInStr($sDefinition, 'COM') < 1 Then $sDefinition = 'COM1 ' & $sDefinition ; COM1...COM256 If StringInStr($sDefinition, 'baud=') < 1 Then $sDefinition &= ' baud=9600' ; 110...115200 If StringInStr($sDefinition, 'parity=') < 1 Then $sDefinition &= ' parity=n' ; {n|e|o|m|s} (n=none,e=even,o=odd,m=mark,s=space) If StringInStr($sDefinition, 'data=') < 1 Then $sDefinition &= ' data=8' ; {5|6|7|8} If StringInStr($sDefinition, 'stop=') < 1 Then $sDefinition &= ' stop=1' ; {1|1.5|2} If StringInStr($sDefinition, 'to=') < 1 Then $sDefinition &= ' to=off' ; {on|off} If StringInStr($sDefinition, 'xon=') < 1 Then $sDefinition &= ' xon=off' ; {on|off} If StringInStr($sDefinition, 'odsr=') < 1 Then $sDefinition &= ' odsr=off' ; {on|off} If StringInStr($sDefinition, 'octs=') < 1 Then $sDefinition &= ' octs=off' ; {on|off} If StringInStr($sDefinition, 'dtr=') < 1 Then $sDefinition &= ' dtr=off' ; {on|off|hs} (hs=handshake) If StringInStr($sDefinition, 'rts=') < 1 Then $sDefinition &= ' rts=off' ; {on|off|hs|tg} (tg=toggle) If StringInStr($sDefinition, 'idsr=') < 1 Then $sDefinition &= ' idsr=off' ; {on|off} ; Not used - 2020-09-25 - DanyFirex ;~ Local $ReadIntervalTimeout = 0 ;~ Local $ReadTotalTimeoutMultiplier = 0 ;~ Local $ReadTotalTimeoutConstant = 0 ;~ Local $WriteTotalTimeoutMultiplier = 0 ;~ Local $WriteTotalTimeoutConstant = 0 ;~ #forceref $ReadIntervalTimeout, $ReadTotalTimeoutMultiplier, $ReadTotalTimeoutConstant, $WriteTotalTimeoutMultiplier, $WriteTotalTimeoutConstant #Tidy_ILC_Pos=70 ; extract $sCOMPort from $sDefinitions Local $sCOMPort = "" Local $iCOMPort = 0 Local $aReg = StringRegExp($sDefinition, 'COM\d{1,3}', 3) If IsArray($aReg) Then $sCOMPort = $aReg[0] Local $aRegNumber = StringRegExp($sCOMPort, '\d{1,3}', 3) If IsArray($aRegNumber) Then $iCOMPort = Number($aRegNumber[0]) $sCOMPort = ($iCOMPort > 9 ? "\\.\" & $sCOMPort : $sCOMPort) ; open the com port Local $tFileName = DllStructCreate('char COMPort[' & StringLen($sCOMPort) + 1 & ']') Local $pFileName = DllStructGetPtr($tFileName, 'COMPort') DllStructSetData($tFileName, 'COMPort', $sCOMPort) #Tidy_ILC_Pos=50 Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'handle', 'CreateFile', _ 'long_ptr', $pFileName, _ 'dword', $GENERIC_READ_WRITE, _ ; DesiredAccess 'dword', 0, _ ; ShareMode 'long_ptr', 0, _ ; SecurityAttributes 'dword', $OPEN_EXISTING, _ ; CreationDisposition 'dword', $FILE_ATTRIBUTE_NORMAL, _ ; FlagsAndAttributes 'handle', 0) ; TemplateFile If @error Then Return SetError(1, 2, -1) Local $hCOMPort = $aCall[0] If $hCOMPort = Ptr(-1) Then _ ; $INVALID_HANDLE_VALUE Return SetError(1, 3, -1) ; prepare structs and pointer Local $tDefinition = DllStructCreate('char Data[255]') Local $pDefinition = DllStructGetPtr($tDefinition) DllStructSetData($tDefinition, 'Data', $sDefinition) Local $tDCB = DllStructCreate( _ 'long DCBlength;' & _ ; DWORD DCBlength; 'long BaudRate;' & _ ; DWORD BaudRate 'long fBitFields;' & _ ; DWORD fBitFields 'short wReserved;' & _ ; WORD wReserved 'short XonLim;' & _ ; WORD XonLim 'short XoffLim;' & _ ; WORD XoffLim 'byte Bytesize;' & _ ; BYTE ByteSize 'byte parity;' & _ ; BYTE Parity 'byte StopBits;' & _ ; BYTE StopBits 'byte XonChar;' & _ ; char XonChar 'byte XoffChar;' & _ ; char XoffChar 'byte ErrorChar;' & _ ; char ErrorChar 'byte EofChar;' & _ ; char EofChar 'byte EvtChar;' & _ ; char EvtChar 'short wReserved1') ; WORD wReserved Local $pDCB = DllStructGetPtr($tDCB) ; parse $sDefinition and fill the parameters in the prepared DCB struct $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'BuildCommDCB', _ 'long_ptr', $pDefinition, _ 'long_ptr', $pDCB) If @error Then Return SetError(1, 4, -1) If Not $aCall[0] Then Return SetError(1, 5, -1) ; set the parameters $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'SetCommState', _ 'handle', $hCOMPort, _ 'long_ptr', $pDCB) If @error Then Return SetError(1, 6, -1) If Not $aCall[0] Then Return SetError(1, 7, -1) ; set timeouts _COM_SetTimeouts($hCOMPort) ; default=no timeout, return immediately ; return the handle to the serial port Return SetError(0, 8, $hCOMPort) EndFunc ;==>_COM_OpenPort ; =============================================================================================================================== ; Function Name: _COM_SetTimeouts($hComPort, ; $iReadIntervalTimeout = -1, $iReadTotalTimeoutMultiplier = 0, $iReadTotalTimeoutConstant = 0, ; $iWriteTotalTimeoutMultiplier = 0, $iWriteTotalTimeoutConstant = 0) ; Description: Could set the timeouts on the serial port ; It fails if non-standard values are provided, for this reason: ; If called with non-default settings it would break the functions ; to read and send data. Be warned, you don't want your program ; to wait forever on a missing serial port input, as the user ; will think the program crashed or failed. ; To have a stable UDF this cannot be allowed. ; For a background program without GUI you might want to wait ; for data, instead of running the idle loop/GUI loop. In this ; case I would recommend creating a new UDF. ; ; Parameters: $hCOMPort - serial port handle (as returned by _COM_OpenPort) ; $iReadIntervalTimeout - ReadIntervalTimeout ; $iReadTotalTimeoutMultiplier - ReadTotalTimeoutMultiplier ; $iReadTotalTimeoutConstant - ReadTotalTimeoutConstant ; $iWriteTotalTimeoutMultiplier - WriteTotalTimeoutMultiplier ; $iWriteTotalTimeoutConstant - WriteTotalTimeoutConstant ; Returns: on success returns 0 ; on error returns -1 and sets @error to 1 ; Note: Default setting: Return immediately from reads without waiting. ; =============================================================================================================================== Func _COM_SetTimeouts($hCOMPort, $iReadIntervalTimeout = -1, $iReadTotalTimeoutMultiplier = 0, $iReadTotalTimeoutConstant = 0, $iWriteTotalTimeoutMultiplier = 0, $iWriteTotalTimeoutConstant = 0) ; SetCommTimeouts: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363437(v=vs.85).aspx ; COMMTIMEOUTS: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363190(v=vs.85).aspx ; Return with an error message if non-standard parameters are provided ; Reasoning: Instant return is expected by all functions in this UDF If $iReadIntervalTimeout <> -1 Then Return SetError(1, 1, -1) If $iReadTotalTimeoutMultiplier <> 0 Then Return SetError(1, 2, -1) If $iReadTotalTimeoutConstant <> 0 Then Return SetError(1, 3, -1) If $iWriteTotalTimeoutMultiplier <> 0 Then Return SetError(1, 4, -1) If $iWriteTotalTimeoutConstant <> 0 Then Return SetError(1, 5, -1) ; Return with an error message if non-standard parameters are provided ; Reasoning: Instant return is expected by all functions in this UDF Local $tCOMMTIMEOUTS = DllStructCreate( _ 'DWORD ReadIntervalTimeout;' & _ 'DWORD ReadTotalTimeoutMultiplier;' & _ 'DWORD ReadTotalTimeoutConstant;' & _ 'DWORD WriteTotalTimeoutMultiplier;' & _ 'DWORD WriteTotalTimeoutConstant') Local $pCOMMTIMEOUTS = DllStructGetPtr($tCOMMTIMEOUTS) DllStructSetData($tCOMMTIMEOUTS, 'ReadIntervalTimeout', $iReadIntervalTimeout) DllStructSetData($tCOMMTIMEOUTS, 'ReadTotalTimeoutMultiplier', $iReadTotalTimeoutMultiplier) DllStructSetData($tCOMMTIMEOUTS, 'ReadTotalTimeoutConstant', $iReadTotalTimeoutConstant) DllStructSetData($tCOMMTIMEOUTS, 'WriteTotalTimeoutMultiplier', $iWriteTotalTimeoutMultiplier) DllStructSetData($tCOMMTIMEOUTS, 'WriteTotalTimeoutConstant', $iWriteTotalTimeoutConstant) Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'SetCommTimeouts', _ 'handle', $hCOMPort, _ 'long_ptr', $pCOMMTIMEOUTS) If @error Then Return SetError(1, 6, -1) If Not $aCall[0] Then Return SetError(1, 7, -1) Return SetError(0, 8, 0) EndFunc ;==>_COM_SetTimeouts ; =============================================================================================================================== ; Function Name: _COM_ClosePort($hComPort) ; Description: Closes serial port ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success, returns 1 ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_ClosePort($hCOMPort) ; CloseHandle: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ "bool", "CloseHandle", _ "handle", $hCOMPort) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) DllClose($__g_hCOMUDF_Kernel32) Return SetError(0, 3, 1) EndFunc ;==>_COM_ClosePort ; =============================================================================================================================== ; Function Name: _COM_GetInputcount($hComPort) ; Description: Retrieves information about the amount of available bytes in the ; input buffer ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success, returns the amount of available bytes ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_GetInputcount($hCOMPort) Local $iRet = __COM_ClearCommError($hCOMPort, 'cbInQue') Return SetError(@error, @extended, $iRet) EndFunc ;==>_COM_GetInputcount ; =============================================================================================================================== ; Function Name: _COM_GetOutputcount($hComPort) ; Description: Retrieves information about the amount of bytes in the output ; buffer (not yet written to the line) ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success, returns the amount of bytes ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_GetOutputcount($hCOMPort) Local $iRet = __COM_ClearCommError($hCOMPort, 'cbOutQue') Return SetError(@error, @extended, $iRet) EndFunc ;==>_COM_GetOutputcount ; =============================================================================================================================== ; Function Name: _COM_ClearOutputBuffer($hComPort) ; Description: Discards all characters from the output buffer. ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success, returns 1 ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_ClearOutputBuffer($hCOMPort) Local $iRet = __COM_Purge($hCOMPort, 0x0004) Return SetError(@error, @extended, $iRet) EndFunc ;==>_COM_ClearOutputBuffer ; =============================================================================================================================== ; Function Name: _COM_ClearInputBuffer($hComPort) ; Description: Discards all characters from the input buffer. ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success, returns 1 ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_ClearInputBuffer($hCOMPort) Local $iRet = __COM_Purge($hCOMPort, 0x0008) Return SetError(@error, @extended, $iRet) EndFunc ;==>_COM_ClearInputBuffer ; =============================================================================================================================== ; Function Name: _COM_SetBreak($hComPort) ; Description: Suspends character transmission for a specified communications ; device and places the transmission line in a break state until ; the _COM_ClearBreak function is called. ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success, returns 1 ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_SetBreak($hCOMPort) ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa363433(v=vs.85).aspx Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ "bool", "SetCommBreak", _ "handle", $hCOMPort) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) Return SetError(0, 3, 1) EndFunc ;==>_COM_SetBreak ; =============================================================================================================================== ; Function Name: _COM_ClearBreak($hComPort) ; Description: Restores character transmission for a specified communications ; device and places the transmission line in a nonbreak state. ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success, returns 1 ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_ClearBreak($hCOMPort) ;https://msdn.microsoft.com/en-us/library/windows/desktop/aa363179(v=vs.85).aspx Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ "bool", "ClearCommBreak", _ "handle", $hCOMPort) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) Return SetError(0, 3, 1) EndFunc ;==>_COM_ClearBreak ; =============================================================================================================================== ; Function Name: _COM_SendByte($hComPort, $bSendByte) ; Description: Send a single byte ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $sSendChar - char to send ; Returns: on success, returns the amout of bytes written ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_SendByte($hCOMPort, $bSendByte) ;WriteFile: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365747(v=vs.85).aspx Local $tBuffer = DllStructCreate('byte b') Local $lBuffer = DllStructGetPtr($tBuffer, 'b') DllStructSetData($tBuffer, 'b', $bSendByte) Local $iNumberOfBytesToWrite = 1 Local $tNumberOfBytesWritten = DllStructCreate('dword n') Local $pNumberOfBytesWritten = DllStructGetPtr($tNumberOfBytesWritten) Local $pOverlapped = 0 ;null pointer Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'WriteFile', _ 'handle', $hCOMPort, _ 'long_ptr', $lBuffer, _ 'dword', $iNumberOfBytesToWrite, _ 'long_ptr', $pNumberOfBytesWritten, _ 'long_ptr', $pOverlapped) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) Return SetError(0, 3, Number(DllStructGetData($tNumberOfBytesWritten, 'n'))) EndFunc ;==>_COM_SendByte ; =============================================================================================================================== ; Function Name: _COM_ReadByte($hComPort) ; Description: Read a single byte from the com port ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; Returns: on success returns a byte (0 to 255) ; on failure (empty buffer) returns -1 ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_ReadByte($hCOMPort) ; ReadFile: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx #Tidy_ILC_Pos=70 Local $bByte ; received byte Local $tBuffer = DllStructCreate('bool b') ; will contain the data read Local $pBuffer = DllStructGetPtr($tBuffer, 'b') Local $iNumberOfBytesToRead = 1 ; number of chars to read Local $tNumberOfBytesRead = DllStructCreate('dword n') ; will contain the number of bytes read Local $pNumberOfBytesRead = DllStructGetPtr($tNumberOfBytesRead) Local $pOverlapped = 0 Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'ReadFile', _ 'handle', $hCOMPort, _ 'long_ptr', $pBuffer, _ 'dword', $iNumberOfBytesToRead, _ 'long_ptr', $pNumberOfBytesRead, _ 'long_ptr', $pOverlapped) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) Local $iNumberOfBytesRead = Number(DllStructGetData($tNumberOfBytesRead, "n")) If $iNumberOfBytesRead = 1 Then $bByte = DllStructGetData($tBuffer, "b") Return SetError(0, 3, $bByte) EndIf Return SetError(0, 4, -1) ; no error, no char read EndFunc ;==>_COM_ReadByte ; =============================================================================================================================== ; Function Name: _COM_SendBinary($hComPort, $binary) ; Description: Send binary data ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $binary - Binary data (e.g. Binary('0xFF00FF00') ; Returns: on success, returns the number of bytes written ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_SendBinary($hCOMPort, $bBinary) ; WriteFile: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365747(v=vs.85).aspx Local $iNumberOfBytesToWrite = BinaryLen($bBinary) Local $tBuffer = DllStructCreate('byte Data[' & $iNumberOfBytesToWrite & ']') Local $pBuffer = DllStructGetPtr($tBuffer, 'Data') DllStructSetData($tBuffer, 'Data', $bBinary) Local $tNumberOfBytesWritten = DllStructCreate('dword n') Local $pNumberOfBytesWritten = DllStructGetPtr($tNumberOfBytesWritten) #Tidy_ILC_Pos=40 Local $pOverlapped = 0 ;null pointer Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'WriteFile', _ 'handle', $hCOMPort, _ 'long_ptr', $pBuffer, _ 'dword', $iNumberOfBytesToWrite, _ 'long_ptr', $pNumberOfBytesWritten, _ 'long_ptr', $pOverlapped) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) Return SetError(0, 3, Number(DllStructGetData($tNumberOfBytesWritten, 'n'))) EndFunc ;==>_COM_SendBinary ; =============================================================================================================================== ; Function Name: _COM_ReadBinary($hComPort, ByRef $binary, $iBytesToRead) ; Description: Receives binary data ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $arrayBinary - will contain the read data ; $iBytesToRead - exact number of bytes to read ; Returns: on success returns 1 ($arrayBinary contains $iBytesToRead bytes) ; on failure success 0 ($arrayBinary is undefined) ; on error returns -1 and sets @error to 1 ; Note: ; If there are less bytes than requested in the input buffer it returns 0 ; =============================================================================================================================== Func _COM_ReadBinary($hCOMPort, ByRef $bBinary, $iBytesToRead) If $iBytesToRead > _COM_GetInputcount($hCOMPort) Then Return SetError(0, 1, 0) #Tidy_ILC_Pos=30 ; ReadFile: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx ;~ Local $byte ; received byte ;not used ;~ #forceref $byte #Tidy_ILC_Pos=80 Local $tBuffer = DllStructCreate('byte Data[' & $iBytesToRead & ']') ; will contain the data read Local $pBuffer = DllStructGetPtr($tBuffer, 'Data') Local $iNumberOfBytesToRead = $iBytesToRead ; number of chars to read Local $tNumberOfBytesRead = DllStructCreate('dword n') ; will contain the number of bytes read Local $pNumberOfBytesRead = DllStructGetPtr($tNumberOfBytesRead) Local $pOverlapped = 0 Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'ReadFile', _ 'handle', $hCOMPort, _ 'long_ptr', $pBuffer, _ 'dword', $iNumberOfBytesToRead, _ 'long_ptr', $pNumberOfBytesRead, _ 'long_ptr', $pOverlapped) If @error Then Return SetError(1, 2, -1) If Not $aCall[0] Then Return SetError(1, 3, -1) Local $iNumberOfBytesRead = Number(DllStructGetData($tNumberOfBytesRead, "n")) ;~ #forceref $iNumberOfBytesRead If $iNumberOfBytesRead = 0 Then Return SetError(1, 4, -1) If $iNumberOfBytesRead <> $iNumberOfBytesToRead Then Return SetError(1, 5, -1) $bBinary = DllStructGetData($tBuffer, "Data") If @error Then Return SetError(@error, 6, $bBinary) Return SetError(0, 7, 1) EndFunc ;==>_COM_ReadBinary ; =============================================================================================================================== ; Function Name: _COM_SendChar($hComPort, $cChar) ; Description: Sends an ASCII char ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $cChar - a char ; Returns: on success returns the number of bytes written ; on error returns -1 and sets @error ; Note: ; =============================================================================================================================== Func _COM_SendChar($hCOMPort, $sChar) Local $iRet = _COM_SendByte($hCOMPort, Asc($sChar)) Return SetError(@error, @extended, $iRet) EndFunc ;==>_COM_SendChar ; =============================================================================================================================== ; Function Name: _COM_ReadChar($hComPort, $cChar) ; Description: Reads an ASCII char ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $cChar - a char ; Returns: on success returns a char if was read ; on failure (no char to read) returns -1 ; on error returns -1 and sets @error ; Note: ; =============================================================================================================================== Func _COM_ReadChar($hCOMPort) Local $bByte = _COM_ReadByte($hCOMPort) If @error Then Return SetError(1, 1, -1) If $bByte = -1 Then Return SetError(0, 2, -1) Return SetError(0, 3, Chr($bByte)) EndFunc ;==>_COM_ReadChar ; =============================================================================================================================== ; Function Name: _COM_SendCharArray($hComPort, $charArray) ; Description: Sends data ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $charArray - the data to write, ; Returns: on success returns the number of bytes written ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_SendCharArray($hCOMPort, $aChar) Local $iCount = 0 For $i = 0 To UBound($aChar) - 1 $iCount += _COM_SendByte($hCOMPort, $aChar[$i]) If @error Then Return SetError(1, 1, -1) Next Return SetError(0, 2, $iCount) EndFunc ;==>_COM_SendCharArray ; =============================================================================================================================== ; Function Name: _COM_ReadCharArray($hComPort, ByRef $charArray, $charsToRead) ; Description: Reads data into an array ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $charArray - will contain the read data ; $charsToRead - exact number of chars (bytes) to read ; Returns: on success returns 1 ($charArray contains $charsToRead bytes) ; on failure returns 0 ($charArray is undefined) ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func _COM_ReadCharArray($hCOMPort, ByRef $aChar, $charsToRead) Local $bBinary Local $iRet = _COM_ReadBinary($hCOMPort, $bBinary, $charsToRead) If @error Then Return SetError(1, 1, -1) EndIf If $iRet = 1 Then ReDim $aChar[$charsToRead] For $i = 0 To BinaryLen($bBinary) - 1 $aChar[$i] = BinaryMid($bBinary, $i + 1, 1) Next Return SetError(0, 2, 1) EndIf Return SetError(0, 3, 0) EndFunc ;==>_COM_ReadCharArray ; =============================================================================================================================== ; Function Name: _COM_SendString($hComPort, $string, $encoding=1) ; Description: Sends data ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $string - the string to write ; $encoding - 1=ANSI (default), 2=UTF-8 ; Returns: on success returns the number of bytes written ; on error returns -1 and sets @error to 1 ; Note: ; If there are less bytes than requested in the input buffer it returns 0 ; =============================================================================================================================== Func _COM_SendString($hCOMPort, $sString, $iEncoding = 1) If $iEncoding < 1 Or $iEncoding > 2 Then Return SetError(1, 1, -1) Local $iRet = _COM_SendBinary($hCOMPort, StringToBinary($sString, ($iEncoding = 1 ? 1 : 4))) Return SetError(@error, @extended, $iRet) EndFunc ;==>_COM_SendString Func _COM_SendString___OLD_VERSION($hCOMPort, $sString, $iEncoding = 1) # REMARK: THIS OLD VERSION SHOULD BE REVIEWED AND EVENTUALLY DELETED FROM THIS UDF If $iEncoding < 1 Or $iEncoding > 2 Then Return SetError(1, 1, -1) Local $aChar = StringToASCIIArray($sString, 0, StringLen($sString), $iEncoding) Local $iRet = _COM_SendCharArray($hCOMPort, $aChar) Return SetError(@error, @extended, $iRet) EndFunc ;==>_COM_SendString___OLD_VERSION ; =============================================================================================================================== ; Function Name: _COM_ReadString($hComPort, $iByteLength, $encoding=1) ; Description: Reads a string ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $iByteLength - exact amount of bytes to read ; Unicode uses more than one byte per character ; $encoding - 1=ANSI (default), 2=UTF-8 ; Returns: on success returns a string ; on failure returns 0 ; on error returns -1 and sets @error to 1 ; Note: ; If there are less bytes than requested in the input buffer it returns 0 ; =============================================================================================================================== Func _COM_ReadString($hCOMPort, $iByteLength, $iEncoding = 1) Local $aChar[0] If $iEncoding < 1 Or $iEncoding > 2 Then Return SetError(1, 1, -1) Local $iRet = _COM_ReadCharArray($hCOMPort, $aChar, $iByteLength) If @error Then Return SetError(1, 2, -1) EndIf If $iRet = 1 Then Return SetError(0, 3, StringFromASCIIArray($aChar, 0, UBound($aChar), $iEncoding)) EndIf Return SetError(0, 4, 0) EndFunc ;==>_COM_ReadString ; =============================================================================================================================== ; Function Name: __COM_ClearCommError($hComPort, $sInfo = 'cbInQue') ; Description: Retrieves information about commincation errors and state ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $sInfo - a string describing the info to return, possible values: ; 'Errors' - Errors that occured (see notes) ; 'Flags' - Flags set or unset ; 'cbInQue' - The number of bytes in the input buffer (net yet read) ; 'cbOutQue' - The number of bytes in the output buffer (not yet send) ; Returns: on success, returns 0 (false), 1 (true) or a positive number ; on error returns -1 and sets @error to 1 ; Note: ; Possible error values: ; CE_BREAK (0x0010) - The hardware detected a break condition ; CE_FRAME (0x0008) - The hardware detected a framing error ; CE_OVERRUN (0x0002) - A character-buffer overrun has occurred, the next ; character is lost ; CE_RXOVER (0x0001) - An input buffer overflow has occurred. There is either no ; room in the input buffer, or a character was received ; after the end-of-file (EOF) character ; CE_RXPARITY (0x0004) - The hardware detected a parity error ; Call _ClearCommBreak to resolve errors ; ; Possible FLAG values: ; fCtsHold (1bit) - Transmission is waiting for the CTS signal to be sent ; fDsrHold (1bit) - Transmission is waiting for the DSR signal to be sent ; fRlsdHold (1bit) - Transmission is waiting for the RLSD signal to be sent ; fXoffHold (1bit) - Transmission is waiting because the XOFF character was received ; fXoffSent (1bit) - Transmission is waiting because the XOFF character was transmitted ; fEof (1bit) - The end-of-file (EOF) character has been received ; fTxim (1bit) - There is a character queued for transmission that has come to ; the communications device by way of the TransmitCommChar function ; Reserved (25bits) ; =============================================================================================================================== Func __COM_ClearCommError($hCOMPort, $sInfo = 'cbInQue') ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa363180(v=vs.85).aspx #Tidy_ILC_Pos=60 ; prepare structs Local $tErrors = DllStructCreate('dword Errors') Local $pErrors = DllStructGetPtr($tErrors) Local $tStat = DllStructCreate( _ 'dword Flags;' & _ ; DWORD flags 'dword cbInQue;' & _ ; DWORD cbInQue 'dword cbOutQue;') ; DWORD cbOutQue Local $pStat = DllStructGetPtr($tStat) ; read the status Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'ClearCommError', _ 'handle', $hCOMPort, _ 'long_ptr', $pErrors, _ 'long_ptr', $pStat) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) ; return requested information Local $iStat If $sInfo = 'cbInQue' Then ; probably most often called, checked first $iStat = DllStructGetData($tStat, $sInfo) Return SetError(0, 3, $iStat) ElseIf $sInfo = 'cbOutQue' Then $iStat = DllStructGetData($tStat, $sInfo) Return SetError(0, 4, $iStat) ElseIf $sInfo = 'Flags' Then $iStat = DllStructGetData($tStat, $sInfo) Return SetError(0, 5, $iStat) ElseIf $sInfo = 'Errors' Then $iStat = DllStructGetData($tErrors, $sInfo) Return SetError(0, 6, $iStat) EndIf Return SetError(1, 7, -1) ; nothing matched EndFunc ;==>__COM_ClearCommError ; =============================================================================================================================== ; Function Name: __COM_Purge($hComPort, $sFlags = 0x0000) ; Description: Discards all characters from the output or input buffer. It can ; also terminate pending read or write operations. ; Parameters: $hComPort - serial port handle (as returned by _COM_OpenPort) ; $sFlage - a combination of any of these numbers: ; 0x0001 - Terminates all outstanding write operations ; 0x0002 - Terminates all outstanding read operations ; 0x0004 - Clears the output buffer ; 0x0008 - Clears the input buffer ; Returns: on success, returns 1 ; on error returns -1 and sets @error to 1 ; Note: ; =============================================================================================================================== Func __COM_Purge($hCOMPort, $iFlags = 0x0000) ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa363428(v=vs.85).aspx Local $aCall = DllCall($__g_hCOMUDF_Kernel32, _ 'bool', 'PurgeComm', _ 'handle', $hCOMPort, _ 'dword', $iFlags) If @error Then Return SetError(1, 1, -1) If Not $aCall[0] Then Return SetError(1, 2, -1) Return SetError(0, 3, 1) EndFunc ;==>__COM_Purge