前言
振动器小模块框架总结
基于 MTK 7.0 源码
驱动
内核配置:kernel-3.18\arch\arm64\configs\E266L_debug_defconfig
CONFIG_MTK_VIBRATOR=y
驱动初始化流程:
// Vibrator_drv.c (kernel-3.18\drivers\misc\mediatek\vibrator)
module_init(vib_mod_init);
static int vib_mod_init(void)
/
// 1. 获得 dts 设置,配置 PMIC 电压输出
vibr_power_set();
/
// 获得 dts 中相应的配置
// E266L.dts (kernel-3.18\arch\arm64\boot\dts)
// vibrator0:vibrator@0 {
// compatible = "mediatek,vibrator";
// vib_timer = <25>;
// vib_limit = <9>;
//
// vib_vol= <6>;
// //
// // hw->vib_vol: Voltage selection
// // 3'b000: 1.2V
// // 3'b001: 1.3V
// // 3'b010: 1.5V
// // 3'b011: 1.8V
// // 3'b100: 2.0V, if PMIC6353, 2.5V
// // 3'b101: 2.8V
// // 3'b110: 3.0V
// // 3'b111: 3.3V
// };
struct vibrator_hw *hw = get_cust_vibrator_dtsi();
struct device_node *led_node = NULL;
pvib_cust = kmalloc(sizeof(struct vibrator_hw), GFP_KERNEL);
led_node = of_find_compatible_node(NULL, NULL, "mediatek,vibrator");
ret = of_property_read_u32(led_node, "vib_timer",&(pvib_cust->vib_timer));
ret =of_property_read_u32(led_node, "vib_limit",&(pvib_cust->vib_limit));
ret =of_property_read_u32(led_node, "vib_vol",&(pvib_cust->vib_vol));
// 设置 vibrator 电压
pmic_set_register_value(PMIC_RG_VIBR_VOSEL, hw->vib_vol);
///
// 2. 注册平台设备
// static struct platform_device vibrator_device = {
// .name = "mtk_vibrator",
// .id = -1,
// };
ret = platform_device_register(&vibrator_device);
///
// 3. 创建工作队列
vibrator_queue = create_singlethread_workqueue(VIB_DEVICE);
INIT_WORK(&vibrator_work, update_vibrator);
///
// 4. 创建定时器
hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
vibe_timer.function = vibrator_timer_func;
///
// 5. 【核心】创建一个定时输出设备?使用 sys 实现的 Android 特有驱动
// static struct timed_output_dev mtk_vibrator = {
// .name = "vibrator",
// .get_time = vibrator_get_time,
// .enable = vibrator_enable,
// };
// 生成节点路径:
// /sys/class/timed_output/vibrator
// /sys/devices/virtual/timed_output/vibrator
timed_output_dev_register(&mtk_vibrator);
// 先看这个目录有没有,没有 sys 下目录的话,创建一个:/sys/devices/virtual/timed_output/
ret = create_timed_output_class();
// Timed_output.c (kernel-3.18\drivers\staging\android)
static int create_timed_output_class(void)
// 创建 sys/class/timed_output/ 类目录
timed_output_class = class_create(THIS_MODULE, "timed_output");
atomic_set(&device_count, 0);
timed_output_class->dev_groups = timed_output_groups;
// 引用加 1
tdev->index = atomic_inc_return(&device_count);
// 创建 /sys/devices/virtual/timed_output/vibrator 目录
tdev->dev = device_create(timed_output_class, NULL,MKDEV(0, tdev->index), NULL, "%s", tdev->name);
dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
return device_create_groups_vargs(class, parent, devt, drvdata, NULL,fmt, args);
retval = device_add(dev);
error = device_create_file(dev, &dev_attr_uevent);
if (MAJOR(dev->devt))
error = device_create_file(dev, &dev_attr_dev);
error = device_create_sys_dev_entry(dev);
devtmpfs_create_node(dev);
//
// 一系列调用之后,添加了 class 的 dev_groups,他已经有两个默认属性了
error = device_add_groups(dev, class->dev_groups);
if (class)
error = device_add_groups(dev, class->dev_groups);
error = bus_add_device(dev);
error = dpm_sysfs_add(dev);
device_pm_add(dev);
dev_set_drvdata(tdev->dev, tdev);
///
// 6. 注册平台驱动
// static struct platform_driver vibrator_driver = {
// .probe = vib_probe,
// .remove = vib_remove,
// .shutdown = vib_shutdown,
// .driver = {
// .name = VIB_DEVICE,
// .owner = THIS_MODULE,
// },
// };
ret = platform_driver_register(&vibrator_driver);
/
// 进入对应的 probe 函数,为空的?作用?
// 7. 创建 sys 属性节点: /sys/class/timed_output/vibrator/vibr_on
ret = device_create_file(mtk_vibrator.dev, &dev_attr_vibr_on);
//
// 上层调用流程:
// 目前 HAL 层是通过 sys/class/timed_output/vibrator/enable 节点来控制马达的启停的
// 初始化的时候此节点已设置为 timed_output 类的操作操作
///
// 1. 打开马达
// echo 时间 > sys/class/timed_output/vibrator/enable
// Timed_output.c (kernel-3.18\drivers\staging\android)
static ssize_t enable_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t size)
struct timed_output_dev *tdev = dev_get_drvdata(dev);
rc = kstrtoint(buf, 0, &value);
tdev->enable(tdev, value);
//
// 本驱动的 enable 函数
static void vibrator_enable(struct timed_output_dev *dev, int value)
struct vibrator_hw *hw = mt_get_cust_vibrator_hw();
while (hrtimer_cancel(&vibe_timer))
// limit 配置项的使用
if (value > hw->vib_limit && value < hw->vib_timer)
value = hw->vib_timer;
value = (value > 15000 ? 15000 : value);
vibe_state = 1;
// 启动了定时器
hrtimer_start(&vibe_timer,ktime_set(value / 1000, (value % 1000) * 1000000), HRTIMER_MODE_REL);
// 调用工作队列打开马达?
queue_work(vibrator_queue, &vibrator_work);
static void update_vibrator(struct work_struct *work)
if (!vibe_state)
vibr_Disable();
else
vibr_Enable();
if (!ldo_state)
vibr_Enable_HW();
///
// 调用 PMIC 操作函数打开马达
pmic_set_register_value(PMIC_LDO_VIBR_EN, 1); // [bit 1]: VIBR_EN, 1=enable
ldo_state = 1;
///
// 2. 获得振动剩余时间
// cat sys/class/timed_output/vibrator/enable
static ssize_t enable_show(struct device *dev, struct device_attribute *attr, char *buf)
int remaining = tdev->get_time(tdev);
//
// 本驱动的 get_time 函数
static int vibrator_get_time(struct timed_output_dev *dev)
if (hrtimer_active(&vibe_timer))
ktime_t r = hrtimer_get_remaining(&vibe_timer);
return ktime_to_ms(r);
HAL
振动器的 HAL 库实现还是蛮简单的,主要是往节点:
/sys/class/timed_output/vibrator/enable
写入振动时间就行了。
文件位置:
Vibrator.c (hardware\libhardware\modules\vibrator)
【初始化流程】
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = VIBRATOR_API_VERSION,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = VIBRATOR_HARDWARE_MODULE_ID,
.name = "Default vibrator HAL",
.author = "The Android Open Source Project",
.methods = &vibrator_module_methods,
//
// static struct hw_module_methods_t vibrator_module_methods = {
// .open = vibra_open,
// };
};
//
static int vibra_open(const hw_module_t* module, const char* id __unused,hw_device_t** device __unused)
///
// 1. 判断是否有振动器设备存在,open() 打开设备
vibra_exists()
//
// static const char THE_DEVICE[] = "/sys/class/timed_output/vibrator/enable";
static int vibra_exists()
fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));
close(fd);
//
// 2. 分配设置 vibrator_device_t 结构体
vibrator_device_t *vibradev = calloc(1, sizeof(vibrator_device_t));
vibradev->common.tag = HARDWARE_DEVICE_TAG;
vibradev->common.module = (hw_module_t *) module;
vibradev->common.version = HARDWARE_DEVICE_API_VERSION(1,0);
vibradev->common.close = vibra_close;
//振动器操作函数
vibradev->vibrator_on = vibra_on;
///
// 打开振动器
static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
return sendit(timeout_ms);
vibradev->vibrator_off = vibra_off;
///
// 关闭振动器
static int vibra_off(vibrator_device_t* vibradev __unused)
/
// 此函数直接往:/sys/class/timed_output/vibrator/enable 写振动时间就行了
return sendit(0);
fd = TEMP_FAILURE_RETRY(open(THE_DEVICE, O_RDWR));
to_write = snprintf(value, sizeof(value), "%u\n", timeout_ms);
written = TEMP_FAILURE_RETRY(write(fd, value, to_write));
close(fd);
///
// 3. 返回 hw_device_t 结构体给 jni 层调用
*device = (hw_device_t *) vibradev;
Framework
本文件位置:frameworks\base\services\core\java\com\android\server\VibratorService.java
【服务启动流程】:
// frameworks\base\services\java\com\android\server\SystemServer.java
public final class SystemServer
startBootstrapServices();
startCoreServices();
startOtherServices();
///
// 1. 创建一个 VibratorService 对象
VibratorService vibrator = null;
vibrator = new VibratorService(context);
/
// frameworks\base\services\core\java\com\android\server\VibratorService.java
// 头文件一看就是个 aidl 接口继承实现 binder 通信的货
// aidl 位置: frameworks\base\core\java\android\os\IVibratorService.aidl
// interface IVibratorService
// { // 这些定义的都是服务端需要提交实现的接口
// boolean hasVibrator();
// void vibrate(int uid, String opPkg, long milliseconds, int usageHint, IBinder token);
// void vibratePattern(int uid, String opPkg, in long[] pattern, int repeat, int usageHint, IBinder token);
// void vibrateLevel(int uid, String opPkg, long milliseconds, int usageHint, int level, int category, IBinder token);
// void vibratePatternLevel(int uid, String opPkg, in long[] pattern, int repeat, int usageHint, int level, int category, IBinder token);
// void cancelVibrate(IBinder token);
// }
public class VibratorService extends IVibratorService.Stub implements InputManager.InputDeviceListener
{
//
// 构造函数
VibratorService(Context context)
{
/
// 调用对应的 jni 初始化函数
// com_android_server_VibratorService.cpp (frameworks\base\services\core\jni)
// 获得 HAL 层实现库
vibratorInit();
int err = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVibraModule);
vibrator_open(gVibraModule, &gVibraDevice);
return module->methods->open(module, VIBRATOR_DEVICE_ID_MAIN, (struct hw_device_t**)device);
// 关闭振动器,即向 /sys/class/timed_output/vibrator/enable 写 0
vibratorOff();
int err = gVibraDevice->vibrator_off(gVibraDevice);
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
/
// 获得华硕添加的 setting 震动设置
mRingstoneVibLevel = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.VIBRATION_LEVEL_RINGTONE, AudioAttributes.LEVEL_GENERAL_0);
mNotificationVibLevel = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.VIBRATION_LEVEL_NOTIFICATION, AudioAttributes.LEVEL_GENERAL_0);
mTouchVibLevel = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.VIBRATION_LEVEL_TOUCH, AudioAttributes.LEVEL_GENERAL_0);
/
// 注册了一个广播接收者,接收屏幕关闭广播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
context.registerReceiver(mIntentReceiver, filter);
}
}
///
// 2. 将本服务添加到 servicemanager 中进行管理
ServiceManager.addService("vibrator", vibrator);
。。。 // 一系列其他初始化函数
///
// 3. 将本服务添加到 servicemanager 中进行管理
vibrator.systemReady();
//
// frameworks\base\services\core\java\com\android\server\VibratorService.java
public void systemReady()
/
// 1. 监听手机设置 setting 的相关变化,变化后都是调用
// updateInputDeviceVibrators() 来更新马达状态
mSettingObserver = new SettingsObserver(mH);
//+++ aras_yin: add vibrator level feature
mVibLvRingtoneObserver = new VibLvRingtoneObserver(mH);
mVibLvNotificationObserver = new VibLvNotificationObserver(mH);
mVibLvTouchObserver = new VibLvTouchObserver(mH);
//--- aras_yin
//
// 2. 注册了一系列需要状态变化,改变马达
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(boolean enabled) {
updateInputDeviceVibrators();
}
});
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
true, mSettingObserver, UserHandle.USER_ALL);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateInputDeviceVibrators();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
//+++ aras_yin: add vibrator level feature
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.VIBRATION_LEVEL_RINGTONE),
true, mVibLvRingtoneObserver, UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.VIBRATION_LEVEL_NOTIFICATION),
true, mVibLvNotificationObserver, UserHandle.USER_ALL);
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.VIBRATION_LEVEL_TOUCH),
true, mVibLvTouchObserver, UserHandle.USER_ALL);
//--- aras_yin
//
// 3. 马达输入设备?看不懂,看完输入子系统再看
updateInputDeviceVibrators();
doCancelVibrateLocked();
doVibratorOff();
// 调用 native 层关马达
vibratorOff();
synchronized (mInputDeviceVibrators)
{ // 一票输入设备相关操作 }
startNextVibrationLocked();
startVibrationLocked(mVibrations.getFirst());
if (vib.mTimeout != 0)
doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint, vib.mVibrationLevel, vib.mVibrationCategory);
/
// 调用 HAL 层开马达
vibratorOn(millis);
// 振动一段时间后,再来更新马达状态
mH.postDelayed(mVibrationRunnable, vib.mTimeout);
else
// 这里创建了一个 VibrateThread 线程
mThread = new VibrateThread(vib);
mThread.start();
/
// 启动线程操作:
private class VibrateThread extends Thread
{
public void run()
{
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
while (!mDone)
{
// sleep until it is time to start the vibrator
delay(duration);
// 启动马达
VibratorService.this.doVibratorOn(duration, uid, usageHint, vibLevel, vibCate);
// 本次振动结束,开始处理下一个
if (!mDone) {
// If this vibration finished naturally, start the next
// vibration.
unlinkVibration(mVibration);
startNextVibrationLocked();
}
}
}
}
App
【马达的应用进程的使用】:
代码位置:vendor\mediatek\proprietary\packages\apps\Emode\src\com\wind\emode\testcase\VibratorStressTest.java
// 1. 导入库,声明变量
import android.os.Vibrator;
private Vibrator mVibrator;
// 2. 获得马达服务
mVibrator = ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE));
// 3. 启动马达
mVibrator.vibrate(array, 0);
//
// @param pattern an array of longs of times for which to turn the vibrator on or off.
// @param repeat the index into pattern at which to repeat, or -1 if you don't want to repeat.
public void vibrate(long[] pattern, int repeat)
// 4. 关闭马达
mVibrator.cancel();