转载加原创Android振动器调试

一:  振动器系统结构和移植内容

振动器负责控制引动电话的振动功能,Android中的振动器系统是一个专供这方面功能的小系统,提供根据时间振动的功能。

振动器系统包含了驱动程序、硬件抽象层、JNI部分、Java框架类等几个部分,也向Java应用程序层提供了简单的API作为平台接口。

Android振动器系统的基本层次结构如图23-1所示。

图23-1  Android振动器系统的基本层次结构

1  振动器部分的结构

Android振动器系统自下而上包含了驱动程序、振动器系统硬件抽象层、振动器系统Java框架类、Java框架中振动器系统使用等几个部分,其结构如图23-2所示。

图23-2  Android振动器系统的结构

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

(1)驱动程序:特定硬件平台振动器的驱动程序,通常基于Android的Timed Output驱动框架实现

(2)硬件抽象层

光系统硬件抽象层接口路径为:hardware/libhardware_legacy/include/hardware_legacy/ vibrator.h

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

hardware/libhardware_legacy/vibrator/vibrator.c

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

(3)JNI部分

代码路径:frameworks/base/services/jni/com_android_server_VibratorService.cpp

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

(4)Java部分

代码路径:

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。

2  移植内容

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

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

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

二:  移植与调试的要点    

1  驱动程序

vibrator驱动提供上层接口有很多种,这里介绍两种方式:一种是timeout方式,一种是属性节点。

一、timeout方式

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

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

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

drivers/staging/android/目录timed_output.h中定义timed_output_dev结构体,其中包含enable和get_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文件,“写”表示使能指定的时间,“读”表示获取剩余时间。

二 文件属性节点

          这种方法就是直接用kernel sys系统创建文件节点,提供上层接口,直接操作底层gpio口或者PWM等控制器。

2  硬件抽象层的内容

2.1 硬件抽象层的接口

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()函数,这个函数的内容如下所示:

  1. <PRE class=cpp name="code">#define THE_DEVICE "/sys/class/timed_output/vibrator/enable"  
  2.   
  3. static int sendit(int timeout_ms)  
  4.   
  5. {  
  6.   
  7.     int nwr, ret, fd;  
  8.   
  9.     char value[20];  
  10.   
  11. #ifdef QEMU_HARDWARE                // 使用QEMU的情况  
  12.   
  13.     if (qemu_check()) {  
  14.   
  15.         return qemu_control_command( "vibrator:%d", timeout_ms );  
  16.   
  17.     }  
  18.   
  19. #endif  
  20.   
  21.     fd = open(THE_DEVICE, O_RDWR);               // 读取sys文件系统中的内容  
  22.   
  23.     if(fd < 0) return errno;  
  24.   
  25.     nwr = sprintf(value, "%d\n", timeout_ms);  
  26.   
  27.     ret = write(fd, value, nwr);  
  28.   
  29.     close(fd);  
  30.   
  31.     return (ret == nwr) ? 0 : -1;  
  32.   
  33. }  
  34.   
  35. </PRE><BR>  
  36. <PRE></PRE>  
  37. <P> </P>  
  38. <P>sendit()函数负责根据时间“振动”:在真实的硬件中,通过sys文件系统的文件进行控制;如果是模拟器环境则通过QEMU发送命令。</P>  
  39. <P>vibrator_on()调用sendit()以时间作为参数,vibrator_on()调用sendit()以0作为参数。</P>  
  40. <P> </P>  
  41. <P><STRONG>上层的情况和注意事项</STRONG></P>  
  42. <P>  frameworks/base/services/jni/目录中的com_android_server_VibratorService.cpp文件是Vibrator硬件抽象层的调用者,它同时也向Java提供JNI支持。</P>  
  43. <P>  其中,为JNI定义的方法列表如下所示:</P>  
  44. <P>  </P>  
  45. <PRE class=cpp name="code"> static JNINativeMethod method_table[] = {  
  46.   
  47.   { "vibratorOn", "(J)V", (void*)vibratorOn }, // 振动器开  
  48.   
  49.   { "vibratorOff", "()V", (void*)vibratorOff } // 振动器关  
  50.   
  51.   };  
  52.   
  53.   int register_android_server_VibratorService(JNIEnv *env) {  
  54.   
  55.   return jniRegisterNativeMethods(env, "com/android/server/VibratorService",  
  56.   
  57.   method_table, NELEM(method_table));  
  58.   
  59.   }  
  60.   //vibratorOn()和vibratorOff()这两个函数的实现分别如下所示:  
  61.   
  62.      
  63.   
  64.   static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms){  
  65.   
  66.   vibrator_on(timeout_ms);  
  67.   
  68.   }  
  69.   
  70.   static void vibratorOff(JNIEnv *env, jobject clazz){  
  71.   
  72.   vibrator_off();  
  73.   
  74.   }  
  75.   
  76. </PRE>  
  77. <P><BR>  
  78.  </P>  
  79. <P>        frameworks/base/services/java/com/android/server/目录中的VibratorService.java通过调用VibratorService JNI来实现com.android.server包中的VibratorService类。</P>  
  80. <P>  frameworks/base/core/java/android/os/目录中的Vibrator.java文件实现了android.os包中的Vibrator类。它通过调用vibrator的Java服务来实现(获得名称为vibrator的服务),配合同目录中的IVibratorService.aidl文件向应用程序层提供Vibrator的相关API。</P>  
  81. <P>-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------</P>  
  82. <P><STRONG>Timeout方式的驱动程序</STRONG></P>  
  83. <STRONG></STRONG><PRE class=cpp name="code">#include <linux/init.h>  
  84. #include <linux/module.h>  
  85. #include <linux/kernel.h>  
  86. #include <linux/types.h>  
  87. #include <linux/device.h>  
  88. #include <linux/workqueue.h>  
  89.   
  90. #include "timed_output.h"  
  91. #include <linux/hrtimer.h>  
  92. #include <linux/err.h>  
  93. #include <linux/platform_device.h>  
  94. #include <linux/spinlock.h>  
  95.   
  96. #include <linux/jiffies.h>  
  97. #include <linux/timer.h>  
  98.   
  99. #include <mach/mt_typedefs.h>  
  100. #include <mach/mt_pll.h>  
  101. #include <mach/mt_gpt.h>  
  102.   
  103. #define VERSION                         "v 0.1"  
  104. #define VIB_DEVICE                      "mt_vibrator"  
  105.   
  106. #define COUNT_DOWN_TIME                 50  
  107.   
  108. #define VIBR_HRTIMER  
  109.   
  110. #ifndef VIBR_HRTIMER  
  111. XGPT_NUM Vibrator_XGPT = XGPT7;  
  112. #endif  
  113.   
  114. /******************************************************************************  
  115. Error Code No.  
  116. ******************************************************************************/  
  117. #define RSUCCESS        0  
  118.   
  119. /******************************************************************************  
  120. Debug Message Settings  
  121. ******************************************************************************/  
  122.   
  123. /* Debug message event */  
  124. #define DBG_EVT_NONE        0x00000000  /* No event */  
  125. #define DBG_EVT_INT         0x00000001  /* Interrupt related event */  
  126. #define DBG_EVT_TASKLET     0x00000002  /* Tasklet related event */  
  127.   
  128. #define DBG_EVT_ALL         0xffffffff  
  129.    
  130. #define DBG_EVT_MASK        (DBG_EVT_TASKLET)  
  131.   
  132. #if 1  
  133. #define MSG(evt, fmt, args...) \  
  134. do {    \  
  135.     if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \  
  136.         printk(fmt, ##args); \  
  137.     } \  
  138. } while(0)  
  139.   
  140. #define MSG_FUNC_ENTRY(f)   MSG(FUC, "<FUN_ENT>: %s\n", __FUNCTION__)  
  141. #else  
  142. #define MSG(evt, fmt, args...) do{}while(0)  
  143. #define MSG_FUNC_ENTRY(f)      do{}while(0)  
  144. #endif  
  145.   
  146. #define VIBR_CON0 ((volatile unsigned long*)(0xF702F7B0))  
  147.   
  148. static int vibr_Enable(void)  
  149. {  
  150.     printk("[vibrator]vibr_Enable \n");  
  151.     hwPowerOn(MT_POWER_LDO_VIBR, VOL_2800 , "VIBR");  
  152.     return 0;  
  153. }  
  154.   
  155. static int vibr_Disable(void)  
  156. {  
  157.     while((INREG32(VIBR_CON0)&1))  
  158.     {  
  159.         printk("[vibrator]vibr_Disable \n");  
  160.     hwPowerDown(MT_POWER_LDO_VIBR , "VIBR");  
  161.         //printk("[vibrator]vibr_Disable:VIBR_CON0=0x%x \r\n", INREG32(VIBR_CON0));  
  162.     }  
  163.       
  164.     return 0;  
  165. }  
  166.   
  167.   
  168. /******************************************************************************  
  169. Global Definations  
  170. ******************************************************************************/  
  171. //static struct work_struct vibrator_work;  
  172. static struct hrtimer vibe_timer;  
  173. static spinlock_t vibe_lock;  
  174.   
  175.   
  176. static int vibrator_get_time(struct timed_output_dev *dev)  
  177. {  
  178.     if (hrtimer_active(&vibe_timer))   
  179.     {  
  180.         ktime_t r = hrtimer_get_remaining(&vibe_timer);  
  181.         return r.tv.sec * 1000 + r.tv.nsec / 1000000;  
  182.     }   
  183.     else  
  184.         return 0;  
  185. }  
  186.   
  187. static void vibrator_enable(struct timed_output_dev *dev, int value)  
  188. {  
  189.         unsigned long   flags;  
  190.   
  191.     spin_lock_irqsave(&vibe_lock, flags);  
  192.   
  193.         #ifdef VIBR_HRTIMER  
  194.     while(hrtimer_cancel(&vibe_timer))  
  195.         {  
  196.             printk("[vibrator]vibrator_enable: try to cancel hrtimer \n");  
  197.         }  
  198.     #else  
  199.         XGPT_Reset(Vibrator_XGPT);  
  200.         #endif  
  201.   
  202.     if (value == 0)  
  203.         {        
  204.             printk("[vibrator]vibrator_enable: disable \n");  
  205.             vibr_Disable();  
  206.             
  207.         }  
  208.     else   
  209.     {  
  210.             value = ((value > 15000) ? 15000 : value);  
  211.             printk("[vibrator]vibrator_enable: vibrator start: %d \n", value);   
  212.            
  213.             #ifdef VIBR_HRTIMER  
  214.         hrtimer_start(&vibe_timer,   
  215.             ktime_set(value / 1000, (value % 1000) * 1000000),  
  216.             HRTIMER_MODE_REL);  
  217.   
  218.             #else  
  219.             XGPT_CONFIG config;  
  220.             config.num = Vibrator_XGPT;  
  221.             config.clkDiv = 0;  
  222.             config.mode = XGPT_ONE_SHOT;  
  223.             config.bIrqEnable = TRUE;  
  224.             config.u4Compare = value*32768/1000;  
  225.               
  226.             if(!XGPT_Config(config))  
  227.             {  
  228.                 printk("[vibrator]vibrator_enable: config XGPT: %d fail!\n", value);   
  229.             }  
  230.               
  231.             XGPT_Start(Vibrator_XGPT);  
  232.             #endif  
  233.              
  234.             vibr_Enable();  
  235.              
  236.     }  
  237.     spin_unlock_irqrestore(&vibe_lock, flags);  
  238.   
  239. }  
  240.   
  241.   
  242. #ifdef VIBR_HRTIMER  
  243. static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)  
  244. {  
  245.      printk("[vibrator]vibrator_timer_func: vibrator will disable \n");  
  246.   
  247.     vibr_Disable();  
  248.               
  249.     return HRTIMER_NORESTART;  
  250. }  
  251.   
  252. #else  
  253. void vibrator_timer_func(UINT16 temp)  
  254. {  
  255.     printk("[vibrator]vibrator_timer_func: vibrator will disable \n");  
  256.   
  257.     vibr_Disable();  
  258. }  
  259. #endif  
  260.   
  261.   
  262. static struct timed_output_dev mt_vibrator =   
  263. {  
  264.     .name = "vibrator",  
  265.     .get_time = vibrator_get_time,  
  266.     .enable = vibrator_enable,  
  267. };  
  268.   
  269. static int vib_probe(struct platform_device *pdev)  
  270. {  
  271.     return 0;  
  272. }  
  273.   
  274. static int vib_remove(struct platform_device *pdev)  
  275. {  
  276.     return 0;  
  277. }  
  278.   
  279. static void vib_shutdown(struct platform_device *pdev)  
  280. {  
  281.         vibr_Disable();  
  282.   
  283. }  
  284. /******************************************************************************  
  285. Device driver structure  
  286. *****************************************************************************/  
  287. static struct platform_driver vibrator_driver =   
  288. {  
  289.     .probe      = vib_probe,  
  290.     .remove     = vib_remove,  
  291.     .shutdown = vib_shutdown,  
  292.     .driver     = {  
  293.     .name = VIB_DEVICE,  
  294.     },  
  295. };  
  296.   
  297. static ssize_t store_vibr_on(struct device *dev,struct device_attribute *attr, const char *buf, size_t size)  
  298. {  
  299.     if(buf != NULL && size != 0)  
  300.     {  
  301.         printk("[vibrator]buf is %s and size is %d \n",buf,size);  
  302.         if(buf[0]== '0')  
  303.         {  
  304.             vibr_Disable();  
  305.         }else  
  306.         {  
  307.             vibr_Enable();  
  308.         }  
  309.     }  
  310.     return size;  
  311. }  
  312.   
  313. static DEVICE_ATTR(vibr_on, 0664, NULL, store_vibr_on);  
  314.   
  315. /******************************************************************************  
  316.  * vib_mod_init  
  317.  *   
  318.  * DESCRIPTION:  
  319.  *   Register the vibrator device driver !   
  320.  *   
  321.  * PARAMETERS:   
  322.  *   None  
  323.  *   
  324.  * RETURNS:   
  325.  *   None  
  326.  *   
  327.  * NOTES:   
  328.  *   RSUCCESS : Success  
  329.  *   
  330.  ******************************************************************************/  
  331.   
  332. static s32 __devinit vib_mod_init(void)  
  333. {     
  334.     s32 ret;  
  335.   
  336.     printk("Mk MT vibrator driver register, version %s\n", VERSION);  
  337.   
  338.     spin_lock_init(&vibe_lock);  
  339.       
  340.         #ifdef VIBR_HRTIMER  
  341.     hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);  
  342.     vibe_timer.function = vibrator_timer_func;  
  343.   
  344.         #else  
  345.         XGPT_Init(Vibrator_XGPT, vibrator_timer_func);  
  346.         #endif  
  347.       
  348.     timed_output_dev_register(&mt_vibrator);  
  349.   
  350.         ret = platform_driver_register(&vibrator_driver);  
  351.   
  352.         if(ret)   
  353.         {  
  354.         printk("[vibrator]Unable to register vibrator driver (%d)\n", ret);  
  355.         return ret;  
  356.         }     
  357.   
  358.     ret = device_create_file(mt_vibrator.dev,&dev_attr_vibr_on);  
  359.     if(ret)  
  360.     {  
  361.         printk("[vibrator]device_create_file vibr_on fail! \n");  
  362.     }  
  363.       
  364.     printk("[vibrator]vib_mod_init Done \n");  
  365.    
  366.     return RSUCCESS;  
  367. }  
  368.   
  369. /******************************************************************************  
  370.  * vib_mod_exit  
  371.  *   
  372.  * DESCRIPTION:   
  373.  *   Free the device driver !   
  374.  *   
  375.  * PARAMETERS:   
  376.  *   None  
  377.  *   
  378.  * RETURNS:   
  379.  *   None  
  380.  *   
  381.  * NOTES:   
  382.  *   None  
  383.  *   
  384.  ******************************************************************************/  
  385.    
  386. static void __exit vib_mod_exit(void)  
  387. {  
  388.     printk("Mk MT vibrator driver unregister, version %s \n", VERSION);  
  389.     printk("[vibrator]vib_mod_exit Done \n");  
  390. }  
  391.   
  392. module_init(vib_mod_init);  
  393. module_exit(vib_mod_exit);  
  394. MODULE_AUTHOR("Mk Inc.");  
  395. MODULE_DESCRIPTION("MT Vibrator Driver (VIB)");  
  396. MODULE_LICENSE("GPL");</PRE>  
  397. <P><BR>  
  398.  </P>  
  399. <P><STRONG></STRONG> </P>  
  400. <P> </P>  
  401. <P> </P>  
  402. <PRE></PRE>  
  403. <PRE></PRE>  

  
  
  
  
  1. #define THE_DEVICE "/sys/class/timed_output/vibrator/enable"   
  2.   
  3. static int sendit(int timeout_ms)  
  4.   
  5. {  
  6.   
  7.     int nwr, ret, fd;  
  8.   
  9.     char value[20];  
  10.   
  11. #ifdef QEMU_HARDWARE                // 使用QEMU的情况   
  12.   
  13.     if (qemu_check()) {  
  14.   
  15.         return qemu_control_command( "vibrator:%d", timeout_ms );  
  16.   
  17.     }  
  18.   
  19. #endif   
  20.   
  21.     fd = open(THE_DEVICE, O_RDWR);               // 读取sys文件系统中的内容   
  22.   
  23.     if(fd < 0) return errno;  
  24.   
  25.     nwr = sprintf(value, "%d\n", timeout_ms);  
  26.   
  27.     ret = write(fd, value, nwr);  
  28.   
  29.     close(fd);  
  30.   
  31.     return (ret == nwr) ? 0 : -1;  
  32.   
  33. }  
#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作为参数。
 
上层的情况和注意事项
  frameworks/base/services/jni/目录中的com_android_server_VibratorService.cpp文件是Vibrator硬件抽象层的调用者,它同时也向Java提供JNI支持。
  其中,为JNI定义的方法列表如下所示:
  

  
  
  
  
  1.  static JNINativeMethod method_table[] = {  
  2.   
  3.   { "vibratorOn""(J)V", (void*)vibratorOn }, // 振动器开   
  4.   
  5.   { "vibratorOff""()V", (void*)vibratorOff } // 振动器关   
  6.   
  7.   };  
  8.   
  9.   int register_android_server_VibratorService(JNIEnv *env) {  
  10.   
  11.   return jniRegisterNativeMethods(env, "com/android/server/VibratorService",  
  12.   
  13.   method_table, NELEM(method_table));  
  14.   
  15.   }  
  16.   //vibratorOn()和vibratorOff()这两个函数的实现分别如下所示:   
  17.   
  18.      
  19.   
  20.   static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms){  
  21.   
  22.   vibrator_on(timeout_ms);  
  23.   
  24.   }  
  25.   
  26.   static void vibratorOff(JNIEnv *env, jobject clazz){  
  27.   
  28.   vibrator_off();  
  29.   
  30.   }  
 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类。它通过调用vibrator的Java服务来实现(获得名称为vibrator的服务),配合同目录中的IVibratorService.aidl文件向应用程序层提供Vibrator的相关API。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我具体的驱动程序

  
  
  
  
  1. #include <linux/init.h>   
  2. #include <linux/module.h>   
  3. #include <linux/kernel.h>   
  4. #include <linux/types.h>   
  5. #include <linux/device.h>   
  6. #include <linux/workqueue.h>   
  7.   
  8. #include "timed_output.h"   
  9. #include <linux/hrtimer.h>   
  10. #include <linux/err.h>   
  11. #include <linux/platform_device.h>   
  12. #include <linux/spinlock.h>   
  13.   
  14. #include <linux/jiffies.h>   
  15. #include <linux/timer.h>   
  16.   
  17. #include <mach/mt_typedefs.h>   
  18. #include <mach/mt_pll.h>   
  19. #include <mach/mt_gpt.h>   
  20.   
  21. #define VERSION                         "v 0.1"   
  22. #define VIB_DEVICE                      "mt_vibrator"   
  23.   
  24. #define COUNT_DOWN_TIME                 50   
  25.   
  26. #define VIBR_HRTIMER   
  27.   
  28. #ifndef VIBR_HRTIMER   
  29. XGPT_NUM Vibrator_XGPT = XGPT7;  
  30. #endif   
  31.   
  32. /****************************************************************************** 
  33. Error Code No. 
  34. ******************************************************************************/  
  35. #define RSUCCESS        0   
  36.   
  37. /****************************************************************************** 
  38. Debug Message Settings 
  39. ******************************************************************************/  
  40.   
  41. /* Debug message event */  
  42. #define DBG_EVT_NONE        0x00000000  /* No event */   
  43. #define DBG_EVT_INT         0x00000001  /* Interrupt related event */   
  44. #define DBG_EVT_TASKLET     0x00000002  /* Tasklet related event */   
  45.   
  46. #define DBG_EVT_ALL         0xffffffff   
  47.    
  48. #define DBG_EVT_MASK        (DBG_EVT_TASKLET)   
  49.   
  50. #if 1   
  51. #define MSG(evt, fmt, args...) \   
  52. do {    \  
  53.     if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \  
  54.         printk(fmt, ##args); \  
  55.     } \  
  56. while(0)  
  57.   
  58. #define MSG_FUNC_ENTRY(f)   MSG(FUC, "<FUN_ENT>: %s\n", __FUNCTION__)   
  59. #else   
  60. #define MSG(evt, fmt, args...) do{}while(0)   
  61. #define MSG_FUNC_ENTRY(f)      do{}while(0)   
  62. #endif   
  63.   
  64. #define VIBR_CON0 ((volatile unsigned long*)(0xF702F7B0))   
  65.   
  66. static int vibr_Enable(void)  
  67. {  
  68.     printk("[vibrator]vibr_Enable \n");  
  69.     hwPowerOn(MT_POWER_LDO_VIBR, VOL_2800 , "VIBR");  
  70.     return 0;  
  71. }  
  72.   
  73. static int vibr_Disable(void)  
  74. {  
  75.     while((INREG32(VIBR_CON0)&1))  
  76.     {  
  77.         printk("[vibrator]vibr_Disable \n");  
  78.     hwPowerDown(MT_POWER_LDO_VIBR , "VIBR");  
  79.         //printk("[vibrator]vibr_Disable:VIBR_CON0=0x%x \r\n", INREG32(VIBR_CON0));   
  80.     }  
  81.       
  82.     return 0;  
  83. }  
  84.   
  85.   
  86. /****************************************************************************** 
  87. Global Definations 
  88. ******************************************************************************/  
  89. //static struct work_struct vibrator_work;   
  90. static struct hrtimer vibe_timer;  
  91. static spinlock_t vibe_lock;  
  92.   
  93.   
  94. static int vibrator_get_time(struct timed_output_dev *dev)  
  95. {  
  96.     if (hrtimer_active(&vibe_timer))   
  97.     {  
  98.         ktime_t r = hrtimer_get_remaining(&vibe_timer);  
  99.         return r.tv.sec * 1000 + r.tv.nsec / 1000000;  
  100.     }   
  101.     else  
  102.         return 0;  
  103. }  
  104.   
  105. static void vibrator_enable(struct timed_output_dev *dev, int value)  
  106. {  
  107.         unsigned long   flags;  
  108.   
  109.     spin_lock_irqsave(&vibe_lock, flags);  
  110.   
  111.         #ifdef VIBR_HRTIMER   
  112.     while(hrtimer_cancel(&vibe_timer))  
  113.         {  
  114.             printk("[vibrator]vibrator_enable: try to cancel hrtimer \n");  
  115.         }  
  116.     #else   
  117.         XGPT_Reset(Vibrator_XGPT);  
  118.         #endif   
  119.   
  120.     if (value == 0)  
  121.         {        
  122.             printk("[vibrator]vibrator_enable: disable \n");  
  123.             vibr_Disable();  
  124.             
  125.         }  
  126.     else   
  127.     {  
  128.             value = ((value > 15000) ? 15000 : value);  
  129.             printk("[vibrator]vibrator_enable: vibrator start: %d \n", value);   
  130.            
  131.             #ifdef VIBR_HRTIMER   
  132.         hrtimer_start(&vibe_timer,   
  133.             ktime_set(value / 1000, (value % 1000) * 1000000),  
  134.             HRTIMER_MODE_REL);  
  135.   
  136.             #else   
  137.             XGPT_CONFIG config;  
  138.             config.num = Vibrator_XGPT;  
  139.             config.clkDiv = 0;  
  140.             config.mode = XGPT_ONE_SHOT;  
  141.             config.bIrqEnable = TRUE;  
  142.             config.u4Compare = value*32768/1000;  
  143.               
  144.             if(!XGPT_Config(config))  
  145.             {  
  146.                 printk("[vibrator]vibrator_enable: config XGPT: %d fail!\n", value);   
  147.             }  
  148.               
  149.             XGPT_Start(Vibrator_XGPT);  
  150.             #endif   
  151.              
  152.             vibr_Enable();  
  153.              
  154.     }  
  155.     spin_unlock_irqrestore(&vibe_lock, flags);  
  156.   
  157. }  
  158.   
  159.   
  160. #ifdef VIBR_HRTIMER   
  161. static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)  
  162. {  
  163.      printk("[vibrator]vibrator_timer_func: vibrator will disable \n");  
  164.   
  165.     vibr_Disable();  
  166.               
  167.     return HRTIMER_NORESTART;  
  168. }  
  169.   
  170. #else   
  171. void vibrator_timer_func(UINT16 temp)  
  172. {  
  173.     printk("[vibrator]vibrator_timer_func: vibrator will disable \n");  
  174.   
  175.     vibr_Disable();  
  176. }  
  177. #endif   
  178.   
  179.   
  180. static struct timed_output_dev mt_vibrator =   
  181. {  
  182.     .name = "vibrator",  
  183.     .get_time = vibrator_get_time,  
  184.     .enable = vibrator_enable,  
  185. };  
  186.   
  187. static int vib_probe(struct platform_device *pdev)  
  188. {  
  189.     return 0;  
  190. }  
  191.   
  192. static int vib_remove(struct platform_device *pdev)  
  193. {  
  194.     return 0;  
  195. }  
  196.   
  197. static void vib_shutdown(struct platform_device *pdev)  
  198. {  
  199.         vibr_Disable();  
  200.   
  201. }  
  202. /****************************************************************************** 
  203. Device driver structure 
  204. *****************************************************************************/  
  205. static struct platform_driver vibrator_driver =   
  206. {  
  207.     .probe      = vib_probe,  
  208.     .remove     = vib_remove,  
  209.     .shutdown = vib_shutdown,  
  210.     .driver     = {  
  211.     .name = VIB_DEVICE,  
  212.     },  
  213. };  
  214.   
  215. static ssize_t store_vibr_on(struct device *dev,struct device_attribute *attr, const char *buf, size_t size)  
  216. {  
  217.     if(buf != NULL && size != 0)  
  218.     {  
  219.         printk("[vibrator]buf is %s and size is %d \n",buf,size);  
  220.         if(buf[0]== '0')  
  221.         {  
  222.             vibr_Disable();  
  223.         }else  
  224.         {  
  225.             vibr_Enable();  
  226.         }  
  227.     }  
  228.     return size;  
  229. }  
  230.   
  231. static DEVICE_ATTR(vibr_on, 0664, NULL, store_vibr_on);  
  232.   
  233. /****************************************************************************** 
  234.  * vib_mod_init 
  235.  *  
  236.  * DESCRIPTION: 
  237.  *   Register the vibrator device driver !  
  238.  *  
  239.  * PARAMETERS:  
  240.  *   None 
  241.  *  
  242.  * RETURNS:  
  243.  *   None 
  244.  *  
  245.  * NOTES:  
  246.  *   RSUCCESS : Success 
  247.  *  
  248.  ******************************************************************************/  
  249.   
  250. static s32 __devinit vib_mod_init(void)  
  251. {     
  252.     s32 ret;  
  253.   
  254.     printk("Mk MT vibrator driver register, version %s\n", VERSION);  
  255.   
  256.     spin_lock_init(&vibe_lock);  
  257.       
  258.         #ifdef VIBR_HRTIMER   
  259.     hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);  
  260.     vibe_timer.function = vibrator_timer_func;  
  261.   
  262.         #else   
  263.         XGPT_Init(Vibrator_XGPT, vibrator_timer_func);  
  264.         #endif   
  265.       
  266.     timed_output_dev_register(&mt_vibrator);  
  267.   
  268.         ret = platform_driver_register(&vibrator_driver);  
  269.   
  270.         if(ret)   
  271.         {  
  272.         printk("[vibrator]Unable to register vibrator driver (%d)\n", ret);  
  273.         return ret;  
  274.         }     
  275.   
  276.     ret = device_create_file(mt_vibrator.dev,&dev_attr_vibr_on);  
  277.     if(ret)  
  278.     {  
  279.         printk("[vibrator]device_create_file vibr_on fail! \n");  
  280.     }  
  281.       
  282.     printk("[vibrator]vib_mod_init Done \n");  
  283.    
  284.     return RSUCCESS;  
  285. }  
  286.   
  287. /****************************************************************************** 
  288.  * vib_mod_exit 
  289.  *  
  290.  * DESCRIPTION:  
  291.  *   Free the device driver !  
  292.  *  
  293.  * PARAMETERS:  
  294.  *   None 
  295.  *  
  296.  * RETURNS:  
  297.  *   None 
  298.  *  
  299.  * NOTES:  
  300.  *   None 
  301.  *  
  302.  ******************************************************************************/  
  303.    
  304. static void __exit vib_mod_exit(void)  
  305. {  
  306.     printk("Mk MT vibrator driver unregister, version %s \n", VERSION);  
  307.     printk("[vibrator]vib_mod_exit Done \n");  
  308. }  
  309.   
  310. module_init(vib_mod_init);  
  311. module_exit(vib_mod_exit);  
  312. MODULE_AUTHOR("Mk Inc.");  
  313. MODULE_DESCRIPTION("MT Vibrator Driver (VIB)");  
  314. MODULE_LICENSE("GPL");  
#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_TIME					50

#define VIBR_HRTIMER

#ifndef VIBR_HRTIMER
XGPT_NUM Vibrator_XGPT = XGPT7;
#endif

/******************************************************************************
Error Code No.
******************************************************************************/
#define RSUCCESS        0

/******************************************************************************
Debug Message Settings
******************************************************************************/

/* Debug message event */
#define DBG_EVT_NONE		0x00000000	/* No event */
#define DBG_EVT_INT			0x00000001	/* Interrupt related event */
#define DBG_EVT_TASKLET		0x00000002	/* Tasklet related event */

#define DBG_EVT_ALL			0xffffffff
 
#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;
	} 
	else
		return 0;
}

static void vibrator_enable(struct timed_output_dev *dev, int value)
{
        unsigned long   flags;

	spin_lock_irqsave(&vibe_lock, flags);

        #ifdef VIBR_HRTIMER
	while(hrtimer_cancel(&vibe_timer))
        {
            printk("[vibrator]vibrator_enable: try to cancel hrtimer \n");
        }
	#else
        XGPT_Reset(Vibrator_XGPT);
        #endif

	if (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_HRTIMER
static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
{
     printk("[vibrator]vibrator_timer_func: vibrator will disable \n");

    vibr_Disable();
            
 	return HRTIMER_NORESTART;
}

#else
void vibrator_timer_func(UINT16 temp)
{
    printk("[vibrator]vibrator_timer_func: vibrator will disable \n");

    vibr_Disable();
}
#endif


static 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_HRTIMER
	hrtimer_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");
 
 
<P><STRONG>SYS文件系统方式的驱动程序</STRONG></P>  

#include <linux/module.h> #include <linux/jiffies.h> #include <linux/platform_device.h> #include <linux/workqueue.h> #include <linux/delay.h> #include <linux/gpio.h> #include <linux/i2c.h> #include <linux/lnw_gpio.h> #include <asm/intel-mid.h>

#define VIBRA_ENABLE_GPIO 91

struct vibra_info {  int     enabled;  struct mutex lock;  struct device *dev;  const char *name;  int gpio_en; };

/* Enable's vibra driver */ static void vibra_enable(struct vibra_info *info) {  mutex_lock(&info->lock);  gpio_set_value(info->gpio_en, 1);  info->enabled = true;  mutex_unlock(&info->lock); }

static void vibra_disable(struct vibra_info *info) {  mutex_lock(&info->lock);  gpio_set_value(info->gpio_en, 0);  info->enabled = false;  mutex_unlock(&info->lock); }

/******************************************************************************  * SYSFS                                                                                            *  ******************************************************************************/

static ssize_t vibra_show_vibrator(struct device *dev,   struct device_attribute *attr, const char *buf, size_t size) {  struct vibra_info *info = dev_get_drvdata(dev);

 return sprintf(buf, "%d\n", info->enabled);

}

static ssize_t vibra_set_vibrator(struct device *dev,         struct device_attribute *attr, const char *buf, size_t size) {  long vibrator_enable;  struct vibra_info *info = dev_get_drvdata(dev);

 if (kstrtol(buf, 10, &vibrator_enable))   return -EINVAL;  else if (vibrator_enable == 0)   vibra_disable(info);  else if (vibrator_enable == 1)   vibra_enable(info);  else   return -EINVAL;  return size; }

static DEVICE_ATTR(vibrator, S_IWUSR | S_IRUGO,      vibra_show_vibrator,vibra_set_vibrator);

static struct attribute *gpio_vibra_attrs[] = {  &dev_attr_vibrator.attr,  NULL, };

static struct attribute_group gpio_vibra_attr_group = {  .attrs = gpio_vibra_attrs, };

#if CONFIG_PM static int vibra_runtime_suspend(struct device *dev) {  printk("In %s\n", __func__);  return 0; }

static int vibra_runtime_resume(struct device *dev) {  printk("In %s\n", __func__);  return 0; }

static const struct dev_pm_ops intel_mid_vibra_pm_ops = {  .suspend = vibra_runtime_suspend,  .resume = vibra_runtime_resume, };

#endif

static int __devinit gpio_vibra_probe(struct platform_device *pdev) {  struct vibra_info *info;  struct mid_vibra_probe *data;  int ret = 0;    info =  kzalloc(sizeof(*info), GFP_KERNEL);  if (!info)   return -ENOMEM;

 info->gpio_en = VIBRA_ENABLE_GPIO;  printk("using gpios en: %d", info->gpio_en);  ret = gpio_request_one(info->gpio_en, GPIOF_DIR_OUT, "VIBRA ENABLE");  if (ret != 0) {   pr_err("gpio_request(%d) fails:%d\n", info->gpio_en, ret);   goto out;  }

 info->name = "intel_mid:vibrator";  mutex_init(&info->lock);

 ret = sysfs_create_group(&pdev->dev.kobj, &gpio_vibra_attr_group);  if (ret) {   pr_err("Unable to export keys/switches, error: %d\n",ret);   goto do_freegpio_vibra_enable;  }

 platform_set_drvdata(pdev, info);

 return ret; do_freegpio_vibra_enable:  sysfs_remove_group(&pdev->dev.kobj, &gpio_vibra_attr_group);  gpio_free(info->gpio_en); out:  return ret; }

static void __devexit gpio_vibra_remove(struct platform_device *pdev) {  struct vibra_info *info = platform_get_drvdata(pdev);  gpio_free(info->gpio_en);  sysfs_remove_group(&pdev->dev.kobj, &gpio_vibra_attr_group); }

static struct of_device_id gpio_vibra_of_match[] = {  { .compatible = "gpio-vibra", },  { }, }; MODULE_DEVICE_TABLE(of, gpio_vibra_of_match);

static struct platform_driver gpio_vibra_device_driver = {  .probe  = gpio_vibra_probe,  .remove  = __devexit_p(gpio_vibra_remove),  .driver  = {   .name = "gpio-vibra",   .owner = THIS_MODULE, #ifdef CONFIG_PM_SLEEP   .pm = &intel_mid_vibra_pm_ops, #endif  .of_match_table = gpio_vibra_of_match,

 } };

static int __init gpio_vibra_init(void) {  int ret = 0;

 ret = platform_driver_register(&gpio_vibra_device_driver);  if (ret)   pr_err("vib driver register failed\n");  return ret; } static void __exit gpio_vibra_exit(void) {  platform_driver_unregister(&gpio_vibra_device_driver);  printk("intel_mid_vibra driver exited\n");  return; }

static struct platform_device vb_device = {  .name  = "gpio-vibra",  .id  = -1,  .dev  = {   .platform_data = NULL,//&gpio_keys,  }, };

static int __init vibra_platform_init(void) {  return platform_device_register(&vb_device); }

late_initcall(vibra_platform_init);

module_init(gpio_vibra_init); module_exit(gpio_vibra_exit);

MODULE_ALIAS("gpio:intel_mid_vibra"); MODULE_DESCRIPTION("gpio control Vibra driver"); MODULE_LICENSE("GPL v2");

 
 
 
 
更多 1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值