Create a logical communication channel on top of a physical connection
Last updated:
The function creates a logical communication channel to the vehicle on the specified pass-thru device. A logical channel overlays an additional protocol scheme on top of an existing physical communication channel.
On success, the function returns STATUS_NOERROR, and the value pointed to by pChannelID
is used as a handle for the created channel. The channel is in the initialized state.
Up to 10 logical channels per physical communication channel are permitted. Creating a logical channel does not affect the operation of the physical channel or of other logical channels associated with it.
long PassThruLogicalConnect(
unsigned long PhysicalChannelID,
unsigned long ProtocolID,
unsigned long Flags,
void *pChannelDescriptor,
unsigned long *pChannelID
)
A newly created logical channel has the following initial state:
Input parameter. The identifier of the physical channel obtained from a call to PassThruConnect().
Input parameter. The protocol identifier for the logical communication channel.
It defines how the logical channel will interact with the vehicle, as well as the type of the pChannelDescriptor structure.
| ProtocolID | Description |
|---|---|
ISO15765_LOGICAL |
ISO 15765-2 with flow control |
Input parameter. Logical channel configuration flags. Flags may be combined using OR.
| Flag | Description | Values |
|---|---|---|
FULL_DUPLEX |
Channel duplex mode. ISO 15765 only. | 0 = half duplex 1 = full duplex |
ISO15765_ON_J1939 |
Masking of priority bits (28-26) in the CAN ID for ISO 15765 messages with a 29-bit identifier (per ISO 15765-2 Annex A and SAE J1939-21). ISO 15765 only. | 0 = masking disabled (standard ISO 15765 processing) 1 = masking enabled |
Input parameter. A pointer to a structure that describes the endpoints of the logical connection.
If the pointer is NULL, the function will return ERR_NULL_PARAMETER.
Input parameter. A pointer to an application-allocated unsigned long variable.
On success, the variable will contain the identifier of the logical channel for use in subsequent function calls.
For the ISO15765_LOGICAL protocol, the ISO15765_CHANNEL_DESCRIPTOR structure is used,
which defines the endpoints of the logical connection:
typedef struct {
unsigned long LocalTxFlags; // TxFlags for LocalAddress
unsigned long RemoteTxFlags; // TxFlags for RemoteAddress
unsigned char LocalAddress[5]; // CAN ID + extended address (local side)
unsigned char RemoteAddress[5]; // CAN ID + extended address (remote side)
} ISO15765_CHANNEL_DESCRIPTOR;
Allowed flags for the ISO 15765 channel descriptor:
| Flag | Applies to | Description |
|---|---|---|
CAN_29BIT_ID |
LocalAddress, RemoteAddress | Use a 29-bit CAN ID (instead of 11-bit) |
ISO15765_ADDR_TYPE |
LocalAddress, RemoteAddress | Use extended addressing |
ISO15765_FRAME_PAD |
RemoteAddress | Enable padding of flow control frames on transmission |
Address[0] — CAN ID bits 28-24 (the three most significant bits must be zero)Address[1] — CAN ID bits 23-16Address[2] — CAN ID bits 15-8Address[3] — CAN ID bits 7-0Address[4] — extended address (if the ISO15765_ADDR_TYPE flag is set)LocalAddress and RemoteAddress
addresses must be unique. Neither address may match the addresses of any other existing logical channels
on the given physical channel. A CAN ID with an extended address must not match a CAN ID without an extended address.
| Code | Description |
|---|---|
| STATUS_NOERROR | Function completed successfully |
| ERR_CONCURRENT_API_CALL | A J2534 API function was called before the previous call completed |
| ERR_DEVICE_NOT_OPEN | PassThruOpen() has not been successfully called |
| ERR_INVALID_CHANNEL_ID | Invalid PhysicalChannelID value |
| ERR_DEVICE_NOT_CONNECTED | Communication error with the pass-thru device. The device has been disconnected. |
| ERR_NOT_SUPPORTED | The DLL does not support this function |
| ERR_LOG_CHAN_NOT_ALLOWED | Logical channel is not allowed for this combination of physical channel and ProtocolID |
| ERR_PROTOCOL_ID_NOT_SUPPORTED | The ProtocolID value is not supported (invalid or unknown) |
| ERR_FLAG_NOT_SUPPORTED | The Flags values are invalid, unknown, or not applicable to the current channel |
| ERR_INVALID_CHANNEL_DESCRIPTOR | One or more elements of the pChannelDescriptor structure are invalid or not applicable to the current channel |
| ERR_NULL_REQUIRED | A parameter that must be NULL is not set to NULL |
| ERR_NULL_PARAMETER | A NULL pointer was passed instead of a required pointer |
| ERR_NOT_UNIQUE | Attempt to create a logical channel with addresses that duplicate those of an existing channel |
| ERR_EXCEEDED_LIMIT | The maximum number of logical channels for the given physical channel has been exceeded |
| ERR_FAILED | Undefined error. Use PassThruGetLastError() to get a description. |
#include "j2534_dll.hpp"
unsigned long deviceID = 0;
unsigned long physicalChannelID = 0;
unsigned long logicalChannelID = 0;
// Open the device
long ret = PassThruOpen("ScanDoc", &deviceID);
if (ret != STATUS_NOERROR) return;
// Create a physical CAN connection
ret = PassThruConnect(deviceID, CAN, CAN_29BIT_ID, 500000, &physicalChannelID);
if (ret != STATUS_NOERROR) {
PassThruClose(deviceID);
return;
}
// Configure the ISO 15765 logical channel descriptor
ISO15765_CHANNEL_DESCRIPTOR channelDesc = {0};
// Local address (adapter) - 0x18DA00F1 (functional request)
channelDesc.LocalTxFlags = CAN_29BIT_ID;
channelDesc.LocalAddress[0] = 0x18;
channelDesc.LocalAddress[1] = 0xDA;
channelDesc.LocalAddress[2] = 0x00;
channelDesc.LocalAddress[3] = 0xF1;
// Remote address (ECU) - 0x18DAF100 (response from ECU)
channelDesc.RemoteTxFlags = CAN_29BIT_ID | ISO15765_FRAME_PAD;
channelDesc.RemoteAddress[0] = 0x18;
channelDesc.RemoteAddress[1] = 0xDA;
channelDesc.RemoteAddress[2] = 0xF1;
channelDesc.RemoteAddress[3] = 0x00;
// Create the logical channel
ret = PassThruLogicalConnect(
physicalChannelID,
ISO15765_LOGICAL,
0, // Flags: half duplex
&channelDesc,
&logicalChannelID
);
if (ret == STATUS_NOERROR) {
printf("Logical channel created: %lu\n", logicalChannelID);
// Now logicalChannelID can be used for PassThruReadMsgs/PassThruQueueMsgs
// Close the logical channel
PassThruLogicalDisconnect(logicalChannelID);
}
// Close the physical channel and device
PassThruDisconnect(physicalChannelID);
PassThruClose(deviceID);
from ctypes import *
# Load the library
j2534 = cdll.LoadLibrary("libj2534_v05_00.dylib")
# Channel descriptor structure
class ISO15765_CHANNEL_DESCRIPTOR(Structure):
_fields_ = [
("LocalTxFlags", c_ulong),
("RemoteTxFlags", c_ulong),
("LocalAddress", c_ubyte * 5),
("RemoteAddress", c_ubyte * 5)
]
device_id = c_ulong()
physical_channel_id = c_ulong()
logical_channel_id = c_ulong()
# Open the device
ret = j2534.PassThruOpen(b"ScanDoc", byref(device_id))
if ret != 0:
print(f"PassThruOpen error: {ret}")
exit()
# Create a physical CAN connection (500 kbit/s, 29-bit ID)
CAN = 0x05
CAN_29BIT_ID = 0x100
ret = j2534.PassThruConnect(device_id, CAN, CAN_29BIT_ID, 500000, byref(physical_channel_id))
if ret != 0:
print(f"PassThruConnect error: {ret}")
j2534.PassThruClose(device_id)
exit()
# Configure the channel descriptor
ISO15765_LOGICAL = 0x200
ISO15765_FRAME_PAD = 0x40
channel_desc = ISO15765_CHANNEL_DESCRIPTOR()
channel_desc.LocalTxFlags = CAN_29BIT_ID
channel_desc.LocalAddress[0] = 0x18
channel_desc.LocalAddress[1] = 0xDA
channel_desc.LocalAddress[2] = 0x00
channel_desc.LocalAddress[3] = 0xF1
channel_desc.RemoteTxFlags = CAN_29BIT_ID | ISO15765_FRAME_PAD
channel_desc.RemoteAddress[0] = 0x18
channel_desc.RemoteAddress[1] = 0xDA
channel_desc.RemoteAddress[2] = 0xF1
channel_desc.RemoteAddress[3] = 0x00
# Create the logical channel
ret = j2534.PassThruLogicalConnect(
physical_channel_id,
ISO15765_LOGICAL,
0,
byref(channel_desc),
byref(logical_channel_id)
)
if ret == 0:
print(f"Logical channel created: {logical_channel_id.value}")
# ...work with the channel...
j2534.PassThruLogicalDisconnect(logical_channel_id)
else:
print(f"Error: {ret}")
j2534.PassThruDisconnect(physical_channel_id)
j2534.PassThruClose(device_id)
PassThruConnect() - Create a physical connectionPassThruLogicalDisconnect() - Close a logical channelPassThruReadMsgs() - Read messages from a channel