A general-purpose function for controlling the device and the channel. It performs different operations depending on the IoctlID parameter: reading/writing configuration, initializing protocols, clearing buffers, and other service operations.
long PassThruIoctl(unsigned long ChannelID, unsigned long IoctlID, void *pInput, void *pOutput)
Parameters
unsigned long ChannelID — the channel identifier obtained from PassThruConnect. For some commands (READ_VBATT, GET_DEVICE_INFO) the DeviceID is used.
unsigned long IoctlID — the operation identifier (see the table below).
void* pInput — pointer to the input data. The type depends on IoctlID.
void* pOutput — pointer to the output data. The type depends on IoctlID.
Solution: check the adapter power and the network connection
ERR_INVALID_CHANNEL_ID
Invalid channel identifier
ChannelID was not obtained through PassThruConnect, or the channel is closed
Solution: make sure PassThruConnect completed successfully
ERR_INVALID_IOCTL_ID
Invalid IoctlID identifier
The specified IoctlID is not supported
Solution: check that the IoctlID value is correct
ERR_NULL_PARAMETER
NULL was passed instead of a required pointer
pInput or pOutput is NULL when a pointer is required
Solution: pass valid pointers
ERR_NOT_SUPPORTED
The operation is not supported
The adapter does not support the requested operation
Solution: check the adapter capabilities via GET_DEVICE_INFO
ERR_INVALID_IOCTL_VALUE
Invalid parameter value
The value in pInput is out of the allowed range
Solution: check the allowed value ranges
ERR_INVALID_MSG
Invalid message structure
Invalid structure in pInput for FAST_INIT
Solution: check that the PASSTHRU_MSG fields are correct
ERR_FAILED
Undefined error
Internal error of the library or the adapter
Solution: call PassThruGetLastError() for a description
READ_VBATT — Read the supply voltage
Returns the voltage on the OBD-II connector (pin 16). The value is in millivolts; to get volts, divide it by 1000. The command does not require an open channel and can be run right after PassThruOpen.
pInput
NULL
pOutput
unsigned long* — voltage in mV
C/C++ example
#include "j2534_dll.hpp"
unsigned long DeviceID; // Obtained from PassThruOpen
unsigned long voltage;
long ret;
ret = PassThruIoctl(DeviceID, READ_VBATT, NULL, &voltage);
if (ret == STATUS_NOERROR)
{
printf("Voltage: %.2f V\n", voltage / 1000.0);
}
Kotlin example (Android)
// deviceID obtained earlier from ptOpen
val result = j2534.ptIoctl(deviceID, READ_VBATT, 0, null)
if (result.status == STATUS_NOERROR) {
val voltageV = result.outputValue / 1000.0
Log.i("J2534", "Voltage: ${"%.2f".format(voltageV)} V")
}
Python example
from ctypes import *
voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_VBATT, None, byref(voltage))
if ret == 0: # STATUS_NOERROR
print(f"Voltage: {voltage.value / 1000:.2f} V")
C# example
uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_VBATT, IntPtr.Zero, out voltage);
if (ret == 0)
{
Console.WriteLine($"Voltage: {voltage / 1000.0:F2} V");
}
READ_PROG_VOLTAGE — Read the programming voltage
Returns the current voltage on the programming output. The value is in millivolts, rounded to the nearest tenth of a volt.
pInput
NULL
pOutput
unsigned long* — voltage in mV
C/C++ example
#include "j2534_dll.hpp"
unsigned long DeviceID;
unsigned long voltage;
long ret;
ret = PassThruIoctl(DeviceID, READ_PROG_VOLTAGE, NULL, &voltage);
if (ret == STATUS_NOERROR)
{
printf("Programming voltage: %.2f V\n", voltage / 1000.0);
}
Kotlin example (Android)
val result = j2534.ptIoctl(deviceID, READ_PROG_VOLTAGE, 0, null)
if (result.status == STATUS_NOERROR) {
val voltageV = result.outputValue / 1000.0
Log.i("J2534", "Programming voltage: ${"%.2f".format(voltageV)} V")
}
Python example
from ctypes import *
voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_PROG_VOLTAGE, None, byref(voltage))
if ret == 0:
print(f"Programming voltage: {voltage.value / 1000:.2f} V")
C# example
uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_PROG_VOLTAGE, IntPtr.Zero, out voltage);
if (ret == 0)
{
Console.WriteLine($"Programming voltage: {voltage / 1000.0:F2} V");
}
FIVE_BAUD_INIT — 5-baud initialization
Starts the slow (5-baud) initialization for the ISO 9141 and ISO 14230 (K-Line) protocols. Receives the KeyWord from the ECU. The initialization mode is set with the FIVE_BAUD_MOD parameter via SET_CONFIG. The baud rate is determined automatically.
pInput
SBYTE_ARRAY* — initialization address (1 byte)
pOutput
SBYTE_ARRAY* — KeyWord (2 bytes)
The FIVE_BAUD_MOD parameter defines the initialization mode: ISO9141-2/ISO14230-4 (0), KB2 inversion (1), address inversion (2), ISO9141 without inversion (3).
// channelID obtained from ptConnect for ISO14230
val initAddress = byteArrayOf(0x33) // Initialization address
val result = j2534.ptFiveBaudInit(channelID, initAddress)
if (result.status == STATUS_NOERROR) {
val keyWord = result.keyWord
Log.i("J2534", "KeyWord: ${keyWord[0].toHex()} ${keyWord[1].toHex()}")
}
var inputMsg = new SBYTE_ARRAY {
NumOfBytes = 1,
BytePtr = new byte[] { 0x33 } // Initialization address
};
var outputMsg = new SBYTE_ARRAY {
NumOfBytes = 2,
BytePtr = new byte[2]
};
int ret = J2534.PassThruIoctl(channelId, FIVE_BAUD_INIT, ref inputMsg, ref outputMsg);
if (ret == 0)
{
Console.WriteLine($"KeyWord: {outputMsg.BytePtr[0]:X2} {outputMsg.BytePtr[1]:X2}");
}
FAST_INIT — Fast initialization
Starts the fast initialization for the ISO 14230 (K-Line) protocol. Sends a StartCommunication request and returns the ECU response. Used for KWP2000.
pInput
PASSTHRU_MSG* — initialization request
pOutput
PASSTHRU_MSG* — ECU response
Important: With a functional (broadcast) address, several ECUs may respond to the request. pOutput will contain only the first response; the rest go into the receive queue.
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID; // Obtained from PassThruConnect
PASSTHRU_MSG InputMsg;
PASSTHRU_MSG OutputMsg;
long ret;
// StartCommunication request
InputMsg.ProtocolID = ISO14230;
InputMsg.TxFlags = 0;
InputMsg.DataSize = 4;
InputMsg.Data[0] = 0x81; // Format: physical address, 1 data byte
InputMsg.Data[1] = 0x10; // Target address (ECU)
InputMsg.Data[2] = 0xF1; // Source address (tester)
InputMsg.Data[3] = 0x81; // SID: StartCommunication
ret = PassThruIoctl(ChannelID, FAST_INIT, &InputMsg, &OutputMsg);
if (ret == STATUS_NOERROR)
{
printf("ECU response: %d bytes\n", OutputMsg.DataSize);
for (int i = 0; i < OutputMsg.DataSize; i++)
printf("%02X ", OutputMsg.Data[i]);
}
Kotlin example (Android)
// channelID obtained from ptConnect for ISO14230
val request = PassThruMsg(
protocolID = ISO14230,
txFlags = 0u,
dataSize = 4,
data = byteArrayOf(0x81.toByte(), 0x10, 0xF1.toByte(), 0x81.toByte())
)
val result = j2534.ptFastInit(channelID, request)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "ECU response: ${result.response.data.toHexString()}")
}
Python example
from ctypes import *
input_msg = PASSTHRU_MSG()
input_msg.ProtocolID = ISO14230
input_msg.TxFlags = 0
input_msg.DataSize = 4
input_msg.Data[0] = 0x81 # Format
input_msg.Data[1] = 0x10 # Target address
input_msg.Data[2] = 0xF1 # Source address
input_msg.Data[3] = 0x81 # SID: StartCommunication
output_msg = PASSTHRU_MSG()
ret = j2534.PassThruIoctl(channel_id, FAST_INIT, byref(input_msg), byref(output_msg))
if ret == 0:
data = bytes(output_msg.Data[:output_msg.DataSize])
print(f"ECU response: {data.hex(' ').upper()}")
C# example
var inputMsg = new PASSTHRU_MSG {
ProtocolID = ISO14230,
TxFlags = 0,
DataSize = 4
};
inputMsg.Data[0] = 0x81; // Format
inputMsg.Data[1] = 0x10; // Target address
inputMsg.Data[2] = 0xF1; // Source address
inputMsg.Data[3] = 0x81; // SID: StartCommunication
var outputMsg = new PASSTHRU_MSG();
int ret = J2534.PassThruIoctl(channelId, FAST_INIT, ref inputMsg, ref outputMsg);
if (ret == 0)
{
var data = new byte[outputMsg.DataSize];
Array.Copy(outputMsg.Data, data, outputMsg.DataSize);
Console.WriteLine($"ECU response: {BitConverter.ToString(data).Replace("-", " ")}");
}
CLEAR_TX_BUFFER — Clear the transmit queue
Removes all messages from the channel's transmit queue. Used to cancel scheduled transmissions.
pInput
NULL
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID;
long ret;
ret = PassThruIoctl(ChannelID, CLEAR_TX_BUFFER, NULL, NULL);
if (ret != STATUS_NOERROR)
{
char error[256];
PassThruGetLastError(error);
printf("Error: %s\n", error);
}
Kotlin example (Android)
val result = j2534.ptIoctl(channelID, CLEAR_TX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "CLEAR_TX_BUFFER error: ${result.status}")
}
Python example
ret = j2534.PassThruIoctl(channel_id, CLEAR_TX_BUFFER, None, None)
if ret != 0:
print(f"CLEAR_TX_BUFFER error: {ret}")
C# example
int ret = J2534.PassThruIoctl(channelId, CLEAR_TX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"CLEAR_TX_BUFFER error: {ret}");
CLEAR_RX_BUFFER — Clear the receive queue
Removes all messages from the channel's receive queue. It is recommended to call it before starting a new diagnostic session.
pInput
NULL
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID;
long ret;
ret = PassThruIoctl(ChannelID, CLEAR_RX_BUFFER, NULL, NULL);
if (ret != STATUS_NOERROR)
{
char error[256];
PassThruGetLastError(error);
printf("Error: %s\n", error);
}
Kotlin example (Android)
val result = j2534.ptIoctl(channelID, CLEAR_RX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "CLEAR_RX_BUFFER error: ${result.status}")
}
Python example
ret = j2534.PassThruIoctl(channel_id, CLEAR_RX_BUFFER, None, None)
if ret != 0:
print(f"CLEAR_RX_BUFFER error: {ret}")
C# example
int ret = J2534.PassThruIoctl(channelId, CLEAR_RX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"CLEAR_RX_BUFFER error: {ret}");
CLEAR_PERIODIC_MSGS — Clear periodic messages
Removes all periodic messages set through PassThruStartPeriodicMsg. Equivalent to calling PassThruStopPeriodicMsg for each message.
pInput
NULL
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID;
long ret;
ret = PassThruIoctl(ChannelID, CLEAR_PERIODIC_MSGS, NULL, NULL);
if (ret != STATUS_NOERROR)
{
char error[256];
PassThruGetLastError(error);
printf("Error: %s\n", error);
}
Kotlin example (Android)
val result = j2534.ptIoctl(channelID, CLEAR_PERIODIC_MSGS, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "CLEAR_PERIODIC_MSGS error: ${result.status}")
}
Python example
ret = j2534.PassThruIoctl(channel_id, CLEAR_PERIODIC_MSGS, None, None)
if ret != 0:
print(f"CLEAR_PERIODIC_MSGS error: {ret}")
C# example
int ret = J2534.PassThruIoctl(channelId, CLEAR_PERIODIC_MSGS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"CLEAR_PERIODIC_MSGS error: {ret}");
CLEAR_MSG_FILTERS — Clear filters
Removes all message filters set through PassThruStartMsgFilter. After the call, all incoming messages are blocked until new filters are set.
pInput
NULL
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID;
long ret;
ret = PassThruIoctl(ChannelID, CLEAR_MSG_FILTERS, NULL, NULL);
if (ret != STATUS_NOERROR)
{
char error[256];
PassThruGetLastError(error);
printf("Error: %s\n", error);
}
Kotlin example (Android)
val result = j2534.ptIoctl(channelID, CLEAR_MSG_FILTERS, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "CLEAR_MSG_FILTERS error: ${result.status}")
}
Python example
ret = j2534.PassThruIoctl(channel_id, CLEAR_MSG_FILTERS, None, None)
if ret != 0:
print(f"CLEAR_MSG_FILTERS error: {ret}")
C# example
int ret = J2534.PassThruIoctl(channelId, CLEAR_MSG_FILTERS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"CLEAR_MSG_FILTERS error: {ret}");
CLEAR_FUNCT_MSG_LOOKUP_TABLE — Clear the functional address table
Clears the J1850 functional address table. Used for the J1850 PWM/VPW protocols when working with functional addressing.
pInput
NULL
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID; // J1850 channel
long ret;
ret = PassThruIoctl(ChannelID, CLEAR_FUNCT_MSG_LOOKUP_TABLE, NULL, NULL);
if (ret != STATUS_NOERROR)
{
// Error handling
}
Python example
ret = j2534.PassThruIoctl(channel_id, CLEAR_FUNCT_MSG_LOOKUP_TABLE, None, None)
C# example
int ret = J2534.PassThruIoctl(channelId, CLEAR_FUNCT_MSG_LOOKUP_TABLE, IntPtr.Zero, IntPtr.Zero);
ADD_TO_FUNCT_MSG_LOOKUP_TABLE — Add a functional address
Adds an address to the J1850 functional address table. Messages with this address will be accepted when functional addressing is used.
pInput
SBYTE_ARRAY* — list of addresses to add
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID;
SBYTE_ARRAY AddrList;
unsigned char addresses[3] = {0x10, 0x18, 0x28}; // ECU addresses
long ret;
AddrList.NumOfBytes = 3;
AddrList.BytePtr = addresses;
ret = PassThruIoctl(ChannelID, ADD_TO_FUNCT_MSG_LOOKUP_TABLE, &AddrList, NULL);
if (ret != STATUS_NOERROR)
{
// Error handling
}
var addrList = new SBYTE_ARRAY {
NumOfBytes = 1,
BytePtr = new byte[] { 0x10 }
};
int ret = J2534.PassThruIoctl(channelId, DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE, ref addrList, IntPtr.Zero);
SW_CAN_HS — SW-CAN high-speed mode
Switches Single-Wire CAN to high-speed mode (83.3 kbit/s). Used for high-speed diagnostics on GM networks.
pInput
NULL
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID; // SW-CAN channel
long ret;
// Switch to high-speed mode
ret = PassThruIoctl(ChannelID, SW_CAN_HS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("SW-CAN in High Speed mode (83.3 kbit/s)\n");
}
Kotlin example (Android)
val result = j2534.ptIoctl(channelID, SW_CAN_HS, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "SW-CAN in High Speed mode (83.3 kbit/s)")
}
Python example
ret = j2534.PassThruIoctl(channel_id, SW_CAN_HS, None, None)
if ret == 0:
print("SW-CAN in High Speed mode (83.3 kbit/s)")
C# example
int ret = J2534.PassThruIoctl(channelId, SW_CAN_HS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("SW-CAN in High Speed mode (83.3 kbit/s)");
SW_CAN_NS — SW-CAN normal mode
Switches Single-Wire CAN to normal mode (33.3 kbit/s). This is the default mode for GM networks.
pInput
NULL
pOutput
NULL
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID; // SW-CAN channel
long ret;
// Switch to normal mode
ret = PassThruIoctl(ChannelID, SW_CAN_NS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("SW-CAN in Normal Speed mode (33.3 kbit/s)\n");
}
Kotlin example (Android)
val result = j2534.ptIoctl(channelID, SW_CAN_NS, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "SW-CAN in Normal Speed mode (33.3 kbit/s)")
}
Python example
ret = j2534.PassThruIoctl(channel_id, SW_CAN_NS, None, None)
if ret == 0:
print("SW-CAN in Normal Speed mode (33.3 kbit/s)")
C# example
int ret = J2534.PassThruIoctl(channelId, SW_CAN_NS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("SW-CAN in Normal Speed mode (33.3 kbit/s)");
BUS_ON — Connect the controller to the bus v5.0
Connects the CAN controller to the physical bus. Used after the controller has been disconnected from the bus via PassThruDisconnect with the CAN_DISCONNECT flag, or after opening the channel without automatic connection.
IoctlID
0x0F
pInput
NULL
pOutput
NULL
This command is available only in J2534 v5.00. In v04.04, the controller connects to the bus automatically during PassThruConnect.
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID; // CAN channel
long ret;
// Connect the controller to the bus
ret = PassThruIoctl(ChannelID, BUS_ON, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("CAN controller connected to the bus\n");
}
Kotlin example (Android)
val result = j2534.ptIoctl(channelID, BUS_ON, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "CAN controller connected to the bus")
}
Python example
ret = j2534.PassThruIoctl(channel_id, BUS_ON, None, None)
if ret == 0:
print("CAN controller connected to the bus")
C# example
int ret = J2534.PassThruIoctl(channelId, BUS_ON, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("CAN controller connected to the bus");
REQUEST_CONNECTION — Establish a TP 2.0 connection J2534-2
Requests the establishment of a TP 2.0 channel and connection between the adapter and the ECU. Used for the TP 2.0 protocol (VAG). The command is non-blocking — the connection result arrives as an indication in the receive queue.
IoctlID
0x800A
pInput
SBYTE_ARRAY* — connection request data (11 bytes)
pOutput
NULL
Data structure (11 bytes)
BytePtr[0-3]
CAN ID (identifier), BytePtr[0] is the most significant byte
BytePtr[4]
Destination — the destination address (ECU)
BytePtr[5]
Opcode — always 0xC0
BytePtr[6-7]
TX-ID-A — CAN ID for transmission
BytePtr[8-9]
RX-ID-A — CAN ID for reception
BytePtr[10]
Application Type — the application type
On a successful connection, an implicit PASS filter is created for RX-ID-A. A CONNECTION_ESTABLISHED indication is placed in the receive queue. On error — CONNECTION_LOST.
If RX-ID-A is already in use by another channel, ERR_NOT_UNIQUE is returned. If NumOfBytes ≠ 11, ERR_INVALID_IOCTL_VALUE is returned.
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID; // TP 2.0 channel
SBYTE_ARRAY InputData;
unsigned char data[11];
long ret;
// CAN ID for broadcast: 0x200
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x02;
data[3] = 0x00;
// Destination (ECU address, e.g. 0x01 for the engine)
data[4] = 0x01;
// Opcode (always 0xC0)
data[5] = 0xC0;
// TX-ID-A (CAN ID for transmission, e.g. 0x300)
data[6] = 0x03;
data[7] = 0x00;
// RX-ID-A (CAN ID for reception, e.g. 0x301)
data[8] = 0x03;
data[9] = 0x01;
// Application Type (0x01 for diagnostics)
data[10] = 0x01;
InputData.NumOfBytes = 11;
InputData.BytePtr = data;
ret = PassThruIoctl(ChannelID, REQUEST_CONNECTION, &InputData, NULL);
if (ret == STATUS_NOERROR)
{
printf("Connection request sent, waiting for CONNECTION_ESTABLISHED\n");
}
else if (ret == ERR_NOT_UNIQUE)
{
printf("RX-ID-A is already in use by another channel\n");
}
Kotlin example (Android)
// channelID — TP 2.0 channel
val data = byteArrayOf(
0x00, 0x00, 0x02, 0x00, // CAN ID: 0x200
0x01, // Destination: ECU 0x01
0xC0.toByte(), // Opcode
0x03, 0x00, // TX-ID-A: 0x300
0x03, 0x01, // RX-ID-A: 0x301
0x01 // Application Type
)
val result = j2534.ptIoctl(channelID, REQUEST_CONNECTION, data.size, data)
when (result.status) {
STATUS_NOERROR -> Log.i("TP2.0", "Connection request sent")
ERR_NOT_UNIQUE -> Log.e("TP2.0", "RX-ID-A is already in use")
else -> Log.e("TP2.0", "Error: ${result.status}")
}
Python example
from ctypes import *
data = (c_ubyte * 11)(
0x00, 0x00, 0x02, 0x00, # CAN ID: 0x200
0x01, # Destination: ECU 0x01
0xC0, # Opcode
0x03, 0x00, # TX-ID-A: 0x300
0x03, 0x01, # RX-ID-A: 0x301
0x01 # Application Type
)
input_data = SBYTE_ARRAY()
input_data.NumOfBytes = 11
input_data.BytePtr = data
ret = j2534.PassThruIoctl(channel_id, REQUEST_CONNECTION, byref(input_data), None)
if ret == 0:
print("Connection request sent, waiting for CONNECTION_ESTABLISHED")
elif ret == ERR_NOT_UNIQUE:
print("RX-ID-A is already in use by another channel")
C# example
var data = new byte[] {
0x00, 0x00, 0x02, 0x00, // CAN ID: 0x200
0x01, // Destination: ECU 0x01
0xC0, // Opcode
0x03, 0x00, // TX-ID-A: 0x300
0x03, 0x01, // RX-ID-A: 0x301
0x01 // Application Type
};
var inputData = new SBYTE_ARRAY {
NumOfBytes = 11,
BytePtr = data
};
int ret = J2534.PassThruIoctl(channelId, REQUEST_CONNECTION, ref inputData, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("Connection request sent, waiting for CONNECTION_ESTABLISHED");
else if (ret == ERR_NOT_UNIQUE)
Console.WriteLine("RX-ID-A is already in use by another channel");
TEARDOWN_CONNECTION — Tear down a TP 2.0 connection J2534-2
Tears down an established TP 2.0 connection between the adapter and the ECU. The command is non-blocking — confirmation of the teardown arrives as a CONNECTION_LOST indication in the receive queue.
IoctlID
0x800B
pInput
SBYTE_ARRAY* — receive CAN ID (4 bytes)
pOutput
NULL
Data structure (4 bytes)
BytePtr[0-3]
RX-ID-A — CAN ID for reception (the same as in REQUEST_CONNECTION), BytePtr[0] is the most significant byte
After the connection is torn down, the implicit PASS filter for RX-ID-A is removed. Filters set through PassThruStartMsgFilter remain active.
C/C++ example
#include "j2534_dll.hpp"
unsigned long ChannelID; // TP 2.0 channel
SBYTE_ARRAY InputData;
unsigned char data[4];
long ret;
// RX-ID-A (the same as in REQUEST_CONNECTION)
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x03;
data[3] = 0x01; // 0x301
InputData.NumOfBytes = 4;
InputData.BytePtr = data;
ret = PassThruIoctl(ChannelID, TEARDOWN_CONNECTION, &InputData, NULL);
if (ret == STATUS_NOERROR)
{
printf("Connection teardown request sent\n");
}
Kotlin example (Android)
// RX-ID-A: 0x301
val data = byteArrayOf(0x00, 0x00, 0x03, 0x01)
val result = j2534.ptIoctl(channelID, TEARDOWN_CONNECTION, data.size, data)
if (result.status == STATUS_NOERROR) {
Log.i("TP2.0", "Connection teardown request sent")
}
Python example
from ctypes import *
# RX-ID-A: 0x301
data = (c_ubyte * 4)(0x00, 0x00, 0x03, 0x01)
input_data = SBYTE_ARRAY()
input_data.NumOfBytes = 4
input_data.BytePtr = data
ret = j2534.PassThruIoctl(channel_id, TEARDOWN_CONNECTION, byref(input_data), None)
if ret == 0:
print("Connection teardown request sent")
C# example
// RX-ID-A: 0x301
var data = new byte[] { 0x00, 0x00, 0x03, 0x01 };
var inputData = new SBYTE_ARRAY {
NumOfBytes = 4,
BytePtr = data
};
int ret = J2534.PassThruIoctl(channelId, TEARDOWN_CONNECTION, ref inputData, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("Connection teardown request sent");