Skip to content

J2534 Support#101

Merged
pd0wm merged 25 commits into
I-CAN-hack:mainfrom
bri3d:j2534
Mar 13, 2026
Merged

J2534 Support#101
pd0wm merged 25 commits into
I-CAN-hack:mainfrom
bri3d:j2534

Conversation

@bri3d

@bri3d bri3d commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

Hi! I have been using this for the past few weeks as part of a rewrite of my VW reflashing stuff and it seems to be doing well.

I will gladly admit this was mostly Claude'd, but I fixed the Claude mistakes as I went and I have hand-reviewed the code and confirmed that I can reflash using both the native and adapter ISO-TP versions, so that's a pretty strong integration test IMO.

What does this do:

  • Fixes some threading-related exit issues in async_can, mostly not double-panicking if the adapter dropped before the parent Drop.
  • Removes Sync from AsyncCanAdapter itself, it's not needed in this location.
  • Breaking (ish, not sure if anyone externally ever used this but it's technically a public API): adds IsoTpTransport trait for IsoTpAdapter so we can swap it out for the J2534 version.
  • Fixes a 32-bit safety issue with ISO_TP_FD_MAX_DLEN where we wanted INT_MAX but didn't calculate it the right way.
  • Adds src/j2534 with J2534 adapter code. There are two adapters here, j2534::CanAdapter which follows the patterns from the AsyncCanAdapter throughout the project, and j2534::IsoTpAdapter which instead implements the new IsoTpTransport (replacing IsoTpAdapter) which allows the use of J2534 adapters which have firmware-implemented ISO-TP. Both implementations use libloading to load up the J2534 DLL and create pointers to the J2534 API functions.

Support for J2534 is a bit incomplete; only native CAN and ISO15765 are supported on the native pins, not any other protocols (although the crate in general doesn't really support anything else, so this is probably OK) and not any weird pin setup / voltage setup / hackery IOCTLs. Extended address support seemed to work but is mostly untested.

Testing:

  • Reflashed VW ECUs using OpenPort 2.0 and an in-house interface, so I have some confidence in the STMIN/STMIN_TX support, the overall adapter support, and the general quality of the code.

Weird gotchas:

  • The default minimum time for native sleep calls on Windows is 1/64 second; the Windows NT timer runs at 64Hz. Somehow the Rust + Tokio runtimes don't patch over this, meaning for reasonable performance as implemented the consumer has to set the timer granularity to 1000Hz using timeBeginPeriod. Even then, the minimum granularity for anything that sleeps, ever, is still 1ms, so nothing is truly compliant with the native interface and it's way slower than firmware ISO-TP. That's Windows, baby! (the solution is to use one of the more modern Windows high resolution timing APIs in place of Tokio's sleep API, but that seemed like a big surgery for this change which is almost completely additive).
  • As you know, a lot of J2534 DLLs are 32-bit, so we have to use 32-bit Rust to interface with those. I fixed the build to work on 32-bit but it's still silly. Claude implemented a rather over-wrought system for detecting if the wrong DLL is used and warning the user, which I thought was kind of cool.

As you know, I am unfortunately cleaning out my automotive closet as I may have to take a hiatus from this line of work, but I will try to support feedback and get this through as time allows.

@pd0wm pd0wm merged commit c0facb6 into I-CAN-hack:main Mar 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants