Hidl interface for gpio (to make wiringPi working with app)

Post Reply
User avatar
joerg
Posts: 1560
Joined: Tue Apr 01, 2014 2:14 am
languages_spoken: german, english, español
ODROIDs: C1, C1+, C2, N1, N2, C4
Location: Germany
Has thanked: 126 times
Been thanked: 264 times
Contact:

Hidl interface for gpio (to make wiringPi working with app)

Post by joerg »

I have developed a hidl interface for gpio access. With the java library that is compiled in the soong space, it is possible to access wiringPi functions without restrictions of Android 11.
Here are the files:
vendor/hardkernel/interfaces/Android.bp

Code: Select all

hidl_package_root {
    name: "vendor.hardkernel.hardware",
    path: "vendor/hardkernel/interfaces",
}
vendor/hardkernel/interfaces/update-makefiles.sh

Code: Select all

#!/bin/bash

source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh

do_makefiles_update \
  "vendor.hardkernel.hardware:vendor/hardkernel/interfaces" \
  "android.hidl:system/libhidl/transport" \
  "android.hardware:hardware/interfaces"
vendor/hardkernel/interfaces/gpio/1.0/Android.bp

Code: Select all

// This file is autogenerated by hidl-gen -Landroidbp.

hidl_interface {
    name: "vendor.hardkernel.hardware.gpio@1.0",
    root: "vendor.hardkernel.hardware",
    system_ext_specific: true,
    srcs: [
        "IGpio.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    gen_java: true,
}
vendor/hardkernel/interfaces/gpio/1.0/IGpio.hal

Code: Select all

package vendor.hardkernel.hardware.gpio@1.0;

interface IGpio {
    gpio(int32_t valueIn) generates (int32_t valueRet);
    setup_wiringPi() generates (int32_t status);
    pin_mode(int32_t pin, int32_t mode);
    digital_read(int32_t pin) generates (int32_t status);
    digital_write(int32_t pin, int32_t value);
    pullupdn_control(int32_t pin, int32_t mode);
    get_alt(int32_t pin) generates (int32_t status);
};
vendor/hardkernel/interfaces/gpio/1.0/default/Android.bp

Code: Select all

cc_library_shared {
    name: "vendor.hardkernel.hardware.gpio@1.0-impl",
    vendor: true,
    relative_install_path: "hw",
    srcs: [
        "Gpio.cpp",
    ],
    shared_libs: [
        "libhidlbase",
        "libutils",
        "liblog",
        "vendor.hardkernel.hardware.gpio@1.0",
        "libwiringPi",
    ],
    include_dirs: [ "vendor/hardkernel/external/wiringPi/wiringPi" ],
}

cc_binary {
    name: "vendor.hardkernel.hardware.gpio@1.0-service",
    defaults: ["hidl_defaults"],
    vendor: true,
    relative_install_path: "hw",
    init_rc: ["vendor.hardkernel.hardware.gpio@1.0-service.rc"],
    vintf_fragments: ["vendor.hardkernel.hardware.gpio@1.0-service.xml"],
    srcs: ["service.cpp"],

    shared_libs: [
        "vendor.hardkernel.hardware.gpio@1.0",
        "vendor.hardkernel.hardware.gpio@1.0-impl",
        "libhidlbase",
        "liblog",
	    "libbase",
	    "libdl",
	    "libhidlbase",
        "libutils",
    ],
}

cc_binary {
    name: "gpioclient",
    defaults: ["hidl_defaults"],
    vendor: true,
    srcs: ["gpioclient.cpp"],

    shared_libs: [
        "vendor.hardkernel.hardware.gpio@1.0",
        "vendor.hardkernel.hardware.gpio@1.0-impl",
        "libhidlbase",
        "liblog",
	    "libbase",
	    "libdl",
	    "libhidlbase",
        "libutils",
    ],
}
vendor/hardkernel/interfaces/gpio/1.0/default/Gpio.cpp

Code: Select all

#include <android-base/logging.h>
#include <log/log.h>
#include "Gpio.h"
#include <wiringPi.h>

namespace vendor::hardkernel::hardware::gpio::V1_0::implementation {

Gpio::Gpio(){
}
Gpio::~Gpio(){
}

// Methods from ::android::hardware::gpio::V1_0::IGpio follow.
Return<int32_t> Gpio::gpio(int32_t valueIn) {
    return valueIn+100;
}

Return<int32_t> Gpio::setup_wiringPi() {
    int32_t status = wiringPiSetup();
    return status;
}

Return<void> Gpio::pin_mode(int32_t pin, int32_t mode) {
    pinMode(pin, mode);
    return Void();
}

Return<int32_t> Gpio::digital_read(int32_t pin) {
    int32_t status = digitalRead(pin);
    return status;
}

Return<void> Gpio::digital_write(int32_t pin, int32_t value) {
    digitalWrite(pin, value);
    return Void();
}

Return<void> Gpio::pullupdn_control(int32_t pin, int32_t mode) {
    pullUpDnControl(pin, mode);
    return Void();
}

Return<int32_t> Gpio::get_alt(int32_t pin) {
    int32_t status = getAlt(pin);
    return status;
}

// Methods from ::android::hidl::base::V1_0::IBase follow.

//IGpio* HIDL_FETCH_IGpio(const char* /* name */) {
    //return new Gpio();
//}
//
}  // namespace vendor::hardkernel::hardware::gpio::implementation
vendor/hardkernel/interfaces/gpio/1.0/default/Gpio.h

Code: Select all

#pragma once

#include <vendor/hardkernel/hardware/gpio/1.0/IGpio.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

namespace vendor::hardkernel::hardware::gpio::V1_0::implementation {

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

class Gpio : public IGpio {
public:

    Gpio();
    // Methods from ::android::hardware::gpio::V1_0::IGpio follow.

    Return<int32_t> gpio(int32_t valueIn) override;
    Return<int32_t> setup_wiringPi() override;
    Return<void> pin_mode(int32_t pin, int32_t mode) override;
    Return<int32_t> digital_read(int32_t pin) override;
    Return<void> digital_write(int32_t pin, int32_t value) override;
    Return<void> pullupdn_control(int32_t pin, int32_t mode) override;
    Return<int32_t> get_alt(int32_t pin) override;

private:
    virtual ~Gpio();
};

// FIXME: most likely delete, this is only for passthrough implementations
// extern "C" IGpio* HIDL_FETCH_IGpio(const char* name);

}  // namespace vendor::hardkernel::hardware::gpio::implementation
vendor/hardkernel/interfaces/gpio/1.0/default/service.cpp

Code: Select all

#define LOG_TAG "vendor.hardkernel.hardware.gpio@1.0-service"
#include <hidl/LegacySupport.h>
#include "Gpio.h"

using vendor::hardkernel::hardware::gpio::V1_0::IGpio;
using vendor::hardkernel::hardware::gpio::V1_0::implementation::Gpio;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;

int main() {
      int res;
      android::sp<IGpio> ser = new Gpio();
      ALOGD("gpio main service");
      configureRpcThreadpool(1, true /*callerWillJoin*/);
 
      if (ser != nullptr) {
          res = ser->registerAsService();
          if(res != 0)
            ALOGE("Can't register instance of GpioHardware, nullptr");
      } else {
          ALOGE("Can't create instance of GpioHardware, nullptr");
       }
 
      joinRpcThreadpool();
 
      return 0; // should never get here
}
vendor/hardkernel/interfaces/gpio/1.0/default/vendor.hardkernel.hardware.gpio@1.0-service.rc

Code: Select all

service gpio_service /vendor/bin/hw/vendor.hardkernel.hardware.gpio@1.0-service
	class hal
	user root
	group root
	seclabel u:r:su:s0
vendor/hardkernel/interfaces/gpio/1.0/default/vendor.hardkernel.hardware.gpio@1.0-service.xml

Code: Select all

<manifest version="1.0" type="device">
    <hal format="hidl">
        <name>vendor.hardkernel.hardware.gpio</name>
        <transport>hwbinder</transport>
        <fqname>@1.0::IGpio/default</fqname>
    </hal>
</manifest>
device/hardkernel/common/manifests/frameworks/vendor.hardkernel.hardware.gpio@1.0-service.xml

Code: Select all

<compatibility-matrix version="1.0" type="framework">
    <hal format="hidl" optional="true">
        <name>vendor.hardkernel.hardware.gpio</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>IGpio</name>
            <instance>default</instance>
        </interface>
    </hal>
</compatibility-matrix>
To be added to vintf.mk (same directory):

Code: Select all

DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE += device/hardkernel/common/manifests/frameworks/vendor.hardkernel.hardware.gpio@1.0-service.xml
And to odroidm1.mk:

Code: Select all

PRODUCT_PACKAGES += \
    vendor.hardkernel.hardware.gpio@1.0-impl \
    vendor.hardkernel.hardware.gpio@1.0-service \
The interface files are installed in vendor space. Therefor wiringPi also needs to be installed there. All modules in Android.bp need:

Code: Select all

vendor: true,

Code: Select all

$lshal
X     ? vendor.hardkernel.hardware.gpio@1.0::I*/* (/vendor/lib/hw/)                  N/A        N/A    
X     ? vendor.hardkernel.hardware.gpio@1.0::I*/* (/vendor/lib64/hw/)                N/A        N/A    4993

Code: Select all

$ps -A|grep gpio
root           4993      1 10775224  4776 binder_thread_read  0 S vendor.hardkernel.hardware.gpio@1.0-service
To work with it in app, two libraries need to be copied from soong space to Android Studio, folder app/libs:
out/soong/.intermediates/frameworks/base/framework.jar
out/soong/.intermediates/vendor/hardkernel/interfaces/gpio/1.0/vendor.hardkernel.hardware.gpio-V1.0-java/android_common/combined/vendor.hardkernel.hardware.gpio-V1.0-java.jar

In build.gradle(app) is to add:

Code: Select all

    implementation fileTree(dir: 'libs', include: ['vendor.hardkernel.hardware.gpio*.jar'])
    dependencies {
        compileOnly files('libs/framework.jar')
    }
Java class:

Code: Select all

import vendor.hardkernel.hardware.gpio.V1_0.IGpio;

public class wiring {

    private static IGpio gpio = null;

    static {
        try {
            gpio = IGpio.getService(true);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    public static int wiringPiSetup() {
        try {
            return gpio.setup_wiringPi();
        } catch (RemoteException e) {
            e.printStackTrace();
            return -1;
        }
    }
    public static int digitalRead(int iGpio) {

        int value = 0;
        if (gpio != null) {
            try {
                value = gpio.digital_read(iGpio);
                return value;
            } catch (RemoteException e) {
                e.printStackTrace();
                return -1;
            }
        }
    }
}    
For sure it's possible to make some more libraries to not to have to use the libraries from song space, but I am happy for now. Nobody knows how often I had to compile and try and compile and try and... :D
gpio.zip
(4.95 KiB) Downloaded 4 times
These users thanked the author joerg for the post:
odroid (Wed May 04, 2022 9:36 am)

User avatar
rooted
Posts: 9438
Joined: Fri Dec 19, 2014 9:12 am
languages_spoken: english
Location: Gulf of Mexico, US
Has thanked: 758 times
Been thanked: 479 times
Contact:

Re: Hidl interface for gpio (to make wiringPi working with app)

Post by rooted »

Well that will certainly make life easier for your builds and for those who need GPIO access in Android.

Awesome

Post Reply

Return to “Android”

Who is online

Users browsing this forum: No registered users and 0 guests