[VB.NET 2008] How to use DeviceIoControl function?
-
Hello everybody, I need to use the function DeviceIoControl to monitor the status of a COM port (RS485) but I don't know how to do. I have declared the functions:
_
Shared Function DeviceIoControl(ByVal hDevice As Integer, ByVal dwIoControlCode As Integer, _
ByVal lpInBuffer As String, ByVal nInBufferSize As Integer, _
ByVal lpOutBuffer() As Byte, ByVal nOutBufferSize As Integer, _
ByRef lpBytesReturned As Integer, ByVal lpOverlapped As Integer) As Integer
End FunctionPrivate Declare Function CreateFile Lib "coredll.dll" _
(ByVal lpFileName As String, ByVal dwDesiredAccess As Int32, _
ByVal dwShareMode As Int32, ByVal lpSecurityAttributes As IntPtr, _
ByVal dwCreationDisposition As Int32, ByVal dwFlagsAndAttributes As Int32, _
ByVal hTemplateFile As IntPtr) As IntPtrDeclare Function CloseHandle Lib "coredll.dll" (ByVal hObject As IntPtr) As Boolean
I use CreateFile (it works) to get an handle to the COM port and I pass it to DeviceIoControl:
Const FILE_SHARE_READ As Integer = &H1
Const FILE_SHARE_WRITE As Integer = &H2
Const GENERIC_READ As Integer = &H80000000
Const GENERIC_WRITE As Integer = &H40000000Dim portPtr As IntPtr
Dim ris As Boolean
Dim InBuffer As String
Dim OutBuffer(100) As Byte
Dim BytesReturned, Overlapped As Int32portPtr = CreateFile(com.PortName & ":", GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
ris = DeviceIoControl(portPtr.ToInt32, IOCTL_SERIAL_GET_COMMSTATUS, InBuffer, InBuffer.Length, OutBuffer, OutBuffer.Count, BytesReturned, Overlapped)
CloseHandle(portPtr)
I don't know what must be the value of
IOCTL_SERIAL_GET_COMMSTATUS
and I'm not sure that I'm using DeviceIoControl in the right way. I have found some information only in C++ like:#define IOCTL_SERIAL_GET_COMMSTATUS CTL_CODE(FILE_DEVICE_SERIAL_PORT, 27, METHOD_BUFFERED, FILE_ANY_ACCESS)
but how can I use it in VB.NET? And then, DeviceIoControl should fill a SERIAL_STATUS structure:
typedef struct _SERIAL_STATUS {
ULONG Errors;
ULONG HoldReasons;
ULONG AmountInInQueue;
ULONG AmountInOutQueue;
BOOLEAN EofReceived;
BOOLEAN WaitForImmediate;
} SERIAL_STATUS, *PSERIAL_STATUS;but a struct
-
Hello everybody, I need to use the function DeviceIoControl to monitor the status of a COM port (RS485) but I don't know how to do. I have declared the functions:
_
Shared Function DeviceIoControl(ByVal hDevice As Integer, ByVal dwIoControlCode As Integer, _
ByVal lpInBuffer As String, ByVal nInBufferSize As Integer, _
ByVal lpOutBuffer() As Byte, ByVal nOutBufferSize As Integer, _
ByRef lpBytesReturned As Integer, ByVal lpOverlapped As Integer) As Integer
End FunctionPrivate Declare Function CreateFile Lib "coredll.dll" _
(ByVal lpFileName As String, ByVal dwDesiredAccess As Int32, _
ByVal dwShareMode As Int32, ByVal lpSecurityAttributes As IntPtr, _
ByVal dwCreationDisposition As Int32, ByVal dwFlagsAndAttributes As Int32, _
ByVal hTemplateFile As IntPtr) As IntPtrDeclare Function CloseHandle Lib "coredll.dll" (ByVal hObject As IntPtr) As Boolean
I use CreateFile (it works) to get an handle to the COM port and I pass it to DeviceIoControl:
Const FILE_SHARE_READ As Integer = &H1
Const FILE_SHARE_WRITE As Integer = &H2
Const GENERIC_READ As Integer = &H80000000
Const GENERIC_WRITE As Integer = &H40000000Dim portPtr As IntPtr
Dim ris As Boolean
Dim InBuffer As String
Dim OutBuffer(100) As Byte
Dim BytesReturned, Overlapped As Int32portPtr = CreateFile(com.PortName & ":", GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
ris = DeviceIoControl(portPtr.ToInt32, IOCTL_SERIAL_GET_COMMSTATUS, InBuffer, InBuffer.Length, OutBuffer, OutBuffer.Count, BytesReturned, Overlapped)
CloseHandle(portPtr)
I don't know what must be the value of
IOCTL_SERIAL_GET_COMMSTATUS
and I'm not sure that I'm using DeviceIoControl in the right way. I have found some information only in C++ like:#define IOCTL_SERIAL_GET_COMMSTATUS CTL_CODE(FILE_DEVICE_SERIAL_PORT, 27, METHOD_BUFFERED, FILE_ANY_ACCESS)
but how can I use it in VB.NET? And then, DeviceIoControl should fill a SERIAL_STATUS structure:
typedef struct _SERIAL_STATUS {
ULONG Errors;
ULONG HoldReasons;
ULONG AmountInInQueue;
ULONG AmountInOutQueue;
BOOLEAN EofReceived;
BOOLEAN WaitForImmediate;
} SERIAL_STATUS, *PSERIAL_STATUS;but a struct
Is there a reason why you cannot use the SerialPort class within .NET? I use that for working with RS-485 ports in my projects. I use C# so my examples wouldn't help you unless you wanted to translate. In any case look here: http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx[^]
-
Is there a reason why you cannot use the SerialPort class within .NET? I use that for working with RS-485 ports in my projects. I use C# so my examples wouldn't help you unless you wanted to translate. In any case look here: http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx[^]
Thank you David, the reason I need to use DeviceIoControl is to catch the UART framing error that happens when I receive a DMX512 data packet. I use the SerialPort class in trasmission without problem because I can create a correct DMX data packet with the starting break (line low - zero - at least for 88 µs) but when I receive data I can't get the break that starts the packet, I just get one zero, it doesn't metter how long the break is, but this break causes a framing error, so, if I get the framing error I get the start of the data packet.
-
Thank you David, the reason I need to use DeviceIoControl is to catch the UART framing error that happens when I receive a DMX512 data packet. I use the SerialPort class in trasmission without problem because I can create a correct DMX data packet with the starting break (line low - zero - at least for 88 µs) but when I receive data I can't get the break that starts the packet, I just get one zero, it doesn't metter how long the break is, but this break causes a framing error, so, if I get the framing error I get the start of the data packet.
The SerialPort class has an ErrorReceived event, which contains the framing error. So you could use that as a way to start reading the packet then. http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.errorreceived.aspx[^]
-
The SerialPort class has an ErrorReceived event, which contains the framing error. So you could use that as a way to start reading the packet then. http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.errorreceived.aspx[^]
Yes, I tried to use the ErrorReceived event but it doesn't seem to work. I use the DataReceived event to receive data and it works but I get no error, on the other hand I read in the help that:
...
PinChanged, DataReceived, and ErrorReceived events may be called out of order, and there may be a slight delay between when the underlying stream reports the error and when code can when the event handler is executed. Only one event handler can execute at a time.
...However, I found another way using API and p/invoke: I use the function
WaitCommEvent()
to get directly the break instaed of the framing error. This solution was suggested by Bruce Eitman in the MSDN Windows Embedded Compact forum and I found a good example in the article "Smart Device Print Engine for Compact Framework" by Orkun GEDiK here in CodeProject. Thanks anyway for your interest and for your time.