前言

振动器小模块框架总结
基于 MTK 7.0 源码

驱动

内核配置:kernel-3.18\arch\arm64\configs\E266L_debug_defconfigCONFIG_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.javapublic 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();

更多相关文章

  1. Android(安卓)-- CursorAdapter
  2. Android(安卓)输入系统解析 (2)
  3. ARM cortex A8/9 - Android(安卓)NDK - NEON介绍以及优化
  4. Android(安卓)4.4KitKat AudioFlinger 流程分析
  5. Android(安卓)页面跳转
  6. Android硬件抽象层加调试信息
  7. Android下载文件时对MediaScanner的调用
  8. Android(安卓)OpenGL ES 开发教程(6):GLSurfaceView
  9. android 串口jni 开发流程

随机推荐

  1. PHP中 __wakeup()方法详解
  2. PHP中__debugInfo()魔术方法详解
  3. php中如何使用魔术变量__line__
  4. PHP中__sleep()方法详解
  5. laradock环境docker-compose操作
  6. PHP语法:goto 语句
  7. PHP中__unset()方法详解
  8. PHP中__autoload()魔术方法详解
  9. 分享几个有意思的数组方法
  10. TP5(layui)excel导入