android APK应用层到kernel层功能接口调用实现总结

android APK应用层到kernel层功能接口调用实现总结

一.问题现象及背景:

客户有个需求需要在上层apk中控制手机上的VMIC、SPK、RAY_LED、OTG、SWITCH、PTT_SWITCH、PTT_PD、BULE_LED、KEYPAD_LED等按键、音频、镭射、OTG、灯的功能切换。其中部分功能是该手机上新增的功能,android原生系统上没有提供相关的接口,因此需要在原生系统框架上增加相关接口,实现APK应用中控制手机上的这些功能。

主要参考原生系统上APK到kernel层接口的调用框架实现,下面以该功能主要代码实现来简述APK应用层到kernel层功能接口调用实现。

 

二.主要代码实现:

   1. apk应用主要代码实现

a. 文件packages\K508Control\src\com\android\tmptest\Test.java

 

package com.android.tmptest;

import android.content.Intent; 

importandroid.content.SharedPreferences; 

import android.os.Bundle; 

importandroid.preference.CheckBoxPreference; 

importandroid.preference.EditTextPreference; 

importandroid.preference.ListPreference; 

importandroid.preference.Preference; 

importandroid.preference.PreferenceActivity; 

importandroid.preference.PreferenceManager; 

importandroid.preference.PreferenceScreen; 

importandroid.preference.Preference.OnPreferenceClickListener; 

import android.util.Log; 

 

//importcom.android.server.K508ControlService;

import android.os.IK508ControlService; 

import android.os.ServiceManager;

 

public class Test extendsPreferenceActivity implements

         Preference.OnPreferenceClickListener,

         Preference.OnPreferenceChangeListener{ 

        

         privatePreference mPreference_VMIC;

         privatePreference mPreference_SPK;

         privatePreference mPreference_RAY;

         privatePreference mPreference_OTG;

         privatePreference mPreference_SWITCH;

         privatePreference mPreference_PTT_SWITC;

         privatePreference mPreference_PTT_PD;

         privatePreference mPreference_BULE;

         privatePreference mPreference_KEYPAD;

 

         privateIK508ControlService k508Service = null; 

 

         @Override

         publicvoid onCreate(Bundle savedInstanceState)

         {

            super.onCreate(savedInstanceState);          

            Log.d("zhengconglong","onCreate");

            addPreferencesFromResource(R.xml.tp_test);

           

            mPreference_VMIC =(Preference)findPreference("K508_IOC_VMIC_EN");

            mPreference_SPK =(Preference)findPreference("K508_IOC_SPK_EN");

            mPreference_RAY =(Preference)findPreference("K508_IOC_RAY_LED_EN");

            mPreference_OTG =(Preference)findPreference("K508_IOC_OTG_EN");

            mPreference_SWITCH =(Preference)findPreference("K508_IOC_SWITCH_EN");

            mPreference_PTT_SWITC =(Preference)findPreference("K508_IOC_PTT_SWITCH_EN");

            mPreference_PTT_PD =(Preference)findPreference("K508_IOC_PTT_PD");

            mPreference_BULE =(Preference)findPreference("K508_IOC_BULE_LED_EN");

            mPreference_KEYPAD =(Preference)findPreference("K508_IOC_KEYPAD_LED_EN");

           

            mPreference_VMIC.setOnPreferenceClickListener(this);

            mPreference_SPK.setOnPreferenceClickListener(this);

            mPreference_RAY.setOnPreferenceClickListener(this);

            mPreference_OTG.setOnPreferenceClickListener(this);

            mPreference_SWITCH.setOnPreferenceClickListener(this);

             mPreference_PTT_SWITC.setOnPreferenceClickListener(this);

            mPreference_PTT_PD.setOnPreferenceClickListener(this);     

            mPreference_BULE.setOnPreferenceClickListener(this);

            mPreference_KEYPAD.setOnPreferenceClickListener(this);

           

            SharedPreferencesshp = PreferenceManager.getDefaultSharedPreferences(this); 

                  

                   k508Service= IK508ControlService.Stub.asInterface(ServiceManager.getService("K508Control"));

         }       

                  

         @Override

         protectedvoid onResume() {           

                   super.onResume();          

         }

 

         @Override

         protectedvoid onPause() {

                   super.onPause();              

         }

        

         publicboolean setSummary(Preference pf) {

            if(pf.getSummary().equals("false")){

                      pf.setSummary("true");

                      return true;

            }else{

                      pf.setSummary("false");

                      return false;

            }       

         }

 

         @Override

   public boolean onPreferenceClick(Preference preference) {

            

//               Log.d("zhengconglong","onPreferenceClick");

       if (preference == mPreference_VMIC) {

//             Log.d("zhengconglong","111111");

                if(setSummary(mPreference_VMIC)){

                     //mPreference_VMIC on

                     try {

                            k508Service.setVal(0,1);

                                     }catch (Throwable e) {    

                                             Log.d("k508ServicemPreference_VMIC", "error");

                                     }

                                     Log.d("k508ServicemPreference_VMIC", "on");

                } else {

                           //mPreference_VMIC off

                           try {

                                  k508Service.setVal(0,0);

                                     }catch (Throwable e) {    

                                             Log.d("k508ServicemPreference_VMIC", "error");

                                     }       

                                      Log.d("k508ServicemPreference_VMIC", "off");

                }

//             Log.d("zhengconglong","K508_IOC_VMIC_EN");

       }else if(preference.getKey().equals("K508_IOC_SPK_EN")) {

//             Log.d("zhengconglong","22222");

                if(setSummary(mPreference_SPK)){

                                     try{

                     k508Service.setVal(1,1);

                                     }catch (Throwable e) {    

                                             Log.d("k508ServiceK508_IOC_SPK_EN", "error");

                                     }

                                     Log.d("k508ServicemPreference_SPK", "on");      

                         

            } else {

                     try{

                     k508Service.setVal(1,0);

                                     }catch (Throwable e) {    

                                             Log.d("k508ServiceK508_IOC_SPK_EN", "error");

                                     }

                                      Log.d("k508Service mPreference_SPK","off");                       

            }

       }else if(preference.getKey().equals("K508_IOC_RAY_LED_EN")) {

                if(setSummary(mPreference_RAY)){

                                     try{

                                               k508Service.setVal(2,1);

                                     }catch (Throwable e) {    

                                             Log.d("k508ServiceK508_IOC_RAY_LED_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_RAY_LED_EN", "on");

            } else {

                     try{

                                               k508Service.setVal(2,0);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_RAY_LED_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_RAY_LED_EN", "off");                      

            }

       }else if(preference.getKey().equals("K508_IOC_OTG_EN")) {

                if(setSummary(mPreference_OTG)){

                                     try{

                                               k508Service.setVal(3,1);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_OTG_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_OTG_EN", "on");

            } else {

                     try{

                                               k508Service.setVal(3,0);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_OTG_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_OTG_EN", "off");                    

            }

       }else if(preference.getKey().equals("K508_IOC_SWITCH_EN")) {

                 if(setSummary(mPreference_SWITCH)){

                                     try{

                                               k508Service.setVal(4,1);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_SWITCH_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_SWITCH_EN", "on");

            } else {

                     try{

                                               k508Service.setVal(4,0);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_SWITCH_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_SWITCH_EN", "off");                       

            }

       }else if(preference.getKey().equals("K508_IOC_PTT_SWITCH_EN")){

                if(setSummary(mPreference_PTT_SWITC)){

                                     try{

                                               k508Service.setVal(5,1);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_PTT_SWITCH_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_PTT_SWITCH_EN", "on");

            } else {

                     try{

                                               k508Service.setVal(5,0);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_PTT_SWITCH_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_PTT_SWITCH_EN", "off");                       

            }

       }elseif(preference.getKey().equals("K508_IOC_PTT_PD")) {

                if(setSummary(mPreference_PTT_PD)){

                                     try{

                                               k508Service.setVal(6,1);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_PTT_PD", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_PTT_PD", "on");

 

            } else {

                       try{

                                               k508Service.setVal(6,0);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_PTT_PD", "error");

                                     }       

                                     Log.d("k508ServiceK508_IOC_PTT_PD", "off");                     

            }

       }else if(preference.getKey().equals("K508_IOC_BULE_LED_EN")) {

                if(setSummary(mPreference_BULE)){

                                     try{

                                               k508Service.setVal(7,1);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_BULE_LED_EN", "error");

                                     }       

                                     Log.d("k508ServiceK508_IOC_BULE_LED_EN", "on");

            } else {

                     try{

                                             k508Service.setVal(7,0);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_BULE_LED_EN", "error");

                                     }       

                                     Log.d("k508ServiceK508_IOC_BULE_LED_EN", "off");                    

            }

       }else if(preference.getKey().equals("K508_IOC_KEYPAD_LED_EN")){

                if(setSummary(mPreference_KEYPAD)){

                                     try{

                                               k508Service.setVal(8,1);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_KEYPAD_LED_EN", "error");

                                     }       

                                     Log.d("k508ServiceK508_IOC_KEYPAD_LED_EN", "on");

 

            } else {

                     try{

                                               k508Service.setVal(8,0);

                                     }catch (Throwable e) {    

                                               Log.d("k508ServiceK508_IOC_KEYPAD_LED_EN", "error");

                                     }

                                     Log.d("k508ServiceK508_IOC_KEYPAD_LED_EN", "off");                        

            }

       }

       

       return false;

   }

        

         @Override

         publicboolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 

                 Preference preference) {

                   Log.d("zhengconglong","onPreferenceTreeClick");

                   returnfalse;

         }

 

         @Override

         publicboolean onPreferenceChange(Preference preference, Object objValue) {

                   Log.i("zheng","onPreferenceChange----->"

                                                        +String.valueOf(preference.getKey()));

                   if(preference == mPreference_RAY) {

                            Log.i("zheng","W " + String.valueOf(objValue));

                   }else if (preference.getKey().equals("K508_IOC_SPK_EN")) {

                            Log.i("zheng","internet " + String.valueOf(objValue));

                            returnfalse;

                   }else if (preference == mPreference_SWITCH) {

                            Log.i("zheng"," NewDeptName" + objValue);

                   }else if (preference.getKey().equals("K508_IOC_PTT_PD")) {

                            Log.i("zheng","change" + String.valueOf(objValue));

                   }else if (preference == mPreference_KEYPAD) {

                            Log.i("zheng","Old Value = " + String.valueOf(objValue));

                            returnfalse;

                   }

                   returntrue;

         }

}

 

2. frameworks  服务层主要代码实现:

a. frameworks/base/Android.mk

红色部分为增加的代码

………

        core/java/android/os/IPowerManager.aidl \

        core/java/android/os/IRemoteCallback.aidl \

        core/java/android/os/IVibratorService.aidl \

       core/java/android/os/IK508ControlService.aidl \

        core/java/android/service/wallpaper/IWallpaperConnection.aidl \

……….

 

b.  该文件为新增文件

frameworks/base/core/java/android/os/IK508ControlService.aidl 

代码实现如下:

package android.os;

 

interface IK508ControlService

{

         voidsetVal(int cmd,long arg);

}

 

c. 该文件为新增文件

frameworks/base/services/java/com/android/server/K508ControlService.java

代码实现如下:

package com.android.server; 

import android.content.Context; 

importandroid.os.IK508ControlService; 

import android.util.Slog; 

 

public class K508ControlService extendsIK508ControlService.Stub

   private static final String TAG = "K508ControlService"; 

   K508ControlService() { 

       init_native(); 

   } 

   public void setVal(int cmd,long arg) { 

       setVal_native(cmd,arg); 

   }    

 

     

   private static native int init_native(); 

   private static native void setVal_native(int cmd,long arg); 

}; 

 

d.frameworks/base/services/java/com/android/server/SystemServer.java

红色部分为增加的代码

 

importcom.android.server.K508ControlService;

public void run() {

 

…………..

 

       try {

           ActivityManagerNative.getDefault().showBootMessage(

                   context.getResources().getText(

                           com.android.internal.R.string.android_upgrading_starting_apps),

                            false);

       } catch (RemoteException e) {

       }

                  

                   try {

                              Slog.e(TAG, "K508Control Service");

                             ServiceManager.addService("K508Control", newK508ControlService());

                   } catch (Throwable e) {

                              Slog.e(TAG, "Failure startingK508Control Service", e);

                   }

 

       if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

 

            try {

                Slog.i(TAG, "DevicePolicy");

                devicePolicy = newDevicePolicyManagerService(context);

               ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);

            } catch (Throwable e) {

                reportWtf("startingDevicePolicyService", e);

            }

 

…………….

 

}

 

 

3.  frameworks  JNI层主要代码实现:

aframeworks/base/services/jni/Android.mk

红色部分为增加的代码

……………

     com_android_server_VibratorService.cpp \

     com_android_server_location_GpsLocationProvider.cpp \

     com_android_server_connectivity_Vpn.cpp \

     com_android_server_K508ControlService.cpp \

     onload.cpp

…………….

 

 

 

b. 新增文件

frameworks/base/services/jni/com_android_server_K508ControlService.cpp

代码实现如下:

#define LOG_TAG"K508ControlService"

#include "jni.h"

#include "JNIHelp.h"

#include"android_runtime/AndroidRuntime.h"

#include

#include

#include

#include

 

#include

 

namespace android

{

 

   struct k508_device_t* k508_device = NULL;

   static void k508_setVal(JNIEnv* env, jobject clazz, jint cmd,jlong arg)

   {

                   intcmd1 = cmd;

                   longarg1= arg;

                   LOGI("K508ControlJNI: set cmd = %d ,arg=%d to device.", cmd1,arg1);

                   if(!k508_device){

                            LOGI("K508ControlJNI: device is not open.");

                            return;

                   }

        

                   k508_device->set_val(k508_device,cmd1,arg1);

         }

 

         staticinline int k508_device_open(const hw_module_t* module, struct k508_device_t**device)

         {

                   returnmodule->methods->open(module, k508_HARDWARE_MODULE_ID, (structhw_device_t**)device);

         }

 

         staticint k508_init(JNIEnv* env, jclass clazz)

         {

                   k508_module_t*module;

                  

                   LOGI("k508JNI: initializing......");

                   if(hw_get_module(k508_HARDWARE_MODULE_ID,(const struct hw_module_t**)&module) == 0) {

                            LOGI("k508JNI:  Stub found.");

                            if(k508_device_open(&(module->common),&k508_device) == 0) {

                                     LOGI("k508JNI:  device is open.");

                                     return0;

                            }

                            LOGE("k508JNI: failed to open  device.");

                            return-1;

                   }

                   LOGE("k508JNI: failed to get  stub module.");

                   return-1;         

         }

 

         staticconst JNINativeMethod method_table[] = {

                   {"init_native","()I", (void*)k508_init},

                   {"setVal_native","(IJ)V", (void*)k508_setVal},

         };

 

         intregister_android_server_K508ControlService(JNIEnv *env)

         {

                      returnjniRegisterNativeMethods(env,"com/android/server/K508ControlService", method_table,NELEM(method_table));

         }

};

 

c.  frameworks/base/services/jni/onload.cpp

红色部分为增加的代码

namespace android {

………….

intregister_android_server_connectivity_Vpn(JNIEnv* env);

intregister_android_server_K508ControlService(JNIEnv *env);

};

 

extern "C" jintJNI_OnLoad(JavaVM* vm, void* reserved)

{

…………….

  register_android_server_connectivity_Vpn(env);

         register_android_server_K508ControlService(env);

   return JNI_VERSION_1_4;

}

 

4. 增加一个节点并修改权限

a.  mediatek/config/mt6577/init.rc

红色部分为增加的代码

………….

   chmod 0660 /dev/OV8825AF

   chmod 0660 /dev/OV8830AF

          chmod0666 /dev/K508_CONTROL

………….

         chownsystem camera /dev/OV8825AF

         chownsystem camera /dev/OV8830AF

         chown system system /dev/K508_CONTROL

……………

 

5. hardware 层主要修改:

a. 新增文件

hardware/libhardware/include/hardware/K508Control.h

代码实现如下:

#ifndef ANDROID_K508_INTERFACE_H  

#define ANDROID_K508_INTERFACE_H  

 

#include  

 

__BEGIN_DECLS 

 

#define k508_HARDWARE_MODULE_ID"k508control"  

 

struct k508_module_t { 

   struct hw_module_t common; 

}; 

 

struct k508_device_t { 

   struct hw_device_t common; 

   int fd; 

   void (*set_val)(struct k508_device_t* dev, int cmd,long arg); 

}; 

 

__END_DECLS 

 

#define K508_IOC_MAGIC               'H'

#define K508_IOC_VMIC_EN          _IO(K508_IOC_MAGIC, 0)  // 音频控制

#define K508_IOC_SPK_EN                _IO(K508_IOC_MAGIC, 1)  // 音频控制

#define K508_IOC_RAY_LED_EN      _IO(K508_IOC_MAGIC, 2)  // 对方修改

#define K508_IOC_OTG_EN                _IO(K508_IOC_MAGIC, 3)  // 不确定

#define K508_IOC_SWITCH_EN        _IO(K508_IOC_MAGIC, 4)  // 双方控

#define K508_IOC_PTT_SWITCH_EN    _IO(K508_IOC_MAGIC, 5)  // 双方控

#define K508_IOC_PTT_PD           _IO(K508_IOC_MAGIC, 6)  // 双方控

#define K508_IOC_BULE_LED_EN       _IO(K508_IOC_MAGIC, 7)  // 不确定

#define K508_IOC_KEYPAD_LED_EN     _IO(K508_IOC_MAGIC, 8)  // 光感加接口

 

#define MAX_K508_IOCTL_CMD_NUM       15

#endif 

 

b. 新增文件

mediatek/source/hardware/K508Control/K508Control.c

代码实现如下:

#define LOG_TAG "k508Stub"  

 

#include  

#include   

#include   

#include   

#include   

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

 

#define DEVICE_NAME"/dev/K508_CONTROL"  

#define MODULE_NAME"K508_CONTROL"  

#define MODULE_AUTHOR"feng.guangyue "  

 

const int K508_CMD[]=

{

         K508_IOC_VMIC_EN,

         K508_IOC_SPK_EN,

         K508_IOC_RAY_LED_EN,

         K508_IOC_OTG_EN,

         K508_IOC_SWITCH_EN,

         K508_IOC_PTT_SWITCH_EN, 

         K508_IOC_PTT_PD,

         K508_IOC_BULE_LED_EN,

         K508_IOC_KEYPAD_LED_EN

};

 

static int k508_device_open(const structhw_module_t* module, const char* name, struct hw_device_t** device); 

static int k508_device_close(structhw_device_t* device); 

 

static void k508_set_val(structk508_device_t* dev, int cmd,long arg); 

 

 

static struct hw_module_methods_tk508_module_methods = { 

   open: k508_device_open 

}; 

 

 

struct k508_module_t HAL_MODULE_INFO_SYM= { 

   common: { 

       tag: HARDWARE_MODULE_TAG, 

       version_major: 1, 

       version_minor: 0, 

       id: k508_HARDWARE_MODULE_ID, 

       name: MODULE_NAME, 

       author: MODULE_AUTHOR, 

       methods: &k508_module_methods, 

   } 

};

 

 

static int k508_device_open(const structhw_module_t* module, const char* name, struct hw_device_t** device)

   struct k508_device_t* dev;

         dev= (struct k508_device_t *)malloc(sizeof(struct k508_device_t)); 

     

   if(!dev) { 

       LOGE("k508 Stub: failed to alloc space"); 

       return -EFAULT; 

   } 

 

   memset(dev, 0, sizeof(struct k508_device_t)); 

   dev->common.tag = HARDWARE_DEVICE_TAG; 

   dev->common.version = 0; 

   dev->common.module = (hw_module_t*)module; 

   dev->common.close = k508_device_close; 

   dev->set_val = k508_set_val; 

   if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) { 

       LOGE("k508 Stub: failed to open /dev/K508_CONTROL -- %s.",strerror(errno));

                  free(dev); 

       return -EFAULT; 

   } 

 

   *device = &(dev->common); 

   LOGI("k508 Stub: open /dev/K508_CONTROL successfully."); 

 

   return 0; 

 

static int k508_device_close(structhw_device_t* device)

   struct k508_device_t* k508_device = (struct k508_device_t*)device; 

 

   if(k508_device) { 

       close(k508_device->fd); 

       free(k508_device); 

   } 

   return 0; 

 

static void k508_set_val(structk508_device_t* dev, int cmd,long arg)

   LOGI("k508 Stub: set value cmd =%d,arg=%d to device.",cmd,arg); 

   ioctl(dev->fd, K508_CMD[cmd], arg); 

 

c. 新增文件

mediatek/source/hardware/K508Control/Android.mk

代码实现如下:

LOCAL_PATH:= $(call my-dir)

 

include $(CLEAR_VARS)

 

LOCAL_SRC_FILES := K508Control.c

 

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE_PATH :=$(TARGET_OUT_SHARED_LIBRARIES)/hw

 

LOCAL_SHARED_LIBRARIES := liblog

 

LOCAL_MODULE := k508control.default

LOCAL_MODULE_TAGS := optional

include $(BUILD_SHARED_LIBRARY)

 

 

6. kernel 层代码实现

a. 新增文件

mediatek/platform/mt6577/kernel/drivers/k508_control/Makefile

代码实现如下

obj-y +=k508_control.o

 

b. 新增文件

mediatek/platform/mt6577/kernel/drivers/k508_control/k508_control.h

代码实现如下

#ifndef_K508_CONTROL_H_  

#define_K508_CONTROL_H_  

 

#include  

#include  

 

#defineK508_DEVICE_NAME "K508_CONTROL"  

 

structk508_android_dev

       int used;

    struct mutex sem; 

    struct cdev dev; 

}; 

 

 

static intdebug_enable = 1;

#define K508_CONTROL_DEBUG(format,args...) do{ \

       if(debug_enable) \

       {\

              printk(KERN_ERR format,##args);\

       }\

}while(0)

 

#endif 

 

 

c. 新增文件

mediatek/platform/mt6577/kernel/drivers/k508_control/k508_control.c

代码实现如下:

#include

#include

#include

#include

#include          /* printk() */

#include              /* kmalloc() */

#include                  /* everything... */

#include /* error codes */

#include /* size_t */

#include

#include    /* O_ACCMODE */

#include

#include

#include                  /* cli(), *_flags */

#include       /* copy_*_user */

#include  

#include    /*class_create*/ 

#include

#include

#include

#include

#include

#include

#include

#include "mach/mt_gpio.h"

#include

#include

#include

#include

#include

#include

#include

 

#include "k508_control.h"

 

 

 

#define K508_IOC_MAGIC               'H'

#define K508_IOC_VMIC_EN          _IO(K508_IOC_MAGIC, 0)

#define K508_IOC_SPK_EN                _IO(K508_IOC_MAGIC, 1) 

#define K508_IOC_RAY_LED_EN      _IO(K508_IOC_MAGIC, 2) 

#define K508_IOC_OTG_EN                _IO(K508_IOC_MAGIC, 3)

#define K508_IOC_SWITCH_EN        _IO(K508_IOC_MAGIC, 4) 

#define K508_IOC_PTT_SWITCH_EN    _IO(K508_IOC_MAGIC, 5) 

#define K508_IOC_PTT_PD           _IO(K508_IOC_MAGIC, 6) 

#define K508_IOC_BULE_LED_EN       _IO(K508_IOC_MAGIC, 7) 

#define K508_IOC_KEYPAD_LED_EN     _IO(K508_IOC_MAGIC, 8)

 

#define MAX_K508_IOCTL_CMD_NUM       15

 

 

static int k508_major = 0; 

static int k508_minor = 0; 

 

static struct class* k508_class =NULL; 

static struct k508_android_dev* k508_dev= NULL; 

 

static int k508_open(struct inode*inode, struct file* filp); 

static int k508_release(struct inode*inode, struct file* filp); 

static long k508_unlocked_ioctl(structfile *file, unsigned int cmd,unsigned long arg);

 

 

static struct file_operations k508_fops= { 

   .owner = THIS_MODULE, 

   .open = k508_open, 

   .release = k508_release, 

         .unlocked_ioctl= k508_unlocked_ioctl,

};

 

static int k508_setup_dev(structk508_android_dev* dev) ;

 

static int k508_control_probe(structplatform_device *dev)

{

        

         interr = -1; 

         dev_ttmp_dev = 0;

         structdevice* temp = NULL; 

 

         K508_CONTROL_DEBUG("Initializing k508 device./n");                    

       if (k508_major)

         {

                   tmp_dev= MKDEV(k508_major, k508_minor);

                   err= register_chrdev_region(tmp_dev, 1, K508_DEVICE_NAME);

         }

         else

         {

                   err= alloc_chrdev_region(&tmp_dev, 0, 1, K508_DEVICE_NAME);

                   k508_major= MAJOR(tmp_dev); 

                   k508_minor= MINOR(tmp_dev);   

         }

        

         if(err< 0)

         {

                   K508_CONTROL_DEBUG(KERN_INFO":register_chrdev err=%d\n", err);

                   return-EIO;

         }         

 

         k508_dev= kmalloc(sizeof(struct k508_android_dev), GFP_KERNEL); 

         if(!k508_dev)

         { 

                   err= -ENOMEM;     

                   K508_CONTROL_DEBUG("Failedto alloc k508_dev./n"); 

                   gotounregister; 

         }                   

 

         err= k508_setup_dev(k508_dev); 

         if(err)

         { 

                   K508_CONTROL_DEBUG("Failedto setup dev: %d./n", err); 

                   gotocleanup; 

         }                   

 

         k508_class= class_create(THIS_MODULE, K508_DEVICE_NAME); 

         if(IS_ERR(k508_class))

         { 

                   err= PTR_ERR(k508_class);   

                   K508_CONTROL_DEBUG("Failedto create k508 class./n"); 

                   gotodestroy_cdev;

         }                   

 

         temp= device_create(k508_class, NULL, tmp_dev, "%s",K508_DEVICE_NAME); 

         if(IS_ERR(temp))

         {       

                   err= PTR_ERR(temp); 

                   K508_CONTROL_DEBUG("Failedto create k508 device.");   

                   gotodestroy_class; 

         }                   

         dev_set_drvdata(temp,k508_dev);                   

         K508_CONTROL_DEBUG("Succeddedto initialize k508 device./n"); 

         return0; 

 

destroy_device: 

         device_destroy(k508_class,tmp_dev); 

destroy_class:

         class_destroy(k508_class);      

destroy_cdev: 

         cdev_del(&(k508_dev->dev));  

cleanup: 

         kfree(k508_dev);  

unregister: 

         unregister_chrdev_region(MKDEV(k508_major,k508_minor), 1); 

fail: 

         returnerr; 

        

}

 

 

static int k508_control_suspend(structplatform_device *dev, pm_message_t state) // only one suspend mode

{

         return0;

}

 

static int k508_control_resume(structplatform_device *dev) // wake up

{

         return0;

}

 

static int k508_control_remove(structplatform_device *dev)

         dev_tdevno = MKDEV(k508_major, k508_minor); 

         K508_CONTROL_DEBUG("Destroyk508 device./n");                               

         if(k508_class)

         { 

                   device_destroy(k508_class,MKDEV(k508_major, k508_minor)); 

                   class_destroy(k508_class);    

         }                   

         if(k508_dev)

         {       

                   cdev_del(&k508_dev->dev); 

                   kfree(k508_dev); 

         }                   

 

         unregister_chrdev_region(devno,1); 

         return0;

}

 

static struct platform_driverk508_control_driver =

{

   .probe      = k508_control_probe,

   .suspend    =k508_control_suspend,

   .resume     = k508_control_resume,

   .remove   = k508_control_remove,

   .driver     = {

       .name       ="k508_control_Driver",

   },

};

 

 

static struct platform_devicek508_control_device = {

         .name        ="k508_control_Driver",             

         .id               = -1,     

};

 

static int k508_open(struct inode*inode, struct file* filp)

   mutex_lock(&k508_dev->sem);

         k508_dev->used++;

         mutex_unlock(&k508_dev->sem);

         K508_CONTROL_DEBUG("k508_opencontuer k508_dev->used = %d\n",k508_dev->used);

//      if(k508_dev->used> 1)

//      {

//               k508_dev->used--;

//               return-EBUSY;         

//      }

   return 0; 

 

static int k508_release(struct inode*inode, struct file* filp)

   mutex_lock(&k508_dev->sem);

         if(k508_dev->used!= 0)

                   k508_dev->used--;

         mutex_unlock(&k508_dev->sem); 

 

         K508_CONTROL_DEBUG("k508_releasecontuer k508_dev->used = %d\n",k508_dev->used);

   return 0; 

 

extern void set_led_on_off(intchannel,int on);

 

static long k508_unlocked_ioctl(structfile *file, unsigned int cmd,unsigned long arg)

{

         longerr = 0;

         inttmp=0;

         void__user *ptr;

        

         mutex_lock(&k508_dev->sem);      

         ptr= (void __user*) arg;

         get_user(tmp,(int*)(&ptr));

         mutex_unlock(&k508_dev->sem);

        

         K508_CONTROL_DEBUG("k508_unlocked_ioctlcmd=%d,tmp=%d\n",cmd,tmp);

                  

         if(_IOC_TYPE(cmd) != K508_IOC_MAGIC ) {

                   return-ENOTTY;

         }

 

         if(_IOC_NR(cmd) > MAX_K508_IOCTL_CMD_NUM ) {

                   return-ENOTTY;

         }

 

         if(_IOC_DIR(cmd) & _IOC_READ) {

                   err= !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));

         }else if (_IOC_DIR(cmd) & _IOC_WRITE) {

                   err=  !access_ok(VERIFY_READ, (void *)arg,_IOC_SIZE(cmd));

         }

        

         if(err) {

                   K508_CONTROL_DEBUG("!!argerror!!\n");

                   return-EFAULT;

         }

 

         switch(cmd)

         {

                   caseK508_IOC_VMIC_EN:

                 mt_set_gpio_mode(GPIO_VMIC_EN,GPIO_VMIC_EN_M_GPIO);

                 mt_set_gpio_dir(GPIO_VMIC_EN,GPIO_DIR_OUT);

                            if(tmp== 0)

                           mt_set_gpio_out(GPIO_VMIC_EN,GPIO_OUT_ZERO);                                     

                            else

                                     mt_set_gpio_out(GPIO_VMIC_EN,GPIO_OUT_ONE);

                            break;

                           

                   caseK508_IOC_SPK_EN:

                mt_set_gpio_mode(GPIO_SPK_EN,GPIO_SPK_EN_M_GPIO);

                mt_set_gpio_dir(GPIO_SPK_EN,GPIO_DIR_OUT);

                            if(tmp== 0)

                                     mt_set_gpio_out(GPIO_SPK_EN,GPIO_OUT_ZERO);

                            else

                          mt_set_gpio_out(GPIO_SPK_EN,GPIO_OUT_ONE);

                            break;

                           

                   caseK508_IOC_RAY_LED_EN:

                 mt_set_gpio_mode(GPIO_RAY_LED_EN,GPIO_RAY_LED_EN_M_GPIO);

                 mt_set_gpio_dir(GPIO_RAY_LED_EN,GPIO_DIR_OUT);

                            if(tmp== 0)

                                      mt_set_gpio_out(GPIO_RAY_LED_EN,GPIO_OUT_ZERO);

                            else

                                   mt_set_gpio_out(GPIO_RAY_LED_EN,GPIO_OUT_ONE);              

                            break;

                           

                   caseK508_IOC_OTG_EN:

//                         mt_set_gpio_mode(GPIO_OTG_EN,GPIO_OTG_EN_M_GPIO);

//                         mt_set_gpio_dir(GPIO_OTG_EN,GPIO_DIR_OUT);

//                         if(tmp== 0)

//                                  mt_set_gpio_out(GPIO_OTG_EN,GPIO_OUT_ZERO);

//                         else

//                                  mt_set_gpio_out(GPIO_OTG_EN,GPIO_OUT_ONE);

                            break;

                           

                   caseK508_IOC_SWITCH_EN:

                            mt_set_gpio_mode(GPIO_SWITCH_EN,GPIO_SWITCH_EN_M_GPIO);

                            mt_set_gpio_dir(GPIO_SWITCH_EN,GPIO_DIR_OUT);

                            if(tmp== 0)

                                     mt_set_gpio_out(GPIO_SWITCH_EN,GPIO_OUT_ZERO);

                            else

                                     mt_set_gpio_out(GPIO_SWITCH_EN,GPIO_OUT_ONE);

                            break;

                           

                   caseK508_IOC_PTT_SWITCH_EN:

                 mt_set_gpio_mode(GPIO_PTT_SWITCH_EN,GPIO_PTT_SWITCH_EN_M_GPIO);

                 mt_set_gpio_dir(GPIO_PTT_SWITCH_EN,GPIO_DIR_OUT);

                            if(tmp== 0)

                                     mt_set_gpio_out(GPIO_PTT_SWITCH_EN,GPIO_OUT_ZERO);    

                            else

                          mt_set_gpio_out(GPIO_PTT_SWITCH_EN,GPIO_OUT_ONE);      

                            break;

                           

                   caseK508_IOC_PTT_PD:

                 mt_set_gpio_mode(GPIO_PTT_PD,GPIO_PTT_PD_M_GPIO);

                 mt_set_gpio_dir(GPIO_PTT_PD,GPIO_DIR_OUT);

                            if(tmp== 0)

                          mt_set_gpio_out(GPIO_PTT_PD,GPIO_OUT_ONE);

                            else

                          mt_set_gpio_out(GPIO_PTT_PD,GPIO_OUT_ZERO);                      

                            break;

                           

                   caseK508_IOC_BULE_LED_EN:

                            K508_CONTROL_DEBUG("K508_IOC_BULE_LED_ENtmp=%d\n",tmp);

                            if(tmp== 0)

                                     set_led_on_off(4,0);

                            else

                                     set_led_on_off(4,1);

                            break;

                   caseK508_IOC_KEYPAD_LED_EN:

                            if(tmp== 0)

                                     set_led_on_off(5,0);

                            else

                                     set_led_on_off(5,1);                          

                            break;

                           

                   default:

                            break;

         }

         returnerr;

}

 

static int k508_setup_dev(structk508_android_dev* dev)

   int err; 

   dev_t devno = MKDEV(k508_major, k508_minor); 

   memset(dev, 0, sizeof(struct k508_android_dev)); 

   cdev_init(&(dev->dev), &k508_fops); 

   dev->dev.owner = THIS_MODULE; 

   dev->dev.ops = &k508_fops;         

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

   if(err) { 

       return err; 

   } 

         dev->used= 0;

   mutex_init(&dev->sem);   

   return 0; 

 

static int __initk508_control_init(void)

{  

         intret = 0;

 

   ret = platform_device_register(&k508_control_device);

         if(ret != 0)

         {

                   K508_CONTROL_DEBUG("[508_control]platform_device_registererror:(%d)\n", ret);

                   returnret;

         }

        

   ret = platform_driver_register(&k508_control_driver);

   if (ret)

   {

       K508_CONTROL_DEBUG("[508_control]platform_driver_registererror:(%d)\n", ret);

       return ret;

   }

 

         return0;

}

 

static void __exitk508_control_exit(void)

         K508_CONTROL_DEBUG("[508_control]k508_control_exit\n");

         platform_driver_unregister(&k508_control_driver);

         platform_device_unregister(&k508_control_device);

}

 

 

late_initcall(k508_control_init);

module_exit(k508_control_exit);

 

MODULE_DESCRIPTION("k508control");

MODULE_VERSION("V1.0");

MODULE_LICENSE("GPL");

MODULE_AUTHOR("feng.guangyue");

 

 

三.总结

上面apk应用模块到kernel层代码实现,接口调用顺序如下:

 

1.     apk模块实现packages/K508Control

2.     frameworks服务层

apk模块与frameworks服务模块通过AIDL(Android Interface Definition Languageandroid内部进程通信接口)机制进行交互;

 

实现文件如下:

     frameworks/base/Android.mk

新增:frameworks/base/core/java/android/os/IK508ControlService.aidl

新增:frameworks/base/services/java/com/android/server/K508ControlService.java

          frameworks/base/services/java/com/android/server/SystemServer.java

3.     frameworks  JNI层

frameworks服务模块通过JNI机制与hardware层交互;

 

实现文件如下:

      frameworks/base/services/jni/onload.cpp

      frameworks/base/services/jni/Android.mk

新增:frameworks/base/services/jni/com_android_server_K508ControlService.cpp

4.     增加一个节点,用于读写参数

mediatek/config/mt6577/init.rc

 

5.     hardware层

实现文件如下:

新增:mediatek/source/hardware/K508Control/Android.mk

新增:mediatek/source/hardware/K508Control/K508Control.c

新增:hardware/libhardware/include/hardware/K508Control.h

 

6.     kernel层

实现文件如下:

新增:mediatek/platform/mt6577/kernel/drivers/k508_control/Makefile    

新增:mediatek/platform/mt6577/kernel/drivers/k508_control/k508_control.c

新增:mediatek/platform/mt6577/kernel/drivers/k508_control/k508_control.h

你可能感兴趣的:(Android实践总结)