Hi @eric.tx, thanks for the quick reply. So I use docker compose to create the container stack for this application and I have two sensors connected to the i2c-3 bus. Looking at the samples, I added the following to my dev-compose.yml file:
volumes: # named volumes for source and caches
- /dev:/dev
device_cgroup_rules:
- 'c 89:* rmw'
devices: # needed for I2C access (e.g. Toradex) ... sets to null if not set in .env
- ${I2C_DEVICE:-/dev/null}
I have a .env file with the following in it:
I2C_DEVICE=/dev/verdin-i2c1
On my setup with the mallow carrier board, verdin-i2c1
is mapped to i2c-3
. I then create the container on the development board using the following docker compose command. This creates the container and keeps it running via an entrypoint script with an attached bash shell:
docker --context devboard-lab compose -f docker/dev-compose.yml --env-file ./.env up -d
The entrypoint in the compose yml looks like this:
entrypoint: ["/bin/bash", "-c", 'echo "$$ENTRYPOINT_SCRIPT" > /home/${USERNAME}/entrypoint.sh && chmod +x /home/${USERNAME}/entrypoint.sh && /home/${USERNAME}/entrypoint.sh "tail -f /dev/null"']
Once the contianer is up and running, I use the following docker exec command to connect to it:
docker --context devboard-lab exec -it sensor-dev bash
This sets up a terminal window into the container. I can then run cargo build and run commands from there as the user rustdev
. With the moutning of the dev
volume and cgroup
rules, I would expect that I can then run my program that reads from the /dev/verdin-i2c1
device.
To debug, I can list the contents of the /dev
folder and see all of the i2c devices and symbolic links. When running i2cdetect -l
as a non-root user (rustdev), I get the following:
i2c-0 unknown 30a20000.i2c N/A
i2c-1 unknown 30a30000.i2c N/A
i2c-2 unknown 30a40000.i2c N/A
i2c-3 unknown 30a50000.i2c N/A
i2c-4 unknown DesignWare HDMI N/A
If running the same command with sudo, the output shows the bus instead of “unknown” as follows:
sudo: unable to resolve host verdin-imx8mp-15132666: Name or service not known
i2c-0 i2c 30a20000.i2c I2C adapter
i2c-1 i2c 30a30000.i2c I2C adapter
i2c-2 i2c 30a40000.i2c I2C adapter
i2c-3 i2c 30a50000.i2c I2C adapter
i2c-4 i2c DesignWare HDMI I2C adapter
Running i2cdetect -y 3
to show the bus 3 devices, I get a permissions error:
Error: Could not open file `/dev/i2c-3': Permission denied
Run as root?
Running the command again as sudo, it outputs the expected:
sudo: unable to resolve host verdin-imx8mp-15132666: Name or service not known
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- UU
50: -- -- -- 53 -- -- -- UU -- -- -- -- -- -- -- 5f
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
When running my application, I use the following comand line:
cargo run -- --orb-name Saraswati --skip-warmup -i ${I2C_DEVICE}
The program runs and generates the expected output until it gets to the first i2c bus read and write and then gets a PermissionDenied
error. The output looks like the following:
2025-03-19T20:14:11.780407Z INFO main ThreadId(01) hazmat: src/main.rs:204: Starting hazmat sensor monitoring...
2025-03-19T20:14:11.780661Z INFO main ThreadId(01) hazmat: src/main.rs:205: Log level set log_level=Level(Info)
2025-03-19T20:14:11.780765Z INFO main ThreadId(01) hazmat: src/main.rs:206: I2C bus configured i2c_bus="/dev/verdin-i2c1"
2025-03-19T20:14:11.780864Z INFO main ThreadId(01) hazmat: src/main.rs:207: Log directory configured log_path="logs"
2025-03-19T20:14:11.780975Z INFO main ThreadId(01) hazmat: src/main.rs:208: Temperature unit configured temp_unit=Both
2025-03-19T20:14:11.781089Z INFO main ThreadId(01) hazmat: src/main.rs:209: Polling interval set interval="1s"
2025-03-19T20:14:11.781211Z INFO main ThreadId(01) hazmat: src/main.rs:210: EdgeDB DSN db_dsn="edgedb://edgedb:@localhost:5656"
2025-03-19T20:14:11.781335Z INFO main ThreadId(01) hazmat: src/main.rs:211: Simulation mode: DISABLED simulation=false
2025-03-19T20:14:11.782339Z INFO main ThreadId(01) hazmat::database: src/database.rs:141: EdgeDB client initialized
2025-03-19T20:14:11.830498Z INFO main ThreadId(01) hazmat: src/main.rs:224: Using sensor name="HazmatAQI" type_id=3 instance_id=1
2025-03-19T20:14:11.830972Z INFO main ThreadId(01) hazmat: src/main.rs:253: Using REAL hardware sensors
2025-03-19T20:14:11.831362Z INFO main ThreadId(01) hazmat: src/main.rs:254: Note: ENS160 sensor requires up to 1 hour after first power-on for full accuracy
Error: Communication(Io(Os { code: 13, kind: PermissionDenied, message: "Permission denied" }))
I can run the program with sudo as follows:
2025-03-19T20:16:19.569974Z INFO main ThreadId(01) hazmat: src/main.rs:204: Starting hazmat sensor monitoring...
2025-03-19T20:16:19.570213Z INFO main ThreadId(01) hazmat: src/main.rs:205: Log level set log_level=Level(Info)
2025-03-19T20:16:19.570324Z INFO main ThreadId(01) hazmat: src/main.rs:206: I2C bus configured i2c_bus="/dev/verdin-i2c1"
2025-03-19T20:16:19.570456Z INFO main ThreadId(01) hazmat: src/main.rs:207: Log directory configured log_path="logs"
2025-03-19T20:16:19.570561Z INFO main ThreadId(01) hazmat: src/main.rs:208: Temperature unit configured temp_unit=Both
2025-03-19T20:16:19.570677Z INFO main ThreadId(01) hazmat: src/main.rs:209: Polling interval set interval="1s"
2025-03-19T20:16:19.570790Z INFO main ThreadId(01) hazmat: src/main.rs:210: EdgeDB DSN db_dsn="edgedb://edgedb:@localhost:5656"
2025-03-19T20:16:19.570925Z INFO main ThreadId(01) hazmat: src/main.rs:211: Simulation mode: DISABLED simulation=false
2025-03-19T20:16:19.571911Z INFO main ThreadId(01) hazmat::database: src/database.rs:141: EdgeDB client initialized
2025-03-19T20:16:19.615374Z INFO main ThreadId(01) hazmat: src/main.rs:224: Using sensor name="HazmatAQI" type_id=3 instance_id=1
2025-03-19T20:16:19.616037Z INFO main ThreadId(01) hazmat: src/main.rs:253: Using REAL hardware sensors
2025-03-19T20:16:19.616318Z INFO main ThreadId(01) hazmat: src/main.rs:254: Note: ENS160 sensor requires up to 1 hour after first power-on for full accuracy
2025-03-19T20:16:19.616556Z INFO main ThreadId(01) hazmat::ens160: src/ens160.rs:68: Starting ENS160 initialization...
2025-03-19T20:16:19.821755Z WARN main ThreadId(01) hazmat::ens160: src/ens160.rs:98: Skipping warm-up wait. Initial readings may be inaccurate.
2025-03-19T20:16:19.929436Z INFO main ThreadId(01) hazmat::hts221: src/hts221.rs:111: Calibration data loaded
2025-03-19T20:16:19.930908Z INFO main ThreadId(01) hazmat::hts221: src/hts221.rs:73: HTS221 Status after init: 0x03
2025-03-19T20:16:19.931144Z INFO main ThreadId(01) hazmat: src/main.rs:276: Waiting for initial sensor stabilization...
2025-03-19T20:16:20.932210Z INFO main ThreadId(01) hazmat: src/main.rs:279: Starting main loop...
2025-03-19T20:16:20.936090Z INFO main ThreadId(01) hazmat: src/main.rs:293: Environmental data: temperature="24.016°C / 75.229°F" humidity="47.812 %RH"
2025-03-19T20:16:20.972493Z INFO main ThreadId(01) hazmat: src/main.rs:313: Air quality data: eCO2="431 (ppm)" TVOC="38 (ppb)" AQI="1 (1-5)" position="lat=33.258146°, lon=-97.149276°, alt=300.0m, hdg=180.0°, spd=12.0m/s"
2025-03-19T20:16:22.007083Z INFO main ThreadId(01) hazmat: src/main.rs:293: Environmental data: temperature="23.998°C / 75.196°F" humidity="47.935 %RH"
2025-03-19T20:16:22.030071Z INFO main ThreadId(01) hazmat: src/main.rs:313: Air quality data: eCO2="400 (ppm)" TVOC="23 (ppb)" AQI="1 (1-5)" position="lat=33.258146°, lon=-97.149276°, alt=300.0m, hdg=180.0°, spd=12.0m/s"
2025-03-19T20:16:23.060569Z INFO main ThreadId(01) hazmat: src/main.rs:293: Environmental data: temperature="23.961°C / 75.129°F" humidity="47.865 %RH"
2025-03-19T20:16:23.081523Z INFO main ThreadId(01) hazmat: src/main.rs:313: Air quality data: eCO2="405 (ppm)" TVOC="26 (ppb)" AQI="1 (1-5)" position="lat=33.258146°, lon=-97.149276°, alt=300.0m, hdg=180.0°, spd=12.0m/s"
So it works under sudo but not as a user. This seems to be corroborated by the fact that i2cdetect can’t read any i2c bus using the -y parameter unless also run under sudo. I have tried using privileged: true
in the compose file, but the behavior is the same.
Based on the checking I have done, it appears that the cgroup
and privileged
entries are ignored. I have tried other ways by adding rmw
to the devices entry, but nothing seems to allow access to the i2c bus from user mode.
I would like to not have to run this program as sudo in the production container, so any help in resolving this would be most appreaciated.