Quantex GmbH
DE RU EN EL
Ваш регион: Европа

PassThruIoctl v4.04 v5.0

Управление вводом-выводом

Последнее изменение:

Описание

Универсальная функция управления устройством и каналом. Выполняет различные операции в зависимости от параметра IoctlID: чтение/запись конфигурации, инициализация протоколов, очистка буферов и другие служебные операции.

long PassThruIoctl(unsigned long ChannelID, unsigned long IoctlID, void *pInput, void *pOutput)

Параметры

IoctlID Значение Описание
GET_CONFIG 0x01 Чтение параметров протокола
SET_CONFIG 0x02 Запись параметров протокола
READ_VBATT 0x03 Чтение напряжения питания
FIVE_BAUD_INIT 0x04 5-бод инициализация K-Line
FAST_INIT 0x05 Fast инициализация K-Line
CLEAR_TX_BUFFER 0x07 Очистка очереди передачи
CLEAR_RX_BUFFER 0x08 Очистка очереди приёма
CLEAR_PERIODIC_MSGS 0x09 Очистка периодических сообщений
CLEAR_MSG_FILTERS 0x0A Очистка всех фильтров
CLEAR_FUNCT_MSG_LOOKUP_TABLE 0x0B Очистка таблицы функциональных адресов
ADD_TO_FUNCT_MSG_LOOKUP_TABLE 0x0C Добавление в таблицу функциональных адресов
DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE 0x0D Удаление из таблицы функциональных адресов
READ_PROG_VOLTAGE 0x0E Чтение напряжения программирования
SW_CAN_HS 0x8000 Переключение SW-CAN в высокоскоростной режим
SW_CAN_NS 0x8001 Переключение SW-CAN в нормальный режим
BUS_ON v5.0 0x0F Подключение контроллера CAN к шине
REQUEST_CONNECTION J2534-2 0x800A Установление TP 2.0 соединения
TEARDOWN_CONNECTION J2534-2 0x800B Разрыв TP 2.0 соединения
GET_DEVICE_INFO J2534-2 0x800C Получение информации об устройстве
GET_PROTOCOL_INFO J2534-2 0x800D Получение информации о протоколе
ISO13400_*ScanDoc 0x8110-0x8113 Команды DoIP (Diagnostics over IP)

Возвращаемые коды ошибок

Код Описание Возможные причины и решения
STATUS_NOERROR Функция выполнена успешно
ERR_DEVICE_NOT_CONNECTED Нет соединения с адаптером
  • Адаптер выключен или вне зоны доступа
  • Решение: проверьте питание адаптера и сетевое подключение
ERR_INVALID_CHANNEL_ID Недействительный идентификатор канала
  • ChannelID не был получен через PassThruConnect или канал закрыт
  • Решение: убедитесь, что PassThruConnect выполнен успешно
ERR_INVALID_IOCTL_ID Недействительный идентификатор IoctlID
  • Указанный IoctlID не поддерживается
  • Решение: проверьте корректность значения IoctlID
ERR_NULL_PARAMETER Передан NULL вместо обязательного указателя
  • pInput или pOutput равен NULL, когда требуется указатель
  • Решение: передайте корректные указатели
ERR_NOT_SUPPORTED Операция не поддерживается
  • Адаптер не поддерживает запрошенную операцию
  • Решение: проверьте возможности адаптера через GET_DEVICE_INFO
ERR_INVALID_IOCTL_VALUE Недопустимое значение параметра
  • Значение в pInput выходит за допустимые пределы
  • Решение: проверьте допустимые диапазоны значений
ERR_INVALID_MSG Неправильная структура сообщения
  • Неверная структура в pInput для FAST_INIT
  • Решение: проверьте корректность полей PASSTHRU_MSG
ERR_FAILED Неопределённая ошибка
  • Внутренняя ошибка библиотеки или адаптера
  • Решение: вызовите PassThruGetLastError() для описания

READ_VBATT — Чтение напряжения питания

Возвращает напряжение на разъёме OBD-II (контакт 16). Значение в милливольтах, для получения вольт разделите на 1000. Команда не требует открытого канала и может выполняться сразу после PassThruOpen.

pInput NULL
pOutput unsigned long* — напряжение в мВ

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long DeviceID;  // Получен от PassThruOpen
unsigned long voltage;
long ret;

ret = PassThruIoctl(DeviceID, READ_VBATT, NULL, &voltage);
if (ret == STATUS_NOERROR)
{
    printf("Напряжение: %.2f V\n", voltage / 1000.0);
}

Пример на Kotlin (Android)

// deviceID получен ранее от ptOpen
val result = j2534.ptIoctl(deviceID, READ_VBATT, 0, null)
if (result.status == STATUS_NOERROR) {
    val voltageV = result.outputValue / 1000.0
    Log.i("J2534", "Напряжение: ${"%.2f".format(voltageV)} V")
}

Пример на Python

from ctypes import *

voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_VBATT, None, byref(voltage))
if ret == 0:  # STATUS_NOERROR
    print(f"Напряжение: {voltage.value / 1000:.2f} V")

Пример на C#

uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_VBATT, IntPtr.Zero, out voltage);
if (ret == 0)
{
    Console.WriteLine($"Напряжение: {voltage / 1000.0:F2} V");
}

READ_PROG_VOLTAGE — Чтение напряжения программирования

Возвращает текущее напряжение на выходе программирования. Значение в милливольтах, округлённое до ближайшей десятой вольта.

pInput NULL
pOutput unsigned long* — напряжение в мВ

Пример на 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("Напряжение программирования: %.2f V\n", voltage / 1000.0);
}

Пример на 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", "Напряжение программирования: ${"%.2f".format(voltageV)} V")
}

Пример на Python

from ctypes import *

voltage = c_ulong()
ret = j2534.PassThruIoctl(device_id, READ_PROG_VOLTAGE, None, byref(voltage))
if ret == 0:
    print(f"Напряжение программирования: {voltage.value / 1000:.2f} V")

Пример на C#

uint voltage;
int ret = J2534.PassThruIoctl(deviceId, READ_PROG_VOLTAGE, IntPtr.Zero, out voltage);
if (ret == 0)
{
    Console.WriteLine($"Напряжение программирования: {voltage / 1000.0:F2} V");
}

FIVE_BAUD_INIT — 5-бод инициализация

Запускает медленную (5 бод) инициализацию для протоколов ISO 9141 и ISO 14230 (K-Line). Принимает KeyWord от ЭБУ. Режим инициализации задаётся параметром FIVE_BAUD_MOD через SET_CONFIG. Скорость обмена определяется автоматически.

pInput SBYTE_ARRAY* — адрес инициализации (1 байт)
pOutput SBYTE_ARRAY* — KeyWord (2 байта)
Параметр FIVE_BAUD_MOD определяет режим инициализации: ISO9141-2/ISO14230-4 (0), инверсия KB2 (1), инверсия адреса (2), ISO9141 без инверсии (3).

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Получен от PassThruConnect
SBYTE_ARRAY InputMsg;
SBYTE_ARRAY OutputMsg;
long ret;

unsigned char initByte[1];
unsigned char keyWord[2];

initByte[0] = 0x33;  // Адрес инициализации ЭБУ

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]);
}

Пример на Kotlin (Android)

// channelID получен от ptConnect для ISO14230
val initAddress = byteArrayOf(0x33)  // Адрес инициализации

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()}")
}

Пример на Python

from ctypes import *

input_msg = SBYTE_ARRAY()
input_msg.NumOfBytes = 1
input_msg.BytePtr = (c_ubyte * 1)(0x33)

output_msg = SBYTE_ARRAY()
output_msg.NumOfBytes = 2
keyword = (c_ubyte * 2)()
output_msg.BytePtr = keyword

ret = j2534.PassThruIoctl(channel_id, FIVE_BAUD_INIT, byref(input_msg), byref(output_msg))
if ret == 0:
    print(f"KeyWord: {keyword[0]:02X} {keyword[1]:02X}")

Пример на C#

var inputMsg = new SBYTE_ARRAY {
    NumOfBytes = 1,
    BytePtr = new byte[] { 0x33 }  // Адрес инициализации
};

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 инициализация

Запускает быструю инициализацию для протокола ISO 14230 (K-Line). Отправляет запрос StartCommunication и возвращает ответ ЭБУ. Используется для KWP2000.

pInput PASSTHRU_MSG* — запрос инициализации
pOutput PASSTHRU_MSG* — ответ ЭБУ
Важно: При функциональном (широковещательном) адресе на запрос могут ответить несколько ЭБУ. В pOutput будет только первый ответ, остальные попадут в приёмную очередь.

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Получен от PassThruConnect
PASSTHRU_MSG InputMsg;
PASSTHRU_MSG OutputMsg;
long ret;

// Запрос StartCommunication
InputMsg.ProtocolID = ISO14230;
InputMsg.TxFlags = 0;
InputMsg.DataSize = 4;
InputMsg.Data[0] = 0x81;  // Формат: физический адрес, 1 байт данных
InputMsg.Data[1] = 0x10;  // Целевой адрес (ЭБУ)
InputMsg.Data[2] = 0xF1;  // Адрес источника (тестер)
InputMsg.Data[3] = 0x81;  // SID: StartCommunication

ret = PassThruIoctl(ChannelID, FAST_INIT, &InputMsg, &OutputMsg);
if (ret == STATUS_NOERROR)
{
    printf("Ответ ЭБУ: %d байт\n", OutputMsg.DataSize);
    for (int i = 0; i < OutputMsg.DataSize; i++)
        printf("%02X ", OutputMsg.Data[i]);
}

Пример на Kotlin (Android)

// channelID получен от ptConnect для 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", "Ответ ЭБУ: ${result.response.data.toHexString()}")
}

Пример на 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  # Формат
input_msg.Data[1] = 0x10  # Целевой адрес
input_msg.Data[2] = 0xF1  # Адрес источника
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"Ответ ЭБУ: {data.hex(' ').upper()}")

Пример на C#

var inputMsg = new PASSTHRU_MSG {
    ProtocolID = ISO14230,
    TxFlags = 0,
    DataSize = 4
};
inputMsg.Data[0] = 0x81;  // Формат
inputMsg.Data[1] = 0x10;  // Целевой адрес
inputMsg.Data[2] = 0xF1;  // Адрес источника
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($"Ответ ЭБУ: {BitConverter.ToString(data).Replace("-", " ")}");
}

CLEAR_TX_BUFFER — Очистка очереди передачи

Удаляет все сообщения из очереди передачи канала. Используется для отмены запланированных передач.

pInput NULL
pOutput NULL

Пример на 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("Ошибка: %s\n", error);
}

Пример на Kotlin (Android)

val result = j2534.ptIoctl(channelID, CLEAR_TX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
    Log.e("J2534", "Ошибка CLEAR_TX_BUFFER: ${result.status}")
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, CLEAR_TX_BUFFER, None, None)
if ret != 0:
    print(f"Ошибка CLEAR_TX_BUFFER: {ret}")

Пример на C#

int ret = J2534.PassThruIoctl(channelId, CLEAR_TX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
    Console.WriteLine($"Ошибка CLEAR_TX_BUFFER: {ret}");

CLEAR_RX_BUFFER — Очистка очереди приёма

Удаляет все сообщения из очереди приёма канала. Рекомендуется вызывать перед началом новой диагностической сессии.

pInput NULL
pOutput NULL

Пример на 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("Ошибка: %s\n", error);
}

Пример на Kotlin (Android)

val result = j2534.ptIoctl(channelID, CLEAR_RX_BUFFER, 0, null)
if (result.status != STATUS_NOERROR) {
    Log.e("J2534", "Ошибка CLEAR_RX_BUFFER: ${result.status}")
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, CLEAR_RX_BUFFER, None, None)
if ret != 0:
    print(f"Ошибка CLEAR_RX_BUFFER: {ret}")

Пример на C#

int ret = J2534.PassThruIoctl(channelId, CLEAR_RX_BUFFER, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
    Console.WriteLine($"Ошибка CLEAR_RX_BUFFER: {ret}");

CLEAR_PERIODIC_MSGS — Очистка периодических сообщений

Удаляет все периодические сообщения, установленные через PassThruStartPeriodicMsg. Эквивалентно вызову PassThruStopPeriodicMsg для каждого сообщения.

pInput NULL
pOutput NULL

Пример на 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("Ошибка: %s\n", error);
}

Пример на Kotlin (Android)

val result = j2534.ptIoctl(channelID, CLEAR_PERIODIC_MSGS, 0, null)
if (result.status != STATUS_NOERROR) {
    Log.e("J2534", "Ошибка CLEAR_PERIODIC_MSGS: ${result.status}")
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, CLEAR_PERIODIC_MSGS, None, None)
if ret != 0:
    print(f"Ошибка CLEAR_PERIODIC_MSGS: {ret}")

Пример на C#

int ret = J2534.PassThruIoctl(channelId, CLEAR_PERIODIC_MSGS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
    Console.WriteLine($"Ошибка CLEAR_PERIODIC_MSGS: {ret}");

CLEAR_MSG_FILTERS — Очистка фильтров

Удаляет все фильтры сообщений, установленные через PassThruStartMsgFilter. После вызова все входящие сообщения будут блокироваться до установки новых фильтров.

pInput NULL
pOutput NULL

Пример на 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("Ошибка: %s\n", error);
}

Пример на Kotlin (Android)

val result = j2534.ptIoctl(channelID, CLEAR_MSG_FILTERS, 0, null)
if (result.status != STATUS_NOERROR) {
    Log.e("J2534", "Ошибка CLEAR_MSG_FILTERS: ${result.status}")
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, CLEAR_MSG_FILTERS, None, None)
if ret != 0:
    print(f"Ошибка CLEAR_MSG_FILTERS: {ret}")

Пример на C#

int ret = J2534.PassThruIoctl(channelId, CLEAR_MSG_FILTERS, IntPtr.Zero, IntPtr.Zero);
if (ret != 0)
    Console.WriteLine($"Ошибка CLEAR_MSG_FILTERS: {ret}");

CLEAR_FUNCT_MSG_LOOKUP_TABLE — Очистка таблицы функциональных адресов

Очищает таблицу функциональных адресов J1850. Используется для протоколов J1850 PWM/VPW при работе с функциональной адресацией.

pInput NULL
pOutput NULL

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Канал J1850
long ret;

ret = PassThruIoctl(ChannelID, CLEAR_FUNCT_MSG_LOOKUP_TABLE, NULL, NULL);
if (ret != STATUS_NOERROR)
{
    // Обработка ошибки
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, CLEAR_FUNCT_MSG_LOOKUP_TABLE, None, None)

Пример на C#

int ret = J2534.PassThruIoctl(channelId, CLEAR_FUNCT_MSG_LOOKUP_TABLE, IntPtr.Zero, IntPtr.Zero);

ADD_TO_FUNCT_MSG_LOOKUP_TABLE — Добавление функционального адреса

Добавляет адрес в таблицу функциональных адресов J1850. Сообщения с этим адресом будут приниматься при использовании функциональной адресации.

pInput SBYTE_ARRAY* — список адресов для добавления
pOutput NULL

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;
SBYTE_ARRAY AddrList;
unsigned char addresses[3] = {0x10, 0x18, 0x28};  // Адреса ECU
long ret;

AddrList.NumOfBytes = 3;
AddrList.BytePtr = addresses;

ret = PassThruIoctl(ChannelID, ADD_TO_FUNCT_MSG_LOOKUP_TABLE, &AddrList, NULL);
if (ret != STATUS_NOERROR)
{
    // Обработка ошибки
}

Пример на Python

addresses = (c_ubyte * 3)(0x10, 0x18, 0x28)
addr_list = SBYTE_ARRAY()
addr_list.NumOfBytes = 3
addr_list.BytePtr = addresses

ret = j2534.PassThruIoctl(channel_id, ADD_TO_FUNCT_MSG_LOOKUP_TABLE, byref(addr_list), None)

Пример на C#

var addrList = new SBYTE_ARRAY {
    NumOfBytes = 3,
    BytePtr = new byte[] { 0x10, 0x18, 0x28 }
};
int ret = J2534.PassThruIoctl(channelId, ADD_TO_FUNCT_MSG_LOOKUP_TABLE, ref addrList, IntPtr.Zero);

DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE — Удаление функционального адреса

Удаляет адрес из таблицы функциональных адресов J1850.

pInput SBYTE_ARRAY* — список адресов для удаления
pOutput NULL

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;
SBYTE_ARRAY AddrList;
unsigned char addresses[1] = {0x10};  // Адрес для удаления
long ret;

AddrList.NumOfBytes = 1;
AddrList.BytePtr = addresses;

ret = PassThruIoctl(ChannelID, DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE, &AddrList, NULL);
if (ret != STATUS_NOERROR)
{
    // Обработка ошибки
}

Пример на Python

addresses = (c_ubyte * 1)(0x10)
addr_list = SBYTE_ARRAY()
addr_list.NumOfBytes = 1
addr_list.BytePtr = addresses

ret = j2534.PassThruIoctl(channel_id, DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE, byref(addr_list), None)

Пример на C#

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

Переключает Single-Wire CAN в высокоскоростной режим (83.3 кбит/с). Используется для диагностики на высокой скорости в сетях GM.

pInput NULL
pOutput NULL

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Канал SW-CAN
long ret;

// Переключение в высокоскоростной режим
ret = PassThruIoctl(ChannelID, SW_CAN_HS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
    printf("SW-CAN в режиме High Speed (83.3 kbit/s)\n");
}

Пример на Kotlin (Android)

val result = j2534.ptIoctl(channelID, SW_CAN_HS, 0, null)
if (result.status == STATUS_NOERROR) {
    Log.i("J2534", "SW-CAN в режиме High Speed (83.3 kbit/s)")
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, SW_CAN_HS, None, None)
if ret == 0:
    print("SW-CAN в режиме High Speed (83.3 kbit/s)")

Пример на C#

int ret = J2534.PassThruIoctl(channelId, SW_CAN_HS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
    Console.WriteLine("SW-CAN в режиме High Speed (83.3 kbit/s)");

SW_CAN_NS — Нормальный режим SW-CAN

Переключает Single-Wire CAN в нормальный режим (33.3 кбит/с). Это режим по умолчанию для сетей GM.

pInput NULL
pOutput NULL

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Канал SW-CAN
long ret;

// Переключение в нормальный режим
ret = PassThruIoctl(ChannelID, SW_CAN_NS, NULL, NULL);
if (ret == STATUS_NOERROR)
{
    printf("SW-CAN в режиме Normal Speed (33.3 kbit/s)\n");
}

Пример на Kotlin (Android)

val result = j2534.ptIoctl(channelID, SW_CAN_NS, 0, null)
if (result.status == STATUS_NOERROR) {
    Log.i("J2534", "SW-CAN в режиме Normal Speed (33.3 kbit/s)")
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, SW_CAN_NS, None, None)
if ret == 0:
    print("SW-CAN в режиме Normal Speed (33.3 kbit/s)")

Пример на C#

int ret = J2534.PassThruIoctl(channelId, SW_CAN_NS, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
    Console.WriteLine("SW-CAN в режиме Normal Speed (33.3 kbit/s)");

BUS_ON — Подключение контроллера к шине v5.0

Подключает CAN-контроллер к физической шине. Используется после отключения контроллера от шины через PassThruDisconnect с флагом CAN_DISCONNECT или после открытия канала без автоматического подключения.

IoctlID 0x0F
pInput NULL
pOutput NULL
Эта команда доступна только в J2534 v5.00. В v04.04 контроллер подключается к шине автоматически при PassThruConnect.

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Канал CAN
long ret;

// Подключение контроллера к шине
ret = PassThruIoctl(ChannelID, BUS_ON, NULL, NULL);
if (ret == STATUS_NOERROR)
{
    printf("CAN-контроллер подключён к шине\n");
}

Пример на Kotlin (Android)

val result = j2534.ptIoctl(channelID, BUS_ON, 0, null)
if (result.status == STATUS_NOERROR) {
    Log.i("J2534", "CAN-контроллер подключён к шине")
}

Пример на Python

ret = j2534.PassThruIoctl(channel_id, BUS_ON, None, None)
if ret == 0:
    print("CAN-контроллер подключён к шине")

Пример на C#

int ret = J2534.PassThruIoctl(channelId, BUS_ON, IntPtr.Zero, IntPtr.Zero);
if (ret == 0)
    Console.WriteLine("CAN-контроллер подключён к шине");

REQUEST_CONNECTION — Установление TP 2.0 соединения J2534-2

Запрашивает установление канала и соединения TP 2.0 между адаптером и ЭБУ. Используется для протокола TP 2.0 (VAG). Команда неблокирующая — результат соединения приходит как индикация в очередь приёма.

IoctlID 0x800A
pInput SBYTE_ARRAY* — данные запроса соединения (11 байт)
pOutput NULL

Структура данных (11 байт)

BytePtr[0-3] CAN ID (идентификатор), BytePtr[0] — старший байт
BytePtr[4] Destination — адрес назначения (ECU)
BytePtr[5] Opcode — всегда 0xC0
BytePtr[6-7] TX-ID-A — CAN ID для передачи
BytePtr[8-9] RX-ID-A — CAN ID для приёма
BytePtr[10] Application Type — тип приложения
При успешном соединении создаётся неявный PASS-фильтр для RX-ID-A. В очередь приёма помещается индикация CONNECTION_ESTABLISHED. При ошибке — CONNECTION_LOST.
Если RX-ID-A уже используется другим каналом, возвращается ERR_NOT_UNIQUE. Если NumOfBytes ≠ 11, возвращается ERR_INVALID_IOCTL_VALUE.

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Канал TP 2.0
SBYTE_ARRAY InputData;
unsigned char data[11];
long ret;

// CAN ID для broadcast: 0x200
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x02;
data[3] = 0x00;
// Destination (адрес ECU, например 0x01 для двигателя)
data[4] = 0x01;
// Opcode (всегда 0xC0)
data[5] = 0xC0;
// TX-ID-A (CAN ID для передачи, например 0x300)
data[6] = 0x03;
data[7] = 0x00;
// RX-ID-A (CAN ID для приёма, например 0x301)
data[8] = 0x03;
data[9] = 0x01;
// Application Type (0x01 для диагностики)
data[10] = 0x01;

InputData.NumOfBytes = 11;
InputData.BytePtr = data;

ret = PassThruIoctl(ChannelID, REQUEST_CONNECTION, &InputData, NULL);
if (ret == STATUS_NOERROR)
{
    printf("Запрос соединения отправлен, ожидаем CONNECTION_ESTABLISHED\n");
}
else if (ret == ERR_NOT_UNIQUE)
{
    printf("RX-ID-A уже используется другим каналом\n");
}

Пример на Kotlin (Android)

// channelID — канал 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", "Запрос соединения отправлен")
    ERR_NOT_UNIQUE -> Log.e("TP2.0", "RX-ID-A уже используется")
    else -> Log.e("TP2.0", "Ошибка: ${result.status}")
}

Пример на 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("Запрос соединения отправлен, ожидаем CONNECTION_ESTABLISHED")
elif ret == ERR_NOT_UNIQUE:
    print("RX-ID-A уже используется другим каналом")

Пример на 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("Запрос соединения отправлен, ожидаем CONNECTION_ESTABLISHED");
else if (ret == ERR_NOT_UNIQUE)
    Console.WriteLine("RX-ID-A уже используется другим каналом");

TEARDOWN_CONNECTION — Разрыв TP 2.0 соединения J2534-2

Разрывает установленное соединение TP 2.0 между адаптером и ЭБУ. Команда неблокирующая — подтверждение разрыва приходит как индикация CONNECTION_LOST в очередь приёма.

IoctlID 0x800B
pInput SBYTE_ARRAY* — CAN ID приёма (4 байта)
pOutput NULL

Структура данных (4 байта)

BytePtr[0-3] RX-ID-A — CAN ID для приёма (тот же, что в REQUEST_CONNECTION), BytePtr[0] — старший байт
После разрыва соединения неявный PASS-фильтр для RX-ID-A удаляется. Фильтры, установленные через PassThruStartMsgFilter, остаются активными.

Пример на C/C++

#include "j2534_dll.hpp"

unsigned long ChannelID;  // Канал TP 2.0
SBYTE_ARRAY InputData;
unsigned char data[4];
long ret;

// RX-ID-A (тот же, что был в 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("Запрос разрыва соединения отправлен\n");
}

Пример на 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", "Запрос разрыва соединения отправлен")
}

Пример на 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("Запрос разрыва соединения отправлен")

Пример на 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("Запрос разрыва соединения отправлен");