# API Reference

> **Library 2.0.0.213** · SAE J2534 v04.04 API

All functions return `int32_t`: `STATUS_NOERROR` (0) on success or an error
code (see [ERROR_HANDLING.md](ERROR_HANDLING.md)). C linkage; `__stdcall` on
Windows.

## Core functions (SAE J2534-1 v04.04)

### PassThruOpen

```c
int32_t PassThruOpen(char *name, uint32_t *device_id);
```

Opens a device. `name` is a connection string (see
[GETTING_STARTED.md](GETTING_STARTED.md#2-connection-strings)); `NULL` or a
string without `;` selects the device configured in `j2534.json`. Returns the
device handle in `*device_id`. Up to 16 devices can be open simultaneously.

### PassThruClose

```c
int32_t PassThruClose(uint32_t device_id);
```

Closes the device and releases the transport. Also deletes `.qlog` files older
than 30 days from the log directory.

### PassThruConnect

```c
int32_t PassThruConnect(uint32_t device_id, uint32_t protocol_id,
                        uint32_t flags, uint32_t baud_rate, uint32_t *channel_id);
```

Opens a protocol channel. `flags` — connect flags (e.g. `CAN_29BIT_ID_CF`,
`CAN_ID_BOTH`, `ISO9141_K_LINE_ONLY`). `baud_rate` — bus speed in bit/s
(e.g. 500000); pass 0 for protocols where it is not applicable (e.g.
`ISO13400_PS`).

### PassThruDisconnect

```c
int32_t PassThruDisconnect(uint32_t channel_id);
```

### PassThruReadMsgs / PassThruWriteMsgs

```c
int32_t PassThruReadMsgs(uint32_t channel_id, pt_msg_t *msg,
                         uint32_t *num_msgs, uint32_t timeout);
int32_t PassThruWriteMsgs(uint32_t channel_id, pt_msg_t *msg,
                          uint32_t *num_msgs, uint32_t timeout);
```

`msg` points to an array of `*num_msgs` messages; on return `*num_msgs` holds
the number actually read/written. `timeout` in ms; `timeout = 0` for `Read`
returns whatever is already buffered (`ERR_BUFFER_EMPTY` if nothing).
Received messages may carry status markers instead of data — check
`rx_status` for `TX_MSG_TYPE` (echo/TX confirmation) and `START_OF_MESSAGE`
(start of a segmented transfer) before interpreting `data`.

### PassThruStartPeriodicMsg / PassThruStopPeriodicMsg

```c
int32_t PassThruStartPeriodicMsg(uint32_t channel_id, pt_msg_t *msg,
                                 uint32_t *msg_id, uint32_t time_interval);
int32_t PassThruStopPeriodicMsg(uint32_t channel_id, uint32_t msg_id);
```

`time_interval` — repetition period in ms (5–65535).

### PassThruStartMsgFilter / PassThruStopMsgFilter

```c
int32_t PassThruStartMsgFilter(uint32_t channel_id, uint32_t filter_type,
                               pt_msg_t *mask_msg, pt_msg_t *pattern_msg,
                               pt_msg_t *flow_control_msg, uint32_t *msg_id);
int32_t PassThruStopMsgFilter(uint32_t channel_id, uint32_t msg_id);
```

| Filter type | Value | Channels |
|-------------|-------|----------|
| `PASS_FILTER` | 1 | non-ISO 15765 |
| `BLOCK_FILTER` | 2 | non-ISO 15765 |
| `FLOW_CONTROL_FILTER` | 3 | ISO 15765 only (`flow_control_msg` required) |

An ISO 15765 channel receives nothing until a flow-control filter is set.

### PassThruSetProgrammingVoltage

```c
int32_t PassThruSetProgrammingVoltage(uint32_t device_id, uint32_t pin, uint32_t voltage);
```

`voltage` in mV (5000–20000), `SHORT_TO_GROUND`, or `VOLTAGE_OFF`.

### PassThruReadVersion

```c
int32_t PassThruReadVersion(uint32_t device_id, char *firmware_version,
                            char *dll_version, char *api_version);
```

Each buffer must hold at least 80 bytes.

### PassThruGetLastError

```c
int32_t PassThruGetLastError(char *error_description);
```

Returns the text behind the most recent `ERR_FAILED`. Buffer ≥ 256 bytes
recommended. See [ERROR_HANDLING.md](ERROR_HANDLING.md).

### PassThruIoctl

```c
int32_t PassThruIoctl(uint32_t channel_id, uint32_t ioctl_id, void *input, void *output);
```

See [IOCTL reference](#ioctl-reference) below.

## Device discovery (SAE J2534-2 / v05.00 subset)

```c
int32_t PassThruScanForDevices(uint32_t *device_count);
int32_t PassThruGetNextDevice(pt_device_t *device);
```

`PassThruScanForDevices` scans available transports (blocks for several
seconds) and returns the number of devices found. Iterate results with
`PassThruGetNextDevice`; `device_name` is a ready-to-use connection string.
Returns `ERR_BUFFER_EMPTY` if no scan was performed, `ERR_EXCEEDED_LIMIT`
after the last device.

```c
typedef struct {
    char     device_name[80];
    uint32_t device_available;
    uint32_t device_dll_fw_status;
    uint32_t device_connect_media;
    uint32_t device_connect_speed;
    uint32_t device_signal_quality;
    uint32_t device_signal_strength;
} pt_device_t;
```

> The remaining v05.00 entry points (`PassThruLogicalConnect`,
> `PassThruLogicalDisconnect`, `PassThruQueueMsgs`, `PassThruSelect`) are
> exported but **not implemented** — they return `ERR_NOT_SUPPORTED`.

## Utility

```c
int32_t LogMsg(uint32_t device_id, const char *message);
```

Thread-safe: appends an application-defined metadata line to the library's
`.qlog` file (see [LOG_FORMAT.md](LOG_FORMAT.md)). Useful for correlating
application events with bus traffic.

## Structures

### pt_msg_t

```c
typedef struct {
    uint32_t protocol_id;
    uint32_t rx_status;     /* RX: status flags (TX_MSG_TYPE, START_OF_MESSAGE, ...) */
    uint32_t tx_flags;      /* TX: flags (ISO15765_FRAME_PAD_TF, CAN_29BIT_ID_TF, ...) */
    uint32_t timestamp;     /* device timestamp, µs */
    uint32_t data_size;     /* valid bytes in data[] */
    uint32_t edi;           /* extra data index */
    uint8_t  data[4128];
} pt_msg_t;
```

For CAN-based protocols `data` starts with the 4-byte CAN ID (big-endian),
followed by payload. For ISO 13400 it starts with the 4-byte logical address
header — see [DOIP.md](DOIP.md).

### pt_config_t / pt_config_list_t (SET_CONFIG / GET_CONFIG)

```c
typedef struct { uint32_t parameter; uint32_t value; } pt_config_t;
typedef struct { uint32_t num_of_params; pt_config_t *config_ptr; } pt_config_list_t;
```

### pt_byte_array_t

```c
typedef struct { uint32_t num_of_bytes; uint8_t *byte_ptr; } pt_byte_array_t;
```

## Protocol IDs

| Protocol | ID | Description |
|----------|----|-------------|
| `J1850VPW` | 1 | J1850 VPW |
| `J1850PWM` | 2 | J1850 PWM |
| `ISO9141` | 3 | ISO 9141-2 (K-Line) |
| `ISO14230` | 4 | ISO 14230 (KWP2000) |
| `CAN` | 5 | Raw CAN |
| `ISO15765` | 6 | ISO 15765-2 over CAN |
| `CAN_PS` | 0x8004 | Raw CAN, pin-selectable |
| `ISO15765_PS` | 0x8005 | ISO 15765, pin-selectable |
| `SW_CAN_PS` | 0x8008 | Single-wire CAN |
| `J1939_PS` | 0x800C | SAE J1939 |
| `TP2_0_PS` | 0x800E | VW TP 2.0 |
| `FD_CAN_PS` | 0x8011 | CAN FD |
| `FD_ISO15765_PS` | 0x8012 | ISO 15765 over CAN FD |
| `HSFZ_PS` | — | BMW HSFZ (vendor extension) |
| `ISO13400_PS` | 0x8FFD | ISO 13400 / DoIP (vendor extension, see [DOIP.md](DOIP.md)) |

Pin selection for `*_PS` protocols: `SET_CONFIG` parameter `J1962_PINS`.

## IOCTL reference

Public IOCTLs (`PassThruIoctl`):

| IOCTL | ID | input | output |
|-------|----|-------|--------|
| `GET_CONFIG` | 0x01 | `pt_config_list_t*` | values filled in place |
| `SET_CONFIG` | 0x02 | `pt_config_list_t*` | — |
| `READ_VBATT` | 0x03 | — | `uint32_t*` (mV) |
| `FIVE_BAUD_INIT` | 0x04 | `pt_byte_array_t*` (address) | `pt_byte_array_t*` (key bytes) |
| `FAST_INIT` | 0x05 | `pt_msg_t*` (wake-up) | `pt_msg_t*` (response) |
| `CLEAR_TX_BUFFER` | 0x07 | — | — |
| `CLEAR_RX_BUFFER` | 0x08 | — | — |
| `CLEAR_PERIODIC_MSGS` | 0x09 | — | — |
| `CLEAR_MSG_FILTERS` | 0x0A | — | — |
| `CLEAR_FUNCT_MSG_LOOKUP_TABLE` | 0x0B | — | — |
| `READ_J1962PIN_VOLTAGE` | 0x800E | pin number | `uint32_t*` (mV) |
| `SW_CAN_HS` | 0x8000 | — | — |
| `SW_CAN_NS` | 0x8001 | — | — |
| `SET_POLL_RESPONSE` | 0x8002 | `pt_byte_array_t*` (GM UART poll response, ≤100 bytes) | — |
| `BECOME_MASTER` | 0x8003 | `uint8_t*` (Poll_ID; 0 = send at once) | — |
| `PROTECT_J1939_ADDR` | 0x8009 | `pt_byte_array_t*` (9 bytes: address, then NAME) | — |
| `REQUEST_CONNECTION` | 0x800A | `pt_byte_array_t*` (TP2.0 — 11 bytes, TP1.6 — 7) | — |
| `TEARDOWN_CONNECTION` | 0x800B | `pt_byte_array_t*` (4 bytes: CAN ID of the connection) | — |
| `GET_DEVICE_INFO` | 0x800C | `pt_param_list_t*` | `supported` and `value` filled in place |
| `GET_PROTOCOL_INFO` | 0x800D | `pt_param_list_t*` | `supported` and `value` filled in place |
| `ISO13400_*` | 0x8110–0x8113 | see [DOIP.md](DOIP.md) | |

`GET_DEVICE_INFO` and `GET_PROTOCOL_INFO` take `pt_param_list_t` (SPARAM_LIST),
not `pt_config_list_t`: each `pt_param_t` carries `parameter`, `value` and
`supported`. An unsupported parameter is flagged in its own `supported` field
and leaves `value` untouched — the call still returns `STATUS_NOERROR`. Both
IOCTLs need an open channel: pass a channel ID, not a device ID.

`BECOME_MASTER` blocks until a poll message arrives (up to 2 s) and returns
`ERR_FAILED` if none does.

Common `SET_CONFIG` parameters: `DATA_RATE`, `LOOPBACK`, `P1_MAX`, `P3_MIN`,
`P4_MIN`, `W0`–`W5`, `TIDLE`, `TWUP`, `PARITY`, `ISO15765_BS`,
`ISO15765_STMIN`, `BS_TX`, `STMIN_TX`, `ISO15765_WFT_MAX`,
`ISO15765_PAD_VALUE`, `J1962_PINS`, `CAN_MIXED_FORMAT`,
`FD_CAN_DATA_PHASE_RATE`, `HS_CAN_TERMINATION`, `N_CR_MAX`. DoIP parameters:
see [DOIP.md](DOIP.md).

Full numeric values of protocols, flags, IOCTLs and parameters are defined in
the `j2534.h` header shipped with the library.
