转载加原创Android振动器调试

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

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

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

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

转载加原创Android振动器调试_第1张图片

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

1  振动器部分的结构

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

转载加原创Android振动器调试_第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()函数,这个函数的内容如下所示:

[html] view plain copy print ?
  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>  
  
  
  
  
[cpp] view plain copy print ?
  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. }  
 
sendit()函数负责根据时间“振动”:在真实的硬件中,通过sys文件系统的文件进行控制;如果是模拟器环境则通过QEMU发送命令。
vibrator_on()调用sendit()以时间作为参数,vibrator_on()调用sendit()以0作为参数。
 
上层的情况和注意事项
  frameworks/base/services/jni/目录中的com_android_server_VibratorService.cpp文件是Vibrator硬件抽象层的调用者,它同时也向Java提供JNI支持。
  其中,为JNI定义的方法列表如下所示:
  
  
  
  
  
[cpp] view plain copy print ?
  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.   }  
 
        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。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我具体的驱动程序
  
  
  
  
[cpp] view plain copy print ?
  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");  
 
 
<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

你可能感兴趣的:(Vibrator)