Android驱动例子(LED灯控制)


本例子,讲述在Android2.1上完全自已开发一个驱动去控制硬件口并写应用测试该驱动,通过这样一个例子,解析android下的驱动开发流程的应用调用流程,可以说是很好的入门引导

要达到的效果:通过android的应用,调用驱动程序,在开发板上控制4个LED的亮灭。

一、硬件原理

clip_image001

如上图,通过4个IO口控制这LED,低电平LED亮,

这4个IO口分别是GPM1, GPM2, GPM3, GPM4,

二、驱动程序

1、在kernel文件夹下的driver目录,新键驱动文件夹

# cd kernel_android_2.6.28.6/drivers

进到开发板的kernel目录,建驱动文件夹

#mkdir ledtest

2、在/driver/ledtest目录下,新建leddriver.c ,leddriver.h , Kconfig, Makefile 等4个文件

leddriver.c

leddriver.c
  1. #include <linux/kernel.h>
  2. #include <linux/sched.h>
  3. #include <linux/timer.h>
  4. #include <linux/init.h>            /* For __init/__exit/... */
  5. #include <linux/module.h>
  6. #include <mach/hardware.h>
  7. #include <asm/io.h>
  8. #include <asm/uaccess.h>
  9. #include <plat/gpio-cfg.h>
  10. #include <plat/regs-clock.h>
  11. #include <plat/regs-lcd.h>
  12. #include <plat/regs-gpio.h>
  13. #include <mach/map.h>
  14. #include <linux/gpio.h>
  15. #include <plat/gpio-bank-m.h>
  16. #include <linux/cdev.h>
  17. #include <linux/fs.h> //for register_chrdev()
  18. #include <linux/device.h>
  19. #include <mach/map.h>
  20. #include "leddriver.h"
  21. #include <linux/miscdevice.h>        /* For MODULE_ALIAS_MISCDEV
  22.                             (WATCHDOG_MINOR) */
  23. #include <linux/watchdog.h>        /* For the watchdog specific items */
  24. #include <linux/fs.h>            /* For file operations */
  25. #define Viberator_MAJOR        97  //?÷éè±?o?
  26. #define SCULL_NR_DEVS           4
  27. #define SCULL_QUANTUM         4000
  28. #define SCULL_QSET             1000
  29. //---do as the GIO driver
  30. #define DEVCOUNT                4
  31. #define GIO_MINOR            2    /* GIO minor no. */
  32. static dev_t dev;        //éê ?? μ?μ??÷ éè±? o?
  33. static struct cdev *cdev_p;
  34. static int openCnt;
  35. //--è???±?á?------------
  36. int VIB_major  = 97;//we asigment it for test
  37. int VIB_minor = 0;
  38. int VIB_nr_devs = SCULL_NR_DEVS;
  39. int VIB_quantum = SCULL_QUANTUM;
  40. int VIB_qset = SCULL_QSET;
  41.  
  42. static struct class *vib_dev_class;
  43. #define GPNCON  S3C64XX_GPNCON
  44. #define GPNDAT  S3C64XX_GPNDAT
  45. #define GPNPUD  S3C64XX_GPNPUD
  46. #define GPMCON S3C64XX_GPMCON
  47. #define GPMDAT  S3C64XX_GPMDAT
  48. #define GPMPUD S3C64XX_GPMPUD
  49.  
  50. #define VIB_ON 0x11
  51.   #defineVIB_OFF 0x22
  52. static const struct file_operations GPIO_Viberator_ctl_ops={
  53.     .owner        = THIS_MODULE,
  54.     .open    = GPIO_VIB_open,
  55.     .read    =GPIO_VIB_read,
  56.     .write    =GPIO_VIB_write,
  57.     .ioctl     = GPIO_VIB_ioctl,
  58.     .release     =GPIO_VIB_release,
  59. };
  60. ssize_t GPIO_VIB_read(struct file * file,char * buf,size_t count,loff_t * f_ops)
  61. {
  62.     printk(" GPIO_VIB_read \r\n");
  63.     gpio_direction_output(S3C64XX_GPM(3), 0);//
  64.     return count ;
  65. }
  66. ssize_t GPIO_VIB_write (struct file * file,const char * buf, size_t count,loff_t * f_ops)
  67. {
  68.       printk(" GPIO_VIB_write \r\n");
  69.       gpio_direction_output(S3C64XX_GPM(3), 1);//
  70.    return count;
  71. }
  72.  
  73. //ssize_t GPIO_VIB_ioctl(struct inode *  inode,struct file * file,unsigned int cmd, long data)
  74. static int GPIO_VIB_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  75. {
  76.     printk(KERN_ERR"VIB:GPIO_VIB_ioctl --CMD=%x \n",cmd);
  77.     switch(cmd)
  78.         {
  79.            case VIB_ON:
  80.             gpio_direction_output(S3C64XX_GPM(1), 0);//
  81.             gpio_direction_output(S3C64XX_GPM(2), 0);//
  82.             gpio_direction_output(S3C64XX_GPM(3), 0);//
  83.             gpio_direction_output(S3C64XX_GPM(4), 1);//
  84.             printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_ON\n");
  85.             break;
  86.          case VIB_OFF:
  87.             {
  88.             printk(KERN_ERR"VIB:GPIO_VIB_ioctl --VIB_OFF\n");
  89.             gpio_direction_output(S3C64XX_GPM(1), 1);//
  90.             gpio_direction_output(S3C64XX_GPM(2), 1);//
  91.             gpio_direction_output(S3C64XX_GPM(3), 1);//
  92.             gpio_direction_output(S3C64XX_GPM(4), 0);//
  93.             break;
  94.          }
  95.          default:break;
  96.                 
  97.     }
  98.         //gpio_free(S3C64XX_GPN(7));
  99. }
  100. ssize_t GPIO_VIB_open(struct inode * inode,struct file * file)
  101. {
  102. //?£?éêy
  103.   //MOD_INC_USE_COUNT;
  104.   printk("GPIO_VIB_open() \n");   
  105.   return 0;
  106. }
  107. ssize_t GPIO_VIB_release(struct inode * inode, struct file * file)
  108. {
  109.    // MOD_DEC_USE_COUNT;//?£?éêy??
  110.      printk("GPIO_VIB_release() \n");   
  111.     return 0;
  112. }
  113. static int GPIO_VIB_CTL_init(void)
  114. {
  115.     int ret  = -ENODEV;
  116.    int error ;
  117.     printk("---------------------------------------------- \r\n");
  118.     //3?ê??ˉ???ú
  119.         s3c_gpio_cfgpin(S3C64XX_GPM(1), S3C_GPIO_SFN(1));//GPM1 output
  120.         s3c_gpio_cfgpin(S3C64XX_GPM(2), S3C_GPIO_SFN(1));//GPM2 output
  121.         s3c_gpio_cfgpin(S3C64XX_GPM(3), S3C_GPIO_SFN(1));//GPM3 output
  122.         s3c_gpio_cfgpin(S3C64XX_GPM(4), S3C_GPIO_SFN(1));//GPM4 output
  123. #if 1 /*?2ì?·?ê?×¢2á?y?ˉ*/
  124. ret = register_chrdev(Viberator_MAJOR, "viberator", &GPIO_Viberator_ctl_ops);
  125. if (ret < 0) {
  126.     printk(KERN_ERR "VIB: unable to get major %d\n", ret);
  127.     return ret;
  128. }
  129. //′′?¨\uc1class
  130. vib_dev_class = class_create(THIS_MODULE, "viberator");
  131. if (IS_ERR(vib_dev_class)) {
  132.     unregister_chrdev(Viberator_MAJOR, "capi20");
  133.     return PTR_ERR(vib_dev_class);
  134. }
  135. //′′?¨?úμ?£?
  136. device_create(vib_dev_class, NULL, MKDEV(Viberator_MAJOR, 0), NULL, "vib");
  137. // create a point under /dev/class/vib  
  138. //í¨1yé????aá?2?£??y?ˉ?ó??oó£??í?á?ú/dev/class/????éú3é\uc1vib?úμ?£?ó|ó?3ìDò?éò???2ù×÷???t???ù2ù×÷?a???úμ?£?í¨1y\uc1open ,write,read μèoˉêy2ù×÷£??ê?é?éò??′oó??μ?ó|ó?ê?ày3ìDò?£
  139.   return 0;    
  140. #endif
  141. #if 0/* ×¢2á?ˉì?*/
  142.     if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "vibrate")) < 0)
  143.         {
  144.         printk(KERN_ERR
  145.                "VIB: Couldn't alloc_chrdev_region, error=%d\n",
  146.                error);
  147.         return 1;
  148.     }
  149.          printk("dev = %d  \n",dev);
  150.     cdev_p = cdev_alloc();
  151.     cdev_p->ops = &GPIO_Viberator_ctl_ops;
  152.     error = cdev_add(cdev_p, dev, DEVCOUNT);
  153.     if (error) {
  154.         printk(KERN_ERR
  155.                "VIB: Couldn't cdev_add, error=%d\n", error);
  156.         return 1;
  157.     }
  158.  
  159.     vib_dev_class = class_create(THIS_MODULE, "vib-dev");
  160.     if (IS_ERR(vib_dev_class)) {
  161.         res = PTR_ERR(vib_dev_class);
  162.         goto out_unreg_class;
  163.     }
  164.     return 0;
  165. #endif
  166. out_unreg_class:
  167.     class_destroy(vib_dev_class);
  168. return 1;
  169. }
  170.  
  171. static int __init S3C6410_VIB_init(void)
  172. {
  173.     int ret = -ENODEV;
  174.     //μ÷ó?oˉêy   
  175.         printk(KERN_ERR "Auly: S3C6410_VIB_init---\n");
  176.     ret = GPIO_VIB_CTL_init();
  177.     if(ret)
  178.         {
  179.         printk(KERN_ERR "Auly: S3C6410_VIB_init--Fail !!!\n");
  180.         return ret;
  181.     }
  182.     return 0;
  183. }
  184. static void __exit cleanup_GPIO_VIB(void)
  185. {
  186.     //×¢?úéè±?
  187.   //  devfs_unregister_chrdev(Viberator_MAJOR,"gpio_vib_ctl");
  188. #if 0
  189.       cdev_del(cdev_p);
  190.     unregister_chrdev_region(dev, DEVCOUNT);
  191.     class_destroy(vib_dev_class);
  192. #endif
  193. device_destroy(vib_dev_class, MKDEV(Viberator_MAJOR, 0));
  194. class_destroy(vib_dev_class);
  195. unregister_chrdev(Viberator_MAJOR, "viberator");
  196. }
  197. MODULE_LICENSE("GPL");
  198. MODULE_DESCRIPTION("Peter first driver");
  199. MODULE_ALIAS_CHARDEV(Viberator_MAJOR, 0);
  200.  
  201. module_init(S3C6410_VIB_init);
  202. module_exit(cleanup_GPIO_VIB);
  • 1
  • 2
  • 3
  • 下一页

相关内容