BananaPi BPI-M2Z(H2+) New Image Android4.4 Release 2018-07-09

Many thanks - will give it a try. Would you also have a link to Android V1 and V3 sources ?

Will try to compare kernels …

Ahh, ok I see - on wiki under M2Zero.

P2Zero links are pointing to M2+

Once again - Thank you

hi my friend. Try this. I already tested. Alleiny.CBpiM2ZeroGpio.java (12,9 KB) bpi_m2z_pines

So I have copy pasted the class as it is - burned new Image to P2-Zero to ensure is has factory settings and getting below error

02-25 17:49:56.138 4879-4879/cz.onehome.onesoftware.onehome_remote E/myApp: Start Configure Gpio
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err: java.io.SyncFailedException: fsync failed: EINVAL (Invalid argument)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at java.io.FileDescriptor.sync(FileDescriptor.java:77)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at java.io.FileOutputStream.flush(FileOutputStream.java:194)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at java.io.FilterOutputStream.flush(FilterOutputStream.java:88)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at java.io.DataOutputStream.flush(DataOutputStream.java:63)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at cz.onehome.onesoftware.onehome_remote.GPIO.CBpiM2ZeroGpio.configGpio(CBpiM2ZeroGpio.java:266)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at cz.onehome.onesoftware.onehome_remote.GPIO.CBpiM2ZeroGpio$1.run(CBpiM2ZeroGpio.java:39)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at android.os.Handler.handleCallback(Handler.java:733)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at android.os.Looper.loop(Looper.java:136)
02-25 17:49:57.168 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5017)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at java.lang.reflect.Method.invoke(Method.java:515)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:816)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:632)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at dalvik.system.NativeStart.main(Native Method)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err: Caused by: libcore.io.ErrnoException: fsync failed: EINVAL (Invalid argument)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at libcore.io.Posix.fsync(Native Method)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at libcore.io.BlockGuardOs.fsync(BlockGuardOs.java:97)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err:     at java.io.FileDescriptor.sync(FileDescriptor.java:74)
02-25 17:49:57.178 4879-4879/cz.onehome.onesoftware.onehome_remote W/System.err: 	... 14 more

Fails on dos.flush

boolean configGpio(String pin)
{
    boolean ret = true;
    FileOutputStream fos ;
    FileWriter fWriter;

    try{
        fos = new FileOutputStream("/sys/class/gpio_sw/" + pin + "/cfg", true);
        fWriter = new FileWriter(fos.getFD());
        fWriter.write("0");
        fWriter.flush();
        fWriter.close();
    }catch(Exception e){
        ret = false;
        try{
            Process p=Runtime.getRuntime().exec("su");
            DataOutputStream dos = new DataOutputStream(p.getOutputStream());
            dos.writeBytes("chmod -R 777 /sys/class/gpio_sw/" + pin + "/*\n");
            dos.writeBytes("exit\n");
            dos.flush();
            dos.close();
            p.waitFor();
        }catch (Exception e1){ }
    }

    return ret;
}

My friend, in the last one clases i share you there is no configGpio function. Please try last one. I already tested in bpi_m2z whith last 4.4 Android versión and works inputs, and outputs well.

Thank you Aleliny. Appreciate that. Working well. Just for curiosity - why in the latest android there is such change and shell comamnds are being used instead of the library?

The reason why I am asking is that using the library I would be able to set the PULL_UP and PULL_DOWN rezistors which is not achievable using shell. At least as far as I am aware.

Many thanks. Ladislav

Hi Ladislav. I really don’t know what the reason is. I am just one more user. Out of curiosity too, what is the library you are talking about? Alleiny.

Hi Alleiny,

com_softwinner_Gpio

You can find it in android sources: android\frameworks\base\swextend\gpio\jni

/* //device/libs/android_runtime/android_os_Gpio.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#define LOG_TAG "com_softwinner_gpio"
#define LOG_NDEBUG 0

#include "JNIHelp.h"
#include "jni.h"
#include "android_runtime/AndroidRuntime.h"
#include "utils/Errors.h"
#include "utils/String8.h"
#include "android_util_Binder.h"
#include <stdio.h>
#include <assert.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "IGpioService.h"



using namespace android;

static sp<IGpioService> gpioService;

static void init_native(JNIEnv *env){
	ALOGD("init");
	sp<IServiceManager> sm = defaultServiceManager();
	sp<IBinder> binder;
	do{
		binder = sm->getService(String16("softwinner.gpio"));
		if(binder != 0){
			break;
		}
		ALOGW("softwinner gpio service not published, waiting...");
		usleep(500000);
	}while(true);

	gpioService = interface_cast<IGpioService>(binder);
}

static void throw_NullPointerException(JNIEnv *env, const char* msg){
	jclass clazz;
	clazz = env->FindClass("java/lang/NullPointerException");
	env->ThrowNew(clazz, msg);
}

static int readGpio_native(JNIEnv *env, jobject clazz, jstring path){
	int value;
	if(gpioService == NULL){
		throw_NullPointerException(env,"gpio service has not start!");
	}
	if(path == NULL){
		return -1;
	}
	const char *chars = env->GetStringUTFChars(path, NULL);
	int ret = gpioService->readData(chars);
	env->ReleaseStringUTFChars(path, chars);
	return ret;
}

static int writeGpio_native(JNIEnv *env, jobject clazz, jstring path, jstring value){
	if(gpioService == NULL){
		throw_NullPointerException(env,"gpio service has not start!");
	}
	if(path == NULL){
		return -1;
	}
	else{
		const char *chars = env->GetStringUTFChars(path, NULL);
		const char *valueStr = env->GetStringUTFChars(value, NULL);
		int ret = gpioService->writeData(valueStr, strlen(valueStr), chars);
		env->ReleaseStringUTFChars(path, chars);
        env->ReleaseStringUTFChars(value, valueStr);
		return ret;
	}
}

static JNINativeMethod method_table[] = {
	{ "nativeInit", "()V", (void*)init_native},
    { "nativeWriteGpio", "(Ljava/lang/String;Ljava/lang/String;)I", (void*)writeGpio_native },
    { "nativeReadGpio", "(Ljava/lang/String;)I", (void*)readGpio_native },
};

static int register_android_os_Gpio(JNIEnv *env){
	return AndroidRuntime::registerNativeMethods(
		env, "com/softwinner/Gpio",method_table, NELEM(method_table));
}

jint JNI_OnLoad(JavaVM* vm, void* reserved){
	JNIEnv* env = NULL;
    jint result = -1;

	ALOGD("Gpio JNI_OnLoad()");

	if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        ALOGE("ERROR: GetEnv failed\n");
        goto bail;
    }
    assert(env != NULL);

    if (register_android_os_Gpio(env) < 0) {
        ALOGE("ERROR: Gpio native registration failed\n");
        goto bail;
    }

    /* success -- return valid version number */
    result = JNI_VERSION_1_4;

bail:
    return result;
}

And this is the Java wrapper: android\frameworks\base\swextend\gpio\java

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.softwinner;

import java.io.IOException;
import android.os.ServiceManager;
import java.lang.Integer;
import java.lang.String;
import android.util.Log;

/**
 * Class that provides access to some of the gpio management functions.
 *
 * {@hide}
 */
public class Gpio
{
	public static final String TAG = "GPIO";

    // can't instantiate this class
    private Gpio()
    {
    }

	static {
		System.loadLibrary("gpio_jni");
		nativeInit();
	}

	private static native void nativeInit();
        private static native int nativeWriteGpio(String path, String value);
	private static native int nativeReadGpio(String path);

	private static final String  mPathstr      = "/sys/class/gpio_sw/P";
	private static final String  mDataName     = "/data";
	private static final String  mPullName     = "/pull";
	private static final String  mDrvLevelName = "/drv_level";
	private static final String  mMulSelName   = "/mul_sel";

	public static int writeGpio(char group, int num, int value){
	    String dataPath = composePinPath(group, num).concat(mDataName);

		return nativeWriteGpio(dataPath, Integer.toString(value));
	}

	public static int readGpio(char group, int num){
	    String dataPath = composePinPath(group, num).concat(mDataName);

		return nativeReadGpio(dataPath);
	}

	public static int setPull(char group, int num, int value){
	    String dataPath = composePinPath(group, num).concat(mPullName);

		return nativeWriteGpio(dataPath, Integer.toString(value));
	}

	public static int getPull(char group, int num){
	    String dataPath = composePinPath(group, num).concat(mPullName);

		return nativeReadGpio(dataPath);
	}

	public static int setDrvLevel(char group, int num, int value){
	    String dataPath = composePinPath(group, num).concat(mDrvLevelName);

		return nativeWriteGpio(dataPath, Integer.toString(value));
	}

	public static int getDrvLevel(char group, int num){
	    String dataPath = composePinPath(group, num).concat(mDrvLevelName);

		return nativeReadGpio(dataPath);
	}

	public static int setMulSel(char group, int num, int value){
	    String dataPath = composePinPath(group, num).concat(mMulSelName);

		return nativeWriteGpio(dataPath, Integer.toString(value));
	}

	public static int getMulSel(char group, int num){
	    String dataPath = composePinPath(group, num).concat(mMulSelName);

		return nativeReadGpio(dataPath);
	}

	private static String composePinPath(char group, int num){
		String  numstr;
		String  groupstr;

		groupstr = String.valueOf(group).toUpperCase();
		numstr = Integer.toString(num);
        return mPathstr.concat(groupstr).concat(numstr);
    }
}