JavaはGPIOによりLEDランプの点灯を制御する(Firefly-RK 3399)(二)

48191 ワード

JavaはGPIOによりLEDランプの点灯を制御する(Firefly-RK 3399)(二)
Note:Android用に開発されたツールAndroid Studio
前編ではLinuxでのGPIOの操作を簡単に紹介し,Javaでの応用を主に説明した.
1.JNI方式
2.Java Linuxコマンドの実行
JNI
JNIはCファイルを呼び出してGPIOを読み書きし、
関連するディレクトリファイルに対して実行する権限が必要で、呆然とした顔をしている.
jni操作gpioには権限が必要です(ASのTerminalウィンドウ):
chmod -R 777/sys/class/gpio/gpio1157/
現在のディレクトリの下にあるすべてのファイルに777権限を与えます.777は高権限(読み取り、書き込み、実行)です.
読み取り/書き込みに失敗した場合は、ステップごとに権限を付与する必要があります.詳細は、次の参照してください.
AndroidはJNI制御GPIO Android NDK開発におけるjni構成および呼び出しGPIO
cファイルは以下の通りです(参考まで):

//
// Created by K_EJ on 2019/3/20.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include "com_ejior_platform_led_GPIOControl.h"

#define TAG "jni_gpio"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)

#define IN              0
#define OUT             1
#define LOW             0
#define HIGH            1

#define BUFFER_MAX    5   //3    1157  5
#define DIRECTION_MAX 66


#include "com_ejior_platform_led_GPIOControl.h"
JNIEXPORT jint JNICALL Java_com_ejior_platform_led_GPIOControl_exportGpio
  (JNIEnv *env, jobject jclass, jint gpio){
    char buffer[BUFFER_MAX];
    int len;
    int fd;

    fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0) {
        LOGE("Failed to open export for writing!
"); return fd; } len = snprintf(buffer, BUFFER_MAX, "%d", gpio); return len; if (write(fd, buffer, len) < 0) { LOGE("Fail to export gpio!
"); return (0); } close(fd); return 1; }; /* * Class: com_ejior_platform_led_GPIOControl * Method: setGpioDirection * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_ejior_platform_led_GPIOControl_setGpioDirection (JNIEnv *env,jobject jclass, jint gpio, jint direction) { static const char dir_str[] = "in\0out"; char path[DIRECTION_MAX]; int fd; snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", gpio); //path fd = open(path, O_WRONLY); if (fd < 0) { LOGE("failed to open gpio direction for writing!
"); return 0; } if (write(fd, &dir_str[direction == IN ? 0 : 3], direction == IN ? 2 : 3) < 0) { LOGE("failed to set direction!
"); return 0; } close(fd); return 1; }; /* * Class: com_ejior_platform_led_GPIOControl * Method: readGpioDirection * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_ejior_platform_led_GPIOControl_readGpioStatus (JNIEnv *env,jobject jclass , jint gpio) { char path[DIRECTION_MAX]; char value_str[3]; int fd; snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", gpio); fd = open(path, O_RDONLY); if (fd < 0) { LOGE("failed to open gpio value for reading!
"); return -1; } if (read(fd, value_str, 3) < 0) { LOGE("failed to read value!
"); return -1; } close(fd); return (atoi(value_str)); }; /* * Class: com_ejior_platform_led_GPIOControl * Method: writeGpioStatus * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_ejior_platform_led_GPIOControl_writeGpioStatus (JNIEnv *env, jobject jclass, jint gpio, jint value) { static const char values_str[] = "01"; char path[DIRECTION_MAX]; int fd; snprintf(path,DIRECTION_MAX,"/sys/class/gpio/gpio%d/value",gpio); fd = open(path,O_WRONLY);//path if(fd<0){ LOGE("failed to open gpio value for writing!
"); return 0; } if(write(fd,&values_str[value == LOW? 0:1],1) < 0){ LOGE("failed to write value!
"); return 0; } close(fd); return 1; }; /* * Class: com_ejior_platform_led_GPIOControl * Method: unexportGpio * Signature: (I)I */ JNIEXPORT jint JNICALL Java_com_ejior_platform_led_GPIOControl_unexportGpio (JNIEnv *env, jobject jclass, jint gpio) { char buffer[BUFFER_MAX]; int len; int fd; fd = open("/sys/class/gpio/unexport",O_WRONLY); if(fd <0){ LOGE("Failed to open unexport for writing!
"); } len = snprintf(buffer, BUFFER_MAX, "%d", gpio); if (write(fd, buffer, len) < 0) { LOGE("Fail to unexport gpio!"); return 0; } close(fd); return 1; };

Note:NDK環境を構成する必要があります>+<
Java方式
つまりjavaで出力ストリームを介してLinuxコマンドに書き込む
**Note:**デバイスにはrootが必要です.rootがなければ、2つの方法で、1.システム署名(ソースコードをコンパイルする必要があります)2.システムディレクトリの下に置く/system(Note、参照するサードパーティsoライブラリ、/system/libの下に入れる必要があります.rk 3399開発ボードでシステムが開かないことに遭遇しました.Recoveryページに定格化し、再録音固定する必要があります.)
rootデバイス
詳細:
【androidツール編】Firefly-RKシリーズ
中に紹介されている方法には、権限を得る目的を達成できないものもあり、ツール類はかえって
Linuxコマンドを書き込むには、次のようにツールクラスShellUtilsを使用する必要があります.
public class ShellUtils {
        public static final String COMMAND_SU = "su";
        public static final String COMMAND_SH = "sh";
        public static final String COMMAND_EXIT = "exit
"; public static final String COMMAND_LINE_END = "
"; private ShellUtils() { throw new AssertionError(); } /** * root * * @return */ public static boolean checkRootPermission() { return execCommand("echo root", true, false).result == 0; } /** * shell , * * @param command command * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot) { return execCommand(new String[]{command}, isRoot, true); } /** * shell , * * @param commands command list * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List commands, boolean isRoot) { return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, true); } /** * shell , * * @param commands command array * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String[] commands, boolean isRoot) { return execCommand(commands, isRoot, true); } /** * execute shell command * * @param command command * @param isNeedResultMsg whether need result msg * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) { return execCommand(new String[]{command}, isRoot, isNeedResultMsg); } /** * execute shell commands * * @param commands command list * @return * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List commands, boolean isRoot, boolean isNeedResultMsg) { return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg); } /** * execute shell commands */ public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) { int result = -1; if (commands == null || commands.length == 0) { return new CommandResult(result, null, null); } Process process = null; BufferedReader successResult = null; BufferedReader errorResult = null; StringBuilder successMsg = null; StringBuilder errorMsg = null; DataOutputStream os = null; try { process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); os = new DataOutputStream(process.getOutputStream()); for (String command : commands) { if (command == null) { continue; } // donnot use os.writeBytes(commmand), avoid chinese charset // error os.write(command.getBytes()); os.writeBytes(COMMAND_LINE_END); os.flush(); } os.writeBytes(COMMAND_EXIT); os.flush(); result = process.waitFor(); // get command result if (isNeedResultMsg) { successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(" "+s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (IOException e) { e.printStackTrace(); } if (process != null) { process.destroy(); } } return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null : errorMsg.toString()); } public static class CommandResult { /** * **/ public int result; /** * **/ public String successMsg; /** * **/ public String errorMsg; public CommandResult(int result) { this.result = result; } public CommandResult(int result, String successMsg, String errorMsg) { this.result = result; this.successMsg = successMsg; this.errorMsg = errorMsg; } @Override public String toString() { return "CommandResult{" + "result=" + result + ", successMsg='" + successMsg + '\'' + ", errorMsg='" + errorMsg + '\'' + '}'; } } }

GPIOの呼び出しクラスを簡単に書きました
public class GPIOUtils {
    //    private static final
    public static final String GPIO_DEFINE_NUM = "GPIO1_B0";
    //GPIO4_D5  rk3399 gpio  157  GPIO1_B0 gpio  40
    // value 1    0   
    public final static int GPIO_VALUE_LOW = 0;//   
    public final static int GPIO_VALUE_HIGH = 1;
    private static final String execCommand = "echo s% > /sys/class/gpio/export";

    public void setGpio(String gpioNum) {
        String export = String.format(execCommand, gpioNum);
        ShellUtils.execCommand(export, true);
    }

    /**
     *    GPIO_DEFINE_NUM
     *
     * @param value
     */
    public static void setDefineGpio(int value) {
        int gpioPin = GPIOUtils.gpioParse(GPIOUtils.GPIO_DEFINE_NUM);//157 
        if (scanGpio() == -1) {
        } else {
            gpioPin = scanGpio() + gpioPin;
        }
        Logger.infod("Define Gpio", scanGpio() + "===" + gpioPin);
        setGpioControl(gpioPin, GPIOControl.GPIO_DIRECTION_OUT_STR, value);
    }
    /**
     *         
     */
    public static void setDefUnexportGpio() {
        int gpioPin = GPIOUtils.gpioParse(GPIOUtils.GPIO_DEFINE_NUM);//157 
        if (scanGpio() == -1) {
        } else {
            gpioPin = scanGpio() + gpioPin;
        }
        gpioRemove(gpioPin);
    }

    /**
     *   gpio  ,  Gpio     ,
     *   Gpiochip    gpiochip1000 gpiochip1032 gpiochip1064 gpiochip1096 gpiochip1128
     *    gpiochip0    gpiochip160  gpiochip64
     * gpiochip128  gpiochip32   gpiochip96
     */
    public static int scanGpio() {
        String lsgpio = "ls /sys/class/gpio/";
        ShellUtils.CommandResult commandResult = ShellUtils.execCommand(lsgpio, true, true);
        String result = commandResult.successMsg;
        Log.d("Scan Gpio", result == null ? "" : result);
        String[] resultArray = result.split(" ");
        List<String> strings = new ArrayList<>();
        for (int i = 0; i < resultArray.length; i++) {
            String s = resultArray[i];
            if (s.contains("gpiochip")) {
                String subStr = s.substring(s.lastIndexOf("gpiochip") + 8, s.length());
                strings.add(subStr);
            }
        }
        if (strings.size() <= 0) {
            return -1;
        }
        String lastStr = strings.get((strings.size() - 1));
        if (lastStr.length() >= 4) {
            return Integer.parseInt(lastStr.substring(0, 1)) * (int) Math.pow(10, (lastStr.length() - 1));
        }
        return -1;
    }

   /**
     * system remount     
     * @return
     */
    public static boolean reRemount() {
        // remount        remount      --- remount   : mount -o ro,remount /system
        String remount = "mount -o remount /system";// mount -o rw,remount /system
        ShellUtils.CommandResult commandResult = ShellUtils.execCommand(remount, true);
        Log.d("GpioControl Remount==", commandResult.toString());
        return commandResult.result == 0;
    }
     /**
     * system remount    
     * @return
     */
    public static boolean reRemountRead() {
        // remount        remount      --- remount   : mount -o ro,remount /system
        String remount = "mount -o ro,remount /system";// mount -o rw,remount /system
        ShellUtils.CommandResult commandResult = ShellUtils.execCommand(remount, true);
        Log.d("Gpio RemountRead==", commandResult.toString());
        return commandResult.result == 0;
    }

    /**
     *      value 1    0   
     */
    public static boolean setGpioControl(int gpio, String direction, int value) {
        String exportPath = "";
        String directionPath = "";
        if (!isGpioOccupied(gpio)) {
            exportPath = "echo " + gpio + " > /sys/class/gpio/export";
            directionPath = "echo " + direction + " > " + " /sys/class/gpio/gpio" + gpio + "/direction";
        }
        String valuePath = "echo " + value + " > /sys/class/gpio/gpio" + gpio + "/value";
        String[] command = {exportPath, directionPath, valuePath};
        ShellUtils.CommandResult commandResult = ShellUtils.execCommand(command, true);
        Log.d("GpioControl Set==", commandResult.toString());
        return commandResult.result == 0;

    }

    public static boolean isGpioOccupied(int gpio) {

        String catGpio = "cat /sys/kernel/debug/gpio | grep gpio-" + gpio;
        ShellUtils.CommandResult commandResult = ShellUtils.execCommand(catGpio, true);
        Log.d("Cat Gpio==", commandResult.toString());
        return commandResult.result == 0;
    }

    /**
     *   GPIO  
     *
     * @param gpioStr
     * @return
     */
    public static int gpioParse(String gpioStr) {//GPIO4_D5
        if (gpioStr != null && gpioStr.length() == 8) {
            gpioStr = gpioStr.toUpperCase();
            if (gpioStr.charAt(4) >= '0' && gpioStr.charAt(4) <= '8') {
                if (gpioStr.charAt(6) >= 'A' && gpioStr.charAt(6) <= 'D') {
                    return gpioStr.charAt(7) >= '0' && gpioStr.charAt(7) <= '7' ?
                            (gpioStr.charAt(4) - 48) * 32 + (gpioStr.charAt(6) - 65) * 8 + (gpioStr.charAt(7) - 48) : -1;
                } else {
                    return -1;
                }
            } else {
                return -1;
            }
        } else {
            System.out.println("input gpio error!");
            return -1;
        }
    }

    public static boolean gpioRemove(int gpio) {
        String unexportPath = "echo " + gpio + " > /sys/class/gpio/unexport";
        ShellUtils.CommandResult commandResult = ShellUtils.execCommand(unexportPath, true);
        Log.d("GpioRemove==", commandResult.toString());
        return commandResult.result == 0;
    }

    public String gpioRead(int gpio) {
        String valuePath = "cat  /sys/class/gpio/gpio" + gpio + "/value";
        ShellUtils.CommandResult commandResult = ShellUtils.execCommand(valuePath, true, true);
        Log.d("GpioRead==", commandResult.toString());
        return commandResult.result == 0 ? commandResult.successMsg : commandResult.errorMsg;
    }

/*
    String command2 = "echo out > /sys/class/gpio/gpio1157/direction";
    String command3 = "echo 0 > /sys/class/gpio/gpio1157/value";
    String[] command = {command1,command2,command3};
    ShellUtils.execCommand(command,true).result+""*/

    
}


呼び出しは以下の通りです.2つのLed切替で、ローレベルは白、ハイレベルは青です.
//    
GPIOUtils.reRemount();
GPIOUtils.setDefineGpio(GPIOUtils.GPIO_VALUE_LOW);//     

 //        
 GPIOUtils.setDefineGpio(GPIOUtils.GPIO_VALUE_HIGH);
 
 //  
   GPIOUtils.setDefUnexportGpio();//           Gpio
   GPIOUtils.reRemountRead();
 

以上がLedランプの制御方法で、java方式設備はroot資源:Demo