Android下新增驅動及HAL_JNI_Service接口實例

#include
#include <linux/semaphore.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>






#define VIRTUALIO_DEVICE_NODE_NAME "virtualio"
#define VIRTUALIO_DEVICE_FILE_NAME "virtualio"
#define VIRTUALIO_DEVICE_PROC_NAME "virtualio"
#define VIRTUALIO_DEVICE_CLASS_NAME "virtualio"


static int virtualio_major = 0;
static int virtualio_minor = 0;


struct virtualio_android_dev
{
char reg1;
char reg2;
char reg3;
char reg4;
struct semaphore sem;
struct cde dev;
};




static struct class *virtualio_class = NULL;
static struct virtualio_android_dev *virtualio_dev = NULL;


static int virtualio_open(struct inode *inode,struct file *filep);
static int virtualio_release(struct inode *inode,struct file *filp);
static ssize_t virtualio_read(struct file*filp,char __user*buf,u8 num);
static ssize_t virtualio_write(struct file *filp,const char __user  *buf,u8 num);




static struct file_operations virtualio_fops =
{
.owner = THIS_MODULE,
.open = virtual_open,
.release = virtualio_release,
.read = virtualio_read,
.write = virtualio_write.
};


static ssize_t virtualio_reg_show(struct device *dev,struct device_attribute *attr,char *buf);
static ssize_t virtualio_reg_store(struct device *dev,struct device_attribute *attr,const char *buf);




static DEVICE_ATTR(val,S_IRUGO | S_IWUSR,virtualio_val_show,virtualio_val_store);




static int virtualio_open(struct inode *inode,struct file *filp)
{
struct virtualio_android_dev *dev;
dev = container_of(inode->i_cdev,struct virtualio_android_dev,dev);
filp->private_data = dev;

return 0;
}
static int virtualio_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t virtualio_read(struct file *filp,char __user *buf,u8 num)
{
ssize_t err = 0;
struct virtualio_android_dev *dev = filp->private_data;

if(down_interruptible(&(dev->sem))){
return -ERESTARTSYS;
}
if(num<1||num>4)
{
goto out;
}

switch(num)
{
case 1:
copy_to_user(buf,&(dev->reg1),1);
break;
case 2:
copy_to_user(buf+1,&(dev->reg2),1);
break;
case 3:
copy_to_user(buf+1,&(dev->reg2),1);
break;
case 4:
copy_to_user(buf+1,&(dev->reg2),1);
break;

default:
err = -EFAULT;
goto out;
break;
}
err = num;
out:
up(&(dev->sem));
return err;
}


static ssize_t virtualio_write(struct ile *filp,const char __user *buf,u8 num)
{
struct virtualio_android_dev *dev = filp->private_data;
ssize_t err = 0;

if(down_interruptible(&(dev->sem)))
return -ERESTARTSYS;

if(num<1||num>4)
{
goto out;
}

switch(num)
{
case 1:
copy_from_user(&(dev->reg1),buf+num-1,1);
break;
case 2:
copy_from_user(&(dev->reg1),buf+num-1,1);
break;
case 3:
copy_from_user(&(dev->reg1),buf+num-1,1);
break;
case 4:
copy_from_user(&(dev->reg1),buf+num-1,1);
break;
default:
err = -EFAULT;
goto out;
break;
}
err = num;
out:
up(&(dev->sem));
return err;
}


static ssize_t __vitualio_get_reg(struct virtualio_android_dev *dev,char *buf)
{
u8 reg1_val = 0;
u8 reg2_val = 0;
u8 reg3_val = 0;
u8 reg4_val = 0;

if(down_interruptible(&(dev->sem)))
return -ERESTARTSYS;

reg1_val = dev->reg1;
reg2_val = dev->reg2;
reg3_val = dev->reg3;
reg4_val = dev->reg4;

up(&(dev->sem));

return snprintf(buf,PAGE_SIZE,"%d,%d,%d,%d\n",reg1_val,reg2_val,reg3_val,reg4_val);
}


static ssize_t __virtual_set_reg(struct virtualio_android_dev *dev,const char buf[])
{
u8 reg1_val = 0;
u8 reg2_val = 0;
u8 reg3_val = 0;
u8 reg4_val = 0;

reg1_val = buf[0];
reg2_val = buf[0];
reg3_val = buf[0];
reg4_val = buf[0];

if(down_interruptible(&dev->sem))
return -ERESTARTSYS;

dev->reg1_val = reg1_val;
dev->reg2_val = reg2_val;
dev->reg3_val = reg3_val;
dev->reg4_val = reg4_val;

up(&(dev->sem));

return count;
}


static ssize_t virtualio_req_show(struct device *dev,struct device_attribute *attr,char *buf)
{
struct virtualio_android_dev *hdev = (struct virtualio_android_dev*)dev_get_drvdata(dev);

return __vitualio_get_reg(hdev,buf);
}


static ssize_t virtualio_req_store(struct device *dev,struct device_attribute *attr,const char *buf,size_t count)
{
struct virtualio_android_dev *hdev = (struct virtualio_android_dev*)dev_get_drvdata(dev);

return __virtualio_set_req(hdev,buf);
}


static ssize_t virtualio_proc_read(char *page,char *start,off_t off,int count,int *eof,void *data)
{
if(off>0){
*eof = 1;
return 0;
}
return __virtual_get_reg(hello_dev,page);
}


static ssize_t virtualio_proc_write(struct file *filp,const char __user *buff,unsigned long len,void *data)
{
int err = 0;
char *page = NULL;
if(len>PAGE_SIZE)
{
printk(KERNEL_ATTR"the buff is too large:%lu.\n",len);
return -EFAULT;
}
page = (char*)_get_free_page(GFP_KERNEL);
if(!page)
{
printk(KERNEL_ATTR"failed to alloc page.\n");
return -ENOMEM;
}
if(copy_from_user(page,buff,len))
{
printk(KERNEL_ATTR"failed to copy buff from user.\n");
err = -EFAULT;
goto out;
}
err = _virtual_set_reg(virtualio_dev,page,len);
out:
free_page((unsigned long)page);
return err;
}
static void virtulio_create_proc(void)
{
struct proc_dir_entry *entry ;
entry = create_proc_entry(VIRTUALIO_DEVICE_PROC_NAME,0,NULL);
if(entry)
{
entry->owner = THIS_MODULE;
entry->read_proc = virtualio_proc_read;
entry->write_proc = virtualio_proc_write;

}
}


static void virtualio_remove_proc(void)
{
remove_proc_entry(VIRTUALIO_DEVICE_PROC_NAME,NULL);
}


static int __virtualio_setup_dev(struct virtualio_android_dev *dev)
{
int err;
dev_t devno = MKDEV(virtualio_major,virtualio_minor);

memset(dev,0,sizeof(struct virtualio_android_dev));
cdev_init(&(dev->dev),&virtualio_fops);
dev->dev.owner = THIS_MODULE;
dev->dev.ops = &virtualio_fops;

err = cdev_add(&(dev->dev),devno,1);
if(err)
return err;

init_MUTEX(&(dev->sem));

dev->reg1 = 0;
dev->reg2 = 0;
dev->reg3 = 0;
dev->reg4 = 0;

return 0;
}


static int __init virtualio_init(void)
{
int err = -1;
dev_t dev = 0;
struct device *temp = NULL;
printk(KERN_ALERT"initializing virtualio device.\n");

err = alloc_chrdev_region(&dev,0,1,VIRTUALIO_DEVICE_NODE_NAME);
if(err<0)
{
printk(KERN_ALERT"failed to alloc char dev region.\n");
goto fail;
}
virtualio_major = MAJOR(dev);
virtualio_minor = MINOR(dev);

virtualio_dev = kmalloc(sizeof(struct virtualio_android_dev),GFP_KERNEL);
if(virtualio_dev)
{
err = -ENOMEM;
printk(KERN_ALERT"failed to alloc virtualio_dev.\n");
goto unregister;
}

err = __virtualio_setup_dev(virtualio_dev);
if(err)
{
printk(KERN_ALERT"failed to setup dev:%d.\n",err);
goto cleanup;
}

//sys/class目錄下創建設備類別目錄
virtualio_class = class_create(THIS_MODULE,VIRTUALIO_DEVICE_CLASS_NAME);
if(IS_ERR(virtualio_class))
{
err = PTR_ERR(virtualio_class);
printk(KERN_ALERT"failed to create virtualio class.\n");
goto destroy_cdev;
}

/*在/dev/目錄和sys/class/virtualio/目錄下分別創建設備文件*/
temp = device_create(virtualio_class,NULL,dev,"%s",VIRTUALIO_DEVICE_FILE_NAME);
if(IS_ERR(temp))
{
err = PTR_ERR(temp);
printk(KERN_ALERT"failed to create virtualio device.");
goto destroy_class;
}
dev_set_drvdata(temp,virtualio_dev);

/*創建/proc/virtualio文件*/
virtual_create_proc();

printk(KERN_ALERT"succedded to initialize virtualio device.\n");
return 0;


destroy_devie:
device_destroy(virtualio_class,dev);


destroy_class:
class_destroy(virtualio_dev);
destroy_cdev:
cdev_del(&(virtualio_dev->dev));
cleanup:
kfree(virtualio_dev);
unregister:
unregister_chrdev_region(MKDEV(virtualio_major,virtualio_minor),1);
fail:
return err;
}


static void __exit virtualio_exit(void)
{
dev_t devno = MKDEV(virtualio_major,virtualio_minor);
printk(KERN_ALERT"destroy virtualio device.\n");

virtualio_remove_proc();

if(virtualio_class)
{
device_destroy(virtualio_class,MKDEV(virtualio_major,virtualio_minor));
class_destroy(virtualio_class);
}
if(virtualio_dev)
{
cdev_del(&(virtualio_dev->dev));
kfree(virtualio_dev);
}
unregister_chrdev_region(devno,1);
}


MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("first device driver ");


module_init(virtualio_init);
module_exit(virtualio_exit);








//native C


#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>


#define DEVICE_NAME "/dev/virtualio"


int main(int argc,char **argv)
{
int fd = -1;
int reg_val = 0;
int i;
fd = open(DEVICE_NAME,O_RDWR);
if(fd==-1)
{
printf("open device %s failed!\n",DEVICE_NAME);
return -1;
}
printf("read original val:\n");
for(i=0;i<4;i++)
{
read(fd,&reg_val,i+1);
printf("%d.\n",reg_val);
}
for(i=0;i<4;i++)
{
reg_val = 6+i;
printf("write value %d to %s\n",reg_val,DEVICE_NAME);
write(fd,&reg_val,i+1);
}

for(i=0;i<4;i++)
{
read(fd,&reg_val,i+1);
printf("%d.\n",reg_val);
}
close(fd);
return 0;
}


Android.mk


LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE :=virtualio
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)




hardware


//hardware/libhardware/include/hardware/virtualio.h
#ifndef ANDROID_VIRTUALIO_INTERFACE_H
#define ANDROID_VIRTUALIO_INTERFACE_H


#include<hardware/hardware.h>


__BEGIN_DECLS


#define VIRTUAL_HARDWARE_MODULE_ID "virtualio"


struct virtualio_module_t{
struct hw_module_t common;
};


struct virtualio_device_t{
struct hw_device_t common;
int fd;
int (*set_reg)(struct virtualio_device_t *dev,char reg);
int (*get_reg)(struct virtualio_device_t *dev,char *reg);
};


__END_DECLS


#endif




//hardware/libhardware/modules/virtualio/virtualio.c


#define LOG_TAG "virtualioStub"


#include<hardware/hardware.h>
#include<hardware/virtualio.h>
#include<fcntl.h>
#include<errno.h>
#include<cutils/log.h>
#include<cutils/atomic.h>


#define DEVICE_NAME "/dev/virtual"
#define MODULE_NAME "Virtualio"
#define MODULE_AUTHOR "simon"


static int virtualio_device_open(const struct hw_module_t *module,const
char *name,struct hw_device_t **device);


static int virtualio_device_close(struct hw_device_t *device);


static int virtualio_set_reg(struct virtualio_device_t *dev,char reg,unsigned char num);
static int virtualio_get_reg(struct virtualio_device_t* dev,char *reg,unsigned char num);




static struct hw_module_methods_t virtualio_module_methods = {
open:virtualio_device_open
};


struct virtualio_module_t HAL_MODULE_INFO_SYM ={
common:
{
tag:HARDWARE_MODULE_TAG,
version_major:1,
version_minor:0,
id:VIRTUAL_HARDWARE_MODULE_ID,
name:MODULE_NAME,
author:MODULE_AUTHOR,

}
};


static int virtualio_device_open(const struct hw_module_t *module,const char name,struct  hw_device_t **device)
{
struct virtualio_device_t *dev;

dev = (struct virtualio_device_t *)malloc(sizeof(struct virtualio_device_t));;
if(!dev)
{
return -EFAULT;
}

memset(dev,0,sizeof(struct hello_device_t));
dev->common.tag = HARDWARE_MODULE_TAG;
dev->common.version = 0;
dev->common.module = (hw_module_t*)module;
dev->common.close = virtualio_device_close;
dev->set_reg = virtualio_set_reg;
dev->get_reg = virtualio_get_reg;

if((dev->fd = open(DEVICE_NAME,O_RDWR))==-1)
{
free(dev);
return -EFAULT;
}
*device = &(dev->common);

return 0;
}


static int virtualio_device_close(struct hw_device_t *device)
{
struct virtualio_device_t *virtualio_device = (struct virtualio_device_t*)device;

if(virtualio_device){
close(virtualio_device->fd);
free(virtualio_device);
}
return 0;
}


static int virtual_set_reg(struct virtualio_device_t *dev,chr reg,unsigned hchar num)
{
LOGI("virtualio Stub:set value %d to device erg.",eg);
write(dev->fd,&reg,num);
return 0;
}


static int virtualio_get_reg(struct virtualio_device_t *dev,char *reg,unsigned char num)
{
if(!reg)
{
LOGE("vitualio stub:error reg pointer");
return -EFAULT;
}
read(dev->fd,val,num);
LOGI("Vritualio Stub,get value %d from device reg",*erg);
return 0;
}


Android.mk


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE :=false
LOCAL_MODULE_PATH :=$(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOAL_SRC_FILES := virtualio.c
LOCAL_MODULE := virtualio.default
include$(BUILD_SHARED_LIBRARY)






//frameworks/base/services/jni/com_android_server_VirtualioService.cpp


#define LOG_TAG "VirtualioService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/virtualio.h>
#include <stdio.h>


namespace android
{
struct virtualio_device_t *vritualio_device = NULL;
static void virtualio_setReg(JNIEnv *env,jobject clazz,jchar value,jchar num)
{
char reg = value;
LOGI("Virtualio JNI:set value %d to device reg.",reg)
if(!virtualio_device)
{
LOGI("Vritualio JNI:deice is not open.");
return;
}
virtualio_device->set_reg(virtualio_device,reg,num);
}

static jnit virtualio_getReg(JNIEnv *env,jobject clazz,jchar num)
{
char reg = 0;
if(!virtualio_device)
{
LOGI("Virtualio JNI:device is not open.");
return reg;
}
virtualio_device->get_reg(virtualio_device,&reg,num);
LOGI("Virtualio jni:get value %d from deice reg",reg);

return reg;
}

static inline int virtualio_device_open(const hw_module_t *module,struct virtualio_device_t **device)
{
return module->methods->open(module,VIRTUALIO_HARDWARE_MODULE_ID,(struct hw_device_t**)device);
}

static jooblean virtualio_init(JNIEnv *env,jclass clazz)
{
virtualio_module_t *module;
LOGI("Virtualio JNI:initializing....");

if(hw_get_module(VIRTUALIO_HARDWARE_MODULE_ID,(const struct hw_module_t**)&module)==0)
{
LOGI("Virtualio JNI:virtualio Stub found.");
if(virtualio_device_open(&(module->common),&virtualio_device)==0)
{
LOGI("Virtualio JNI:virtualio device is open.");
return 0;
}
LOGE("virtualio jni:failed to open virtualio device.");
return -1;
}
LOGE("virtualio jni:failed to get virtualio stub module.");
return -1;

}


static const JNINativeMethod method_table[] = 
{
{"init_native","()Z",(void*)virtualio_init},
{"setReg_native","(I)V",(void*)virtualio_setReg},
{"getReg_native","()I",(void*)virtualio_getReg},
};


int register_android_server_VirtualService(JNIEnv *env)
{
return jniRegisterNativeMethods(env,"com/android/server/VirtualioServer",method_table,NELEM(method_table));
}

};


//在framework/base/services/jni/onload.cpp中增加註冊聲明及調用


//在framework層增加virtualio服務


//framework/base/core/java/android/os/IVirtualioService.aidl
package android.os;


interface IVirtualioService{
void setReg(int val);
int getReg();
}


//在framework/base/Android.mk文件中增加IVirtualiService.aidl源文件


//mmm framework/base後會生成IVirtualioService.aidl相應的IVirtualioService.Stu接口


//framework/base/service/java/com/andrid/server/IVirtualService.java
package com.android.server;
import android.content.Context;
import android.os.IVirtualService;
import android.util.Slog;


public class VirtualioService extends IVirtualService.Stub
{
private static final String TAG = "VirtualioService";
VirtualioService()
{
init_native();
}
public void setReg(int val)
{
setR_native(val);
}
public int getReg()
{
return getReg_native();
}

private static native boolean init_native();
private static native void setReg_native(int val);
private static native int getReg_native();
};


//在framework/base/service/java/com/andrid/server/SystemServer.java的run中增加virtualioServer的調用


public void run()
{
...
try{
Slog.i(TAG,"DiskStats Service");
ServiceManager.addService("diskstats",new DiskStatsServcie(context));
}catch(Thorwable e)
{
Slog.e(TAG,"Failure starting DiskStats Service",e);
}

try{
Slog.i(TAG,"Virtualio service");
ServiceManager.addService("virtualio",new VirtualioService());
}catch(Throwable e)
{
Slog.e(TAG,"Failure starting Virtualio Service",e);
}
}



























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章