uds: ISO 14229 (Unified Diagnostic Services) in pure Racket
| (require uds) | package: uds |
This package implements the message layer of ISO 14229-1 — UDS (Unified Diagnostic Services), the application protocol spoken by automotive ECUs over ISO-TP (isotp) or DoIP. It covers service identifiers, negative response codes, diagnostic trouble codes, and request/response construction and parsing.
The library is transport-agnostic and pure: builders return the payload bytes of one ISO-TP message and parsers consume them; timing, transport and security-algorithm concerns stay with the caller. There is no FFI and no system dependency.
1 Quick start
(require uds) (diagnostic-session-control 'extended) (read-data-by-identifier '(61840)) (response-parse #"P\3\0002\0\310") (session-control-response (positive-response-data (response-parse #"P\3\0002\0\310")))
2 Service identifiers
The sid:* bindings name every ISO 14229-1 service (sid:diagnostic-session-control, sid:read-data-by-identifier, …). service-name maps an ID back to a symbol, and service-uses-sub-function? tells whether the service’s second byte is a sub-function — the distinction that drives generic framing.
procedure
(positive-sid sid) → (integer-in 0 255)
sid : (integer-in 0 255)
procedure
(response-sid->request-sid sid) → (integer-in 0 255)
sid : (integer-in 0 255)
procedure
(make-sub-function-byte sub suppress?) → (integer-in 0 255)
sub : (integer-in 0 127) suppress? : boolean?
procedure
(parse-sub-function-byte b) →
(integer-in 0 127) boolean? b : (integer-in 0 255)
3 Negative response codes
Negative responses are framed as 7F <echoed SID> <NRC>.
struct
(struct negative-response (sid nrc))
sid : (integer-in 0 255) nrc : (integer-in 0 255)
4 Diagnostic trouble codes
struct
number : (integer-in 0 65535) status-byte : (integer-in 0 255)
struct
(struct dtc-status ( test-failed test-failed-this-operation-cycle pending confirmed test-not-completed-since-last-clear test-failed-since-last-clear test-not-completed-this-operation-cycle warning-indicator-requested)) test-failed : boolean? test-failed-this-operation-cycle : boolean? pending : boolean? confirmed : boolean? test-not-completed-since-last-clear : boolean? test-failed-since-last-clear : boolean? test-not-completed-this-operation-cycle : boolean? warning-indicator-requested : boolean?
5 Requests
struct
sid : (integer-in 0 255) sub-function : (or/c #f (integer-in 0 127)) suppress? : boolean? data : bytes?
procedure
(make-request sid [ #:sub-function sub #:suppress? suppress? #:data data]) → bytes? sid : (integer-in 0 255) sub : (or/c #f (integer-in 0 127)) = #f suppress? : boolean? = #f data : bytes? = #""
procedure
(diagnostic-session-control type [ #:suppress? suppress?]) → bytes? type : (or/c 'default 'programming 'extended (integer-in 0 127)) suppress? : boolean? = #f
procedure
type : (or/c 'hard 'key-off-on 'soft (integer-in 0 127)) suppress? : boolean? = #f
procedure
(tester-present [#:suppress? suppress?]) → bytes?
suppress? : boolean? = #f
procedure
(control-dtc-setting mode [ #:suppress? suppress? #:data data]) → bytes? mode : (or/c 'on 'off (integer-in 0 127)) suppress? : boolean? = #f data : bytes? = #""
procedure
(clear-diagnostic-information group) → bytes?
group : (integer-in 0 16777215)
procedure
(read-dtc-by-status-mask mask) → bytes?
mask : (integer-in 0 255)
procedure
mask : (integer-in 0 255)
procedure
(report-supported-dtc [#:suppress? suppress?]) → bytes?
suppress? : boolean? = #f
procedure
(security-access-request-seed level) → bytes?
level : (integer-in 0 63)
procedure
(security-access-send-key level key) → bytes?
level : (integer-in 0 63) key : bytes?
procedure
(read-data-by-identifier dids) → bytes?
dids : (listof (integer-in 0 65535))
procedure
(write-data-by-identifier did data) → bytes?
did : (integer-in 0 65535) data : bytes?
procedure
(input-output-control-by-identifier did data) → bytes? did : (integer-in 0 65535) data : bytes?
procedure
(routine-control action routine-id [ #:record record #:suppress? suppress?]) → bytes? action : (or/c 'start 'stop 'request-results (integer-in 0 127)) routine-id : (integer-in 0 65535) record : bytes? = #"" suppress? : boolean? = #f
procedure
(read-memory-by-address address address-bytes size size-bytes) → bytes? address : integer? address-bytes : (integer-in 1 15) size : integer? size-bytes : (integer-in 1 15)
procedure
(write-memory-by-address address address-bytes data) → bytes? address : integer? address-bytes : (integer-in 1 15) data : bytes?
procedure
(request-download data-format-id address address-bytes size size-bytes) → bytes? data-format-id : (integer-in 0 255) address : integer? address-bytes : (integer-in 1 15) size : integer? size-bytes : (integer-in 1 15)
procedure
(transfer-data counter [#:data data]) → bytes?
counter : (integer-in 0 255) data : bytes? = #""
procedure
(request-transfer-exit [#:data data]) → bytes?
data : bytes? = #""
6 Responses
procedure
(response-parse payload)
→ (or/c positive-response? negative-response?) payload : bytes?
struct
(struct positive-response (sid sub-function data))
sid : (integer-in 0 255) sub-function : (or/c #f (integer-in 0 127)) data : bytes?
Record decoders for the common positive responses:
session-control-response — session type, P2 (ms) and P2* (ms; wire value × 10).
security-seed-response — the seed bytes.
max-block-length-response — maxNumberOfBlockLength.
number-of-dtc-response — format identifier and DTC count.
dtc-list-response — the DTC records as dtc? values.
transfer-data-response — echoed block counter and record.
7 Caveats
Authentication (SID 0x29) framing is included in the service table but no typed builder yet; use make-request.
Security algorithms (seed/key) are ECU-specific by design and stay with the caller.
The library does not manage sessions, timing (P2/P2*) or retransmission; pair it with isotp for the transport layer.