Detailed explanation of Vibrator System on Android platform

Source: Internet
Author: User

Email: wei7758@126.com

Blog: http://blog.csdn.net/yinwei520

Author: yww

Time: 2011-9-24

Update:

(Please specify the source for reprinting. Thank you)

 

 

Here we reference the explanation in the book "Android system-level deep development-porting and debugging". The real vibrator code analysis is based on the Code in my project.

 

I. vibrator system structure and porting content

The vibrator is responsible for controlling the vibration function of the mobile phone. The Vibrator System in Android is a small system dedicated to this function and provides the time-based Vibration function.

The vibrator system includes the driver, hardware abstraction layer, JNI, and Java framework. It also provides a simple API to the Java application layer as a platform interface.

The basic hierarchy of Android vibrator is shown in Figure 23-1.

Figure 23-1 Basic hierarchy of the android Vibrator System

1. vibrator part structure

The android vibrator system consists of the driver, the hardware abstraction layer of the vibrator system, the Java framework of the vibrator system, and the use of the vibrator system in the Java framework. Its structure is 23-2.

Figure 23-2 Android Vibrator System Structure

From the bottom up, the android vibrator system is divided into the following parts.

(1) DRIVER: the driver of the vibrator on a specific hardware platform, which is usually implemented based on the android timed output driver framework.

(2) Hardware Abstraction Layer

The interface path of the hardware abstraction layer of the optical system is hardware/libhardware_legacy/include/hardware_legacy/vibrator. h.

The Hardware Abstraction Layer of the vibrator system has the default implementation in Android. The code path is as follows:

Hardware/libhardware_legacy/vibrator. c

The Hardware Abstraction Layer of the vibrator usually does not need to be implemented again. It is part of libhardware_legacy.so.

(3) JNI Section

Code path: Frameworks/base/services/JNI/com_android_server_vibratorservice.cpp

This class is the JNI part of the vibrator and provides interfaces to the upstream layer by calling the hardware abstraction layer.

(4) Java Section

Code path:

Frameworks/base/services/Java/COM/Android/Server/vibratorservice. Java

Frameworks/base/CORE/Java/Android/OS/vibrator. Java

Vibratorservice. Java implements the vibratorservice class in the com. Android. server package by calling vibratorservice JNI. This class is not a platform API and is called by a small part of the Java framework of the Android system.

The Vibrator. Java file implements the vibrator class in the Android. OS package, which is an API provided to the Java layer.

2. Transplant content

There are two ways to port the vibrator system to a specific hardware platform.

Method 1 (usually): Because the hardware abstraction layer is already in place, only the driver program needs to be implemented to transplant the vibrator system. This driver must be based on the timed output driver framework in the android kernel.

Method 2: Re-implement the hardware abstraction layer interface of the vibrator according to the self-implemented Driver (which must be in the libhardware_legacy.so library). Because the interface of the hardware abstraction layer of the vibrator is very simple, therefore, this implementation method is not very complex.

II. Key Points of transplantation and debugging

1 Driver

Vibrator drivers only need to implement the vibration interface, which is an output device and must accept the vibration time as a parameter. Because it is relatively simple, vibrator drivers can be implemented in multiple ways.

In Android, we recommend that you define the timed output driver framework based on the android kernel to implement the vibrator driver.

Timed output refers to scheduled output, which is used to periodically send an output. In fact, the driver is still based on the Sys File System.

Drivers/staging/Android/directory timed_output.h defines the timed_output_dev struct, which contains the Enable and get_time function pointers. after implementing the struct, use timed_output_dev_register () and register () function registration and logout.

The timed output driver framework creates a subdirectory for each device in the/sys/class/timed_output/directory. The enable file in the subdirectory is the control file of the device. Reading the enable file indicates obtaining the remaining time. Writing this file indicates time-based vibration.

Debug the timed output driver through the Sys File System.

For the vibrator device, the implementation of the timed output driver should be named "vibrator ". Therefore, the method of vibrator in SYS file system is as follows:

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

# Cat/sys/class/timed_output/vibrator/enable

3290

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

For an enable file, "write" indicates the time specified for enabling, and "read" indicates obtaining the remaining time.

2 Hardware Abstraction Layer content

2.1 hardware abstraction layer interface

The Vibrator hardware abstraction layer interface is defined in the vibrator. h file of the hardware/libhardware_legacy/include/hardware_legacy/directory:

Int vibrator_on (INT timeout_ms );
// Start Vibration

Int vibrator_off ();
// Turn off Vibration

The Vibrator. h file defines two interfaces, indicating vibration and shutdown, respectively, starting with Millisecond (MS) as the unit of time.

Tip: The timed output driver has the ability to obtain the remaining time (read the enable file). However, this function is not used on all interfaces above the hardware abstraction layer of Android vibrator.

2.2 Implementation of the standard hardware abstraction layer

The Vibrator hardware abstraction layer has standard implementation in vibrator. c In the hardware/libhardware_legacy/vibrator/directory.

The core content of the implementation is the sendit () function. The content of this function is as follows:

# 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 // If (qemu_check () {return qemu_control_command ("vibrator: % d", timeout_ms) ;}# endif FD = open (the_device, o_rdwr); // read the contents of SYS file system if (FD <0) return errno; nwr = sprintf (value, "% d \ n", timeout_ms ); ret = write (FD, value, nwr); close (FD) ; Return (ret = nwr )? 0:-1 ;}

 

The sendit () function is responsible for "vibration" based on time: in real hardware, it controls the file through the Sys File System; in a simulator environment, it sends commands through qemu.

Vibrator_on () calls sendit () with time as the parameter, and vibrator_on () calls sendit () with 0 as the parameter.

 

Upper-layer situations and precautions

The com_android_server_vibratorservice.cpp file in the frameworks/base/services/JNI/directory is the caller of the vibrator hardware abstraction layer. It also provides JNI support to Java.

The list of methods defined for JNI is as follows:

  

Static jninativemethod method_table [] = {"vibratoron", "(j) V", (void *) vibratoron}, // vibrator opening {"vibratoroff ","() V ", (void *) vibratoroff} // vibrator off}; int mask (jnienv * env) {return jniregisternativemethods (ENV," com/Android/Server/vibratorservice ", method_table, nelem (method_table);} // The Implementation of The vibratoron () and vibratoroff () functions are as follows: static void vibratoron (jnienv * ENV, jobject clazz, jlong timeout_ms) {vibrator_on (timeout_ms);} static void vibratoroff (jnienv * ENV, jobject clazz) {vibrator_off ();}

 

Vibratorservice. Java in frameworks/base/services/Java/COM/Android/Server/directory implements the vibratorservice class in the com. Android. server package by calling vibratorservice JNI.

The Vibrator. Java file in the frameworks/base/CORE/Java/Android/OS/directory implements the vibrator class in the Android. OS package. It is implemented by calling the Java service of vibrator (to obtain the service named vibrator), and works with the ivibratorservice. aidl file in the same directory to provide relevant APIs of vibrator to the application layer.

Zookeeper -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

My specific driver

#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/device.h>#include <linux/workqueue.h>#include "timed_output.h"#include <linux/hrtimer.h>#include <linux/err.h>#include <linux/platform_device.h>#include <linux/spinlock.h>#include <linux/jiffies.h>#include <linux/timer.h>#include <mach/mt_typedefs.h>#include <mach/mt_pll.h>#include <mach/mt_gpt.h>#define VERSION        "v 0.1"#define VIB_DEVICE        "mt_vibrator"#define COUNT_DOWN_TIME50#define VIBR_HRTIMER#ifndef VIBR_HRTIMERXGPT_NUM Vibrator_XGPT = XGPT7;#endif/******************************************************************************Error Code No.******************************************************************************/#define RSUCCESS        0/******************************************************************************Debug Message Settings******************************************************************************//* Debug message event */#define DBG_EVT_NONE0x00000000/* No event */#define DBG_EVT_INT0x00000001/* Interrupt related event */#define DBG_EVT_TASKLET0x00000002/* Tasklet related event */#define DBG_EVT_ALL0xffffffff #define DBG_EVT_MASK      (DBG_EVT_TASKLET)#if 1#define MSG(evt, fmt, args...) \do {\if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \printk(fmt, ##args); \} \} while(0)#define MSG_FUNC_ENTRY(f)MSG(FUC, "<FUN_ENT>: %s\n", __FUNCTION__)#else#define MSG(evt, fmt, args...) do{}while(0)#define MSG_FUNC_ENTRY(f)   do{}while(0)#endif#define VIBR_CON0 ((volatile unsigned long*)(0xF702F7B0))static int vibr_Enable(void){    printk("[vibrator]vibr_Enable \n");hwPowerOn(MT_POWER_LDO_VIBR, VOL_2800 , "VIBR");return 0;}static int vibr_Disable(void){    while((INREG32(VIBR_CON0)&1))    {        printk("[vibrator]vibr_Disable \n");hwPowerDown(MT_POWER_LDO_VIBR , "VIBR");        //printk("[vibrator]vibr_Disable:VIBR_CON0=0x%x \r\n", INREG32(VIBR_CON0));    }return 0;}/******************************************************************************Global Definations******************************************************************************///static struct work_struct vibrator_work;static struct hrtimer vibe_timer;static spinlock_t vibe_lock;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;} elsereturn 0;}static void vibrator_enable(struct timed_output_dev *dev, int value){        unsigned long   flags;spin_lock_irqsave(&vibe_lock, flags);        #ifdef VIBR_HRTIMERwhile(hrtimer_cancel(&vibe_timer))        {            printk("[vibrator]vibrator_enable: try to cancel hrtimer \n");        }#else        XGPT_Reset(Vibrator_XGPT);        #endifif (value == 0)        {                  printk("[vibrator]vibrator_enable: disable \n");            vibr_Disable();                  }else {value = ((value > 15000) ? 15000 : value);            printk("[vibrator]vibrator_enable: vibrator start: %d \n", value);                      #ifdef VIBR_HRTIMER    hrtimer_start(&vibe_timer, ktime_set(value / 1000, (value % 1000) * 1000000),HRTIMER_MODE_REL);            #else            XGPT_CONFIG config;config.num = Vibrator_XGPT;            config.clkDiv = 0;            config.mode = XGPT_ONE_SHOT;            config.bIrqEnable = TRUE;            config.u4Compare = value*32768/1000;                        if(!XGPT_Config(config))            {                printk("[vibrator]vibrator_enable: config XGPT: %d fail!\n", value);             }                        XGPT_Start(Vibrator_XGPT);            #endif                       vibr_Enable();           }spin_unlock_irqrestore(&vibe_lock, flags);}#ifdef VIBR_HRTIMERstatic enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer){     printk("[vibrator]vibrator_timer_func: vibrator will disable \n");    vibr_Disable();             return HRTIMER_NORESTART;}#elsevoid vibrator_timer_func(UINT16 temp){    printk("[vibrator]vibrator_timer_func: vibrator will disable \n");    vibr_Disable();}#endifstatic struct timed_output_dev mt_vibrator = {.name = "vibrator",.get_time = vibrator_get_time,.enable = vibrator_enable,};static int vib_probe(struct platform_device *pdev){return 0;}static int vib_remove(struct platform_device *pdev){return 0;}static void vib_shutdown(struct platform_device *pdev){vibr_Disable();}/******************************************************************************Device driver structure*****************************************************************************/static struct platform_driver vibrator_driver = {    .probe= vib_probe,.remove    = vib_remove,    .shutdown = vib_shutdown,    .driver     = {    .name = VIB_DEVICE,    },};static ssize_t store_vibr_on(struct device *dev,struct device_attribute *attr, const char *buf, size_t size){if(buf != NULL && size != 0){printk("[vibrator]buf is %s and size is %d \n",buf,size);if(buf[0]== '0'){vibr_Disable();}else{vibr_Enable();}}return size;}static DEVICE_ATTR(vibr_on, 0664, NULL, store_vibr_on);/****************************************************************************** * vib_mod_init *  * DESCRIPTION: *   Register the vibrator device driver !  *  * PARAMETERS:  *   None *  * RETURNS:  *   None *  * NOTES:  *   RSUCCESS : Success *  ******************************************************************************/static s32 __devinit vib_mod_init(void){s32 ret;printk("Mk MT vibrator driver register, version %s\n", VERSION);spin_lock_init(&vibe_lock);            #ifdef VIBR_HRTIMERhrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);vibe_timer.function = vibrator_timer_func;        #else        XGPT_Init(Vibrator_XGPT, vibrator_timer_func);        #endif    timed_output_dev_register(&mt_vibrator);        ret = platform_driver_register(&vibrator_driver);        if(ret)         {printk("[vibrator]Unable to register vibrator driver (%d)\n", ret);return ret;        }ret = device_create_file(mt_vibrator.dev,&dev_attr_vibr_on);    if(ret)    {        printk("[vibrator]device_create_file vibr_on fail! \n");    }    printk("[vibrator]vib_mod_init Done \n");     return RSUCCESS;}/****************************************************************************** * vib_mod_exit *  * DESCRIPTION:  *   Free the device driver !  *  * PARAMETERS:  *   None *  * RETURNS:  *   None *  * NOTES:  *   None *  ******************************************************************************/ static void __exit vib_mod_exit(void){printk("Mk MT vibrator driver unregister, version %s \n", VERSION);printk("[vibrator]vib_mod_exit Done \n");}module_init(vib_mod_init);module_exit(vib_mod_exit);MODULE_AUTHOR("Mk Inc.");MODULE_DESCRIPTION("MT Vibrator Driver (VIB)");MODULE_LICENSE("GPL");

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.