Quantex GmbH
Your region: Europe

PassThruReadMsgs v4.04 v5.0

Reading received messages

Last updated:

Description

The function reads received messages from the channel queue. The adapter can hold a maximum of 100 messages per queue for a single channel and has 64 KB of free memory for all queues. When a queue or the entire free memory is full, message reception is paused.

long PassThruReadMsgs(unsigned long ChannelID, PASSTHRU_MSG* pMsg, unsigned long* pNumMsgs, unsigned long Timeout)
Important: For the ISO 9141 and ISO 14230 protocols, an indicator message START_OF_MESSAGE with the timestamp of the start of reception is generated for every received packet; for ISO 15765 it is generated for every segmented packet. It is followed by the main message with the timestamp of the end of reception.

Parameters

Return error codes

Code Description Possible causes and solutions
STATUS_NOERROR Function completed successfully -
ERR_CONCURRENT_API_CALL v5.0 Concurrent API call
  • A SAE J2534 API function was called before the previous call completed
  • Solution: wait for the previous call to complete before making a new one
ERR_DEVICE_NOT_OPEN v5.0 Device not open
  • PassThruOpen was not called successfully
  • Solution: call PassThruOpen before use
ERR_DEVICE_NOT_CONNECTED No connection to the adapter
  • The adapter is turned off or the connection has been lost
  • Solution: check the adapter power and the network connection
ERR_INVALID_DEVICE_ID Invalid device identifier
  • DeviceID was not obtained through PassThruOpen
  • Solution: make sure the device is open
ERR_INVALID_CHANNEL_ID Invalid channel identifier
  • ChannelID was not obtained through PassThruConnect
  • The channel is already closed
  • Solution: make sure the channel is open
ERR_NOT_SUPPORTED v5.0 Function not supported
  • The device does not support this API function for the given ChannelID
  • Solution: check the device capabilities
ERR_NULL_PARAMETER Buffer pointer not specified
  • pMsg or pNumMsgs is NULL
  • Solution: pass valid pointers
ERR_TIMEOUT The wait timeout expired
  • Fewer messages arrived within the specified time than were requested
  • Solution: this is a normal situation; check pNumMsgs for the number received
ERR_BUFFER_EMPTY The receive queue is empty
  • No messages in the queue when Timeout = 0
  • Solution: retry the request later or use a non-zero timeout
ERR_BUFFER_OVERFLOW The receive queue has overflowed
  • Messages were lost due to overflow
  • Solution: read messages more often or increase the polling rate
ERR_BUFFER_TOO_SMALL v5.0 Buffer too small
  • The DataBuffer size in the PASSTHRU_MSG structure is too small for the full message
  • Solution: increase the data buffer size
ERR_NO_FLOW_CONTROL Flow Control filter not set
  • ISO 15765 requires a Flow Control filter
  • Solution: call PassThruStartMsgFilter with the FLOW_CONTROL_FILTER type
ERR_FAILED Internal error
  • Memory allocation error or stack failure
  • Solution: use PassThruGetLastError() for details

Examples

C/C++ example

#include "j2534_dll.hpp"

unsigned long ChannelID; // ID obtained from PassThruConnect
PASSTHRU_MSG Msgs[10];   // Buffer for messages
unsigned long NumMsgs = 10; // Request up to 10 messages
unsigned long Timeout = 1000; // Timeout 1000 ms

long ret = PassThruReadMsgs(ChannelID, &Msgs[0], &NumMsgs, Timeout);
if (ret == STATUS_NOERROR || ret == ERR_TIMEOUT)
{
    // Process the received messages (NumMsgs of them)
    for (unsigned long i = 0; i < NumMsgs; i++) {
        if (Msgs[i].RxStatus & START_OF_MESSAGE) {
            // Start-of-message indicator
            continue;
        }
        // Process the data in Msgs[i].Data, Msgs[i].DataSize
    }
}
else
{
    char error[256];
    PassThruGetLastError(error);
    printf("Error: %s\n", error);
}

Kotlin example (Android)

// channelID obtained earlier from ptConnect
val numMsgsToRead = 10
val timeout = 1000 // ms

val result = j2534.ptReadMsgs(channelID, numMsgsToRead, timeout)
if (result.status == STATUS_NOERROR || result.status == ERR_TIMEOUT) {
    // Successfully read result.msgs.size messages
    for (msg in result.msgs) {
        if (msg.rxStatus and START_OF_MESSAGE != 0) {
            continue // Skip the start indicator
        }
        Log.i("J2534", "Received: ${msg.data.toHexString()}")
    }
} else {
    Log.e("J2534", "Read error: ${result.status}")
}

Python example (ctypes)

from ctypes import *
import platform

# Load the library
if platform.system() == "Windows":
    j2534 = windll.LoadLibrary("j2534sd_v04_04_x64.dll")
elif platform.system() == "Darwin":
    j2534 = cdll.LoadLibrary("libj2534_v04_04.dylib")
else:
    j2534 = cdll.LoadLibrary("libj2534_v04_04.so")

# PASSTHRU_MSG structure
class PASSTHRU_MSG(Structure):
    _fields_ = [
        ("ProtocolID", c_ulong),
        ("RxStatus", c_ulong),
        ("TxFlags", c_ulong),
        ("Timestamp", c_ulong),
        ("DataSize", c_ulong),
        ("ExtraDataIndex", c_ulong),
        ("Data", c_ubyte * 4128)
    ]

# channel_id obtained earlier from PassThruConnect
msgs = (PASSTHRU_MSG * 10)()
num_msgs = c_ulong(10)
timeout = c_ulong(1000)

ret = j2534.PassThruReadMsgs(channel_id, byref(msgs[0]), byref(num_msgs), timeout)

if ret == 0 or ret == 0x09:  # STATUS_NOERROR or ERR_TIMEOUT
    print(f"Received {num_msgs.value} messages")
    for i in range(num_msgs.value):
        if msgs[i].RxStatus & 0x02:  # START_OF_MESSAGE
            continue
        data = bytes(msgs[i].Data[:msgs[i].DataSize])
        print(f"Data: {data.hex()}")
else:
    error = create_string_buffer(256)
    j2534.PassThruGetLastError(error)
    print(f"Error: {error.value.decode()}")

C# example (P/Invoke)

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct PASSTHRU_MSG
{
    public uint ProtocolID;
    public uint RxStatus;
    public uint TxFlags;
    public uint Timestamp;
    public uint DataSize;
    public uint ExtraDataIndex;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4128)]
    public byte[] Data;
}

class J2534
{
    [DllImport("j2534sd_v04_04_x64.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern int PassThruReadMsgs(
        uint ChannelID,
        [In, Out] PASSTHRU_MSG[] pMsg,
        ref uint pNumMsgs,
        uint Timeout);

    [DllImport("j2534sd_v04_04_x64.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern int PassThruGetLastError(
        [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder pErrorDescription);
}

// Usage:
// channelId obtained earlier from PassThruConnect
PASSTHRU_MSG[] msgs = new PASSTHRU_MSG[10];
for (int i = 0; i < msgs.Length; i++)
    msgs[i].Data = new byte[4128];

uint numMsgs = 10;
uint timeout = 1000;

int ret = J2534.PassThruReadMsgs(channelId, msgs, ref numMsgs, timeout);

if (ret == 0 || ret == 0x09) // STATUS_NOERROR or ERR_TIMEOUT
{
    Console.WriteLine($"Received {numMsgs} messages");
    for (uint i = 0; i < numMsgs; i++)
    {
        if ((msgs[i].RxStatus & 0x02) != 0) // START_OF_MESSAGE
            continue;
        byte[] data = new byte[msgs[i].DataSize];
        Array.Copy(msgs[i].Data, data, msgs[i].DataSize);
        Console.WriteLine($"Data: {BitConverter.ToString(data)}");
    }
}
else
{
    var error = new System.Text.StringBuilder(256);
    J2534.PassThruGetLastError(error);
    Console.WriteLine($"Error: {error}");
}