基于Android振动器系统构架的驱动实现

  实验环境:友坚三星四核UT4412BV03开发板

Android振动器驱动是基于linux内核新增加的一类驱动程序框架,其写法必须基于

time_out驱动构架,并实现其中的相应函数。振动器负责控制引用电话的震动功能,Android中的振动器系统是一个专供这方面功能的小系统,提供根据时间的振动功能。振动器系统包含了驱动程序,硬件抽象层,JNI部分,java框架类等几个部分,也向java应用程序层提供了简单的API作为平台接口

对于android系统振动器的实现相对来说较为简单,由于android系统已经提供了振动器系统的硬件抽象层、JNI部分、Java框架类等几个部分,因此,我们只需根据需要实现基于振动器系统的驱动程序即可。

 

Android振动器系统层次结构

友坚4412开发板Android振动器系统构架的驱动实现_第1张图片
 

 

 

一.根据上图我们基本了解了4412开发板平台的android振动器系统模型

自下而上,Android的振动器系统分成了以下部分

1驱动程序:特定硬件平台振动器的驱动程序,其驱动程序可以是控制GPIO,其书写通常基于AndroidTimed Output驱动框架实现,实现Timed Output驱动框架中的相关函数,并且驱动必须以vibrator命名。

2)硬件抽象层

振动器系统硬件抽象层接口路径为:

hardware/libhardware_legacy/include/hardware_legacy/ vibrator.h

振动器系统的硬件抽象层在Android中已经具有默认实现,代码路径:

hardware/libhardware_legacy/vibrator/vibrator.c

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

3JNI部分

代码路径:

frameworks/base/services/jni/com_android_server_VibratorService.cpp

这个类是振动器的JNI部分,通过调用硬件抽象层向上层提供接口。

4Java部分

代码路径:

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

frameworks/base/core/java/android/os/Vibrator.java

VibratorService.java通过调用,VibratorService JNI来实现com.android.server包中的VibratorService类。这个类不是平台的API,被Android系统Java框架中的一小部分调用。

Vibrator.java文件实现了android.os包中的Vibrator类,这是向Java层提供的API

二.  4412开发板平台的移植内容

针对特定的硬件平台,振动器系统的移植有两种方法。

 第一种方法(通常情况):由于已经具有硬件抽象层,振动器系统的移植只需要实现驱动程序即可。这个驱动程序需要基于Android内核中的Timed Output驱动框架。

 第二种方法:根据自己实现的驱动程序,重新实现振动器的硬件抽象层定义接口(需要在libhardware_legacy.so库中),由于振动器硬件抽象层的接口非常简单,因此这种实现方式也不会很复杂。

三.移植与调试的要点   

1  驱动程序

Vibrator的驱动程序只需要实现振动的接口即可,这是一个输出设备,需要接受振动时间作为参数。由于比较简单,因此Vibrator的驱动程序可以使用多种方式来实现。

Android中,推荐基于Android内核定义Timed Output驱动程序框架来实现Vibrator的驱动程序。

Timed Output的含义为定时输出,用于定时发出某个输出。实际上,这种驱动程序依然是基于sys文件系统来完成的。

drivers/staging/android/目录timed_output.h中定义timed_output_dev结构体,其中包含enableget_time这两个函数指针,实现结构体后,使用timed_output_dev_register()timed_output_dev_unregister()函数注册和注销即可。

Timed Output驱动程序框架将为每个设备在/sys/class/timed_output/目录中建立一个子目录,设备子目录中的enable文件就是设备的控制文件。读enable文件表示获得剩余时间,写这个文件表示根据时间振动。

Timed Output驱动的设备调试,通过sys文件系统即可。

对于Vibrator设备,其实现的Timed Output驱动程序的名称应该为“vibrator”。因此Vibrator设备在sys文件系统中的方法如下所示:

# echo "10000" > /sys/class/timed_output/vibrator/enable

# cat /sys/class/timed_output/vibrator/enable

3290

# echo "0"  > /sys/class/timed_output/vibrator/enable

对于enable文件,表示使能指定的时间,表示获取剩余时间。

2  硬件抽象层的内容

硬件抽象层的接口

Vibrator硬件抽象层的接口在hardware/libhardware_legacy/include/hardware_legacy/目录的vibrator.h文件中定义:

int vibrator_on(int timeout_ms);         // 开始振动

int vibrator_off();                         // 关闭振动

vibrator.h文件中定义两个接口,分别表示振动和关闭,振动开始以毫秒(ms)作为时间单位。

 提示:Timed Output类型驱动本身有获得剩余时间的能力(读enable文件),但是在Android Vibrator硬件抽象层以上的各层接口都没有使用这个功能。

2.2 标准硬件抽象层的实现

Vibrator硬件抽象层具有标准的实现,在hardware/libhardware_legacy/vibrator/目录的vibrator.c中。

其中实现的核心内容为sendit()函数,这个函数的内容如下所示:

#define THE_DEVICE "/sys/class/timed_output/vibrator/enable"

static int sendit(int timeout_ms)

{

    int nwr, ret, fd;

    char value[20];

#ifdef QEMU_HARDWARE                // 使用QEMU的情况

    if (qemu_check()) {

        return qemu_control_command( "vibrator:%d", timeout_ms );

    }

#endif

    fd = open(THE_DEVICE, O_RDWR);               // 读取sys文件系统中的内容

    if(fd < 0) return errno;

    nwr = sprintf(value, "%d\n", timeout_ms);

    ret = write(fd, value, nwr);

    close(fd);

    return (ret == nwr) ? 0 : -1;

}

sendit()函数负责根据时间振动:在真实的硬件中,通过sys文件系统的文件进行控制;如果是模拟器环境则通过QEMU发送命令。

vibrator_on()调用sendit()以时间作为参数,vibrator_on()调用sendit()0作为参数。

 

3. 振动器框架层的实现

frameworks/base/services/jni/目录中的com_android_server_VibratorService.cpp文件是Vibrator硬件抽象层的调用者,它同时也向Java提供JNI支持。

其中,为JNI定义的方法列表如下所示:

static JNINativeMethod method_table[] = {

    { "vibratorOn", "(J)V", (void*)vibratorOn },   // 振动器开

    { "vibratorOff", "()V", (void*)vibratorOff }   // 振动器关

};

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类。它通过调用vibratorJava服务来实现(获得名称为vibrator的服务),配合同目录中的IVibratorService.aidl文件向应用程序层提供Vibrator的相关API

三.基于振动器的驱动程序设计

本驱动程序是基于UT4412BV03开发板上的蜂鸣器接口实现的驱动程序,希望通过基于本驱动了解振动器驱动的实现方法。前面已经讲到Vibrator的驱动程序只需要实现振动的接口即可,我们将基于Android内核定义Timed Output驱动程序框架来实现Vibrator的驱动程序。

振动器驱动程序设计是基于drivers/staging/android/目录timed_output.h中定义timed_output_dev结构体中的enableget_time这两个函数指针,实现结构体后,使用timed_output_dev_register()timed_output_dev_unregister()函数注册和注销即可。

下面将分析基于振动器的蜂鸣器驱动程序

驱动程序源码:

/* 

 * drivers/urbetter/buzzer_vibrator.c

 * Buzzer driver. 

 * Copyright (c) 2015  Urbetter Ltd.

 * This software is licensed under the terms of the GNU General Public

 * License version 2, as published by the Free Software Foundation, and

 * may be copied, distributed, and modified under those terms.

 * This program is distributed in the hope that it will be useful,

 * but WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

 * GNU General Public License for more details.

 * added by orangeyang@2/4/2015

 */

struct timer_list mototimer;

static struct work_struct moto_work;

 

void moto_function(unsigned long val);

 

static void moto_work_func(struct work_struct *work)

{

printk("%s\n",__FUNCTION__);


gpio_direction_output(EXYNOS4_GPD0(0), 0);

del_timer(&mototimer);

}

 

void moto_function(unsigned long val)

{

schedule_work(&moto_work);

}

 

void vibrator_enable(struct timed_output_dev *sdev, int timeout)

{


gpio_direction_output(EXYNOS4_GPD0(0), 1);


//moto.expires=jiffies+msecs_to_jiffies(timeout);

if(timeout<100)

timeout=100;

mod_timer(&mototimer,jiffies+msecs_to_jiffies(timeout));

return;

}

int vibrator_get_time(struct timed_output_dev *sdev)

{

printk("%s\n",__FUNCTION__);

return 0;

}

 

struct timed_output_dev vibrator={

.name="vibrator",

.enable=vibrator_enable,

.get_time=vibrator_get_time,

};

 

static int __init viabrator_timed_output_init(void)

{

mototimer.function=moto_function;

init_timer(&mototimer);


INIT_WORK(&moto_work, moto_work_func);

return timed_output_dev_register(&vibrator);

}

 

static void __exit viabrator_timed_output_exit(void)

{

timed_output_dev_unregister(&vibrator);  

}

 

module_init(viabrator_timed_output_init);

module_exit(viabrator_timed_output_exit);

 

MODULE_AUTHOR("orange_yang ");

MODULE_DESCRIPTION("buzzer driver");

MODULE_LICENSE("GPL");

 

 

 

 

 

 

下面两个函数是基于timed_output_dev结构体中的函数的具体实现

void vibrator_enable(struct timed_output_dev *sdev, int timeout)

in vibrator_get_time(struct timed_output_dev *sdev)

当我们实现了驱动程序,并选上相应的配置

首先根据此段函数在知道创建了/sys/class/timed_output/目录

友坚4412开发板Android振动器系统构架的驱动实现_第2张图片
 

根据下面这段函数我们最终知道了驱动生成的名字节点


 

/sys/class/timed_output/vibrator/enable

驱动的测试:

在控制台输入如下命令将让蜂鸣器发生

# echo "10000" > /sys/class/timed_output/vibrator/enable

 

在控制台输入如下命令将读取到剩余时间

# cat /sys/class/timed_output/vibrator/enable

 



更多相关文章

  1. 在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬
  2. Android硬件抽象层(HAL)深入剖析(一)
  3. Android 4.0硬件加速及绘制技巧
  4. Android获取系统的硬件信息、系统版本以及如何检测ROM类型
  5. Android setLayerType 硬件加速问题
  6. Android 硬件加速的优缺点
  7. android 硬件加速后webview闪烁问题
  8. 访问Android硬件资源の管理网络和Wifi连接

随机推荐

  1. Android(安卓)中不同的系统版本隐藏和显
  2. 在Android(安卓)Studio中进行单元测试和U
  3. 【Android】关于Android控件EditText的属
  4. android4.0.3多点触摸屏设备设置
  5. Android开发——(二)运行你的APP
  6. 国际版TikTok使用教程(2020更新)
  7. 自定义圆形ProgressBar
  8. Android面试宝典
  9. android 获取当前时间精确到毫秒的两种方
  10. iOS, Android, WindowsPhone三大平台交互