前言

振动器小模块框架总结
基于 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_onret = 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();elsevibr_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 SystemServerstartBootstrapServices();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.javapublic void systemReady()/// 1. 监听手机设置 setting 的相关变化,变化后都是调用//    updateInputDeviceVibrators() 来更新马达状态 mSettingObserver = new SettingsObserver(mH);//+++ aras_yin: add vibrator level featuremVibLvRingtoneObserver = new VibLvRingtoneObserver(mH);mVibLvNotificationObserver = new VibLvNotificationObserver(mH);mVibLvTouchObserver = new VibLvTouchObserver(mH);//--- aras_yin//// 2. 注册了一系列需要状态变化,改变马达 mPowerManagerInternal.registerLowPowerModeObserver(new PowerManagerInternal.LowPowerModeListener() {@Overridepublic 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() {@Overridepublic void onReceive(Context context, Intent intent) {updateInputDeviceVibrators();}}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);//+++ aras_yin: add vibrator level featuremContext.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 vibratordelay(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();

Android Vibrator 框架总结相关推荐

  1. android驱动框架介绍

    android驱动框架介绍 了解android驱动框架: 1.方法1--jni调用底层驱动 在android框架中写入c/c++直接调用底层linux驱动,并向上提供jni接口给应用程序: 优点:简单 ...

  2. Android View框架的measure机制

    Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure)Android View框架的measure机制 http://www.cnblogs.com/xyh ...

  3. 5个最佳的Android测试框架

    2019独角兽企业重金招聘Python工程师标准>>> 谷歌的Android生态系统正在不断地迅速扩张.有证据表明,新的移动OEM正在攻陷世界的每一个角落,不同的屏幕尺寸.ROM / ...

  4. 开发自己的山寨Android注解框架

    目录 开发自己的山寨Android注解框架 开发自己的山寨Android注解框架 参考 Github黄油刀 Overview 在上一章我们学习了Java的注解(Annotation),但是我想大家可能 ...

  5. android layout后还原位置,Android图片框架photoview如何记住所有状态并还原,包括缩放度,缩放后的移动的距离等等...

    Android图片框架photoview如何记住状态并还原,包括缩放度,缩放后的移动的距离等等,尝试了好多方法都没有作用. private void generateImages() { for (i ...

  6. Android 数据库框架ormlite 使用精要

    Android 数据库框架ormlite 使用精要 前言 本篇博客记录一下笔者在实际开发中使用到的一个数据库框架,这个可以让我们快速实现数据库操作,避免频繁手写sql,提高我们的开发效率,减少出错的机 ...

  7. Android 插件框架机制之Small

    Android 插件框架机制系列文章: Android 插件框架机制之预热篇 Android 插件框架机制之DroidPlugin 引言 上一篇文章提到过Small,这次就简单说一下Small,这只是 ...

  8. Android开源框架——图表MPAndroidChart

    开源官网:https://github.com/PhilJay/MPAndroidChart Android开源框架--图表MPAndroidChart 特点 配置 图表类型 Demo MPAndro ...

  9. Android——开源框架Universal-Image-Loader + Fragment使用+轮播广告

    原文地址: Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用 Android 开源框架Universal-Image-Loader完全解析(二) ...

最新文章

  1. 【linux练习】基础作业一
  2. Eclipse 导入逆向工程
  3. 选型java程序_Java程序员自动化指南
  4. 分享几个病毒分析检测网址
  5. EMLOG仿微信主题模板V3.11
  6. nefu 519 昨日重现
  7. 潮流海报模板|2021渐变流体必备
  8. Node.js入门(二)
  9. java List 排序 Collections.sort()
  10. Windows Phone 7开发人员向导已经发布
  11. Linux-I/O重定向和管道
  12. Producer-Consumer question : OO 生产者-消费者:面向对象
  13. 一阶倒立摆的起摆与稳摆simulink仿真
  14. 如何将CAD格式转成可以编辑的矢量图
  15. Redis学习之lpush命令
  16. kd718和kb688参数_GJK SPP 5BGK AEC F04A tB9 D4 RMP
  17. 华大单片机开发板HC32L13X上手入门
  18. 构造方法(设计一个Fan类来表示一个风扇)
  19. nas家庭服务器是无线连接吗,NAS家庭存储服务器搭建需要注意哪些问题?(上)...
  20. 区块链研究生专业_“区块链大数据赋能低碳发展”高端研讨活动 在增城低碳总部举行...

热门文章

  1. filter函数(JS)
  2. PostgreSQL SERIAL创建自增列
  3. 阿娇赵雅芝等众女星撩人透视照
  4. Android基础知识 - ListView
  5. 为什么房产销售员获取客户这么难
  6. 名厨 android项目,一起当名厨app
  7. 对计算机的态度作文,对人工智能的态度作文(2)
  8. java 设置xmlns xsi_以Spring Bean配置文件为例解释 xmlns,xmlns:xsi,xsi:schemaLocation
  9. PTA测试数据输入麻烦?输入输出重定向解决它
  10. 薄板激光切割机的前世今生