Universelle Funktion zur Steuerung von Gerät und Kanal. Sie führt je nach Parameter IoctlID verschiedene Operationen aus: Lesen/Schreiben der Konfiguration, Initialisierung von Protokollen, Leeren von Puffern und weitere dienstliche Operationen.
long PassThruIoctl(unsigned long ChannelID, unsigned long IoctlID, void *pInput, void *pOutput)
Parameter
unsigned long ChannelID — Kennung des Kanals, die von PassThruConnect zurückgegeben wurde. Für einige Befehle (READ_VBATT, GET_DEVICE_INFO) wird DeviceID verwendet.
unsigned long IoctlID — Kennung der Operation (siehe Tabelle unten).
void* pInput — Zeiger auf die Eingabedaten. Der Typ hängt von IoctlID ab.
void* pOutput — Zeiger auf die Ausgabedaten. Der Typ hängt von IoctlID ab.
Der Adapter ist ausgeschaltet oder außerhalb der Reichweite
Lösung: Prüfen Sie die Stromversorgung des Adapters und die Netzwerkverbindung
ERR_INVALID_CHANNEL_ID
Ungültige Kanal-Kennung
ChannelID wurde nicht über PassThruConnect ermittelt oder der Kanal ist geschlossen
Lösung: Stellen Sie sicher, dass PassThruConnect erfolgreich ausgeführt wurde
ERR_INVALID_IOCTL_ID
Ungültige IoctlID-Kennung
Die angegebene IoctlID wird nicht unterstützt
Lösung: Prüfen Sie die Richtigkeit des IoctlID-Werts
ERR_NULL_PARAMETER
NULL anstelle eines erforderlichen Zeigers übergeben
pInput oder pOutput ist NULL, obwohl ein Zeiger erforderlich ist
Lösung: Übergeben Sie gültige Zeiger
ERR_NOT_SUPPORTED
Operation wird nicht unterstützt
Der Adapter unterstützt die angeforderte Operation nicht
Lösung: Prüfen Sie die Fähigkeiten des Adapters über GET_DEVICE_INFO
ERR_INVALID_IOCTL_VALUE
Unzulässiger Parameterwert
Der Wert in pInput liegt außerhalb des zulässigen Bereichs
Lösung: Prüfen Sie die zulässigen Wertebereiche
ERR_INVALID_MSG
Fehlerhafte Nachrichtenstruktur
Ungültige Struktur in pInput für FAST_INIT
Lösung: Prüfen Sie die Richtigkeit der Felder von PASSTHRU_MSG
ERR_FAILED
Nicht näher bestimmter Fehler
Interner Fehler der Bibliothek oder des Adapters
Lösung: Rufen Sie PassThruGetLastError() für eine Beschreibung auf
READ_VBATT — Lesen der Versorgungsspannung
Gibt die Spannung am OBD-II-Stecker (Pin 16) zurück. Der Wert wird in Millivolt angegeben; zur Umrechnung in Volt durch 1000 teilen. Der Befehl erfordert keinen geöffneten Kanal und kann unmittelbar nach PassThruOpen ausgeführt werden.
pInput
NULL
pOutput
unsigned long* — Spannung in mV
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long DeviceID; // Von PassThruOpen erhalten
unsigned long voltage;
long ret;
ret = PassThruIoctl(DeviceID, READ_VBATT, NULL, &voltage);
if (ret == STATUS_NOERROR)
{
printf("Spannung: %.2f V\n", voltage / 1000.0);
}
Beispiel in Kotlin (Android)
// deviceID zuvor von ptOpen erhalten
val result = j2534.ptIoctl(deviceID, READ_VBATT, 0, null)
if (result.status == STATUS_NOERROR) {
val voltageV = result.outputValue / 1000.0
Log.i("J2534", "Spannung: ${"%.2f".format(voltageV)} V")
}
Beispiel in Python
from ctypes import *
voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_VBATT, None, byref(voltage))
if ret == 0: # STATUS_NOERROR
print(f"Spannung: {voltage.value / 1000:.2f} V")
Beispiel in C#
uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_VBATT, IntPtr.Zero, out voltage);
if (ret == 0)
{
Console.WriteLine($"Spannung: {voltage / 1000.0:F2} V");
}
READ_PROG_VOLTAGE — Lesen der Programmierspannung
Gibt die aktuelle Spannung am Programmierausgang zurück. Der Wert wird in Millivolt angegeben und auf das nächste Zehntel Volt gerundet.
pInput
NULL
pOutput
unsigned long* — Spannung in mV
Beispiel in C/C++
#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("Programmierspannung: %.2f V\n", voltage / 1000.0);
}
Beispiel in Kotlin (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", "Programmierspannung: ${"%.2f".format(voltageV)} V")
}
Beispiel in Python
from ctypes import *
voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_PROG_VOLTAGE, None, byref(voltage))
if ret == 0:
print(f"Programmierspannung: {voltage.value / 1000:.2f} V")
Beispiel in C#
uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_PROG_VOLTAGE, IntPtr.Zero, out voltage);
if (ret == 0)
{
Console.WriteLine($"Programmierspannung: {voltage / 1000.0:F2} V");
}
FIVE_BAUD_INIT — 5-Baud-Initialisierung
Startet die langsame (5-Baud-)Initialisierung für die Protokolle ISO 9141 und ISO 14230 (K-Line). Empfängt das KeyWord vom Steuergerät. Der Initialisierungsmodus wird über den Parameter FIVE_BAUD_MOD mittels SET_CONFIG festgelegt. Die Übertragungsrate wird automatisch ermittelt.
pInput
SBYTE_ARRAY* — Initialisierungsadresse (1 Byte)
pOutput
SBYTE_ARRAY* — KeyWord (2 Byte)
Der Parameter FIVE_BAUD_MOD bestimmt den Initialisierungsmodus: ISO9141-2/ISO14230-4 (0), Inversion von KB2 (1), Inversion der Adresse (2), ISO9141 ohne Inversion (3).
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Von PassThruConnect erhalten
SBYTE_ARRAY InputMsg;
SBYTE_ARRAY OutputMsg;
long ret;
unsigned char initByte[1];
unsigned char keyWord[2];
initByte[0] = 0x33; // Initialisierungsadresse des Steuergeräts
InputMsg.NumOfBytes = 1;
InputMsg.BytePtr = initByte;
OutputMsg.NumOfBytes = 2;
OutputMsg.BytePtr = keyWord;
ret = PassThruIoctl(ChannelID, FIVE_BAUD_INIT, &InputMsg, &OutputMsg);
if (ret == STATUS_NOERROR)
{
printf("KeyWord: %02X %02X\n", keyWord[0], keyWord[1]);
}
Beispiel in Kotlin (Android)
// channelID von ptConnect für ISO14230 erhalten
val initAddress = byteArrayOf(0x33) // Initialisierungsadresse
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 } // Initialisierungsadresse
};
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-Initialisierung
Startet die schnelle Initialisierung für das Protokoll ISO 14230 (K-Line). Sendet eine StartCommunication-Anfrage und gibt die Antwort des Steuergeräts zurück. Wird für KWP2000 verwendet.
pInput
PASSTHRU_MSG* — Initialisierungsanfrage
pOutput
PASSTHRU_MSG* — Antwort des Steuergeräts
Wichtig: Bei einer funktionalen (Broadcast-)Adresse können mehrere Steuergeräte auf die Anfrage antworten. In pOutput steht nur die erste Antwort, die übrigen gelangen in die Empfangswarteschlange.
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Von PassThruConnect erhalten
PASSTHRU_MSG InputMsg;
PASSTHRU_MSG OutputMsg;
long ret;
// StartCommunication-Anfrage
InputMsg.ProtocolID = ISO14230;
InputMsg.TxFlags = 0;
InputMsg.DataSize = 4;
InputMsg.Data[0] = 0x81; // Format: physische Adresse, 1 Byte Daten
InputMsg.Data[1] = 0x10; // Zieladresse (Steuergerät)
InputMsg.Data[2] = 0xF1; // Quelladresse (Tester)
InputMsg.Data[3] = 0x81; // SID: StartCommunication
ret = PassThruIoctl(ChannelID, FAST_INIT, &InputMsg, &OutputMsg);
if (ret == STATUS_NOERROR)
{
printf("Antwort des Steuergeräts: %d Byte\n", OutputMsg.DataSize);
for (int i = 0; i < OutputMsg.DataSize; i++)
printf("%02X ", OutputMsg.Data[i]);
}
Beispiel in Kotlin (Android)
// channelID von ptConnect für ISO14230 erhalten
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", "Antwort des Steuergeräts: ${result.response.data.toHexString()}")
}
Beispiel in Python
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 # Zieladresse
input_msg.Data[2] = 0xF1 # Quelladresse
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"Antwort des Steuergeräts: {data.hex(' ').upper()}")
Beispiel in C#
var inputMsg = new PASSTHRU_MSG {
ProtocolID = ISO14230,
TxFlags = 0,
DataSize = 4
};
inputMsg.Data[0] = 0x81; // Format
inputMsg.Data[1] = 0x10; // Zieladresse
inputMsg.Data[2] = 0xF1; // Quelladresse
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($"Antwort des Steuergeräts: {BitConverter.ToString(data).Replace("-", " ")}");
}
CLEAR_TX_BUFFER — Leeren der Sendewarteschlange
Entfernt alle Nachrichten aus der Sendewarteschlange des Kanals. Wird verwendet, um geplante Sendungen abzubrechen.
pInput
NULL
pOutput
NULL
Beispiel in C/C++
#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("Fehler: %s\n", error);
}
Beispiel in Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_TX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Fehler CLEAR_TX_BUFFER: ${result.status}")
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_TX_BUFFER, None, None)
if ret != 0:
print(f"Fehler CLEAR_TX_BUFFER: {ret}")
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_TX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Fehler CLEAR_TX_BUFFER: {ret}");
CLEAR_RX_BUFFER — Leeren der Empfangswarteschlange
Entfernt alle Nachrichten aus der Empfangswarteschlange des Kanals. Es wird empfohlen, diesen Befehl vor Beginn einer neuen Diagnosesitzung aufzurufen.
pInput
NULL
pOutput
NULL
Beispiel in C/C++
#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("Fehler: %s\n", error);
}
Beispiel in Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_RX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Fehler CLEAR_RX_BUFFER: ${result.status}")
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_RX_BUFFER, None, None)
if ret != 0:
print(f"Fehler CLEAR_RX_BUFFER: {ret}")
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_RX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Fehler CLEAR_RX_BUFFER: {ret}");
CLEAR_PERIODIC_MSGS — Löschen der periodischen Nachrichten
Entfernt alle periodischen Nachrichten, die über PassThruStartPeriodicMsg eingerichtet wurden. Entspricht dem Aufruf von PassThruStopPeriodicMsg für jede einzelne Nachricht.
pInput
NULL
pOutput
NULL
Beispiel in C/C++
#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("Fehler: %s\n", error);
}
Beispiel in Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_PERIODIC_MSGS, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Fehler CLEAR_PERIODIC_MSGS: ${result.status}")
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_PERIODIC_MSGS, None, None)
if ret != 0:
print(f"Fehler CLEAR_PERIODIC_MSGS: {ret}")
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_PERIODIC_MSGS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Fehler CLEAR_PERIODIC_MSGS: {ret}");
CLEAR_MSG_FILTERS — Löschen der Filter
Entfernt alle Nachrichtenfilter, die über PassThruStartMsgFilter eingerichtet wurden. Nach dem Aufruf werden alle eingehenden Nachrichten blockiert, bis neue Filter eingerichtet werden.
pInput
NULL
pOutput
NULL
Beispiel in C/C++
#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("Fehler: %s\n", error);
}
Beispiel in Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_MSG_FILTERS, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Fehler CLEAR_MSG_FILTERS: ${result.status}")
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_MSG_FILTERS, None, None)
if ret != 0:
print(f"Fehler CLEAR_MSG_FILTERS: {ret}")
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_MSG_FILTERS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Fehler CLEAR_MSG_FILTERS: {ret}");
CLEAR_FUNCT_MSG_LOOKUP_TABLE — Leeren der Tabelle der funktionalen Adressen
Leert die Tabelle der funktionalen Adressen für J1850. Wird bei den Protokollen J1850 PWM/VPW verwendet, wenn mit funktionaler Adressierung gearbeitet wird.
pInput
NULL
pOutput
NULL
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // J1850-Kanal
long ret;
ret = PassThruIoctl(ChannelID, CLEAR_FUNCT_MSG_LOOKUP_TABLE, NULL, NULL);
if (ret != STATUS_NOERROR)
{
// Fehlerbehandlung
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_FUNCT_MSG_LOOKUP_TABLE, None, None)
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_FUNCT_MSG_LOOKUP_TABLE, IntPtr.Zero, IntPtr.Zero);
ADD_TO_FUNCT_MSG_LOOKUP_TABLE — Hinzufügen einer funktionalen Adresse
Fügt eine Adresse zur Tabelle der funktionalen Adressen für J1850 hinzu. Nachrichten mit dieser Adresse werden bei Verwendung der funktionalen Adressierung empfangen.
pInput
SBYTE_ARRAY* — Liste der hinzuzufügenden Adressen
pOutput
NULL
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID;
SBYTE_ARRAY AddrList;
unsigned char addresses[3] = {0x10, 0x18, 0x28}; // ECU-Adressen
long ret;
AddrList.NumOfBytes = 3;
AddrList.BytePtr = addresses;
ret = PassThruIoctl(ChannelID, ADD_TO_FUNCT_MSG_LOOKUP_TABLE, &AddrList, NULL);
if (ret != STATUS_NOERROR)
{
// Fehlerbehandlung
}
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 — Hochgeschwindigkeitsmodus SW-CAN
Schaltet Single-Wire CAN in den Hochgeschwindigkeitsmodus (83,3 kbit/s) um. Wird für die Diagnose mit hoher Geschwindigkeit in GM-Netzwerken verwendet.
pInput
NULL
pOutput
NULL
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // SW-CAN-Kanal
long ret;
// Umschalten in den Hochgeschwindigkeitsmodus
ret = PassThruIoctl(ChannelID, SW_CAN_HS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("SW-CAN im High-Speed-Modus (83.3 kbit/s)\n");
}
Beispiel in Kotlin (Android)
val result = j2534.ptIoctl(channelID, SW_CAN_HS, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "SW-CAN im High-Speed-Modus (83.3 kbit/s)")
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, SW_CAN_HS, None, None)
if ret == 0:
print("SW-CAN im High-Speed-Modus (83.3 kbit/s)")
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, SW_CAN_HS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("SW-CAN im High-Speed-Modus (83.3 kbit/s)");
SW_CAN_NS — Normalmodus SW-CAN
Schaltet Single-Wire CAN in den Normalmodus (33,3 kbit/s) um. Dies ist der Standardmodus für GM-Netzwerke.
pInput
NULL
pOutput
NULL
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // SW-CAN-Kanal
long ret;
// Umschalten in den Normalmodus
ret = PassThruIoctl(ChannelID, SW_CAN_NS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("SW-CAN im Normal-Speed-Modus (33.3 kbit/s)\n");
}
Beispiel in Kotlin (Android)
val result = j2534.ptIoctl(channelID, SW_CAN_NS, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "SW-CAN im Normal-Speed-Modus (33.3 kbit/s)")
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, SW_CAN_NS, None, None)
if ret == 0:
print("SW-CAN im Normal-Speed-Modus (33.3 kbit/s)")
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, SW_CAN_NS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("SW-CAN im Normal-Speed-Modus (33.3 kbit/s)");
BUS_ON — Anschließen des Controllers an den Bus v5.0
Schließt den CAN-Controller an den physischen Bus an. Wird verwendet, nachdem der Controller über PassThruDisconnect mit dem Flag CAN_DISCONNECT vom Bus getrennt wurde oder nachdem ein Kanal ohne automatisches Anschließen geöffnet wurde.
IoctlID
0x0F
pInput
NULL
pOutput
NULL
Dieser Befehl ist nur in J2534 v5.00 verfügbar. In v04.04 wird der Controller bei PassThruConnect automatisch an den Bus angeschlossen.
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // CAN-Kanal
long ret;
// Anschließen des Controllers an den Bus
ret = PassThruIoctl(ChannelID, BUS_ON, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("CAN-Controller an den Bus angeschlossen\n");
}
Beispiel in Kotlin (Android)
val result = j2534.ptIoctl(channelID, BUS_ON, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "CAN-Controller an den Bus angeschlossen")
}
Beispiel in Python
ret = j2534.PassThruIoctl(channel_id, BUS_ON, None, None)
if ret == 0:
print("CAN-Controller an den Bus angeschlossen")
Beispiel in C#
int ret = J2534.PassThruIoctl(channelId, BUS_ON, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("CAN-Controller an den Bus angeschlossen");
REQUEST_CONNECTION — Aufbau einer TP-2.0-Verbindung J2534-2
Fordert den Aufbau eines Kanals und einer TP-2.0-Verbindung zwischen Adapter und Steuergerät an. Wird für das Protokoll TP 2.0 (VAG) verwendet. Der Befehl ist nicht blockierend — das Ergebnis der Verbindung trifft als Indikation in der Empfangswarteschlange ein.
IoctlID
0x800A
pInput
SBYTE_ARRAY* — Daten der Verbindungsanfrage (11 Byte)
pOutput
NULL
Datenstruktur (11 Byte)
BytePtr[0-3]
CAN ID (Kennung), BytePtr[0] — höchstwertiges Byte
BytePtr[4]
Destination — Zieladresse (ECU)
BytePtr[5]
Opcode — immer 0xC0
BytePtr[6-7]
TX-ID-A — CAN ID für die Übertragung
BytePtr[8-9]
RX-ID-A — CAN ID für den Empfang
BytePtr[10]
Application Type — Anwendungstyp
Bei erfolgreicher Verbindung wird ein impliziter PASS-Filter für RX-ID-A erstellt. In die Empfangswarteschlange wird die Indikation CONNECTION_ESTABLISHED eingestellt. Bei einem Fehler — CONNECTION_LOST.
Wird RX-ID-A bereits von einem anderen Kanal verwendet, wird ERR_NOT_UNIQUE zurückgegeben. Ist NumOfBytes ≠ 11, wird ERR_INVALID_IOCTL_VALUE zurückgegeben.
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // TP-2.0-Kanal
SBYTE_ARRAY InputData;
unsigned char data[11];
long ret;
// CAN ID für Broadcast: 0x200
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x02;
data[3] = 0x00;
// Destination (ECU-Adresse, z. B. 0x01 für den Motor)
data[4] = 0x01;
// Opcode (immer 0xC0)
data[5] = 0xC0;
// TX-ID-A (CAN ID für die Übertragung, z. B. 0x300)
data[6] = 0x03;
data[7] = 0x00;
// RX-ID-A (CAN ID für den Empfang, z. B. 0x301)
data[8] = 0x03;
data[9] = 0x01;
// Application Type (0x01 für Diagnose)
data[10] = 0x01;
InputData.NumOfBytes = 11;
InputData.BytePtr = data;
ret = PassThruIoctl(ChannelID, REQUEST_CONNECTION, &InputData, NULL);
if (ret == STATUS_NOERROR)
{
printf("Verbindungsanfrage gesendet, warte auf CONNECTION_ESTABLISHED\n");
}
else if (ret == ERR_NOT_UNIQUE)
{
printf("RX-ID-A wird bereits von einem anderen Kanal verwendet\n");
}
Beispiel in Kotlin (Android)
// channelID — TP-2.0-Kanal
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", "Verbindungsanfrage gesendet")
ERR_NOT_UNIQUE -> Log.e("TP2.0", "RX-ID-A wird bereits verwendet")
else -> Log.e("TP2.0", "Fehler: ${result.status}")
}
Beispiel in Python
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("Verbindungsanfrage gesendet, warte auf CONNECTION_ESTABLISHED")
elif ret == ERR_NOT_UNIQUE:
print("RX-ID-A wird bereits von einem anderen Kanal verwendet")
Beispiel in C#
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("Verbindungsanfrage gesendet, warte auf CONNECTION_ESTABLISHED");
else if (ret == ERR_NOT_UNIQUE)
Console.WriteLine("RX-ID-A wird bereits von einem anderen Kanal verwendet");
TEARDOWN_CONNECTION — Trennen einer TP-2.0-Verbindung J2534-2
Trennt eine bestehende TP-2.0-Verbindung zwischen Adapter und Steuergerät. Der Befehl ist nicht blockierend — die Bestätigung der Trennung trifft als Indikation CONNECTION_LOST in der Empfangswarteschlange ein.
IoctlID
0x800B
pInput
SBYTE_ARRAY* — CAN ID für den Empfang (4 Byte)
pOutput
NULL
Datenstruktur (4 Byte)
BytePtr[0-3]
RX-ID-A — CAN ID für den Empfang (dieselbe wie in REQUEST_CONNECTION), BytePtr[0] — höchstwertiges Byte
Nach dem Trennen der Verbindung wird der implizite PASS-Filter für RX-ID-A entfernt. Über PassThruStartMsgFilter eingerichtete Filter bleiben aktiv.
Beispiel in C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // TP-2.0-Kanal
SBYTE_ARRAY InputData;
unsigned char data[4];
long ret;
// RX-ID-A (dieselbe wie 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("Anfrage zum Trennen der Verbindung gesendet\n");
}
Beispiel in Kotlin (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", "Anfrage zum Trennen der Verbindung gesendet")
}
Beispiel in Python
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("Anfrage zum Trennen der Verbindung gesendet")
Beispiel in C#
// 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("Anfrage zum Trennen der Verbindung gesendet");