Chinaunix首页 | 论坛 | 博客
  • 博客访问: 501512
  • 博文数量: 92
  • 博客积分: 3146
  • 博客等级: 中校
  • 技术积分: 2314
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-27 10:20
文章分类

全部博文(92)

文章存档

2014年(3)

2013年(17)

2012年(16)

2011年(22)

2010年(34)

分类: 嵌入式

2012-07-11 19:29:46

前一段时间刚好要调试几个sensors,最开始手头上啥代码也没有,最后花了几天的时间熟悉了这一块,最
后感觉sensors相对其他的模块还是要简单的多!
 
第一步:
     完成相关驱动的编写,这里最开始我挺犹豫的,我驱动的数据如何上报??通过ioctl??我不想那么麻烦,最好在网上找到一个关于用input机制上报对应的值,这样就简单多了,先贴下代码

点击(此处)折叠或打开

  1. #include <linux/platform_device.h>
  2. #include <linux/input-polldev.h>
  3. #include <linux/kernel.h>
  4. #include <linux/module.h>
  5. #include <mach/adc.h>
  6. //#include <linux/saradc.h>

  7. #define POLL_INTERVAL    2000     /* poll for input every 2s*/
  8. #define LUX_LEVEL    4                    /* 0~4 report 5 levels*/

  9. static struct platform_device *pdev;
  10. static struct input_dev *idev;
  11. static struct input_polled_dev *light_sensor_idev;



  12. static const int sAdcValues[LUX_LEVEL] = {
  13.     200,
  14.       1000,
  15.     1800,
  16.     3400,
  17. };

  18. struct light_sensor_info {
  19.     int lux_level;
  20.     int suspend;
  21. };
  22. static struct light_sensor_info ls_info;

  23. /* Sysfs Files */
  24. static ssize_t light_sensor_lux_level_show(struct device *dev,
  25.                  struct device_attribute *attr, char *buf)
  26. {
  27.     return sprintf(buf, "(%d)\n",get_s3c_adc_convert(3));
  28. }

  29. static DEVICE_ATTR(lux_level, 0444, light_sensor_lux_level_show, NULL);

  30. static struct attribute *light_sensor_attributes[] = {
  31.     &dev_attr_lux_level.attr,
  32.     NULL,
  33. };

  34. static struct attribute_group light_sensor_attribute_group = {
  35.     .attrs = light_sensor_attributes,
  36. };


  37. /* Device model stuff */
  38. static int light_sensor_probe(struct platform_device *dev)
  39. {
  40.     printk(KERN_INFO "light_sensor: device successfully initialized.\n");
  41.     return 0;
  42. }

  43. #ifdef CONFIG_PM
  44. static int light_sensor_suspend(struct platform_device *dev, pm_message_t state)
  45. {
  46.         ls_info.suspend = 1;
  47.     return 0;
  48. }

  49. static int light_sensor_resume(struct platform_device *dev)
  50. {
  51.         ls_info.suspend = 0;
  52.     return 0;
  53. }
  54. #else
  55.     #define light_sensor_suspend NULL
  56.     #define light_sensor_resume NULL
  57. #endif

  58. static struct platform_driver light_sensor_driver = {
  59.     .probe = light_sensor_probe,
  60.     .resume = light_sensor_resume,
  61.     .suspend = light_sensor_suspend,
  62.     .driver    = {
  63.         .name = "light_sensor",
  64.         .owner = THIS_MODULE,
  65.     },
  66. };

  67. static void light_sensor_dev_poll(struct input_polled_dev *dev)
  68. {
  69.         int adc_val, i;

  70.     adc_val = get_s3c_adc_convert(3);
  71.     for(i = 0; i < LUX_LEVEL; i++) {
  72.         if(adc_val < sAdcValues[i])
  73.             break;
  74.     }

  75.    
  76.     
  77.     if(ls_info.lux_level != i) {
  78.         ls_info.lux_level = i;    
  79.         input_report_abs(idev, ABS_X, ls_info.lux_level);
  80.         input_sync(idev);
  81.         
  82.     }    

  83. }

  84. /* Module stuff */
  85. static int __init light_sensor_init(void)
  86. {
  87.     
  88.     int ret;

  89.     ret = platform_driver_register(&light_sensor_driver);
  90.     if (ret)
  91.         goto out;

  92.     pdev = platform_device_register_simple("light_sensor", -1, NULL, 0);
  93.     if (IS_ERR(pdev)) {
  94.         ret = PTR_ERR(pdev);
  95.         goto out_driver;
  96.     }

  97.     ret = sysfs_create_group(&pdev->dev.kobj, &light_sensor_attribute_group);
  98.     if (ret)
  99.         goto out_device;

  100.     light_sensor_idev = input_allocate_polled_device();
  101.     if (!light_sensor_idev) {
  102.         ret = -ENOMEM;
  103.         goto out_group;
  104.     }

  105.     light_sensor_idev->poll = light_sensor_dev_poll;//在hal层成功打开的时候会开始轮询
  106.     light_sensor_idev->poll_interval = POLL_INTERVAL;

  107.     /* initialize the input class */
  108.     idev = light_sensor_idev->input;
  109.     idev->name = "light_sensor";//这个名字到时和你hal写的name必须一致
  110.     idev->phys = "light_sensor/input0";
  111.     idev->id.bustype = BUS_ISA;
  112.     idev->dev.parent = &pdev->dev;
  113.     idev->evbit[0] = BIT_MASK(EV_ABS);
  114.     input_set_abs_params(idev, ABS_X,
  115.             0, LUX_LEVEL, 0, 1);

  116.     ret = input_register_polled_device(light_sensor_idev);
  117.     if (ret)
  118.         goto out_idev;

  119.     
  120.     printk(KERN_INFO "huabinbin test light_sensor: driver successfully loaded.\n");
  121.     return 0;

  122. out_idev:
  123.     input_free_polled_device(light_sensor_idev);
  124. out_group:
  125.     sysfs_remove_group(&pdev->dev.kobj, &light_sensor_attribute_group);
  126. out_device:
  127.     platform_device_unregister(pdev);
  128. out_driver:
  129.     platform_driver_unregister(&light_sensor_driver);
  130. out:
  131.     printk(KERN_WARNING "light_sensor: driver init failed (ret=%d)!\n", ret);
  132.     return ret;
  133. }

  134. static void __exit light_sensor_exit(void)
  135. {
  136.     input_unregister_polled_device(light_sensor_idev);
  137.     input_free_polled_device(light_sensor_idev);
  138.     sysfs_remove_group(&pdev->dev.kobj, &light_sensor_attribute_group);
  139.     platform_device_unregister(pdev);
  140.     platform_driver_unregister(&light_sensor_driver);    

  141.     printk(KERN_INFO "light_sensor: driver unloaded.\n");
  142. }

  143. module_init(light_sensor_init);
  144. module_exit(light_sensor_exit);

 

经过实际测试,上面的代码有严重的问题,具体代码更新如下:

点击(此处)折叠或打开

  1. #include <linux/platform_device.h>
  2. #include <linux/input-polldev.h>
  3. #include <linux/kernel.h>
  4. #include <linux/module.h>
  5. #include <mach/adc.h>
  6. #include <linux/kthread.h>
  7. #include <linux/delay.h>
  8. //#include <linux/saradc.h>

  9. #define POLL_INTERVAL    993     /* poll for input every 2s*/
  10. #define LUX_LEVEL    3            /* 0~4 report 5 levels*/
  11. #define LUX_MAX 3300

  12. static struct platform_device *pdev;
  13. static struct input_dev *idev;
  14. static struct input_polled_dev *light_sensor_idev;
  15. static int32_t enable_als(uint32_t enable);
  16. static struct completion thread_completion;
  17. static bool bThreadRunning;
  18. /*define for polling thread*/
  19. static int polling_function(void* arg);
  20. static struct task_struct *polling_tsk;

  21. static const int sAdcValues[LUX_LEVEL] = {
  22.     200,
  23.       1000,
  24.     2300,
  25.     3400,
  26. };

  27. #define SAMPLE_NUM 10

  28. static int Sample_value[SAMPLE_NUM];

  29. struct light_sensor_info {
  30.     int lux_level;
  31.     int suspend;
  32. };
  33. static struct light_sensor_info ls_info;

  34. /* Sysfs Files */
  35. static ssize_t light_sensor_enable_show(struct device *dev,
  36.                  struct device_attribute *attr, char *buf)
  37. {
  38.     //return sprintf(buf, "(%d)\n",get_s3c_adc_convert(3));
  39.     return sprintf(buf, "%d\n", bThreadRunning);
  40. }

  41. static ssize_t light_sensor_enable_store(struct device *dev,
  42.                  struct device_attribute *attr, char *buf,size_t len)
  43. {
  44.     uint32_t value = simple_strtoul(buf, NULL, 10);
  45.    printk("huabinbin test : Enable LS : %d\n",value);
  46.     enable_als(value);
  47.     return len;
  48. }

  49. static DEVICE_ATTR(ls_enable, 0666, light_sensor_enable_show, light_sensor_enable_store);

  50. static struct attribute *light_sensor_attributes[] = {
  51.     &dev_attr_ls_enable.attr,
  52.     NULL,
  53. };

  54. static struct attribute_group light_sensor_attribute_group = {
  55.     .attrs = light_sensor_attributes,
  56. };

  57. static void sample_vol(unsigned int vol)
  58. {
  59.     int i = 0;

  60.     for(i = 0; i < SAMPLE_NUM -1; i++)
  61.     Sample_value[i] = Sample_value[i+1];
  62.     Sample_value[SAMPLE_NUM - 1]=vol;
  63.     return;
  64. }

  65. static int get_lux_average()
  66. {
  67.     int i,sum = 0;

  68.     for(i = 0; i < SAMPLE_NUM-1; i++)
  69.         sum += Sample_value[i];

  70.     //printk("hbb test %s adc_val = %d\n",__func__,sum / SAMPLE_NUM);
  71.     return (sum / SAMPLE_NUM);
  72. }

  73. static int polling_function(void* arg)
  74. {
  75.     int adc_val, i;
  76.     init_completion(&thread_completion);

  77.     while (1)
  78.     {
  79.         adc_val = get_s3c_adc_convert(3);
  80.         //printk("hbb test %s adc_val = %d\n",__func__,adc_val);
  81.         sample_vol(adc_val);
  82.         #if 0
  83.         
  84.         for(i = 0; i <= LUX_LEVEL; i++) {
  85.             if(adc_val < sAdcValues[i])
  86.                 break;
  87.         }

  88.         if(ls_info.lux_level != i) {
  89.             ls_info.lux_level = i;    
  90.             //input_report_abs(idev, ABS_X, ls_info.lux_level);
  91.             input_report_abs(idev, ABS_MISC, ls_info.lux_level);
  92.             input_sync(idev);
  93.             
  94.             printk(KERN_INFO "light_sensor: light_sensor_dev_poll lux_level = %d\n",sAdcValues[ls_info.lux_level]);
  95.         }    
  96.         #else
  97.         input_report_abs(idev, ABS_MISC,get_lux_average());
  98.         input_sync(idev);
  99.         #endif
  100.         if (bThreadRunning == false)
  101.             break;
  102.         msleep(POLL_INTERVAL);

  103.     };
  104.     complete(&thread_completion);
  105.     return 0;
  106. }

  107. static int32_t enable_als(uint32_t enable)
  108. {
  109.     int32_t ret;
  110.     if (enable)
  111.     {

  112.         if (bThreadRunning == 0)
  113.         {
  114.             bThreadRunning = 1;
  115.             polling_tsk = kthread_run(polling_function,NULL,"ls_polling");
  116.         }
  117.         else
  118.         {
  119.          printk("huabinbin test : thread has running\n");
  120.         }
  121.     }
  122.     else
  123.     {
  124.         if (bThreadRunning)
  125.         {
  126.             bThreadRunning = false;
  127.             wait_for_completion(&thread_completion);
  128.             polling_tsk = NULL;
  129.         }
  130.     }
  131.     return ret;
  132. }

  133. /* Device model stuff */
  134. static int light_sensor_probe(struct platform_device *dev)
  135. {
  136.     printk(KERN_INFO "light_sensor: device successfully initialized.\n");
  137.     return 0;
  138. }

  139. #ifdef CONFIG_PM
  140. static int light_sensor_suspend(struct platform_device *dev, pm_message_t state)
  141. {
  142.         ls_info.suspend = 1;
  143.     return 0;
  144. }

  145. static int light_sensor_resume(struct platform_device *dev)
  146. {
  147.         ls_info.suspend = 0;
  148.     return 0;
  149. }
  150. #else
  151.     #define light_sensor_suspend NULL
  152.     #define light_sensor_resume NULL
  153. #endif

  154. static struct platform_driver light_sensor_driver = {
  155.     .probe = light_sensor_probe,
  156.     .resume = light_sensor_resume,
  157.     .suspend = light_sensor_suspend,
  158.     .driver    = {
  159.         .name = "light_sensor",
  160.         .owner = THIS_MODULE,
  161.     },
  162. };

  163. static void light_sensor_dev_poll(struct input_polled_dev *dev)
  164. {
  165.     //printk("huabinbin test light_sensor_dev_poll get adc %d\n",get_s3c_adc_convert(3));
  166.     int adc_val, i;

  167.     adc_val = get_s3c_adc_convert(3);
  168.     for(i = 0; i < LUX_LEVEL; i++) {
  169.         if(adc_val < sAdcValues[i])
  170.             break;
  171.     }

  172.     //printk("huabinbin test get adc %d\n",get_s3c_adc_convert(3));
  173.     
  174.     if(ls_info.lux_level != i) {
  175.         ls_info.lux_level = i;    
  176.         input_report_abs(idev, ABS_X, ls_info.lux_level);
  177.         input_sync(idev);
  178.         
  179.         //printk(KERN_INFO "light_sensor: light_sensor_dev_poll lux_level = %d\n",sAdcValues[ls_info.lux_level]);
  180.     }    

  181. }

  182. /* Module stuff */
  183. static int __init light_sensor_init(void)
  184. {
  185.     
  186.     int ret;

  187.     ret = platform_driver_register(&light_sensor_driver);
  188.     if (ret)
  189.         goto out;

  190.     pdev = platform_device_register_simple("light_sensor", -1, NULL, 0);
  191.     if (IS_ERR(pdev)) {
  192.         ret = PTR_ERR(pdev);
  193.         goto out_driver;
  194.     }

  195.     ret = sysfs_create_group(&pdev->dev.kobj, &light_sensor_attribute_group);
  196.     if (ret)
  197.         goto out_device;

  198. //    light_sensor_idev = input_allocate_polled_device();
  199. //    if (!light_sensor_idev) {
  200.     //    ret = -ENOMEM;
  201.     //    goto out_group;
  202.     //}

  203.     bThreadRunning = false;
  204.     
  205.     //light_sensor_idev->poll = light_sensor_dev_poll;
  206.     //light_sensor_idev->poll_interval = POLL_INTERVAL;

  207.     /* initialize the input class */
  208.     //idev = light_sensor_idev->input;
  209.     idev = input_allocate_device();
  210.     idev->name = "light_sensor";
  211.     idev->phys = "light_sensor/input0";
  212.     idev->id.bustype = BUS_ISA;
  213.     idev->dev.parent = &pdev->dev;
  214.     idev->evbit[0] = BIT_MASK(EV_ABS);
  215.     //input_set_abs_params(idev, ABS_MISC,0, LUX_LEVEL, 0, 1);
  216.     input_set_abs_params(idev, ABS_MISC,0, LUX_MAX, 0, 1);

  217.     ret = input_register_device(idev);
  218.     if (ret)
  219.         goto out_idev;

  220.     
  221.     printk(KERN_INFO "huabinbin test light_sensor: driver successfully loaded.\n");
  222.     return 0;

  223. out_idev:
  224.      input_free_device(idev);
  225. out_group:
  226.     sysfs_remove_group(&pdev->dev.kobj, &light_sensor_attribute_group);
  227. out_device:
  228.     platform_device_unregister(pdev);
  229. out_driver:
  230.     platform_driver_unregister(&light_sensor_driver);
  231. out:
  232.     printk(KERN_WARNING "light_sensor: driver init failed (ret=%d)!\n", ret);
  233.     return ret;
  234. }

  235. static void __exit light_sensor_exit(void)
  236. {
  237.     input_unregister_polled_device(light_sensor_idev);
  238.     input_free_polled_device(light_sensor_idev);
  239.     sysfs_remove_group(&pdev->dev.kobj, &light_sensor_attribute_group);
  240.     platform_device_unregister(pdev);
  241.     platform_driver_unregister(&light_sensor_driver);    

  242.     printk(KERN_INFO "light_sensor: driver unloaded.\n");
  243. }

  244. module_init(light_sensor_init);
  245. module_exit(light_sensor_exit);

  246. MODULE_AUTHOR("bb.hua@unistrong.com");
  247. MODULE_DESCRIPTION("Light Sensor Driver - po188");
  248. MODULE_LICENSE("GPL");


 

阅读(5450) | 评论(5) | 转发(6) |
给主人留下些什么吧!~~

huabinbin002013-01-08 19:10:44

Xorono: MTK的HAL也是一样的吗? SYSFS是不是一定要建立? 想请问一下原因.......
不一定要建立,我建立那个sys主要目的就是在睡眠之前系统会往那个文件里写0,即停止你这个线程了,mtk不清楚,mtk应该封装的很好才对啊

Xorono2013-01-07 17:02:09

huabinbin00: 上报的事件和你hal对应就可以了!代码都是经过测试有效才上传的.....
MTK的HAL也是一样的吗? SYSFS是不是一定要建立? 想请问一下原因..

huabinbin002013-01-06 18:40:30

Xorono: 更新的代码有经过测试么? light sensor报的是事件ABS_MISC么?.....
上报的事件和你hal对应就可以了!代码都是经过测试有效才上传的

Xorono2013-01-05 16:36:39

更新的代码有经过测试么? light sensor报的是事件ABS_MISC么?

Xorono2013-01-05 16:36:05

你好,