linux-embedded-hal icon indicating copy to clipboard operation
linux-embedded-hal copied to clipboard

2 Writes give "Operation not supported on transport endpoint"

Open fishrockz opened this issue 5 months ago • 4 comments

I was trying to get the examples in https://github.com/alexeden/adafruit-seesaw to work on linux but i kept getting errors

I managed to track down the problem to this MVP example

use embedded_hal::i2c::{Error, I2c, Operation};
use linux_embedded_hal::{Delay, I2CError, I2cdev, i2cdev::core::I2CDevice};

fn main() {
    let mut i2c = I2cdev::new("/dev/i2c-10").unwrap();

    let regester_num: &[u8] = &[0x00, 0x7F];
    let mut data = [0xFF];
    let mut ops = [Operation::Write(regester_num), Operation::Write(&data)];
    i2c.transaction(0x36_u8, &mut ops).unwrap();
}
thread 'main' panicked at crates/rig/src/bin/gps.rs:10:40:
called `Result::unwrap()` on an `Err` value: I2CError { err: Errno(95) }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

using https://www.adafruit.com/product/4471 and https://www.adafruit.com/product/5880 but i had the same issue with other i2c peripherals.

95 	EOPNOTSUPP 	Operation not supported on transport endpoint

Please note that a single write of a longer array does not cause the same error.

It should be noted that a single write operation with a longer array does run, let mut ops = [Operation::Write(&[0x00, 0x7F, 0xFF ])]

I cant tell if im doing something wrong or if there is a bug some were.

fishrockz avatar Jul 25 '25 00:07 fishrockz

I think this is an error the kernel might return if the driver for the i2cdev you are talking to doesn't support smbus or the particular transfer you are attempting. What's your host hardware and/or the device you're using to talk SPI to the seesaw?

posborne avatar Jul 25 '25 06:07 posborne

I get this with both https://www.adafruit.com/product/4471 and https://thepihut.com/products/usb-uart-i2c-debugger which I think both use MCP2221

❯ lsusb
Bus 001 Device 057: ID 04d8:00dd Microchip Technology, Inc. MCP2221(a) UART/I2C Bridge

The data sheet seems to suggest that this does support smbus https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP2221A-Data-Sheet-20005565E.pdf

I have tried two write operation with other non seasaw peripherals and get similar.

I can write then read eg

-    let mut ops = [Operation::Write(regester_num), Operation::Write(data)];
+    let mut ops = [Operation::Write(regester_num), Operation::Read(data)];

Does anyone have a known good i2c adaptor that supports 2 write operations in series?

fishrockz avatar Jul 25 '25 11:07 fishrockz

Here's the kernel code for the mcp https://github.com/torvalds/linux/blob/327579671a9becc43369f7c0637febe7e03d4003/drivers/hid/hid-mcp2221.c#L353-L405 which does indeed look off to me in that it assumes that you're going to do a write then a read.

I haven't used it, but I think you can reprogram a Pi Pico using i2c-pco-usb to emulate the i2c-tiny which has a driver in tree. I took a quick look and it seemed to not have similar quirks in its master_xfer code.

posborne avatar Jul 25 '25 16:07 posborne

Looking at the datasheet it looks like the chip itself does support multiple writes in the same transaction. What isn't supported is a read followed by a write, so it can't implement all combinations supported by i2c.transaction(). The driver implemented in the linux kernel however only implements a single write followed by a single read.

There also is a rust driver for the device that seems to be talking to the USB bus directly, not using the hid-mcp2221 driver. Maybe you can use that instead of linux-embedded-hal, to circumvent the kernel limitations? https://docs.rs/mcp2221-hal/latest/mcp2221_hal/struct.MCP2221.html#i2c

Anyway, this doesn't look like an issue linux-embedded-hal could solve.

jannic avatar Nov 19 '25 21:11 jannic