Search code examples
linux-device-driverd

How can I access a linux character device with D?


I would like to turn a led (character device) of an embedded linux board (BeagleBone Black) on and off with a script written in D.

Via the command line a led can be turned on and off (e.g. for led "USER LEDS D2 0") with:

cd /sys/class/leds/beaglebone:green:usr0
echo none > trigger
echo 1 > brightness
echo 0 > brightness

(echo none > trigger disables the default "heartbeat" flashing)

In the D Cookbook on page 93 I found info about how to make linux system calls via the C interface like follows:

void main(){
   import core.sys.posix.unistd;  // analogous to #include <unistd.h>
   string hello = "Hello, world!";
   write(1 /*stdout file descriptor*/, hello.ptr, hello.length);
}

Is that a suitable way to access a character device or are there better alternatives?


Solution

  • The unistd calls are indeed the correct way to do it. A character device in Linux is a special kind of file and is accessed the same way: you open it by path, then read or write to it, and close it when finished.

    Note that open is actually inside core.sys.posix.fcntl, while read is in core.sys.posix.unistd.

    You could also use std.file.write() from the D standard library to be a bit shorter. There's also chdir in there. So your shell example would literally become:

    import std.file;
    chdir("/sys/class/leds/beaglebone:green:usr0");
    std.file.write("trigger", "none"); // write "filename", "data string"
    std.file.write("brightness", "1");
    std.file.write("brightness", "0");
    

    You don't strictly have to use std.file.write as the full name with the import, I just like to since write is such a common word it clears up which one we mean.

    Anyway, this function just wraps up the unistd calls for you: it opens, writes the string, and closes all in one (just like the shell echo!).

    One small difference is shell echo sticks a \n at the end of the string. I didn't do that here. If the code doesn't work, try "1\n" and such instead, maybe the device requires that. But I doubt it.

    But the std.file.write vs the core.sys.posix.unistd.write aren't that much different. The former is more convenient, the latter gives more precise control over it.