在前面的几篇文章中,我们介绍了如何在Rockchip平台上实现客制化的GPIO接口,包括硬件部分和driver,hal,jni,server部分。在本文中,我们将介绍如何在应用层使用这个接口,以及如何通过SystemGpio类来控制GPIO的读写和方向。
Rockchip系列之客制化GPIO接口Driver部分(2)
SystemGpio类
SystemGpio类是一个封装了GPIO服务的Java类,位于frameworks/base/core/java/android/xxx/SystemGpio.java。它提供了一些简单的方法,让应用层可以方便地操作GPIO。下面我们来看看这个类的主要内容:
package android.xxx; import android.os.ParcelFileDescriptor; import android.os.ServiceManager; import android.os.RemoteException; import java.io.IOException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.util.Log; import android.content.Context; import android.media.AudioAttributes; import android.util.Log; /** Gpio implementation that controls the main system gpio. @hide */ public class SystemGpio { private static final String TAG = "gpio"; private final IGpioService mService; public SystemGpio() { mService = IGpioService.Stub.asInterface( ServiceManager.getService("gpio")); // add null checking and logging if (mService == null) { Log.e(TAG, "Failed to get gpio service"); throw new RuntimeException("Failed to get gpio service"); } else { Log.d(TAG, "Successfully got gpio service"); } } public SystemGpio(Context context) { mService = IGpioService.Stub.asInterface( ServiceManager.getService("gpio")); // add null checking and logging if (mService == null) { Log.e(TAG, "Failed to get gpio service"); throw new RuntimeException("Failed to get gpio service"); } else { Log.d(TAG, "Successfully got gpio service"); } } public void gpioWrite(int gpio,int value) { try { mService.gpioWrite(gpio, value); // add logging Log.d(TAG, "gpioWrite: gpio=" + gpio + ", value=" + value); } catch(Exception e) { // add logging and error handling Log.e(TAG, "gpioWrite: failed to write gpio", e); throw new RuntimeException("Failed to write gpio", e); } } public int gpioRead(int gpio) { try { int value = mService.gpioRead(gpio); // add logging Log.d(TAG, "gpioRead: gpio=" + gpio + ", value=" + value); return value; } catch(Exception e) { // add logging and error handling Log.e(TAG, "gpioRead: failed to read gpio", e); throw new RuntimeException("Failed to read gpio", e); } } public void gpioDirection(int gpio,int direction,int value) { try { mService.gpioDirection(gpio, direction, value); // add logging Log.d(TAG, "gpioDirection: gpio=" + gpio + ", direction=" + direction + ", value=" + value); } catch(Exception e) { // add logging and error handling Log.e(TAG, "gpioDirection: failed to set direction", e); throw new RuntimeException("Failed to set direction", e); } } public int gpioRegKeyEvent(int gpio) { try { int ret = mService.gpioRegKeyEvent(gpio); // add logging Log.d(TAG, "gpioRegKeyEvent: gpio=" + gpio + ", ret=" + ret); return ret; } catch(Exception e) { // add logging and error handling Log.e(TAG, "gpioRegKeyEvent: failed to register key event", e); throw new RuntimeException("Failed to register key event", e); } } public int gpioUnregKeyEvent(int gpio) { try { int ret = mService.gpioUnregKeyEvent(gpio); // add logging Log.d(TAG, "gpioUnregKeyEvent: gpio=" + gpio + ", ret=" + ret); return ret; } catch(Exception e) { // add logging and error handling Log.e(TAG, "gpioUnregKeyEvent: failed to unregister key event", e); throw new RuntimeException("Failed to unregister key event", e); } } public int gpioGetNumber() { try { int number = mService.gpioGetNumber(); // add logging Log.d(TAG, "gpioGetNumber: number=" + number); return number; } catch(Exception e) { // add logging and error handling Log.e(TAG, "gpioGetNumber: failed to get number", e); throw new RuntimeException("Failed to get number", e); } } }
从上面的代码可以看出,SystemGpio类主要有以下几个特点:
- 它是一个单例类,通过ServiceManager获取GPIO服务的实例。
- 它提供了两个构造函数,一个无参的,一个带有Context参数的。两者都会调用ServiceManager.getService(“gpio”)来获取GPIO服务的接口。
- 它提供了七个公开的方法,分别是:
- gpioWrite(int gpio,int value):用于向指定的GPIO写入高电平或低电平。
- gpioRead(int gpio):用于从指定的GPIO读取电平状态。
- gpioDirection(int gpio,int direction,int value):用于设置指定的GPIO的方向,输入或输出,并且可以指定输出时的初始电平。
- gpioRegKeyEvent(int gpio):用于注册指定的GPIO作为按键事件,返回一个按键码。
- gpioUnregKeyEvent(int gpio):用于取消注册指定的GPIO作为按键事件,返回一个结果码。
- gpioGetNumber():用于获取系统支持的GPIO总数。
- 它使用了Log类来打印日志信息,方便调试和排错。
- 它使用了try-catch语句来处理异常情况,并且抛出RuntimeException。
如何在应用层使用SystemGpio类
要在应用层使用SystemGpio类,我们需要做以下几个步骤:
- 在应用的AndroidManifest.xml文件中,添加以下权限:
<uses-permission android:name="android.permission.GPIO" />
这个权限是必须的,否则应用无法访问GPIO服务。
- 在应用的代码中,导入android.btf.SystemGpio类,并创建一个SystemGpio对象:
import android.xxx.SystemGpio; SystemGpio mGpio = new SystemGpio(this); // this is the context
- 调用SystemGpio对象的方法来操作GPIO,例如:
// 设置GPIO0为输出,并写入高电平 mGpio.gpioDirection(0, 1, 1); // 1 means output, 1 means high mGpio.gpioWrite(0, 1); // 设置GPIO1为输入,并读取电平状态 mGpio.gpioDirection(1, 0, 0); // 0 means input, 0 means low int value = mGpio.gpioRead(1); // 注册GPIO2作为按键事件,并获取按键码 int keyCode = mGpio.gpioRegKeyEvent(2); // 取消注册GPIO2作为按键事件,并获取结果码 int result = mGpio.gpioUnregKeyEvent(2); // 获取系统支持的GPIO总数 int number = mGpio.gpioGetNumber();
- 在应用中处理按键事件,例如:
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_XXX: // replace XXX with the actual key code from gpioRegKeyEvent() // do something when GPIO2 is pressed break; default: return super.onKeyDown(keyCode, event); } return true; }
总结
本文介绍了如何在应用层使用SystemGpio类来控制GPIO的读写和方向,以及如何注册和取消注册GPIO作为按键事件。通过这个类,我们可以在app中方便地调用android系统的GPIO服务,实现客制化的GPIO功能。这个类是基于Rockchip平台的,如果你使用的是其他平台,你可能需要根据你的硬件和驱动进行相应的修改和适配。
希望GPIO系列文章对你有所帮助,如果你有任何问题或建议,请在评论区留言。谢谢你的阅读和支持。😊