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

振动器负责控制引动电话的振动功能,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. <PREclass=cppname="code">#defineTHE_DEVICE"/sys/class/timed_output/vibrator/enable"
  2. staticintsendit(inttimeout_ms)
  3. {
  4. intnwr,ret,fd;
  5. charvalue[20];
  6. #ifdefQEMU_HARDWARE//使用QEMU的情况
  7. if(qemu_check()){
  8. returnqemu_control_command("vibrator:%d",timeout_ms);
  9. }
  10. #endif
  11. fd=open(THE_DEVICE,O_RDWR);//读取sys文件系统中的内容
  12. if(fd<0)returnerrno;
  13. nwr=sprintf(value,"%d\n",timeout_ms);
  14. ret=write(fd,value,nwr);
  15. close(fd);
  16. return(ret==nwr)?0:-1;
  17. }
  18. </PRE><BR>
  19. <PRE></PRE>
  20. <P></P>
  21. <P>sendit()函数负责根据时间“振动”:在真实的硬件中,通过sys文件系统的文件进行控制;如果是模拟器环境则通过QEMU发送命令。</P>
  22. <P>vibrator_on()调用sendit()以时间作为参数,vibrator_on()调用sendit()以0作为参数。</P>
  23. <P></P>
  24. <P><STRONG>上层的情况和注意事项</STRONG></P>
  25. <P>  frameworks/base/services/jni/目录中的com_android_server_VibratorService.cpp文件是Vibrator硬件抽象层的调用者,它同时也向Java提供JNI支持。</P>
  26. <P>  其中,为JNI定义的方法列表如下所示:</P>
  27. <P>  </P>
  28. <PREclass=cppname="code"> staticJNINativeMethodmethod_table[]={
  29.   {"vibratorOn","(J)V",(void*)vibratorOn},//振动器开
  30.   {"vibratorOff","()V",(void*)vibratorOff}//振动器关
  31.   };
  32.   intregister_android_server_VibratorService(JNIEnv*env){
  33.   returnjniRegisterNativeMethods(env,"com/android/server/VibratorService",
  34.   method_table,NELEM(method_table));
  35.   }
  36.   //vibratorOn()和vibratorOff()这两个函数的实现分别如下所示:
  37.   
  38.   staticvoidvibratorOn(JNIEnv*env,jobjectclazz,jlongtimeout_ms){
  39.   vibrator_on(timeout_ms);
  40.   }
  41.   staticvoidvibratorOff(JNIEnv*env,jobjectclazz){
  42.   vibrator_off();
  43.   }
  44. </PRE>
  45. <P><BR>
  46. </P>
  47. <P>frameworks/base/services/java/com/android/server/目录中的VibratorService.java通过调用VibratorServiceJNI来实现com.android.server包中的VibratorService类。</P>
  48. <P>  frameworks/base/core/java/android/os/目录中的Vibrator.java文件实现了android.os包中的Vibrator类。它通过调用vibrator的Java服务来实现(获得名称为vibrator的服务),配合同目录中的IVibratorService.aidl文件向应用程序层提供Vibrator的相关API。</P>
  49. <P>-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------</P>
  50. <P><STRONG>Timeout方式的驱动程序</STRONG></P>
  51. <STRONG></STRONG><PREclass=cppname="code">#include<linux/init.h>
  52. #include<linux/module.h>
  53. #include<linux/kernel.h>
  54. #include<linux/types.h>
  55. #include<linux/device.h>
  56. #include<linux/workqueue.h>
  57. #include"timed_output.h"
  58. #include<linux/hrtimer.h>
  59. #include<linux/err.h>
  60. #include<linux/platform_device.h>
  61. #include<linux/spinlock.h>
  62. #include<linux/jiffies.h>
  63. #include<linux/timer.h>
  64. #include<mach/mt_typedefs.h>
  65. #include<mach/mt_pll.h>
  66. #include<mach/mt_gpt.h>
  67. #defineVERSION"v0.1"
  68. #defineVIB_DEVICE"mt_vibrator"
  69. #defineCOUNT_DOWN_TIME50
  70. #defineVIBR_HRTIMER
  71. #ifndefVIBR_HRTIMER
  72. XGPT_NUMVibrator_XGPT=XGPT7;
  73. #endif
  74. /******************************************************************************
  75. ErrorCodeNo.
  76. ******************************************************************************/
  77. #defineRSUCCESS0
  78. /******************************************************************************
  79. DebugMessageSettings
  80. ******************************************************************************/
  81. /*Debugmessageevent*/
  82. #defineDBG_EVT_NONE0x00000000/*Noevent*/
  83. #defineDBG_EVT_INT0x00000001/*Interruptrelatedevent*/
  84. #defineDBG_EVT_TASKLET0x00000002/*Taskletrelatedevent*/
  85. #defineDBG_EVT_ALL0xffffffff
  86. #defineDBG_EVT_MASK(DBG_EVT_TASKLET)
  87. #if1
  88. #defineMSG(evt,fmt,args...)\
  89. do{\
  90. if((DBG_EVT_##evt)&DBG_EVT_MASK){\
  91. printk(fmt,##args);\
  92. }\
  93. }while(0)
  94. #defineMSG_FUNC_ENTRY(f)MSG(FUC,"<FUN_ENT>:%s\n",__FUNCTION__)
  95. #else
  96. #defineMSG(evt,fmt,args...)do{}while(0)
  97. #defineMSG_FUNC_ENTRY(f)do{}while(0)
  98. #endif
  99. #defineVIBR_CON0((volatileunsignedlong*)(0xF702F7B0))
  100. staticintvibr_Enable(void)
  101. {
  102. printk("[vibrator]vibr_Enable\n");
  103. hwPowerOn(MT_POWER_LDO_VIBR,VOL_2800,"VIBR");
  104. return0;
  105. }
  106. staticintvibr_Disable(void)
  107. {
  108. while((INREG32(VIBR_CON0)&1))
  109. {
  110. printk("[vibrator]vibr_Disable\n");
  111. hwPowerDown(MT_POWER_LDO_VIBR,"VIBR");
  112. //printk("[vibrator]vibr_Disable:VIBR_CON0=0x%x\r\n",INREG32(VIBR_CON0));
  113. }
  114. return0;
  115. }
  116. /******************************************************************************
  117. GlobalDefinations
  118. ******************************************************************************/
  119. //staticstructwork_structvibrator_work;
  120. staticstructhrtimervibe_timer;
  121. staticspinlock_tvibe_lock;
  122. staticintvibrator_get_time(structtimed_output_dev*dev)
  123. {
  124. if(hrtimer_active(&vibe_timer))
  125. {
  126. ktime_tr=hrtimer_get_remaining(&vibe_timer);
  127. returnr.tv.sec*1000+r.tv.nsec/1000000;
  128. }
  129. else
  130. return0;
  131. }
  132. staticvoidvibrator_enable(structtimed_output_dev*dev,intvalue)
  133. {
  134. unsignedlongflags;
  135. spin_lock_irqsave(&vibe_lock,flags);
  136. #ifdefVIBR_HRTIMER
  137. while(hrtimer_cancel(&vibe_timer))
  138. {
  139. printk("[vibrator]vibrator_enable:trytocancelhrtimer\n");
  140. }
  141. #else
  142. XGPT_Reset(Vibrator_XGPT);
  143. #endif
  144. if(value==0)
  145. {
  146. printk("[vibrator]vibrator_enable:disable\n");
  147. vibr_Disable();
  148. }
  149. else
  150. {
  151. value=((value>15000)?15000:value);
  152. printk("[vibrator]vibrator_enable:vibratorstart:%d\n",value);
  153. #ifdefVIBR_HRTIMER
  154. hrtimer_start(&vibe_timer,
  155. ktime_set(value/1000,(value%1000)*1000000),
  156. HRTIMER_MODE_REL);
  157. #else
  158. XGPT_CONFIGconfig;
  159. config.num=Vibrator_XGPT;
  160. config.clkDiv=0;
  161. config.mode=XGPT_ONE_SHOT;
  162. config.bIrqEnable=TRUE;
  163. config.u4Compare=value*32768/1000;
  164. if(!XGPT_Config(config))
  165. {
  166. printk("[vibrator]vibrator_enable:configXGPT:%dfail!\n",value);
  167. }
  168. XGPT_Start(Vibrator_XGPT);
  169. #endif
  170. vibr_Enable();
  171. }
  172. spin_unlock_irqrestore(&vibe_lock,flags);
  173. }
  174. #ifdefVIBR_HRTIMER
  175. staticenumhrtimer_restartvibrator_timer_func(structhrtimer*timer)
  176. {
  177. printk("[vibrator]vibrator_timer_func:vibratorwilldisable\n");
  178. vibr_Disable();
  179. returnHRTIMER_NORESTART;
  180. }
  181. #else
  182. voidvibrator_timer_func(UINT16temp)
  183. {
  184. printk("[vibrator]vibrator_timer_func:vibratorwilldisable\n");
  185. vibr_Disable();
  186. }
  187. #endif
  188. staticstructtimed_output_devmt_vibrator=
  189. {
  190. .name="vibrator",
  191. .get_time=vibrator_get_time,
  192. .enable=vibrator_enable,
  193. };
  194. staticintvib_probe(structplatform_device*pdev)
  195. {
  196. return0;
  197. }
  198. staticintvib_remove(structplatform_device*pdev)
  199. {
  200. return0;
  201. }
  202. staticvoidvib_shutdown(structplatform_device*pdev)
  203. {
  204. vibr_Disable();
  205. }
  206. /******************************************************************************
  207. Devicedriverstructure
  208. *****************************************************************************/
  209. staticstructplatform_drivervibrator_driver=
  210. {
  211. .probe=vib_probe,
  212. .remove=vib_remove,
  213. .shutdown=vib_shutdown,
  214. .driver={
  215. .name=VIB_DEVICE,
  216. },
  217. };
  218. staticssize_tstore_vibr_on(structdevice*dev,structdevice_attribute*attr,constchar*buf,size_tsize)
  219. {
  220. if(buf!=NULL&&size!=0)
  221. {
  222. printk("[vibrator]bufis%sandsizeis%d\n",buf,size);
  223. if(buf[0]=='0')
  224. {
  225. vibr_Disable();
  226. }else
  227. {
  228. vibr_Enable();
  229. }
  230. }
  231. returnsize;
  232. }
  233. staticDEVICE_ATTR(vibr_on,0664,NULL,store_vibr_on);
  234. /******************************************************************************
  235. *vib_mod_init
  236. *
  237. *DESCRIPTION:
  238. *Registerthevibratordevicedriver!
  239. *
  240. *PARAMETERS:
  241. *None
  242. *
  243. *RETURNS:
  244. *None
  245. *
  246. *NOTES:
  247. *RSUCCESS:Success
  248. *
  249. ******************************************************************************/
  250. statics32__devinitvib_mod_init(void)
  251. {
  252. s32ret;
  253. printk("MkMTvibratordriverregister,version%s\n",VERSION);
  254. spin_lock_init(&vibe_lock);
  255. #ifdefVIBR_HRTIMER
  256. hrtimer_init(&vibe_timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
  257. vibe_timer.function=vibrator_timer_func;
  258. #else
  259. XGPT_Init(Vibrator_XGPT,vibrator_timer_func);
  260. #endif
  261. timed_output_dev_register(&mt_vibrator);
  262. ret=platform_driver_register(&vibrator_driver);
  263. if(ret)
  264. {
  265. printk("[vibrator]Unabletoregistervibratordriver(%d)\n",ret);
  266. returnret;
  267. }
  268. ret=device_create_file(mt_vibrator.dev,&dev_attr_vibr_on);
  269. if(ret)
  270. {
  271. printk("[vibrator]device_create_filevibr_onfail!\n");
  272. }
  273. printk("[vibrator]vib_mod_initDone\n");
  274. returnRSUCCESS;
  275. }
  276. /******************************************************************************
  277. *vib_mod_exit
  278. *
  279. *DESCRIPTION:
  280. *Freethedevicedriver!
  281. *
  282. *PARAMETERS:
  283. *None
  284. *
  285. *RETURNS:
  286. *None
  287. *
  288. *NOTES:
  289. *None
  290. *
  291. ******************************************************************************/
  292. staticvoid__exitvib_mod_exit(void)
  293. {
  294. printk("MkMTvibratordriverunregister,version%s\n",VERSION);
  295. printk("[vibrator]vib_mod_exitDone\n");
  296. }
  297. module_init(vib_mod_init);
  298. module_exit(vib_mod_exit);
  299. MODULE_AUTHOR("MkInc.");
  300. MODULE_DESCRIPTION("MTVibratorDriver(VIB)");
  301. MODULE_LICENSE("GPL");</PRE>
  302. <P><BR>
  303. </P>
  304. <P><STRONG></STRONG></P>
  305. <P></P>
  306. <P></P>
  307. <PRE></PRE>
  308. <PRE></PRE>
                         [cpp]      view plain     copy     print     ?                    
  1. #defineTHE_DEVICE"/sys/class/timed_output/vibrator/enable"
  2. staticintsendit(inttimeout_ms)
  3. {
  4. intnwr,ret,fd;
  5. charvalue[20];
  6. #ifdefQEMU_HARDWARE//使用QEMU的情况
  7. if(qemu_check()){
  8. returnqemu_control_command("vibrator:%d",timeout_ms);
  9. }
  10. #endif
  11. fd=open(THE_DEVICE,O_RDWR);//读取sys文件系统中的内容
  12. if(fd<0)returnerrno;
  13. nwr=sprintf(value,"%d\n",timeout_ms);
  14. ret=write(fd,value,nwr);
  15. close(fd);
  16. return(ret==nwr)?0:-1;
  17. }
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.  staticJNINativeMethodmethod_table[]={
  2.   {"vibratorOn","(J)V",(void*)vibratorOn},//振动器开
  3.   {"vibratorOff","()V",(void*)vibratorOff}//振动器关
  4.   };
  5.   intregister_android_server_VibratorService(JNIEnv*env){
  6.   returnjniRegisterNativeMethods(env,"com/android/server/VibratorService",
  7.   method_table,NELEM(method_table));
  8.   }
  9.   //vibratorOn()和vibratorOff()这两个函数的实现分别如下所示:
  10.   
  11.   staticvoidvibratorOn(JNIEnv*env,jobjectclazz,jlongtimeout_ms){
  12.   vibrator_on(timeout_ms);
  13.   }
  14.   staticvoidvibratorOff(JNIEnv*env,jobjectclazz){
  15.   vibrator_off();
  16.   }
 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. #include"timed_output.h"
  8. #include<linux/hrtimer.h>
  9. #include<linux/err.h>
  10. #include<linux/platform_device.h>
  11. #include<linux/spinlock.h>
  12. #include<linux/jiffies.h>
  13. #include<linux/timer.h>
  14. #include<mach/mt_typedefs.h>
  15. #include<mach/mt_pll.h>
  16. #include<mach/mt_gpt.h>
  17. #defineVERSION"v0.1"
  18. #defineVIB_DEVICE"mt_vibrator"
  19. #defineCOUNT_DOWN_TIME50
  20. #defineVIBR_HRTIMER
  21. #ifndefVIBR_HRTIMER
  22. XGPT_NUMVibrator_XGPT=XGPT7;
  23. #endif
  24. /******************************************************************************
  25. ErrorCodeNo.
  26. ******************************************************************************/
  27. #defineRSUCCESS0
  28. /******************************************************************************
  29. DebugMessageSettings
  30. ******************************************************************************/
  31. /*Debugmessageevent*/
  32. #defineDBG_EVT_NONE0x00000000/*Noevent*/
  33. #defineDBG_EVT_INT0x00000001/*Interruptrelatedevent*/
  34. #defineDBG_EVT_TASKLET0x00000002/*Taskletrelatedevent*/
  35. #defineDBG_EVT_ALL0xffffffff
  36. #defineDBG_EVT_MASK(DBG_EVT_TASKLET)
  37. #if1
  38. #defineMSG(evt,fmt,args...)\
  39. do{\
  40. if((DBG_EVT_##evt)&DBG_EVT_MASK){\
  41. printk(fmt,##args);\
  42. }\
  43. }while(0)
  44. #defineMSG_FUNC_ENTRY(f)MSG(FUC,"<FUN_ENT>:%s\n",__FUNCTION__)
  45. #else
  46. #defineMSG(evt,fmt,args...)do{}while(0)
  47. #defineMSG_FUNC_ENTRY(f)do{}while(0)
  48. #endif
  49. #defineVIBR_CON0((volatileunsignedlong*)(0xF702F7B0))
  50. staticintvibr_Enable(void)
  51. {
  52. printk("[vibrator]vibr_Enable\n");
  53. hwPowerOn(MT_POWER_LDO_VIBR,VOL_2800,"VIBR");
  54. return0;
  55. }
  56. staticintvibr_Disable(void)
  57. {
  58. while((INREG32(VIBR_CON0)&1))
  59. {
  60. printk("[vibrator]vibr_Disable\n");
  61. hwPowerDown(MT_POWER_LDO_VIBR,"VIBR");
  62. //printk("[vibrator]vibr_Disable:VIBR_CON0=0x%x\r\n",INREG32(VIBR_CON0));
  63. }
  64. return0;
  65. }
  66. /******************************************************************************
  67. GlobalDefinations
  68. ******************************************************************************/
  69. //staticstructwork_structvibrator_work;
  70. staticstructhrtimervibe_timer;
  71. staticspinlock_tvibe_lock;
  72. staticintvibrator_get_time(structtimed_output_dev*dev)
  73. {
  74. if(hrtimer_active(&vibe_timer))
  75. {
  76. ktime_tr=hrtimer_get_remaining(&vibe_timer);
  77. returnr.tv.sec*1000+r.tv.nsec/1000000;
  78. }
  79. else
  80. return0;
  81. }
  82. staticvoidvibrator_enable(structtimed_output_dev*dev,intvalue)
  83. {
  84. unsignedlongflags;
  85. spin_lock_irqsave(&vibe_lock,flags);
  86. #ifdefVIBR_HRTIMER
  87. while(hrtimer_cancel(&vibe_timer))
  88. {
  89. printk("[vibrator]vibrator_enable:trytocancelhrtimer\n");
  90. }
  91. #else
  92. XGPT_Reset(Vibrator_XGPT);
  93. #endif
  94. if(value==0)
  95. {
  96. printk("[vibrator]vibrator_enable:disable\n");
  97. vibr_Disable();
  98. }
  99. else
  100. {
  101. value=((value>15000)?15000:value);
  102. printk("[vibrator]vibrator_enable:vibratorstart:%d\n",value);
  103. #ifdefVIBR_HRTIMER
  104. hrtimer_start(&vibe_timer,
  105. ktime_set(value/1000,(value%1000)*1000000),
  106. HRTIMER_MODE_REL);
  107. #else
  108. XGPT_CONFIGconfig;
  109. config.num=Vibrator_XGPT;
  110. config.clkDiv=0;
  111. config.mode=XGPT_ONE_SHOT;
  112. config.bIrqEnable=TRUE;
  113. config.u4Compare=value*32768/1000;
  114. if(!XGPT_Config(config))
  115. {
  116. printk("[vibrator]vibrator_enable:configXGPT:%dfail!\n",value);
  117. }
  118. XGPT_Start(Vibrator_XGPT);
  119. #endif
  120. vibr_Enable();
  121. }
  122. spin_unlock_irqrestore(&vibe_lock,flags);
  123. }
  124. #ifdefVIBR_HRTIMER
  125. staticenumhrtimer_restartvibrator_timer_func(structhrtimer*timer)
  126. {
  127. printk("[vibrator]vibrator_timer_func:vibratorwilldisable\n");
  128. vibr_Disable();
  129. returnHRTIMER_NORESTART;
  130. }
  131. #else
  132. voidvibrator_timer_func(UINT16temp)
  133. {
  134. printk("[vibrator]vibrator_timer_func:vibratorwilldisable\n");
  135. vibr_Disable();
  136. }
  137. #endif
  138. staticstructtimed_output_devmt_vibrator=
  139. {
  140. .name="vibrator",
  141. .get_time=vibrator_get_time,
  142. .enable=vibrator_enable,
  143. };
  144. staticintvib_probe(structplatform_device*pdev)
  145. {
  146. return0;
  147. }
  148. staticintvib_remove(structplatform_device*pdev)
  149. {
  150. return0;
  151. }
  152. staticvoidvib_shutdown(structplatform_device*pdev)
  153. {
  154. vibr_Disable();
  155. }
  156. /******************************************************************************
  157. Devicedriverstructure
  158. *****************************************************************************/
  159. staticstructplatform_drivervibrator_driver=
  160. {
  161. .probe=vib_probe,
  162. .remove=vib_remove,
  163. .shutdown=vib_shutdown,
  164. .driver={
  165. .name=VIB_DEVICE,
  166. },
  167. };
  168. staticssize_tstore_vibr_on(structdevice*dev,structdevice_attribute*attr,constchar*buf,size_tsize)
  169. {
  170. if(buf!=NULL&&size!=0)
  171. {
  172. printk("[vibrator]bufis%sandsizeis%d\n",buf,size);
  173. if(buf[0]=='0')
  174. {
  175. vibr_Disable();
  176. }else
  177. {
  178. vibr_Enable();
  179. }
  180. }
  181. returnsize;
  182. }
  183. staticDEVICE_ATTR(vibr_on,0664,NULL,store_vibr_on);
  184. /******************************************************************************
  185. *vib_mod_init
  186. *
  187. *DESCRIPTION:
  188. *Registerthevibratordevicedriver!
  189. *
  190. *PARAMETERS:
  191. *None
  192. *
  193. *RETURNS:
  194. *None
  195. *
  196. *NOTES:
  197. *RSUCCESS:Success
  198. *
  199. ******************************************************************************/
  200. statics32__devinitvib_mod_init(void)
  201. {
  202. s32ret;
  203. printk("MkMTvibratordriverregister,version%s\n",VERSION);
  204. spin_lock_init(&vibe_lock);
  205. #ifdefVIBR_HRTIMER
  206. hrtimer_init(&vibe_timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
  207. vibe_timer.function=vibrator_timer_func;
  208. #else
  209. XGPT_Init(Vibrator_XGPT,vibrator_timer_func);
  210. #endif
  211. timed_output_dev_register(&mt_vibrator);
  212. ret=platform_driver_register(&vibrator_driver);
  213. if(ret)
  214. {
  215. printk("[vibrator]Unabletoregistervibratordriver(%d)\n",ret);
  216. returnret;
  217. }
  218. ret=device_create_file(mt_vibrator.dev,&dev_attr_vibr_on);
  219. if(ret)
  220. {
  221. printk("[vibrator]device_create_filevibr_onfail!\n");
  222. }
  223. printk("[vibrator]vib_mod_initDone\n");
  224. returnRSUCCESS;
  225. }
  226. /******************************************************************************
  227. *vib_mod_exit
  228. *
  229. *DESCRIPTION:
  230. *Freethedevicedriver!
  231. *
  232. *PARAMETERS:
  233. *None
  234. *
  235. *RETURNS:
  236. *None
  237. *
  238. *NOTES:
  239. *None
  240. *
  241. ******************************************************************************/
  242. staticvoid__exitvib_mod_exit(void)
  243. {
  244. printk("MkMTvibratordriverunregister,version%s\n",VERSION);
  245. printk("[vibrator]vib_mod_exitDone\n");
  246. }
  247. module_init(vib_mod_init);
  248. module_exit(vib_mod_exit);
  249. MODULE_AUTHOR("MkInc.");
  250. MODULE_DESCRIPTION("MTVibratorDriver(VIB)");
  251. 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 mutexlock;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);elsereturn -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_PMstatic 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

更多相关文章

  1. 开发可统计单词个数的Android驱动程序(2)
  2. Android开发平台振动器系统详解
  3. android 振动器系统
  4. Android平台中振动器系统详解

随机推荐

  1. Android设置对话框去除黑边
  2. Android网络检测
  3. Android(安卓)使用PdfDocument生成PDF文
  4. Android(安卓)禁止Edittext弹出系统软键
  5. Android(安卓)imageView图片按比例缩放
  6. ImageView的属性android:scaleType
  7. CMD命令创建、编译Android应用程序
  8. ViewPager实现一个页面多个Item的显示
  9. Android(安卓)VideoPlayer
  10. Android(安卓)开源优秀项目