Función universal de gestión del dispositivo y del canal. Ejecuta diferentes operaciones según el parámetro IoctlID: lectura/escritura de la configuración, inicialización de protocolos, vaciado de búferes y otras operaciones de servicio.
long PassThruIoctl(unsigned long ChannelID, unsigned long IoctlID, void *pInput, void *pOutput)
Parámetros
unsigned long ChannelID — identificador del canal obtenido de PassThruConnect. Para algunos comandos (READ_VBATT, GET_DEVICE_INFO) se utiliza DeviceID.
unsigned long IoctlID — identificador de la operación (véase la tabla siguiente).
void* pInput — puntero a los datos de entrada. El tipo depende de IoctlID.
void* pOutput — puntero a los datos de salida. El tipo depende de IoctlID.
Solución: compruebe la alimentación del adaptador y la conexión de red
ERR_INVALID_CHANNEL_ID
Identificador de canal no válido
El ChannelID no se obtuvo mediante PassThruConnect o el canal está cerrado
Solución: asegúrese de que PassThruConnect se haya ejecutado correctamente
ERR_INVALID_IOCTL_ID
Identificador IoctlID no válido
El IoctlID indicado no es compatible
Solución: compruebe que el valor de IoctlID sea correcto
ERR_NULL_PARAMETER
Se ha pasado NULL en lugar de un puntero obligatorio
pInput o pOutput es igual a NULL cuando se requiere un puntero
Solución: pase punteros correctos
ERR_NOT_SUPPORTED
Operación no compatible
El adaptador no admite la operación solicitada
Solución: compruebe las capacidades del adaptador mediante GET_DEVICE_INFO
ERR_INVALID_IOCTL_VALUE
Valor de parámetro no admitido
El valor de pInput está fuera de los límites permitidos
Solución: compruebe los rangos de valores admitidos
ERR_INVALID_MSG
Estructura de mensaje incorrecta
Estructura incorrecta en pInput para FAST_INIT
Solución: compruebe que los campos de PASSTHRU_MSG sean correctos
ERR_FAILED
Error indeterminado
Error interno de la biblioteca o del adaptador
Solución: llame a PassThruGetLastError() para obtener la descripción
READ_VBATT — Lectura de la tensión de alimentación
Devuelve la tensión en el conector OBD-II (pin 16). El valor se da en milivoltios; para obtener voltios, divídalo entre 1000. El comando no requiere un canal abierto y puede ejecutarse inmediatamente después de PassThruOpen.
pInput
NULL
pOutput
unsigned long* — tensión en mV
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long DeviceID; // Obtenido de PassThruOpen
unsigned long voltage;
long ret;
ret = PassThruIoctl(DeviceID, READ_VBATT, NULL, &voltage);
if (ret == STATUS_NOERROR)
{
printf("Tensión: %.2f V\n", voltage / 1000.0);
}
Ejemplo en Kotlin (Android)
// deviceID obtenido previamente de ptOpen
val result = j2534.ptIoctl(deviceID, READ_VBATT, 0, null)
if (result.status == STATUS_NOERROR) {
val voltageV = result.outputValue / 1000.0
Log.i("J2534", "Tensión: ${"%.2f".format(voltageV)} V")
}
Ejemplo en Python
from ctypes import *
voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_VBATT, None, byref(voltage))
if ret == 0: # STATUS_NOERROR
print(f"Tensión: {voltage.value / 1000:.2f} V")
Ejemplo en C#
uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_VBATT, IntPtr.Zero, out voltage);
if (ret == 0)
{
Console.WriteLine($"Tensión: {voltage / 1000.0:F2} V");
}
READ_PROG_VOLTAGE — Lectura de la tensión de programación
Devuelve la tensión actual en la salida de programación. El valor se da en milivoltios, redondeado a la décima de voltio más cercana.
pInput
NULL
pOutput
unsigned long* — tensión en mV
Ejemplo en 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("Tensión de programación: %.2f V\n", voltage / 1000.0);
}
Ejemplo en 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", "Tensión de programación: ${"%.2f".format(voltageV)} V")
}
Ejemplo en Python
from ctypes import *
voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_PROG_VOLTAGE, None, byref(voltage))
if ret == 0:
print(f"Tensión de programación: {voltage.value / 1000:.2f} V")
Ejemplo en C#
uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_PROG_VOLTAGE, IntPtr.Zero, out voltage);
if (ret == 0)
{
Console.WriteLine($"Tensión de programación: {voltage / 1000.0:F2} V");
}
FIVE_BAUD_INIT — Inicialización a 5 baudios
Inicia la inicialización lenta (5 baudios) para los protocolos ISO 9141 e ISO 14230 (K-Line). Recibe el KeyWord de la ECU. El modo de inicialización se establece con el parámetro FIVE_BAUD_MOD mediante SET_CONFIG. La velocidad de transmisión se determina automáticamente.
pInput
SBYTE_ARRAY* — dirección de inicialización (1 byte)
pOutput
SBYTE_ARRAY* — KeyWord (2 bytes)
El parámetro FIVE_BAUD_MOD determina el modo de inicialización: ISO9141-2/ISO14230-4 (0), inversión de KB2 (1), inversión de la dirección (2), ISO9141 sin inversión (3).
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Obtenido de PassThruConnect
SBYTE_ARRAY InputMsg;
SBYTE_ARRAY OutputMsg;
long ret;
unsigned char initByte[1];
unsigned char keyWord[2];
initByte[0] = 0x33; // Dirección de inicialización de la ECU
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]);
}
Ejemplo en Kotlin (Android)
// channelID obtenido de ptConnect para ISO14230
val initAddress = byteArrayOf(0x33) // Dirección de inicialización
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 } // Dirección de inicialización
};
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 — Inicialización Fast
Inicia la inicialización rápida para el protocolo ISO 14230 (K-Line). Envía la solicitud StartCommunication y devuelve la respuesta de la ECU. Se utiliza para KWP2000.
pInput
PASSTHRU_MSG* — solicitud de inicialización
pOutput
PASSTHRU_MSG* — respuesta de la ECU
Importante: Con una dirección funcional (de difusión), varias ECU pueden responder a la solicitud. En pOutput solo estará la primera respuesta; las demás se colocarán en la cola de recepción.
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Obtenido de PassThruConnect
PASSTHRU_MSG InputMsg;
PASSTHRU_MSG OutputMsg;
long ret;
// Solicitud StartCommunication
InputMsg.ProtocolID = ISO14230;
InputMsg.TxFlags = 0;
InputMsg.DataSize = 4;
InputMsg.Data[0] = 0x81; // Formato: dirección física, 1 byte de datos
InputMsg.Data[1] = 0x10; // Dirección de destino (ECU)
InputMsg.Data[2] = 0xF1; // Dirección de origen (tester)
InputMsg.Data[3] = 0x81; // SID: StartCommunication
ret = PassThruIoctl(ChannelID, FAST_INIT, &InputMsg, &OutputMsg);
if (ret == STATUS_NOERROR)
{
printf("Respuesta de la ECU: %d bytes\n", OutputMsg.DataSize);
for (int i = 0; i < OutputMsg.DataSize; i++)
printf("%02X ", OutputMsg.Data[i]);
}
Ejemplo en Kotlin (Android)
// channelID obtenido de ptConnect para 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", "Respuesta de la ECU: ${result.response.data.toHexString()}")
}
Ejemplo en 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 # Formato
input_msg.Data[1] = 0x10 # Dirección de destino
input_msg.Data[2] = 0xF1 # Dirección de origen
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"Respuesta de la ECU: {data.hex(' ').upper()}")
Ejemplo en C#
var inputMsg = new PASSTHRU_MSG {
ProtocolID = ISO14230,
TxFlags = 0,
DataSize = 4
};
inputMsg.Data[0] = 0x81; // Formato
inputMsg.Data[1] = 0x10; // Dirección de destino
inputMsg.Data[2] = 0xF1; // Dirección de origen
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($"Respuesta de la ECU: {BitConverter.ToString(data).Replace("-", " ")}");
}
CLEAR_TX_BUFFER — Vaciado de la cola de transmisión
Elimina todos los mensajes de la cola de transmisión del canal. Se utiliza para cancelar las transmisiones programadas.
pInput
NULL
pOutput
NULL
Ejemplo en 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("Error: %s\n", error);
}
Ejemplo en Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_TX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Error CLEAR_TX_BUFFER: ${result.status}")
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_TX_BUFFER, None, None)
if ret != 0:
print(f"Error CLEAR_TX_BUFFER: {ret}")
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_TX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Error CLEAR_TX_BUFFER: {ret}");
CLEAR_RX_BUFFER — Vaciado de la cola de recepción
Elimina todos los mensajes de la cola de recepción del canal. Se recomienda invocarlo antes de iniciar una nueva sesión de diagnóstico.
pInput
NULL
pOutput
NULL
Ejemplo en 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("Error: %s\n", error);
}
Ejemplo en Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_RX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Error CLEAR_RX_BUFFER: ${result.status}")
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_RX_BUFFER, None, None)
if ret != 0:
print(f"Error CLEAR_RX_BUFFER: {ret}")
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_RX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Error CLEAR_RX_BUFFER: {ret}");
CLEAR_PERIODIC_MSGS — Vaciado de los mensajes periódicos
Elimina todos los mensajes periódicos establecidos mediante PassThruStartPeriodicMsg. Equivale a llamar a PassThruStopPeriodicMsg para cada mensaje.
pInput
NULL
pOutput
NULL
Ejemplo en 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("Error: %s\n", error);
}
Ejemplo en Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_PERIODIC_MSGS, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Error CLEAR_PERIODIC_MSGS: ${result.status}")
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_PERIODIC_MSGS, None, None)
if ret != 0:
print(f"Error CLEAR_PERIODIC_MSGS: {ret}")
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_PERIODIC_MSGS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Error CLEAR_PERIODIC_MSGS: {ret}");
CLEAR_MSG_FILTERS — Vaciado de filtros
Elimina todos los filtros de mensajes establecidos mediante PassThruStartMsgFilter. Tras la invocación, todos los mensajes entrantes se bloquearán hasta que se establezcan nuevos filtros.
pInput
NULL
pOutput
NULL
Ejemplo en 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("Error: %s\n", error);
}
Ejemplo en Kotlin (Android)
val result = j2534.ptIoctl(channelID, CLEAR_MSG_FILTERS, 0, null)
if (result.status != STATUS_NOERROR) {
Log.e("J2534", "Error CLEAR_MSG_FILTERS: ${result.status}")
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_MSG_FILTERS, None, None)
if ret != 0:
print(f"Error CLEAR_MSG_FILTERS: {ret}")
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_MSG_FILTERS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
Console.WriteLine($"Error CLEAR_MSG_FILTERS: {ret}");
CLEAR_FUNCT_MSG_LOOKUP_TABLE — Vaciado de la tabla de direcciones funcionales
Vacía la tabla de direcciones funcionales J1850. Se utiliza para los protocolos J1850 PWM/VPW al trabajar con direccionamiento funcional.
pInput
NULL
pOutput
NULL
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Canal J1850
long ret;
ret = PassThruIoctl(ChannelID, CLEAR_FUNCT_MSG_LOOKUP_TABLE, NULL, NULL);
if (ret != STATUS_NOERROR)
{
// Tratamiento del error
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, CLEAR_FUNCT_MSG_LOOKUP_TABLE, None, None)
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, CLEAR_FUNCT_MSG_LOOKUP_TABLE, IntPtr.Zero, IntPtr.Zero);
ADD_TO_FUNCT_MSG_LOOKUP_TABLE — Adición de una dirección funcional
Añade una dirección a la tabla de direcciones funcionales J1850. Los mensajes con esta dirección se recibirán al utilizar el direccionamiento funcional.
pInput
SBYTE_ARRAY* — lista de direcciones a añadir
pOutput
NULL
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID;
SBYTE_ARRAY AddrList;
unsigned char addresses[3] = {0x10, 0x18, 0x28}; // Direcciones de ECU
long ret;
AddrList.NumOfBytes = 3;
AddrList.BytePtr = addresses;
ret = PassThruIoctl(ChannelID, ADD_TO_FUNCT_MSG_LOOKUP_TABLE, &AddrList, NULL);
if (ret != STATUS_NOERROR)
{
// Tratamiento del error
}
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 — Modo de alta velocidad SW-CAN
Conmuta Single-Wire CAN al modo de alta velocidad (83.3 kbit/s). Se utiliza para el diagnóstico a alta velocidad en las redes GM.
pInput
NULL
pOutput
NULL
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Canal SW-CAN
long ret;
// Conmutación al modo de alta velocidad
ret = PassThruIoctl(ChannelID, SW_CAN_HS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("SW-CAN en modo High Speed (83.3 kbit/s)\n");
}
Ejemplo en Kotlin (Android)
val result = j2534.ptIoctl(channelID, SW_CAN_HS, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "SW-CAN en modo High Speed (83.3 kbit/s)")
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, SW_CAN_HS, None, None)
if ret == 0:
print("SW-CAN en modo High Speed (83.3 kbit/s)")
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, SW_CAN_HS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("SW-CAN en modo High Speed (83.3 kbit/s)");
SW_CAN_NS — Modo normal SW-CAN
Conmuta Single-Wire CAN al modo normal (33.3 kbit/s). Es el modo predeterminado para las redes GM.
pInput
NULL
pOutput
NULL
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Canal SW-CAN
long ret;
// Conmutación al modo normal
ret = PassThruIoctl(ChannelID, SW_CAN_NS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("SW-CAN en modo Normal Speed (33.3 kbit/s)\n");
}
Ejemplo en Kotlin (Android)
val result = j2534.ptIoctl(channelID, SW_CAN_NS, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "SW-CAN en modo Normal Speed (33.3 kbit/s)")
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, SW_CAN_NS, None, None)
if ret == 0:
print("SW-CAN en modo Normal Speed (33.3 kbit/s)")
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, SW_CAN_NS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("SW-CAN en modo Normal Speed (33.3 kbit/s)");
BUS_ON — Conexión del controlador al bus v5.0
Conecta el controlador CAN al bus físico. Se utiliza tras desconectar el controlador del bus mediante PassThruDisconnect con la marca CAN_DISCONNECT, o tras abrir el canal sin conexión automática.
IoctlID
0x0F
pInput
NULL
pOutput
NULL
Este comando solo está disponible en J2534 v5.00. En v04.04 el controlador se conecta al bus automáticamente con PassThruConnect.
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Canal CAN
long ret;
// Conexión del controlador al bus
ret = PassThruIoctl(ChannelID, BUS_ON, NULL, NULL);
if (ret == STATUS_NOERROR)
{
printf("Controlador CAN conectado al bus\n");
}
Ejemplo en Kotlin (Android)
val result = j2534.ptIoctl(channelID, BUS_ON, 0, null)
if (result.status == STATUS_NOERROR) {
Log.i("J2534", "Controlador CAN conectado al bus")
}
Ejemplo en Python
ret = j2534.PassThruIoctl(channel_id, BUS_ON, None, None)
if ret == 0:
print("Controlador CAN conectado al bus")
Ejemplo en C#
int ret = J2534.PassThruIoctl(channelId, BUS_ON, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
Console.WriteLine("Controlador CAN conectado al bus");
REQUEST_CONNECTION — Establecimiento de la conexión TP 2.0 J2534-2
Solicita el establecimiento del canal y de la conexión TP 2.0 entre el adaptador y la ECU. Se utiliza para el protocolo TP 2.0 (VAG). El comando es no bloqueante: el resultado de la conexión llega como una indicación a la cola de recepción.
IoctlID
0x800A
pInput
SBYTE_ARRAY* — datos de la solicitud de conexión (11 bytes)
pOutput
NULL
Estructura de datos (11 bytes)
BytePtr[0-3]
CAN ID (identificador), BytePtr[0] — byte más significativo
BytePtr[4]
Destination — dirección de destino (ECU)
BytePtr[5]
Opcode — siempre 0xC0
BytePtr[6-7]
TX-ID-A — CAN ID para la transmisión
BytePtr[8-9]
RX-ID-A — CAN ID para la recepción
BytePtr[10]
Application Type — tipo de aplicación
Con una conexión correcta se crea un filtro PASS implícito para RX-ID-A. En la cola de recepción se coloca la indicación CONNECTION_ESTABLISHED. En caso de error — CONNECTION_LOST.
Si RX-ID-A ya está siendo utilizado por otro canal, se devuelve ERR_NOT_UNIQUE. Si NumOfBytes ≠ 11, se devuelve ERR_INVALID_IOCTL_VALUE.
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Canal TP 2.0
SBYTE_ARRAY InputData;
unsigned char data[11];
long ret;
// CAN ID para broadcast: 0x200
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x02;
data[3] = 0x00;
// Destination (dirección de la ECU, p. ej. 0x01 para el motor)
data[4] = 0x01;
// Opcode (siempre 0xC0)
data[5] = 0xC0;
// TX-ID-A (CAN ID para la transmisión, p. ej. 0x300)
data[6] = 0x03;
data[7] = 0x00;
// RX-ID-A (CAN ID para la recepción, p. ej. 0x301)
data[8] = 0x03;
data[9] = 0x01;
// Application Type (0x01 para diagnóstico)
data[10] = 0x01;
InputData.NumOfBytes = 11;
InputData.BytePtr = data;
ret = PassThruIoctl(ChannelID, REQUEST_CONNECTION, &InputData, NULL);
if (ret == STATUS_NOERROR)
{
printf("Solicitud de conexión enviada, esperando CONNECTION_ESTABLISHED\n");
}
else if (ret == ERR_NOT_UNIQUE)
{
printf("RX-ID-A ya está siendo utilizado por otro canal\n");
}
Ejemplo en Kotlin (Android)
// channelID — canal TP 2.0
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", "Solicitud de conexión enviada")
ERR_NOT_UNIQUE -> Log.e("TP2.0", "RX-ID-A ya está en uso")
else -> Log.e("TP2.0", "Error: ${result.status}")
}
Ejemplo en 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("Solicitud de conexión enviada, esperando CONNECTION_ESTABLISHED")
elif ret == ERR_NOT_UNIQUE:
print("RX-ID-A ya está siendo utilizado por otro canal")
Ejemplo en 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("Solicitud de conexión enviada, esperando CONNECTION_ESTABLISHED");
else if (ret == ERR_NOT_UNIQUE)
Console.WriteLine("RX-ID-A ya está siendo utilizado por otro canal");
TEARDOWN_CONNECTION — Cierre de la conexión TP 2.0 J2534-2
Cierra la conexión TP 2.0 establecida entre el adaptador y la ECU. El comando es no bloqueante: la confirmación del cierre llega como la indicación CONNECTION_LOST a la cola de recepción.
IoctlID
0x800B
pInput
SBYTE_ARRAY* — CAN ID de recepción (4 bytes)
pOutput
NULL
Estructura de datos (4 bytes)
BytePtr[0-3]
RX-ID-A — CAN ID para la recepción (el mismo que en REQUEST_CONNECTION), BytePtr[0] — byte más significativo
Tras cerrar la conexión, el filtro PASS implícito para RX-ID-A se elimina. Los filtros establecidos mediante PassThruStartMsgFilter permanecen activos.
Ejemplo en C/C++
#include "j2534_dll.hpp"
unsigned long ChannelID; // Canal TP 2.0
SBYTE_ARRAY InputData;
unsigned char data[4];
long ret;
// RX-ID-A (el mismo que se usó en 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("Solicitud de cierre de conexión enviada\n");
}
Ejemplo en 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", "Solicitud de cierre de conexión enviada")
}
Ejemplo en 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("Solicitud de cierre de conexión enviada")
Ejemplo en 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("Solicitud de cierre de conexión enviada");