GPIO例程:
DTS:
pwn-gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>;
#include <linux/of_gpio.h>
struct sensor_data {
...
int pwn_gpio;
...
}
struct sensor_data *max9286_data;
dev = &max9286_data->client->dev;
max9286_data->pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
if (!gpio_is_valid(max9286_data->pwn_gpio)) {
dev_err(dev, "no sensor pwdn pin available\n");
return -ENODEV;
}
retval = devm_gpio_request_one(dev, max9286_data->pwn_gpio, GPIOF_OUT_INIT_HIGH,
"max9286_pwd");
if (retval < 0)
return retval;
gpio_set_value(max9286_data->pwn_gpio, 1);
内核线程例程:
#include <linux/kthread.h>
static struct task_struct *tp_rst_task;
int tp_rst_threadfunc(void *data){
printk("enter the kthread\n");
int i=0;
while(1){
//set_current_state(TASK_UNINTERRUPTIBLE);//将当前的状态表示设置为休眠
//if(kthread_should_stop())
// break; //解释见“注意”
//if(1 == filereadp(filename,readbuf)){
if(HasSignal != 0 ) {
printk(" test HasSignal=0x%02x i=[%d]",HasSignal,i);
i++;
}
else{//条件为假
//让出CPU运行其他线程,并在指定的时间内重新被调度
//schedule_timeout(0.1*HZ); // 休眠,与set_current_state配合使用,需要计算,这里表示休眠一秒
//printk("kthread sleep\n");
//msleep(20);
;
}
}
return 0;
}
static tp_rst_thread_init(void)
{
int err;
tp_rst_task = kthread_create(tp_rst_threadfunc,NULL, "tp_rst_task");
if(IS_ERR(tp_rst_task)){
printk("Unable to start kernel thread.\n");
err = PTR_ERR(tp_rst_task);
tp_rst_task =NULL;
return err;
}
wake_up_process(tp_rst_task);
}
static tp_rst_thread_exit(void)
{
if(tp_rst_task){
kthread_stop(tp_rst_task);
tp_rst_task = NULL;
}
}
ds90ub948_probe(...)
{
tp_rst_thread_init();
}
内核线程状态指示灯例程:
#define INDICATOR_LED_GPIO 3
int indicator_thread_func(void *data){
printk("start check arm workfunction thread\n");
GPIO_MultiFun_Set(INDICATOR_LED_GPIO, PINMUX_LEVEL_GPIO_END_FLAG);
gpio_request(INDICATOR_LED_GPIO, "output");
while(1){
gpio_direction_output(INDICATOR_LED_GPIO,0);
msleep(1000);
gpio_direction_output(INDICATOR_LED_GPIO,1);
msleep(1000);
if (kthread_should_stop())
break;
}
return 0;
}
static indicator_thread_init(void)
{
int err;
arm_check_task = kthread_create(indicator_thread_func, NULL, "arm_check_task");
if(IS_ERR(arm_check_task)){
printk("Unable to start kernel thread.\n");
err = PTR_ERR(arm_check_task);
arm_check_task =NULL;
return err;
}
wake_up_process(arm_check_task);
}
static indicator_thread_exit(void)
{
if(arm_check_task){
kthread_stop(arm_check_task);
arm_check_task = NULL;
}
}
内核线程检测aux拔插功能例程
static int aux_detect_kthread_func(void *unused)
{
char *envp[2];
int pre_gpio_value,cur_gpio_value;
printk("enter %s!\n",__func__);
GPIO_MultiFun_Set(AUX_DECT_GPIO, PINMUX_LEVEL_GPIO_END_FLAG);
gpio_request(AUX_DECT_GPIO, "input");
gpio_direction_input(AUX_DECT_GPIO);
envp[1] = NULL;
while(1) {
cur_gpio_value = gpio_get_value(AUX_DECT_GPIO);
//printk("cur_gpio_value = %d!\n",cur_gpio_value);
if (pre_gpio_value != cur_gpio_value) {
if(0 == cur_gpio_value)
envp[0] = "AUX_STATUS=PLUG_IN";
else
envp[0] = "AUX_STATUS=PLUG_OUT";
printk("Send uevent: %s!\n",envp[0]);
kobject_uevent_env(&_mic_dev.dev.kobj, KOBJ_CHANGE, envp);
pre_gpio_value = cur_gpio_value;
}
msleep(500);
if (kthread_should_stop())
break;
}
gpio_free(AUX_DECT_GPIO);
return 0;
}
static void aux_detect_thread_init()
{
aux_detect_thread_tsk = kthread_run(aux_detect_kthread_func, NULL, "aux_detect_kthread_func");
if (!aux_detect_thread_tsk) {
printk("[%s] create aux_detect_kthread_func fail!\n",__func__);
}
}
static void aux_detect_thread_exit()
{
if(aux_detect_thread_tsk){
kthread_stop(aux_detect_thread_tsk);
aux_detect_thread_tsk = NULL;
}
}
sysfs文件节点创建
#include <linux/fs.h>
unsigned char HasSignal = 0;
//devfs文件系统的读接口
static ssize_t sysfs_read(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
ssize_t ss;
ss= sprintf(buf, "sysfs_read:[%d]\r\n", HasSignal);
HasSignal =0;
return ss;
}
//devfs文件系统的写接口
static ssize_t sysfs_write(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,ssize_t count)
{
int val = 0;
//字符串转为数字
val = simple_strtol(buf, NULL, 10);
if(val == 0)
{
...
}
else
{
...
}
return count;
}
//devfs文件系统的设备属性
static struct kobj_attribute SignalType_read =__ATTR(SignalType, S_IRUGO | S_IWUSR, sysfs_read, NULL);
static struct kobj_attribute SignalType_write =__ATTR(write, S_IWUGO, NULL,sysfs_write);
static struct attribute *tsc_rst[] = {
&SignalType_read.attr,
&SignalType_write.attr,
NULL,
};
static struct attribute_group my_attr_group = {
.attrs = tsc_rst,
};
static int sysfs_status = 0 ;
struct kobject *soc_kobj = NULL;
//文件节点名称为tsc_rst
#define SYSFS_NAME "tsc_rst"
static int sys_decodernode(void)
{
int ret = 0;
cyttsp6_dbg("==>func = %s ,line = %d\n",__func__,__LINE__);
soc_kobj = kobject_create_and_add(SYSFS_NAME, NULL);
if (!soc_kobj)
goto err_board_obj;
//创建devfs文件系统接口设备
ret = sysfs_create_group(soc_kobj, &my_attr_group);
if (ret)
goto err_soc_sysfs_create;
sysfs_status = 1;
return 0;
}
xxx_probe(...)
{
sys_decodernode();
}
void sysnode_exit(void)
{
cyttsp6_dbg("==>func = %s ,line = %d\n",__func__,__LINE__);
if(sysfs_status == 1){
sysfs_status = 0;
kobject_put(soc_kobj);
sysfs_remove_group(soc_kobj, &my_attr_group);
}
}
static int cyttsp6_i2c_remove(struct i2c_client *client)
{
sysnode_exit();
}
Android sysfs文件节点读写
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
File awakeTimeFile = new File("/sys/devices/platform/5b0d0000.usb/ci_hdrc.0/driver/ci_hdrc.0/role");
FileWriter fr;
写操作:
try {
fr = new FileWriter(awakeTimeFile);
fr_xen = new FileWriter(awakeTimeFileXen);
writebuf[0] = 'h';
writebuf[1] = 'o';
writebuf[2] = 's';
writebuf[3] = 't';
fr.write(writebuf);
fr_xen.write(writebuf);
Log.d("ROOT","write host finish!");
fr.close();
os.writeBytes("exit\n");
os.flush();
}
catch (IOException e) {
e.printStackTrace();
}
读操作:
try{
File readFile = new File("/sys/devices/platform/5b0d0000.usb/ci_hdrc.0/driver/ci_hdrc.0/role");
FileReader inCmd = new FileReader(readFile);
try{
while((hasRead = inCmd.read(readbuf)) > 0){
for(int i = 0; i < readbuf.length; i ++) {
System.out.println(readbuf[i] + "\n");
}
}
}catch (IOException e){
e.printStackTrace();
}
} catch (FileNotFoundException e){
e.printStackTrace();
}
Android如何增加自己的服务
并开机自启动,以android9.0 selinuxswitch为例
1.首先增加selinux权限
device/fsl/imx8q/sepolicy_car/selinuxswitch.te
type selinuxswitch, domain;
type selinuxswitch_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(selinuxswitch)
set_prop(selinuxswitch, public_vendor_default_prop)
allow selinuxswitch vendor_shell_exec:file rx_file_perms;
allow selinuxswitch vendor_toolbox_exec:file rx_file_perms;
# Allow insmod
allow selinuxswitch self:capability sys_module;
allow selinuxswitch system_file:file { getattr setattr open read write create };
allow selinuxswitch vendor_file:file { getattr setattr open read write create };
allow selinuxswitch wc_prop:property_service { set };
allow selinuxswitch shell_exec:file { map read execute getattr setattr create append };
allow selinuxswitch sysfs:file { getattr setattr };
allow selinuxswitch sysfs:dir { getattr setattr };
allow selinuxswitch selinuxswitch:capability { dac_read_search chown fowner fsetid };
allow selinuxswitch toolbox_exec:file { getattr setattr execute read open write execute_no_trans map };
allow selinuxswitch wifi_data_file:dir { read getattr setattr open search };
allow selinuxswitch wifi_data_file:file { read getattr setattr };
allow selinuxswitch wpa_socket:dir { read getattr setattr open search };
allow selinuxswitch wpa_socket:file { read getattr setattr };
allow selinuxswitch wpa_socket:sock_file { read getattr setattr };
allow selinuxswitch selinuxfs:file { read write open };
allow selinuxswitch system_wpa_socket:sock_file { read getattr setattr };
device/fsl/imx8q/sepolicy_car/file_contexts
/vendor/bin/selinuxswitch u:object_r:selinuxswitch_exec:s0
2.拷贝执行文件
device/fsl/imx8q/mek_8q/BoardConfig.mk
120: device/fsl/imx8q/etc/selinuxswitch:vendor/bin/selinuxswitch \
3.在init.rc增加触发
device/fsl/imx8q/mek_8q/init_car.rc +150
148 on property:vendor.all.setup_core.ready=1
149 start boot_completed_main_sh
150 start selinuxswitch
174 service selinuxswitch /vendor/bin/selinuxswitch
175 class main
176 user root
177 group root shell
178 disabled
179 oneshot
或者自己增加环境变量触发的方法也可以
#on 后面的是触发器 option是指令
on property:test.wugn=wugn_test
start selinuxswitch
触发条件:
setprop test.wugn wugn_test