norly/elmcan

Installing elm327 on Ubuntu 20.04 - errors received

Closed this issue · 13 comments

Hello,

I'm trying to install the elm327 driver on Ubuntu 20.04 with kernel 5.4.0-113-generic with the following commands:

sudo modprobe can-dev
cd module/
sudo dkms install .

These commands results in the following error found at /var/lib/dkms/can327/1/build/make.log:

elm327

Whats going wrong?

Thanks!

Maybe something is going wrong with my kernel version: #if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)

I will try again today with a more recent Ubuntu distribution / kernel version.

BufferOverf;pw

It's working with a newer Ubuntu kernel. I think the driver can communicate with my OBD interface, but reveive a buffer overflow and blocked communication message almost directly after plugging in the OBD port. Is this the known problem with the ELM chip with too little memory?

norly commented

I'm trying to install the elm327 driver on Ubuntu 20.04 with kernel 5.4.0-113-generic with the following commands:
...
These commands results in the following error found at /var/lib/dkms/can327/1/build/make.log:

Looks like my efforts to make the driver compile on older kernels were not 100% successful. I try to be mindful of older kernels, but I don't test them unless someone complains like you did. Thanks for pointing this out, I'll look into it.

It's working with a newer Ubuntu kernel. I think the driver can communicate with my OBD interface, but reveive a buffer overflow and blocked communication message almost directly after plugging in the OBD port. Is this the known problem with the ELM chip with too little memory?

No, this is something else entirely: The serial port hands the driver too much data. Or in other words, can327's ELM327_SIZE_RXBUF is not large enough. Which is hard to imagine, because the serial port is sloooooow (I see you're using 115200 baud) and all UART buffers I've seen so far are a fraction of this driver's internal buffer. In normal operation, can327 should empty its RX buffer way before it runs full, hence the error message.

  1. Can you try commit 09f05c3 - i.e. just before my RX parser optimisation? Maybe it contains a mistake there that I have missed.
  2. Can you increase ELM327_SIZE_RXBUF to something big, like 1024 or 4096 and see if the error still happens? This shouldn't happen in the first place, but who knows.

What UART hardware is serving your /dev/ttyS0, maybe it has a huge buffer I've never heard of before?

What is the newer Ubuntu kernel's version?

Thanks for your fast response!

I'm using the vGate vLinker FS adapter with a Ford Fiesta MK8 from 2017. This adapter is recommended by the ForScan team, because it can automatically switch between the HSCAN en MSCAN busses without the need of a physical switch, so I can see and program everything with ForScan https://www.vgatemall.com/productinfo/661382.html. It has a 8192 bytes serial buffer and the manufacturer promise 3Mbps transmission speed. Also the default baudrate to connect with the adapter is 115200 bps. Internally this adapter is also based on the ELM327 chip (v2.2), and testing directly from the serial port with the AT MA command, I got a BUFFER FULL error after a few seconds. So I was thinking the problem was related with this chip in combination with my cars busy CAN bus. I've read some topics about this chip and why it's incompatible with candump/cansniffer by default, because of the low buffer... I've also a cheap China made elm327 adapter, but I have not tested this one together with the driver.

  1. How can I commit easily an older version of the driver? I don't have much experience with Git. I have an older snapshot of a clean Ubuntu version before installing the driver, so it's possible for me to install it again with other GIT commands easily. The kernel version I'm using right now is 5.15.0-35-generic.

  2. I will try this suggestion and let you know the results, thanks!

I've changed the following function

static bool can327_is_valid_rx_char(u8 c)

{
	static const bool lut_char_is_valid['z'] = {
		['\r'] = true,
		[' '] = true,
		['.'] = true,
		['0'] = true, true, true, true, true,
		['5'] = true, true, true, true, true,
		['<'] = true,
		[ELM327_READY_CHAR] = true,
		['?'] = true,
		['A'] = true, true, true, true, true, true, true,
		['H'] = true, true, true, true, true, true, true,
		['O'] = true, true, true, true, true, true, true,
		['V'] = true, true, true, true, true,
		['a'] = true,
		['b'] = true,
		['v'] = true,
		[ELM327_DUMMY_CHAR] = true,
	};
	BUILD_BUG_ON(ELM327_DUMMY_CHAR >= 'z');

	return (c < ARRAY_SIZE(lut_char_is_valid) &&
		lut_char_is_valid[c]);
}

To this function from an older release:

static bool can327_is_valid_rx_char(char c)
{
	return (isdigit(c) ||
		isupper(c) ||
		c == ELM327_DUMMY_CHAR ||
		c == ELM327_READY_CHAR ||
		c == '<' ||
		c == 'a' ||
		c == 'b' ||
		c == 'v' ||
		c == '.' ||
		c == '?' ||
		c == '\r' ||
		c == ' ');
}

And extends the buffer size to 4096:

#define ELM327_SIZE_RXBUF 4096

Now the adapter is working fine. Next step is to figure out the right CAN codes for some automation to work, but that's another challange. There are so many CAN codes haha. Thanks!

norly commented

Great, I'm glad to hear that it's working!
You did two changes. Can you please try only one at a time, and tell me which one helps?

I've also just pushed a new version, which prints how much the UART RX buffer overflowed by. Can you please give this a try, too?

Please don't forget to unload the driver (sudo rmmod can327) before loading another version.

I would like to fix this permanently, so you can simply use the code as-is (and hopefully get it included in Linux upstream!). Your help would be greatly appreciated!

BTW, I've fixed compilation on Linux v5.4 as well.

count256

Thanks! The driver is working fine with only the parameter #define ELM327_SIZE_RXBUF 4096 set.

norly commented

Thanks a lot for the screenshot! I'll have to increase ELM327_SIZE_RXBUF then.

Could you please also test the following ELM327_SIZE_RXBUF values?

  • 736 (= 224+2*256)
  • 992 (= 224+3*256)
    Basically, I'd like to use the smallest one which works without the error.

Also, can you please tell me what USB-UART bridge chip is used? It should be visible in the kernel messages immediately after plugging in the adapter. If that chip really has a 8192 byte buffer, then I'll have to be much more generous with the RX buffer.

For future reference, if someone revisits this ticket: I assume that the "Vgate vLinker FS OBD2" is a device based on either STN1110 or a similar ELM327 clone. The 115200 baud speed hints at this, as the STN1110 programming manual mentions it as the default speed for USB OBD adapters.

No errors reveived with #define ELM327_SIZE_RXBUF 736.

It's a virtual machine running from a Windows machine with serial port passthrough so no information is visible, so I will look at a physical Linux system to find out the UART bridge chip with dmesg.

It's a rainy day, so it's difficult to do more tests in the car. Hopefully you've enough information right now :)

norly commented

Oh, a VM. That explains why it was ttyS0 :)
And maybe it also explains the unexpectedly fat RX buffers being piped in by Linux's UART driver. Could it be that your adapter is really running at 3M baud, and the 115200 speed selected inside the VM is ignored? That would explain the high load.

Anyway, I'll increase the buffer to 992 then - if 736 was fine, then this is hopefully enough for a long time!

norly commented

Fixed in eea160f. Please keep an eye on your kernel messages, and please do reopen this ticket if the RX buffer needs further enlargement.

If you ever get to plug the adapter into a Linux box, I'd still appreciate some info on the USB UART chip. Of course, that doesn't need to happen in the car ;)

Thank you for your help!

Hello, thanks! I've an installed physical Linux machine in place haha, but no Linux installed on my laptop and it's hard to move the PC outside for reading CAN stuff in my car :)

Here is the dmesg log from my PC:

[ 84.379416] usb 8-1: new full-speed USB device number 3 using uhci_hcd
[ 84.592459] usb 8-1: New USB device found, idVendor=0403, idProduct=6015, bcdDevice=10.00
[ 84.592462] usb 8-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 84.592464] usb 8-1: Product: vLinker FS
[ 84.592466] usb 8-1: Manufacturer: www.vgatemall.com
[ 84.592468] usb 8-1: SerialNumber: D36DLMCN
[ 84.734157] usbcore: registered new interface driver usbserial_generic
[ 84.734166] usbserial: USB Serial support registered for generic
[ 84.748007] usbcore: registered new interface driver ftdi_sio
[ 84.748111] usbserial: USB Serial support registered for FTDI USB Serial Device
[ 84.748249] ftdi_sio 8-1:1.0: FTDI USB Serial Device converter detected
[ 84.748329] usb 8-1: Detected FT-X
[ 84.752601] usb 8-1: FTDI USB Serial Device converter now attached to ttyUSB0

In my Windows device manager the adapter was configured with 115200 baudrate. I don't know how Linux VM interacts with the Windows host and the device and if something is ignored, but it's working :). I can try with wrong baudrates inside the VM and see what happened. With the Forscan app in Windows it was required to configure the baudrate to 115200 inside the app.

norly commented

Ah, so it's an FTDI chip. And looking around, they do seem to have huge buffers. For example, the FT232B has a 384 byte UART RX buffer, and the newer FT232R still has 256 bytes:
https://ftdichip.com/products/ft232bq/
https://ftdichip.com/products/ft232rl/

So the way larger ELM327_SIZE_RXBUF is really important. The above FTDI specs still can't explain why it overflowed as much as it did (224 bytes buffer, plus 256 bytes left unprocessed) but maybe this is some additional buffering going on at the virtualisation level.

Thank you, and enjoy tinkering with your apparently really busy CAN bus!