It’s a bit difficult to begin thinking about using the I2C bus when one doesn’t have documentation about the daemon on the phone end:
GitHub - sailfishos/symbiosis: Sailfish TOH service · GitHub is a dead link
Yep, maybe something to raise in the next community meeting.
But while symbiosis is supposed to be the daemon handling TOH, the i2c may already be usable. Playing around with i2cdetect from busybox-symlinks-i2c-tools may already allow to talk over the i2c pins of the phone? Looking in /dev/i2c-*, it seems there are several i2c buses on board, which is not surprising. Looking at permissions, only the bus 8 is usable by the default user. That may be an indication that this bus is the one exposed on the pogo pins.
I’ve some i2c gadgets at home that I would like to interface with the phone, but I first need to find a way to connect to the pogo pins reliably (my skills on board design and 3D printing are close to zero)…
Yeah, @poetaster I wonder if… ![]()
Ok, but if one can talk to devices directly, that would be best anyway, at least for a number of use cases I have in mind where I don’t really want the opinions of the OS gettting in my way ![]()
Here it landed : GitHub - sailfishos/symbiosis: Sailfish TOH service · GitHub and it’s written in Rust !
Oh, no. Not rust. Oh, no. EDIT, seriously, I will not go to rust land to build a TOH. Can we please have an example in C++.
If we look at symbiosis/src/bus.rs file, the i2c device is exposed by the kernel at /sys/devices/platform/soc/11d00000.i2c. And then, there is code to know to which device it is mapped to, by looking in that directory what is the name starting with i2c- followed by an index. In my case it is 0, so the i2c device is /dev/i2c-0 (and not /dev/i2c-8 as speculated before).
From comments in symbiosis/src/i2cdev.rs, that exposes a Rust API to read / write on the right i2c bus, this device may vary.
PS : I would have liked a C++ API also, but that can be an invite to learn more about Rust… and use rust-cbindgen to expose the Rust API into C and C++ ;-D
I’ve gone through the example after reading the spec of the device https://doc.awinic.com/doc/202310/17d55983-ee5c-4390-b95e-25a062925cd4.pdf
which is why I sort of did a ‘shudder’. I really, really dislike rust. I’d even prefer assembly.
EDIT: I must admit, even on linux (raspi) I’ve sort of resorted to doing raw device stuff and ignoring the system as much as I can.
I feel that I should clarify some things here. Symbiosis is indeed written in Rust, and a lot of that choice comes from the ability to write very reliable software without a lot of debugging. At the same time, there is no reason that any TOH specific services or drivers would need to be written in Rust too. Symbiosis exposes its functionality over D-Bus and config files. I haven’t yet written documentation on how to use either of those things but I should do that at some point. The idea is that symbiosis does as much of the automatic TOH detection and configuration as it can without resorting to anything specific about any TOH, including the official ones. Let’s see how that will end up but that has been my plan.
It is possible to write software against the library part of symbiosis, just like the example is but if you don’t want to do that, you should just look at the example config and the D-Bus interface. There is also a bit more in toh-content repo. They don’t necessarily cover everything that is in the configs though but that’s exactly why I should write some documentation, otherwise the code is the documentation.
And last, symbiosis is not yet released in Sailfish OS but it will be there – hopefully very soon – and it will replace the hacks that we wrote for Day1 to get something out so we can demonstrate Inari Blue’s LEDs. I do wish to build more of symbiosis together with the community.
I had sort of assumed as much. I’m a bit concerned about doing hardware in this context since I can’t get consistent behaviour out of the DBus at all (ie. attempted to use the s-office approach for a harbour compatible app, failed. though I have functional dbus using older workarounds). Although there is documentation, it seems difficult to apply. Probably just me.
Most of my I2C (and I2S, SPI) use is in an embedded context where communication on the wire is direct. In the example you give, (of the 3 led device) it does look fairly direct as well and I’m hoping for a raw example of a c(++) driver. Edit: often use GitHub - bitbank2/BitBang_I2C: A software I2C implementation to run on any GPIO pins on any system · GitHub
Can’t wait to see what kind of official ones comes out!
Equally interested to see what kind of 3rd party ones popup
Not critical, and I haven’t checked whether that’s already there, but on the app side I guess there will/needs to be a “ToH” sailjail permission to get access to that dbus interface?
Or is it accessible to any app (Base permission)?
Since no one else seems to have said it yet, let me be the first one: Thank you, I appreciate your work on this! Can’t wait to see what I can build with this.
(And I do appreciate your choice of Rust, too!)
Yeah, it definitely needs a firejail rule to allow that D-Bus interface. Whether it is a new sailjail permission or included in Base permission has not been decided yet. We need to discuss this more in the team still that how widely this would be accessible.
There are also discussions to have about packaging the TOH specific services and drivers that we have not yet had but we already know we will need to do things on the store side, in harbour validator and probably also in symbiosis for those.
So in practice the things you can already do with symbiosis D-Bus interfaces (assuming you build and install it, or wait until it is released in the OS), is to fetch information about attached TOH and access the i2c-dev character device. (Loading and binding drivers may also already work, if the kernel has the module loaded, but this part needs more work.) The character device is what the example uses and it’s basically just a file (descriptor) that you write and read. D-Bus should not get in the way here. The target device address is set with an ioctl on the file descriptor. This should be familiar to those that have done low level unix/posix things.
If you need more precise control, I think you should consider your options between creating a Linux driver (or using existing one if there is one) or having a microcontroller in between that buffers things and manages timings. I personally think that this i2c-dev is quite nice for talking to your own mcu. Bare metal embedded programming is quite different even from kernel driver development because you have control of pretty much everything, but when there is a non-realtime OS in control you don’t have so strict guarantees. And even less so if the code runs in userspace.
Thank you.
Your code helped me a lot in understanding how to communicate with the TOH and, ultimately, write an Automagic action that allows the Inari Blue to blink in different patterns. ![]()
Yes, I did recognize that it was basically the same register writing that I’m accustomed to, the bit bang library that I often use I also use on linux (raspis) but directly with GPIO pins (ie. no kernel driver at all). I’ll have to give it some thought, but the i2c-dev route should not be too difficult and it’s just a question of whether or not I want to deal with, ah, users ![]()
EDIT: just checked and the driver I’m using on the raspi …
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
so, same, same …
Is that in a recent version of automagic? I’ve only gotten to 1.0.32… EDIT, @fingus answered for me ![]()
Is it really necessary for the logic that changes the blinking pattern of the Inari Blue TOH to be run as root?
Reference:
I do not believe a ‘user’ can write to:
with open(f"/sys/devices/platform/soc/11d00000.i2c/i2c-{bus}/new_device", "w") as f:
as the python script does.