can, tty: elmcan CAN/ldisc driver for ELM327 based OBD-II adapters
PATCH v5 1/1 can, tty: elmcan CAN/ldisc driver for ELM327 based OBD-II adapters
This is the elmcan driver. It does a surprisingly good job at turning ELM327 based OBD-II interfaces into cheap CAN interfaces for simple homebrew projects.
Please see the included documentation for details and limitations:Documentation/networking/device_drivers/can/elmcan.rst
---
Many thanks to Greg, Marc, Vincent for reviewing v3!
I've CC'd you hoping you'd check whether you are happy with the changes. Please do let me know.
Changes in v5:
- Fixed lockdep asserts (I didn't have lockdep enabled in my build)
- Restore: TTY wakeup request before write() in elm327_send()
- Clear TTY wakeup on uart_side_failure
- checkpatch style fixes
- Repack struct elmcan
Changes in v4:
- Rebased on top of v5.18-rc5
- Simplified TTY locking.
The ldisc layer already blocks our ldisc ops from running concurrently. No elm_get(), no RCU are needed, except locking against the TX worker.
- Removed .hangup() ldisc op which only called .close().
The ldisc layer calls .close() in a good place anyway.
- Restart on netdev down/up, even after UART failure.
This is in line with Marc's line of thinking, and there was no good reason not to implement it. It also cleaned up the code.
- hw_failure is now uart_side_failure and shutdown looks closer to es58x.
- Clarified memory/string comparisons.
One helper function remains, but it's hopefully clear now :)
- lockdep_assert_held() instead of comments.
- Cleaned up types in struct elmcan and used pahole to pack it. unsigned instead of int, u8 instead of char, ...
- The TX buffer is now a static part of struct elmcan. No more kmalloc().
- Removed dummy mailbox_read() for rx_offload.
by using can_rx_offload_add_manual() instead of can_rx_offload_add_fifo().
- netif_wake_queue() is moved to happen as late as possible.
Wake when the ELM327 is going into monitoring mode, not every time after flushing whatever UART buffer we were TX'ing.
- Use alloc_can_skb() and avoid late allocation and copy.
- elmcan_netdev_start_xmit(): Used can_dropped_invalid_skb().
- Replaced ->can_dlc with ->len.
- Clarified size of local TX buffer in elm327_handle_prompt().
- Renamed TODO_* to ELM327_TX_DO_* and ELM_* to ELM327_STATE_*.
- Minor string and other cleanups.
pr_fmt, MODULE_*, unnecessary checks, ...
- Clarified file header.
Changes in v3:
- Now depends on c2faf737abfb for new ldisc number 30.
- Eliminated hardcoded string lengths (GCC will work its magic).
- Emit generic error frames if an error message couldn't be parsed.
- Silence driver startup and init (but still announce ldattach).
- Cleaned up comments, strings, readme.
- Removed sole module option "accept_flaky_uart".
I likely had EMI in earlier testing, which is gone now. This means we can stay strict, unless anyone objects.
Changes in v2:
- Moved to SocketCAN's rx-offload wrapper for NAPI, thus avoiding packets being reordered.
- Updated TTY ldisc code for Linux v5.17-rc3. A lot of cleanup has happened there lately.
- netif_stop_queue() is called earlier in _netdev_close().
- Minor cleanup: More helpful strings and return values.
--- .../networking/device_drivers/can/elmcan.rst | 325 +++++ .../networking/device_drivers/can/index.rst | 1 + MAINTAINERS | 7 + drivers/net/can/Kconfig | 17 + drivers/net/can/Makefile | 1 + drivers/net/can/elmcan.c | 1152 +++++++++++++++++ include/uapi/linux/tty.h | 3 +- 7 files changed, 1505 insertions(+), 1 deletion(-) create mode 100644 Documentation/networking/device_drivers/can/elmcan.rst create mode 100644 drivers/net/can/elmcan.c
Documentation/networking/device_drivers/can/elmcan.rst new file +325 -0
@@ -0,0 +1,325 @@ +.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) + +ELM327 driver for Linux SocketCAN +================================== + +Authors +-------- + +Max Staudt <[email protected]> + + + +Motivation +----------- + +This driver aims to lower the initial cost for hackers interested in +working with CAN buses. + +CAN adapters are expensive, few, and far between. +ELM327 interfaces are cheap and plentiful. +Let's use ELM327s as CAN adapters. + + + +Introduction +------------- + +This driver is an effort to turn abundant ELM327 based OBD interfaces +into full fledged (as far as possible) CAN interfaces. + +Since the ELM327 was never meant to be a stand alone CAN controller, +the driver has to switch between its modes as quickly as possible in +order to fake full-duplex operation. + +As such, elmcan is a best effort driver. However, this is more than +enough to implement simple request-response protocols (such as OBD II), +and to monitor broadcast messages on a bus (such as in a vehicle). + +Most ELM327s come as nondescript serial devices, attached via USB or +Bluetooth. The driver cannot recognize them by itself, and as such it +is up to the user to attach it in form of a TTY line discipline +(similar to PPP, SLIP, slcan, ...). + +This driver is meant for ELM327 versions 1.4b and up, see below for +known limitations in older controllers and clones. + + + +Data sheet +----------- + +The official data sheets can be found at ELM electronics' home page: + + https://www.elmelectronics.com/ + + + +How to check the controller version +------------------------------------ + +Use a terminal program to attach to the controller. +The default settings are 38400 baud/s, 8 data bits, no parity, 1 stopbit. + +After issuing the "``AT WS``" command, the controller will respond with +its version:: + + >AT WS + + + ELM327 v1.4b + + > + +Note that clones may claim to be any version they like. +It is not indicative of their actual feature set. + + + +How to attach the line discipline +---------------------------------- + +Every ELM327 chip is factory programmed to operate at a serial setting +of 38400 baud/s, 8 data bits, no parity, 1 stopbit. + +The line discipline can be attached on a command prompt as follows:: + + sudo ldattach \ + --debug \ + --speed 38400 \ + --eightbits \ + --noparity \ + --onestopbit \ + --iflag -ICRNL,INLCR,-IXOFF \ + 30 \ + /dev/ttyUSB0 + +To change the ELM327's serial settings, please refer to its data +sheet. This needs to be done before attaching the line discipline. + +Once the ldisc is attached, the CAN interface starts out unconfigured. +Set the speed before starting it: + + # The interface needs to be down to change parameters + sudo ip link set can0 down + sudo ip link set can0 type can bitrate 500000 + sudo ip link set can0 up + +500000 bit/s is a common rate for OBD-II diagnostics. +If you're connecting straight to a car's OBD port, this is the speed +that most cars (but not all!) expect. + +After this, you can set out as usual with candump, cansniffer, etc. + + + +Known limitations of the controller +------------------------------------ + +- Clone devices ("v1.5" and others) + + Sending RTR frames is not supported and will be dropped silently. + + Receiving RTR with DLC 8 will appear to be a regular frame with + the last received frame's DLC and payload. + + "``AT CSM``" not supported, thus no ACK-ing frames while listening: + "``AT MA``" will always be silent. However, immediately after + sending a frame, the ELM327 will be in "receive reply" mode, in + which it *does* ACK any received frames. Once the bus goes silent + or an error occurs (such as BUFFER FULL), the ELM327 will end reply + reception mode on its own and elmcan will fall back to "``AT MA``" + in order to keep monitoring the bus. + + +- All versions + + No full duplex operation is supported. The driver will switch + between input/output mode as quickly as possible. + + The length of outgoing RTR frames cannot be set. In fact, some + clones (tested with one identifying as "``v1.5``") are unable to + send RTR frames at all. + + We don't have a way to get real-time notifications on CAN errors. + While there is a command (``AT CS``) to retrieve some basic stats, + we don't poll it as it would force us to interrupt reception mode. + + +- Versions prior to 1.4b + + These versions do not send CAN ACKs when in monitoring mode (AT MA). + However, they do send ACKs while waiting for a reply immediately + after sending a frame. The driver maximizes this time to make the + controller as useful as possible. + + Starting with version 1.4b, the ELM327 supports the "``AT CSM``" + command, and the "listen-only" CAN option will take effect. + + +- Versions prior to 1.4 + + These chips do not support the "``AT PB``" command, and thus cannot + change bitrate or SFF/EFF mode on-the-fly. This will have to be + programmed by the user before attaching the line discipline. See the + data sheet for details. + + +- Versions prior to 1.3 + + These chips cannot be used at all with elmcan. They do not support + the "``AT D1``" command, which is necessary to avoid parsing conflicts + on incoming data, as well as distinction of RTR frame lengths. + + Specifically, this allows for easy distinction of SFF and EFF + frames, and to check whether frames are complete. While it is possible + to deduce the type and length from the length of the line the ELM327 + sends us, this method fails when the ELM327's UART output buffer + overruns. It may abort sending in the middle of the line, which will + then be mistaken for something else. + + + +Known limitations of the driver +-------------------------------- + +- No 8/7 timing. + + ELM327 can only set CAN bitrates that are of the form 500000/n, where + n is an integer divisor. + However there is an exception: With a separate flag, it may set the + speed to be 8/7 of the speed indicated by the divisor. + This mode is not currently implemented. + +- No evaluation of command responses. + + The ELM327 will reply with OK when a command is understood, and with ? + when it is not. The driver does not currently check this, and simply + assumes that the chip understands every command. + The driver is built such that functionality degrades gracefully + nevertheless. See the section on known limitations of the controller. + +- No use of hardware CAN ID filtering + + An ELM327's UART sending buffer will easily overflow on heavy CAN bus + load, resulting in the "``BUFFER FULL``" message. Using the hardware + filters available through "``AT CF xxx``" and "``AT CM xxx``" would be + helpful here, however SocketCAN does not currently provide a facility + to make use of such hardware features. + + + +Communication example +---------------------- + +This is a short and incomplete introduction on how to talk to an ELM327. + + +The ELM327 has two modes: + +- Command mode +- Reception mode + +In command mode, it expects one command per line, terminated by CR. +By default, the prompt is a "``>``", after which a command can be +entered:: + + >ATE1 + OK + > + +The init script in the driver switches off several configuration options +that are only meaningful in the original OBD scenario the chip is meant +for, and are actually a hindrance for elmcan. + + +When a command is not recognized, such as by an older version of the +ELM327, a question mark is printed as a response instead of OK:: + + >ATUNKNOWN + ? + > + +At present, elmcan does not evaluate this response and silently assumes +that all commands are recognized. It is structured such that it will +degrade gracefully when a command is unknown. See the sections above on +known limitations for details. + + +When a CAN frame is to be sent, the target address is configured, after +which the frame is sent as a command that consists of the data's hex +dump:: + + >ATSH123 + OK + >DEADBEEF12345678 + OK + > + +The above interaction sends the frame "``DE AD BE EF 12 34 56 78``" with +the 11 bit CAN ID ``0x123``. +For this to function, the controller must be configured for 11 bit CAN +ID sending mode (using "``AT PB``", see code or datasheet). + + +Once a frame has been sent and wait-for-reply mode is on (``ATR1``, +configured on ``listen-only=off``), or when the reply timeout expires and +the driver sets the controller into monitoring mode (``ATMA``), the ELM327 +will send one line for each received CAN frame, consisting of CAN ID, +DLC, and data:: + + 123 8 DEADBEEF12345678 + +For 29 bit CAN frames, the address format is slightly different, which +elmcan uses to tell the two apart:: + + 12 34 56 78 8 DEADBEEF12345678 + +The ELM327 will receive both 11 and 29 bit frames - the current CAN +config (``ATPB``) does not matter. + + +If the ELM327's internal UART sending buffer runs full, it will abort +the monitoring mode, print "BUFFER FULL" and drop back into command +mode. Note that in this case, unlike with other error messages, the +error message may appear on the same line as the last (usually +incomplete) data frame:: + + 12 34 56 78 8 DEADBEEF123 BUFFER FULL + + + +Rationale behind the chosen configuration +------------------------------------------ + +``AT E1`` + Echo on + + We need this to be able to get a prompt reliably. + +``AT S1`` + Spaces on + + We need this to distinguish 11/29 bit CAN addresses received. + + Note: + We can usually do this using the line length (odd/even), + but this fails if the line is not transmitted fully to + the host (BUFFER FULL). + +``AT D1`` + DLC on + + We need this to tell the "length" of RTR frames. + + + +A note on CAN bus termination +------------------------------ + +Your adapter may have resistors soldered in which are meant to terminate +the bus. This is correct when it is plugged into a OBD-II socket, but +not helpful when trying to tap into the middle of an existing CAN bus. + +If communications don't work with the adapter connected, check for the +termination resistors on its PCB and try removing them.
Documentation/networking/device_drivers/can/index.rst +1 -0
@@ -10,6 +10,7 @@ Contents: .. toctree:: :maxdepth: 2 + elmcan freescale/flexcan .. only:: subproject and html
MAINTAINERS +7 -0
@@ -7218,6 +7218,13 @@ L: [email protected] S: Maintained F: drivers/net/ethernet/ibm/ehea/ +ELM327 CAN NETWORK DRIVER +M: Max Staudt <[email protected]> +L: [email protected] +S: Maintained +F: Documentation/networking/device_drivers/can/elmcan.rst +F: drivers/net/can/elmcan.c + EM28XX VIDEO4LINUX DRIVER M: Mauro Carvalho Chehab <[email protected]> L: [email protected]
drivers/net/can/Kconfig +17 -0
@@ -180,6 +180,23 @@ source "drivers/net/can/softing/Kconfig" source "drivers/net/can/spi/Kconfig" source "drivers/net/can/usb/Kconfig" +config CAN_ELMCAN + tristate "Serial / USB serial ELM327 based OBD-II Interfaces (elmcan)" + depends on TTY + help + CAN driver for several 'low cost' OBD-II interfaces based on the + ELM327 OBD-II interpreter chip. + + This is a best effort driver - the ELM327 interface was never + designed to be used as a standalone CAN interface. However, it can + still be used for simple request-response protocols (such as OBD II), + and to monitor broadcast messages on a bus (such as in a vehicle). + + Please refer to the documentation for information on how to use it: + Documentation/networking/device_drivers/can/elmcan.rst + + If this driver is built as a module, it will be called elmcan. + endif config CAN_DEBUG_DEVICES
drivers/net/can/Makefile +1 -0
@@ -6,6 +6,7 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o obj-$(CONFIG_CAN_VXCAN) += vxcan.o obj-$(CONFIG_CAN_SLCAN) += slcan.o +obj-$(CONFIG_CAN_ELMCAN) += elmcan.o obj-y += dev/ obj-y += rcar/
drivers/net/can/elmcan.c new file +1152 -0
1,152 lines not on this page · raw message
include/uapi/linux/tty.h +2 -1
@@ -38,8 +38,9 @@#define N_NULL 27/* Null ldisc used for error handling */ #define N_MCTP 28/* MCTP-over-serial */ #define N_DEVELOPMENT 29/* Manual out-of-tree testing */ +#define N_ELMCAN 30/* Serial / USB serial OBD-II Interfaces */ /* Always the newest line discipline + 1 */ -#define NR_LDISCS 30 +#define NR_LDISCS 31#endif /* _UAPI_LINUX_TTY_H */
Signature · 1 line
2.30.2