t字型布局的网站在dw怎么做,怎么用网站做地标,简述网页制作步骤,东莞网站建设方案托管本文档提供了在 Android 10 设备上通过应用程序#xff08;App#xff09;控制通用输入输出#xff08;GPIO#xff09;的详细指南。这涵盖了从创建 gpio驱动到App 配置 以及 SELinux 策略以允许特定访问的所有必要步骤。
1. 驱动实现
添加创建gpio控制驱动bsp\kernel\ke…本文档提供了在 Android 10 设备上通过应用程序App控制通用输入输出GPIO的详细指南。这涵盖了从创建 gpio驱动到App 配置 以及 SELinux 策略以允许特定访问的所有必要步骤。
1. 驱动实现
添加创建gpio控制驱动bsp\kernel\kernel4.14\drivers\gpio\gpio_led.c并添加好对应的Makfile编译
#include linux/init.h#include linux/slab.h#include linux/module.h#include linux/kernel.h#include linux/fs.h#include linux/cdev.h#include linux/device.h#include linux/ioctl.h#include linux/uaccess.h#include linux/string.h#include linux/wait.h#include linux/types.h#include linux/proc_fs.h#include linux/of.h#include linux/of_gpio.h#include linux/gpio.h#include linux/delay.h#include linux/platform_device.h#include linux/err.h#include linux/gpio/consumer.h#include linux/io.h#include linux/miscdevice.h#include linux/irq.h#include linux/of_irq.h#include linux/kernel.h#include linux/dmi.h#include linux/firmware.h#include linux/gpio/consumer.h#include linux/input.h#include linux/input/mt.h#include linux/module.h#include linux/delay.h#include linux/irq.h#include linux/interrupt.h#include linux/slab.h#include linux/acpi.h#include linux/of.h#include asm/unaligned.h#define GPIO_HIGH _IO(L, 0)#define GPIO_LOW _IO(L, 1)#define LED_ON 1#define LED_OFF 0#define SIMPIE_LED_MAX 4// Upper interface value //// 驱动模块名称定义#define MODULE_NAME gpio_led // 驱动模块的名字#define MISC_NAME gpio_led_device // 用于注册为“misc”设备的名字// 模块函数接口定义供上层应用调用的接口。通过MM_DEV_MAGIC区分不同系统接口通过_IO()加上自己的编号作为接口number。#define MM_DEV_MAGIC N// LED 控制命令#define RFID_IO1 _IO(MM_DEV_MAGIC, 93)#define RFID_IO2 _IO(MM_DEV_MAGIC, 130)#define RFID_IO3 _IO(MM_DEV_MAGIC, 121)#define RFID_LED _IO(MM_DEV_MAGIC, 138)static int major;static struct class *cls;// GPIO 描述数组struct gpio_desc *led_gpio[SIMPIE_LED_MAX];// cat命令将调用该函数static ssize_t gpio_value_show(struct device *dev, struct device_attribute *attr, char *buf){return sprintf(buf, %d\n, gpiod_get_value(led_gpio[0]));}// echo命令将调用该函数static ssize_t gpio_value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len){pr_err([vanxoak]%c\n, buf[0]);if (0 buf[0]){gpiod_direction_output(led_gpio[0], 0);pr_err([vanxoak]: _%s_ :gpio off\n, __func__);}else if (1 buf[0]){gpiod_direction_output(led_gpio[0], 1);pr_err([vanxoak]: _%s_ :gpio on\n, __func__);}elsepr_err(I only support 0 or 1 to ctrl gpio on or off\n);pr_err([vanxoak]gpio_value_store\n);return len;}// 定义一个名为gpio_led的设备属性static DEVICE_ATTR(gpio_led, 0664, gpio_value_show, gpio_value_store);// 提供给上层控制的接口long gpio_led_ioctl(struct file *file, unsigned int cmd, unsigned long arg){switch (cmd){case RFID_LED:gpiod_direction_output(led_gpio[0], arg);break;case RFID_IO1:gpiod_direction_output(led_gpio[1], arg);break;case RFID_IO2:gpiod_direction_output(led_gpio[2], arg);break;case RFID_IO3:gpiod_direction_output(led_gpio[3], arg);break;default:pr_err([vanxoak] %s default: break\n, __func__);break;}return 0;}struct file_operations gpio_led_ops {.owner THIS_MODULE,.unlocked_ioctl gpio_led_ioctl,};// LED灯初始化static int simpie_led_init(struct platform_device *pdev){int ret 0;int i;// 申请gpio设备led_gpio[0] devm_gpiod_get(pdev-dev, led0, GPIOD_OUT_LOW);led_gpio[1] devm_gpiod_get(pdev-dev, led1, GPIOD_OUT_LOW);led_gpio[2] devm_gpiod_get(pdev-dev, led2, GPIOD_OUT_LOW);led_gpio[3] devm_gpiod_get(pdev-dev, led3, GPIOD_OUT_LOW);for (i 0; i SIMPIE_LED_MAX; i){if (IS_ERR(led_gpio[i])){ret PTR_ERR(led_gpio[i]);return ret;}// 输出初始电平ret gpiod_direction_output(led_gpio[i], LED_OFF);}device_create_file(pdev-dev, dev_attr_gpio_led);return ret;}// 驱动入口static int gpio_led_probe(struct platform_device *pdev){int ret 0;pr_err([vanxoak]gpio_led_probe start...\n);// LED灯gpio初始化及输出配置ret simpie_led_init(pdev);pr_err([vanxoak]gpio_led_probe end...\n);return 0;}// 绑定设备static struct of_device_id gpio_led_match_table[] {{.compatible yz,gpio-led},{}};static int gpio_led_remove(struct platform_device *pdev){pr_err([vanxoak]gpio_led_remove...\n);return 0;}static struct platform_driver gpio_led_driver {.driver {.name MODULE_NAME,.owner THIS_MODULE,.of_match_table gpio_led_match_table,},.probe gpio_led_probe,.remove gpio_led_remove,};// gpio初始化入口static int gpio_led_init(void){struct device *mydev;pr_err([vanxoak]gpio_led_init start...\n);platform_driver_register(gpio_led_driver);major register_chrdev(0, gpiotest, gpio_led_ops);// 创建gpio_led_class设备cls class_create(THIS_MODULE, gpio_led_class);// 在gpio_led_class设备目录下创建一个gpio_led_device属性文件mydev device_create(cls, 0, MKDEV(major, 0), NULL, MISC_NAME);if (sysfs_create_file((mydev-kobj), dev_attr_gpio_led.attr)){return -1;}return 0;}static void gpio_led_exit(void){pr_err([vanxoak]gpio_led_exit...\n);platform_driver_unregister(gpio_led_driver);device_destroy(cls, MKDEV(major, 0));class_destroy(cls);unregister_chrdev(major, gpiotest);}module_init(gpio_led_init);module_exit(gpio_led_exit);MODULE_DESCRIPTION(Device_create Driver);MODULE_LICENSE(GPL);
设备树配置
gpio_led: yz,gpio-led {status disabled;compatible yz,gpio-led;led0-gpio ap_gpio 138 GPIO_ACTIVE_HIGH;led1-gpio ap_gpio 93 GPIO_ACTIVE_HIGH;led2-gpio ap_gpio 130 GPIO_ACTIVE_HIGH;led3-gpio ap_gpio 121 GPIO_ACTIVE_HIGH;};
配置好上面gpio驱动后重新编译更新kernel 可以在/dev目录下找到对应的设备文件
/dev/gpio_led_device通过读写设备文件就可以操作gpio了。
1.2 创建 Native 库
1.2.1设置 JNI 方法
在 App 中定义 JNI 方法以实现与 GPIO 设备的交互。
public class NativeClass {static {try {System.loadLibrary(jni_gpiocontrol);Log.d(NativeClass, Native library loaded successfully.);} catch (UnsatisfiedLinkError e) {Log.e(NativeClass, Failed to load native library: e.getMessage());// throw new RuntimeException(Failed to load native library, e);}}// 声明本地方法public native int controlGPIO(int cmd, long arg);
}
1.2.2 实现 Native 方法
在app/src/main目录下创建一个cpp文件夹如果你的项目是用Kotlin编写的这个步骤仍然适用因为JNI是用C/C实现的。将你的libjni_gpiocontrol.cpp文件放到这个cpp目录中。
注意事项确保本地方法签名正确Java方法签名和本地C/C方法实现之间必须完全匹配。
#include jni.h#include fcntl.h#include unistd.h#include sys/ioctl.h#include stdio.h#include android/log.h#include errno.h#include string.h#define MM_DEV_MAGIC N#define RFID_LED _IO(MM_DEV_MAGIC, 138)#define RFID_IO1 _IO(MM_DEV_MAGIC, 93)#define RFID_IO2 _IO(MM_DEV_MAGIC, 130)#define RFID_IO3 _IO(MM_DEV_MAGIC, 121)#define DEVICE_PATH /dev/gpio_led_device#define LOG_TAG GPIOControlextern C JNIEXPORT jint JNICALLJava_com_example_gpio_NativeClass_controlGPIO(JNIEnv *env, jobject obj, jint cmd, jlong arg) {int device_fd;long ioctl_result;unsigned int ioctl_cmd cmd;// Open the device filedevice_fd open(DEVICE_PATH, O_RDWR);if (device_fd 0) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, Could not open device: %s, strerror(errno));return -1;}// Translate cmd to appropriate ioctl command based on inputswitch (cmd) {case 138:ioctl_cmd RFID_LED;break;case 93:ioctl_cmd RFID_IO1;break;case 130:ioctl_cmd RFID_IO2;break;case 121:ioctl_cmd RFID_IO3;break;default:__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, Invalid command);close(device_fd);return -1;}// Send an ioctl to the deviceioctl_result ioctl(device_fd, ioctl_cmd, arg);if (ioctl_result 0) {__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, Failed to call ioctl: %s, strerror(errno));close(device_fd);return -1;}// Close the deviceclose(device_fd);return 0;} 1.2.3 编译 Native 库
使用 CMake 或 ndk-build 工具编译你的 native 代码为共享库.so 文件。
添加app\src\main\cpp\CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)project(gpiotest)add_library(jni_gpiocontrol SHARED libjni_gpiocontrol.cpp)find_library( log-lib log )target_link_libraries(jni_gpiocontrol${log-lib} )
1.2.4 调用 Native 方法
通过 JNI 接口在 App 中调用实现的 native 方法以控制 GPIO。
public class MainActivity extends AppCompatActivity {private NativeClass nativeClass;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);nativeClass new NativeClass();// 示例打开LEDint result nativeClass.controlGPIO(138, 1);// 根据result处理结果}}
2. SELinux 配置
由于直接访问硬件设备在 Android 中受到 SELinux 策略的限制需要修改 SELinux 策略以允许 App 访问 GPIO 设备文件。 定义设备类型为 GPIO 设备定义一个新的 SELinux 类型如 gpio_led_device_t。
在SDK_dir/device/sprd/sharkle/common/sepolicy/device.te 添加
# 定义新的设备类型type gpio_led_device_t, dev_type;
分配文件上下文为 GPIO 设备文件分配新定义的 SELinux 类型。
SDK_dir/device/sprd/sharkle/common/sepolicy/file_contexts中添加
/dev/gpio_led_device u:object_r:gpio_led_device_t:s0 授予权限在 SELinux 策略中添加规则允许 App 访问 GPIO 设备。
SDK_dir/device/sprd/sharkle/common/sepolicy/system_app.te
# 允许 system_app 访问 gpio_led_deviceallow system_app gpio_led_device_t:chr_file { read write };
重新编译 SELinux 策略对更改的 SELinux 策略进行编译并将其部署到设备上。这一步骤的目的是将自定义的安全策略更改应用到Android构建系统的预设SELinux策略中确保在编译系统镜像时这些更改会被包含进去。
cp system/sepolicy/public/app.te system/sepolicy/prebuilts/api/29.0/public/app.tecp system/sepolicy/private/coredomain.te system/sepolicy/prebuilts/api/29.0/private/coredomain.te 3. 测试与部署
测试 App在具有所需硬件支持的 Android 10 设备上测试 App。确保 App 能成功加载 native 库并能通过 JNI 调用控制 GPIO。
SELinux 策略测试验证 SELinux 策略更改是否允许 App 无障碍地访问 GPIO 设备。
问题排查如果遇到访问被拒绝的情况请检查 SELinux 审计日志以确定是否需要进一步调整策略。
3.1注意事项
安全性在修改 SELinux 策略以增加访问权限时务必小心谨慎避免引入安全漏洞。
设备兼容性确保你的实现考虑到了不同设备可能存在的硬件和配置差异。
文档和维护适当记录你的设计和实现过程包括 JNI 接口、native 代码和 SELinux 策略更改以便于未来的审计和维护。
通过遵循以上步骤你可以在遵守 Android 安全模型的同时实现 App 对 GPIO 的有效控制。