如何在安卓上打开GPIO芯片?

huangapple go评论89阅读模式
英文:

How to open GPIO chip on Android?

问题

以下是您要翻译的内容:

尝试访问运行Android的嵌入式系统上的GPIO线路。使用GPIO字符设备接口(而不是已过时且似乎不在目标系统上的sysfs)。在C中编写(带有JNI包装器),因为我认为在Java中无法完成。

问题:调用open()总是失败(返回-1)

在模拟器上,errno是ENOENT(未找到),这是有道理的,因为显然它没有GPIO设置。在我的开发板上,我得到了一个已知存在的路径的EACCESS(访问被拒绝)。此外,对于已知不存在的路径,我得到ENOENT。因此,似乎open找到了路径然后拒绝访问。

问题:在Android中是否可能使用GPIO?或者Android是否非常严密,以至于这不可能?如果可能,我该如何做?

具有JNI包装的C代码:

JNIEXPORT jstring JNICALL Java_com_example_test_1jni_MainActivity_openGpioChip(JNIEnv* env, jobject _this, jstring path) {
    const char* pathStr = (*env)->GetStringUTFChars(env, path, NULL);
    int file = open(pathStr, O_RDWR | O_CLOEXEC);
    const char* message[265];
    if (file < 0) {
        const char* errmsg = "??";
        switch (errno) {
            case ENOENT: errmsg = "ENOENT (not found)"; break;
            case EACCES: errmsg = "EACCES (access denied)"; break;
        }
        sprintf(message, "open failed - errno: %d %s", errno, errmsg);
    } else {
        sprintf(message, "open succeeded");
    }
    return (*env)->NewStringUTF(env, message);
}

这是调用JNI函数的Java代码:

private void testForSO() {
    String resultMessage1 = openGpioChip("/dev/gpiochip0");
    String resultMessage2 = openGpioChip("/dev/notthere");
    Log.d("test", resultMessage1);
    Log.d("test", resultMessage2);
}

通过设备的终端,我需要root权限才能访问/dev/gpiochip0(就像cat一样)。这很奇怪,因为我读到GPIO字符访问是“用户模式”。这意味着它不应该需要root访问权限,对吗?

我将/dev和/dev/gpiochip0的文件权限设置为777,但这没有改变任何事情。

这个项目过去使用Android Things进行I/O...但那已经不存在了。我们正在尝试将其更新到最新的Android,这意味着没有Things。

关于使用GPIO字符设备的信息非常有限。关于现在已过时的技术sysfs有更多信息。

我看过gpiod。它相当庞大,最近进行了重写,大多数文档都是针对v1而不是v2的。无论如何,在v1和v2中都使用了这个open命令"open(path, O_RDWR | O_CLOEXEC)"。

gpiod工具不在目标SOM上。我不知道如何将它们放在那里。而且我认为那对我没有帮助。

  • Android版本:12
  • SDK(编译、最小、目标):31
  • 目标系统:Variscite IMX8
英文:

Trying to access GPIO lines on an embedded system running Android. Using the GPIO character device interface (not the sysfs which is obsolete and does not seem to be on the target system). Writing in C (with JNI wrapper) since I assume can't do in Java.

PROBLEM: Call to open() always fails (returns -1)

On an emulator errno is ENOENT (not found) which makes sense since surely it does not have GPIO setup. On my board I get EACCESS (access denied) for a path I know does exist. Further, I get ENOENT for a path that is known not to exist. So, it seems that open finds a path and then denies access.

QUESTION: Is GPIO possible in Android? Or is Android locked so tight that this is not possible? And if possible, how do I do it?

The C code with JNI wrapping:

JNIEXPORT jstring JNICALL Java_com_example_test_1jni_MainActivity_openGpioChip(JNIEnv* env, jobject _this, jstring path) {
    const char* pathStr = (*env)-&gt;GetStringUTFChars(env, path, NULL);
    int file = open(pathStr, O_RDWR | O_CLOEXEC);
    const char* message[265];
    if (file &lt; 0) {
        const char* errmsg = &quot;??&quot;;
        switch (errno) {
            case ENOENT: errmsg = &quot;ENOENT (not found)&quot;; break;
            case EACCES: errmsg = &quot;EACCES (access denied)&quot;; break;
        }
        sprintf(message, &quot;open failed - errno: %d %s&quot;, errno, errmsg);
    } else {
        sprintf(message, &quot;open succeeded&quot;);
    }
    return (*env)-&gt;NewStringUTF(env, message);
}

Here's the Java code that calls the JNI function.

private void testForSO() {
    String resultMessage1 = openGpioChip(&quot;/dev/gpiochip0&quot;);
    String resultMessage2 = openGpioChip(&quot;/dev/notthere&quot;);
    Log.d(&quot;test&quot;, resultMessage1);
    Log.d(&quot;test&quot;, resultMessage2);
}

Via a terminal to the device, I need root priv to access /dev/gpiochip0 (like to cat). That's odd since I read that GPIO character access is 'user mode'. That means it shouldn't require root access, right?

I set file perm to 777 for /dev and /dev/gpiochip0. But that didn't change anything.

This project used to use Android Things for I/O ... but that's gone now. We're trying to update it to latest Android which means no Things.

I find very little information about using GPIO character device. There is much more on the now-obsolete tech: sysfs.

I've looked at gpiod. It's rather large and it's confusing that it was re-written recently and most docs are for v1; not v2. Anyway, it uses this open command "open(path, O_RDWR | O_CLOEXEC)" in both v1 and v2.

The gpiod tools are not on the target SOM. I don't know how I would get them on there. And I don't think that would help me.

  • Android version: 12
  • SDK (compile,min,target): 31
  • target system: Variscite IMX8

答案1

得分: 0

在经过大量研究、实验以及Variscite的提示后,我有了一个解决方法。请执行以下两个步骤:

  1. 设置 SELinux 为宽容模式:执行命令 setenforce 0

  2. 设置 GPIO 芯片路径的文件权限:执行命令 chmod +rw /dev/gpiochip*

我实际上在几周前猜到了 chmod 的部分,但由于我不知道我还需要执行 setenforce,我没有意识到 chmod 其实是答案的一部分。

这只是一个临时解决方法,因为这两个设置在启动时会重置。因此,我仍然需要找到一种方法来为生产系统设置这些内容。

英文:

After much research, experimentation and a hint from Variscite I have a workaround. Do both of the following:

Set permissive SELinux mode: setenforce 0

Set file perms on GPIO chip paths: chmod +rw /dev/gpiochip*

I actually guessed at the chmod some weeks ago, but since I didn't know that I also have to do setenforce I didn't realize the chmod was actually part of the answer.

This a workaround since both things reset at startup. So, I still need to find a way to setup this stuff for a production system.

huangapple
  • 本文由 发表于 2023年5月25日 07:01:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76327900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定