基于MSM平台的振动器驱动移植

前言:

振动器是Android智能手机操作系统中比较常见的功能之一,在实际应用中可以将来电显示设置为振动模式作为提醒。在Android系统中,通过振动系统米快可以实现俩点铃声和来电的振动功能。。本篇blog主要是向大家介绍在高通平台上移植振动器驱动框架以及代码实现的过程。

一、振动器系统框架

振动器系统自下而上包含了驱动程序、振动器系统硬件抽象层、振动器系统Java框架类、Java框架中振动器系统使用等几部分,其结构如下图所示


Android振动器系统的框架结构 振动器系统结构元素

结构说明:

1)驱动程序:某个特定硬件凭条振动其的驱动程序。通常是基于Android的timed output 驱动框架来实现的。

2)硬件抽象层:振动器系统的硬件抽象层的接口路径是hardware/libhardware_legacy/include/hardware_legacy/vibrator.h

其默认代码路径是:hardware/libhardware_legacy/vibrator/vibrator.c

因为Android振动器的硬件抽象层是libhardware_legacy.so的一部分。所以通常并不需要重新实现。

3)JNI框架部分:代码路径是frameworks/base/services/jni/com_andriod_server_vibrarorservice.cpp

此文件定义了振动器的JNI部分,通过调用硬件抽象层向上层提供接口。

4)Java应用部分:振动器系统的Java不封的代码路径是frameworks/base/services/java/com/android/server/vibratorservice.java和frameworks/base/vore/java/android/ps/vibrator.java

文件vibaratorservice.java通过调用vibratorService JNI来实现包com.android.server中的类VibratorService。

类Vibtator.java中实现Android.os包中的Vibrator类。这是想Java层提供的API。


二、代码分析

1)在hardware/libhardware_legacy/include/hardware_legacy/vibrator.h中主要实现功能分析:

int vibrator_exists(); //判断设备是否注册到系统中

int vibrator_on(int timeout_ms); //按照形参的值来决定Vibrator运行的时间

int vibrator_off(); //关闭Vibtator


2)在hardware/libhardware_legacy/vibrator/vibrator.c中主要函数分析:

int vibrator_exists(); //判断设备是否注册到系统中

static int sendit(int timeout_ms); //设置Vibrator的运行时间

int vibrator_on(int timeout_ms); //开启Vibrator

int vibrator_off(); //关闭Vibrator


3)在frameworks/base/services/jni/com_andriod_server_vibrarorservice.cpp中主要函数分析:


static JNINativeMethod method_table[] = {

 
  { "vibratorOn", "(J)V", (void*)vibrator_on }, // 振动器开
 
  { "vibratorOff", "()V", (void*)vibrator_off } // 振动器关
 
  };
 
  int register_android_server_VibratorService(JNIEnv *env) {
 
  return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
 
  method_table, NELEM(method_table));
 
  }
  //vibratorOn()和vibratorOff()这两个函数的实现分别如下所示:
 
  
 
  static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms){
 
  vibrator_on(timeout_ms);
 
  }
 
  static void vibratorOff(JNIEnv *env, jobject clazz){
 
  vibrator_off();
 
  }

frameworks/base/services/java/com/android/server/目录中的VibratorService.java通过调用VibratorService JNI来实现com.android.server包中的VibratorService类。

  frameworks/base/core/java/android/os/目录中的Vibrator.java文件实现了android.os包中的Vibrator类。它通过调用vibrator的Java服务来实现(获得名称为vibrator的服务),配合同目录中的IVibratorService.aidl文件向应用程序层提供Vibrator的相关API。



4)在内核驱动代码kernel/arch/arm/mach-msm/msm_vibrator.c中的实现:

#define PMIC_VIBRATOR_LEVEL     (3000) //设置震动强度,3000mv  
  
static struct work_struct work_vibrator;  
static int vibe_state; //记录motor的状态  
static struct hrtimer vibe_timer;  
  
static DEFINE_MUTEX(vibe_mtx);  
static spinlock_t vibe_lock;  
  
static void update_vibrator(struct work_struct *work)  
{  
        set_pmic_vibrator(vibe_state);  
}  
//star timer or not,schedule work.NOT control vibrator voltage!  
static void vibrator_enable(struct timed_output_dev *dev, int value)  
{  
        unsigned long   flags;  
        spin_lock_irqsave(&vibe_lock, flags);  
        hrtimer_cancel(&vibe_timer);  
  
        if (value == 0)  
                vibe_state = 0;  
        else {  
                value = (value > 15000 ? 15000 : value);          
                vibe_state = 1;  
                hrtimer_start(&vibe_timer,  
                              ktime_set(value / 1000, (value % 1000) * 1000000),  
                              HRTIMER_MODE_REL);  
        }  
        spin_unlock_irqrestore(&vibe_lock, flags);  
        schedule_work(&work_vibrator);//执行这个函数会立即导致work_vibrator这个work_struct中的func函数被调用  
}  
static int vibrator_get_time(struct timed_output_dev *dev)  
{  
        if (hrtimer_active(&vibe_timer)) {  
                ktime_t r = hrtimer_get_remaining(&vibe_timer);  
                return r.tv.sec * 1000 + r.tv.nsec / 1000000;  
        } else  
                return 0;  
}  
//turn ON/OFF Motor  
static void set_pmic_vibrator(int on)  
{  
    static struct msm_rpc_endpoint *vib_endpoint;  
    struct set_vib_on_off_req {  
        struct rpc_request_hdr hdr;  
        uint32_t data;  
    } req;  
    if(mutex_lock_interruptible(&vibe_mtx))  
               return;  
  
    if (!vib_endpoint) {  
        vib_endpoint = msm_rpc_connect(PM_LIBPROG, PM_LIBVERS, 0);  
        if (IS_ERR(vib_endpoint)) {  
            printk(KERN_ERR "init vib rpc failed!\n");  
            vib_endpoint = 0;  
            mutex_unlock(&vibe_mtx);  
            return;  
        }  
    }  
  
    if (on)  
        req.data = cpu_to_be32(PMIC_VIBRATOR_LEVEL);//bigendian32,设置驱动马达的voltage  
    else  
        req.data = cpu_to_be32(0);//停止震动  
  
    //控制电压,使motor震动或关闭  
    msm_rpc_call(vib_endpoint, HTC_PROCEDURE_SET_VIB_ON_OFF, &req,  
        sizeof(req), 5 * HZ);  
  
    mutex_unlock(&vibe_mtx);  
}   
//定时器time out会调用这个函数,修改state,调度work  
static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)  
{  
        vibe_state = 0;  
        schedule_work(&work_vibrator);//  
        return HRTIMER_NORESTART;  
}  
<pre name="code" class="cpp">static struct timed_output_dev pmic_vibrator = {   
        .name = "vibrator",//sysFS下文件夹的名字 /sys/class/timed_output/vibrator  
        .get_time = vibrator_get_time,  
        .enable = vibrator_enable,  
};  
<pre name="code" class="cpp">void __init msm_init_pmic_vibrator(void)  
{  
        INIT_WORK(&work_vibrator, update_vibrator);//仅仅是初始化work_vibrator这个结构体  
  
        spin_lock_init(&vibe_lock);  
        vibe_state = 0;  
  
        hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);//初始hrtimer  
        vibe_timer.function = vibrator_timer_func;//给定时器超时callback函数赋值  
  
        timed_output_dev_register(&pmic_vibrator);//注册这个vibrator设备  
}  
  
MODULE_DESCRIPTION("timed output pmic vibrator device");  
MODULE_LICENSE("GPL");


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值